mirror of
https://github.com/hknsh/project-knedita.git
synced 2024-11-28 17:41:15 +00:00
feat: implemented unit tests
This commit is contained in:
parent
e31b7d083e
commit
f73a12e454
15 changed files with 2158 additions and 28 deletions
1767
package-lock.json
generated
1767
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,8 @@
|
||||||
"prisma:generate": "npx prisma generate",
|
"prisma:generate": "npx prisma generate",
|
||||||
"prisma:seed": "prisma db seed",
|
"prisma:seed": "prisma db seed",
|
||||||
"prisma:studio": "npx prisma studio",
|
"prisma:studio": "npx prisma studio",
|
||||||
"prod:start": "npx prisma migrate deploy && pm2-runtime start dist/server.js"
|
"prod:start": "npx prisma migrate deploy && pm2-runtime start dist/server.js",
|
||||||
|
"test": "vitest run"
|
||||||
},
|
},
|
||||||
"ts-standard": {
|
"ts-standard": {
|
||||||
"project": "tsconfig.json",
|
"project": "tsconfig.json",
|
||||||
|
@ -62,7 +63,9 @@
|
||||||
"supertest": "^6.3.3",
|
"supertest": "^6.3.3",
|
||||||
"ts-node-dev": "^2.0.0",
|
"ts-node-dev": "^2.0.0",
|
||||||
"tsconfig-paths": "^4.2.0",
|
"tsconfig-paths": "^4.2.0",
|
||||||
"typescript": "^5.1.6"
|
"typescript": "^5.1.6",
|
||||||
|
"vite-tsconfig-paths": "^4.2.1",
|
||||||
|
"vitest": "^0.34.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^5.0.0",
|
"@prisma/client": "^5.0.0",
|
||||||
|
|
45
src/__tests__/post/post-create.test.ts
Normal file
45
src/__tests__/post/post-create.test.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import app from '../../app'
|
||||||
|
import { expect, describe, beforeAll, afterAll, it } from 'vitest'
|
||||||
|
import request from 'supertest'
|
||||||
|
import signUpNewUser from '../utils/create-user'
|
||||||
|
import deleteUser from '../utils/delete-user'
|
||||||
|
import type User from 'interfaces/user'
|
||||||
|
|
||||||
|
let user: User
|
||||||
|
|
||||||
|
describe('POST /post/create', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await signUpNewUser()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
await deleteUser(user.username!)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with 200 status code if the user send the token and the content', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.post('/post/create')
|
||||||
|
.send({
|
||||||
|
content: 'Hello world',
|
||||||
|
})
|
||||||
|
.set('Authorization', `Bearer ${user.token ?? ''}`)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(response.body).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
content: expect.any(String),
|
||||||
|
authorId: expect.any(String),
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
updatedAt: expect.any(String),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with 400 status code if the user send no token', async () => {
|
||||||
|
const response = await request(app).post('/post/create').expect(401)
|
||||||
|
|
||||||
|
expect(response.body).toHaveProperty('error')
|
||||||
|
})
|
||||||
|
})
|
37
src/__tests__/post/post-delete.test.ts
Normal file
37
src/__tests__/post/post-delete.test.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import app from '../../app'
|
||||||
|
import { describe, beforeAll, afterAll, it } from 'vitest'
|
||||||
|
import request from 'supertest'
|
||||||
|
import signUpNewUser from '../utils/create-user'
|
||||||
|
import deleteUser from '../utils/delete-user'
|
||||||
|
import type User from 'interfaces/user'
|
||||||
|
|
||||||
|
let user: User
|
||||||
|
|
||||||
|
describe('DELETE /post/delete', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await signUpNewUser()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
await deleteUser(user.username!)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should delete the post successfully', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.post('/post/create')
|
||||||
|
.send({
|
||||||
|
content: 'lorem ipsum',
|
||||||
|
})
|
||||||
|
.set('Authorization', `Bearer ${user.token ?? ''}`)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
await request(app)
|
||||||
|
.post('/post/delete')
|
||||||
|
.send({
|
||||||
|
postId: response.body.id,
|
||||||
|
})
|
||||||
|
.set('Authorization', `Bearer ${user.token ?? ''}`)
|
||||||
|
.expect(200)
|
||||||
|
})
|
||||||
|
})
|
55
src/__tests__/post/post-info.test.ts
Normal file
55
src/__tests__/post/post-info.test.ts
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import app from '../../app'
|
||||||
|
import { expect, describe, beforeAll, afterAll, it } from 'vitest'
|
||||||
|
import request from 'supertest'
|
||||||
|
import signUpNewUser from '../utils/create-user'
|
||||||
|
import deleteUser from '../utils/delete-user'
|
||||||
|
import type User from 'interfaces/user'
|
||||||
|
|
||||||
|
let postId: string
|
||||||
|
|
||||||
|
let user: User
|
||||||
|
|
||||||
|
describe('POST /post/info', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await signUpNewUser()
|
||||||
|
|
||||||
|
const token = user.token ?? ''
|
||||||
|
|
||||||
|
const post = await request(app)
|
||||||
|
.post('/post/create')
|
||||||
|
.send({
|
||||||
|
content: 'Hello world',
|
||||||
|
})
|
||||||
|
.set('Authorization', `Bearer ${token}`)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
postId = post.body.id
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
await deleteUser(user.username!)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with 200 status code and return some info about the post', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.get(`/post/info?id=${postId}`)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(response.body).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
content: expect.any(String),
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
updatedAt: expect.any(String),
|
||||||
|
author: expect.any(Object),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with 400 status code if the post does not exists', async () => {
|
||||||
|
const response = await request(app).get('/post/info?id=abc').expect(400)
|
||||||
|
|
||||||
|
expect(response.body).toHaveProperty('error')
|
||||||
|
})
|
||||||
|
})
|
57
src/__tests__/post/post-update.test.ts
Normal file
57
src/__tests__/post/post-update.test.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import app from '../../app'
|
||||||
|
import { expect, describe, beforeAll, afterAll, it } from 'vitest'
|
||||||
|
import request from 'supertest'
|
||||||
|
import signUpNewUser from '../utils/create-user'
|
||||||
|
import deleteUser from '../utils/delete-user'
|
||||||
|
import type User from 'interfaces/user'
|
||||||
|
|
||||||
|
let user: User
|
||||||
|
|
||||||
|
describe('PUT /post/update', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await signUpNewUser()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
await deleteUser(user.username!)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should create a new post and update the content of it', async () => {
|
||||||
|
const post = await request(app)
|
||||||
|
.post('/post/create')
|
||||||
|
.send({
|
||||||
|
content: 'Lorem',
|
||||||
|
})
|
||||||
|
.set('Authorization', `Bearer ${user.token ?? ''}`)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(post.body).toHaveProperty('id')
|
||||||
|
|
||||||
|
const fieldsToUpdate = {
|
||||||
|
postId: post.body.id,
|
||||||
|
content: 'Lorem ipsum',
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await request(app)
|
||||||
|
.put('/post/update')
|
||||||
|
.send(fieldsToUpdate)
|
||||||
|
.set('Authorization', `Bearer ${user.token ?? ''}`)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
// Post content should be Lorem Ipsum
|
||||||
|
if (post.body.content === response.body.content) {
|
||||||
|
throw new Error("Post didn't update")
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(response.body).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
content: expect.any(String),
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
updatedAt: expect.any(String),
|
||||||
|
author: expect.any(Object),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
46
src/__tests__/user/user-auth.test.ts
Normal file
46
src/__tests__/user/user-auth.test.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import app from '../../app'
|
||||||
|
import deleteUser from '../utils/delete-user'
|
||||||
|
import { expect, describe, beforeAll, afterAll, it } from 'vitest'
|
||||||
|
import request from 'supertest'
|
||||||
|
import signUpNewUser from '../utils/create-user'
|
||||||
|
|
||||||
|
import type User from 'interfaces/user'
|
||||||
|
let user: User
|
||||||
|
|
||||||
|
describe('POST /user/auth', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await signUpNewUser()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
await deleteUser(user.username!)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with a error if the user does not exists', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.post('/user/auth')
|
||||||
|
.send({ email: 'mm@mm.com', password: 'aa' })
|
||||||
|
.expect(400)
|
||||||
|
|
||||||
|
expect(response.body).toHaveProperty('error')
|
||||||
|
expect(response.body.error).toBe('Invalid email or password')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with a error if receive an invalid email or password', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.post('/user/auth')
|
||||||
|
.send({ email: user.email, password: 'fake_pass' })
|
||||||
|
.expect(400)
|
||||||
|
|
||||||
|
expect(response.body).toHaveProperty('error')
|
||||||
|
expect(response.body.error).toBe('Invalid email or password')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with a error if receive an empty body', async () => {
|
||||||
|
const response = await request(app).post('/user/auth').send({}).expect(400)
|
||||||
|
|
||||||
|
expect(response.body).toHaveProperty('error')
|
||||||
|
expect(response.body.error).toBe('Missing fields')
|
||||||
|
})
|
||||||
|
})
|
20
src/__tests__/user/user-delete.test.ts
Normal file
20
src/__tests__/user/user-delete.test.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import app from '../../app'
|
||||||
|
import { describe, beforeAll, it } from 'vitest'
|
||||||
|
import request from 'supertest'
|
||||||
|
import signUpNewUser from '../utils/create-user'
|
||||||
|
import type User from 'interfaces/user'
|
||||||
|
|
||||||
|
let user: User
|
||||||
|
|
||||||
|
describe('DELETE /user/delete', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await signUpNewUser()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should delete the user successfully', async () => {
|
||||||
|
await request(app)
|
||||||
|
.post('/user/delete')
|
||||||
|
.set('Authorization', `Bearer ${user.token ?? ''}`)
|
||||||
|
.expect(200)
|
||||||
|
})
|
||||||
|
})
|
38
src/__tests__/user/user-info.test.ts
Normal file
38
src/__tests__/user/user-info.test.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import app from '../../app'
|
||||||
|
import { expect, describe, beforeAll, afterAll, it } from 'vitest'
|
||||||
|
import request from 'supertest'
|
||||||
|
import deleteUser from '../utils/delete-user'
|
||||||
|
import signUpNewUser from '../utils/create-user'
|
||||||
|
import type User from 'interfaces/user'
|
||||||
|
|
||||||
|
let user: User
|
||||||
|
|
||||||
|
describe('POST /user/info', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await signUpNewUser()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
await deleteUser(user.username!)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with 200 status code and return the user data', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.get(`/user/info?u=${user.username ?? ''}`)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(response.body).toHaveProperty('profileImage')
|
||||||
|
expect(response.body).toHaveProperty('displayName')
|
||||||
|
expect(response.body).toHaveProperty('username')
|
||||||
|
expect(response.body).toHaveProperty('createdAt')
|
||||||
|
expect(response.body).toHaveProperty('posts')
|
||||||
|
expect(response.body).toHaveProperty('likedPosts')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with 400 status code if the user send no username', async () => {
|
||||||
|
const response = await request(app).get('/user/info?u=').expect(400)
|
||||||
|
|
||||||
|
expect(response.body).toHaveProperty('error')
|
||||||
|
})
|
||||||
|
})
|
46
src/__tests__/user/user-signup.test.ts
Normal file
46
src/__tests__/user/user-signup.test.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import app from '../../app'
|
||||||
|
import { describe, beforeAll, afterAll, it } from 'vitest'
|
||||||
|
import request from 'supertest'
|
||||||
|
import deleteUser from '../utils/delete-user'
|
||||||
|
import signUpNewUser from '../utils/create-user'
|
||||||
|
import type User from 'interfaces/user'
|
||||||
|
|
||||||
|
let user: User
|
||||||
|
|
||||||
|
describe('POST /user/signup', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await signUpNewUser()
|
||||||
|
delete user.token
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
await deleteUser(user.username!)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with a 400 status code if sent any invalid data', async () => {
|
||||||
|
await request(app)
|
||||||
|
.post('/user/signup')
|
||||||
|
.send({
|
||||||
|
username: 'username12@',
|
||||||
|
email: user.email,
|
||||||
|
password: user.password,
|
||||||
|
})
|
||||||
|
.expect(400)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with a 400 status code for an existing username or email', async () => {
|
||||||
|
await request(app)
|
||||||
|
.post('/user/signup')
|
||||||
|
.send({
|
||||||
|
username: user.username,
|
||||||
|
email: user.email,
|
||||||
|
password: user.password,
|
||||||
|
})
|
||||||
|
.expect(400)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should respond with a 400 status code if receive an empty body', async () => {
|
||||||
|
await request(app).post('/user/signup').send({}).expect(400)
|
||||||
|
})
|
||||||
|
})
|
37
src/__tests__/utils/create-user.ts
Normal file
37
src/__tests__/utils/create-user.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import app from '../../app'
|
||||||
|
import request from 'supertest'
|
||||||
|
import { faker } from '@faker-js/faker'
|
||||||
|
import type userPayload from '../../interfaces/user'
|
||||||
|
|
||||||
|
async function signUpNewUser(): Promise<userPayload> {
|
||||||
|
// To avoid conflicts with existing usernames or emails
|
||||||
|
const username = faker.internet.userName({ lastName: 'doe' }).toLowerCase()
|
||||||
|
const email = faker.internet.email()
|
||||||
|
const password = faker.internet.password() + '@1'
|
||||||
|
|
||||||
|
await request(app)
|
||||||
|
.post('/user/signup')
|
||||||
|
.send({
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
})
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
const response = await request(app)
|
||||||
|
.post('/user/auth')
|
||||||
|
.send({
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
})
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
return {
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
token: response.body.token,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default signUpNewUser
|
17
src/__tests__/utils/delete-user.ts
Normal file
17
src/__tests__/utils/delete-user.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import prisma from '../../clients/prisma-client'
|
||||||
|
|
||||||
|
export default async function deleteUser(username: string) {
|
||||||
|
await prisma.post.deleteMany({
|
||||||
|
where: {
|
||||||
|
author: {
|
||||||
|
username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
await prisma.user.deleteMany({
|
||||||
|
where: {
|
||||||
|
username,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ import logger from 'helpers/logger'
|
||||||
|
|
||||||
let maxConnections
|
let maxConnections
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
||||||
logger.info('Development environment detected. Rate limit is now disabled.')
|
logger.info('Development environment detected. Rate limit is now disabled.')
|
||||||
maxConnections = 0
|
maxConnections = 0
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"middlewares/*": ["middlewares/*"],
|
"middlewares/*": ["middlewares/*"],
|
||||||
"services/*": ["services/*"]
|
"services/*": ["services/*"]
|
||||||
},
|
},
|
||||||
"typeRoots": ["./src/@types", "./node_modules/@types"],
|
"typeRoots": ["./src/@types", "./node_modules/@types", "./node_modules/@types/minimist/index.d.ts"],
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"removeComments": true,
|
"removeComments": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
|
10
vitest.config.ts
Normal file
10
vitest.config.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [tsconfigPaths()],
|
||||||
|
test: {
|
||||||
|
name: 'Project Knedita',
|
||||||
|
env: { NODE_ENV: 'test' },
|
||||||
|
},
|
||||||
|
})
|
Loading…
Reference in a new issue