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:seed": "prisma db seed",
|
||||
"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": {
|
||||
"project": "tsconfig.json",
|
||||
|
@ -62,7 +63,9 @@
|
|||
"supertest": "^6.3.3",
|
||||
"ts-node-dev": "^2.0.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": {
|
||||
"@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
|
||||
|
||||
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.')
|
||||
maxConnections = 0
|
||||
} else {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"middlewares/*": ["middlewares/*"],
|
||||
"services/*": ["services/*"]
|
||||
},
|
||||
"typeRoots": ["./src/@types", "./node_modules/@types"],
|
||||
"typeRoots": ["./src/@types", "./node_modules/@types", "./node_modules/@types/minimist/index.d.ts"],
|
||||
"outDir": "./dist",
|
||||
"removeComments": 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