test: add note controller case (#939)

This commit is contained in:
2023-01-17 19:10:53 +08:00
committed by GitHub
parent 7adff99a14
commit 02a08ad9f3
31 changed files with 937 additions and 161 deletions

View File

@@ -13,3 +13,5 @@ packages/*/test
packages/*/tests packages/*/tests
packages/*/esm packages/*/esm
packages/*/types packages/*/types
test/**/*.db.ts

View File

@@ -7,6 +7,7 @@ on:
push: push:
branches: branches:
- '**' - '**'
pull_request: pull_request:
branches: [master] branches: [master]

View File

@@ -6,6 +6,8 @@ on:
- '**' - '**'
tags: tags:
- 'v*' - 'v*'
paths-ignore:
- test/**
pull_request: pull_request:
branches: [master] branches: [master]

View File

@@ -0,0 +1,103 @@
import { ModuleMetadata } from '@nestjs/common'
import { APP_INTERCEPTOR } from '@nestjs/core'
import { NestFastifyApplication } from '@nestjs/platform-fastify'
import { BeAnObject, ReturnModelType } from '@typegoose/typegoose/lib/types'
import { HttpCacheInterceptor } from '~/common/interceptors/cache.interceptor'
import { DbQueryInterceptor } from '~/common/interceptors/db-query.interceptor'
import { JSONTransformInterceptor } from '~/common/interceptors/json-transform.interceptor'
import { ResponseFilterInterceptor } from '~/common/interceptors/response-filter.interceptor'
import { ResponseInterceptor } from '~/common/interceptors/response.interceptor'
import { getModelToken } from '~/transformers/model.transformer'
import { dbHelper } from './db-mock.helper'
import { redisHelper } from './redis-mock.helper'
import { setupE2EApp } from './setup-e2e'
type ClassType = new (...args: any[]) => any
type ModelMap = Map<
ClassType,
{
name: string
token: string
model: ReturnModelType<ClassType, BeAnObject>
}
>
interface E2EAppMetaData {
models?: ClassType[]
pourData?: (modelMap: ModelMap) => Promise<void | (() => Promise<any>)>
}
export const createE2EApp = (module: ModuleMetadata & E2EAppMetaData) => {
const proxy: {
app: NestFastifyApplication
} = {} as any
let pourDataCleanup: (() => Promise<void>) | undefined
beforeAll(async () => {
const { CacheService, token } = await redisHelper
const { models, pourData, ...nestModule } = module
nestModule.providers ||= []
nestModule.providers.push(
{
provide: APP_INTERCEPTOR,
useClass: DbQueryInterceptor,
},
{
provide: APP_INTERCEPTOR,
useClass: HttpCacheInterceptor, // 5
},
{
provide: APP_INTERCEPTOR,
useClass: JSONTransformInterceptor, // 3
},
{
provide: APP_INTERCEPTOR,
useClass: ResponseFilterInterceptor, // 2
},
{
provide: APP_INTERCEPTOR,
useClass: ResponseInterceptor, // 1
},
)
nestModule.providers.push({ provide: token, useValue: CacheService })
const modelMap = new Map() as ModelMap
if (models) {
models.forEach((model) => {
const token = getModelToken(model.name)
const modelInstance = dbHelper.getModel(model)
nestModule.providers.push({
provide: token,
useValue: modelInstance,
})
modelMap.set(model, {
name: model.name,
token,
model: modelInstance,
})
})
}
if (pourData) {
const cleanup = await pourData(modelMap)
// @ts-ignore
pourDataCleanup = cleanup
}
const app = await setupE2EApp(nestModule)
proxy.app = app
})
afterAll(async () => {
if (pourDataCleanup) {
return await pourDataCleanup()
}
})
return proxy
}

View File

@@ -0,0 +1,74 @@
import { MongoMemoryServer } from 'mongodb-memory-server'
import mongoose from 'mongoose'
import { nanoid } from 'nanoid/async'
import { getModelForClass } from '@typegoose/typegoose'
import {
AnyParamConstructor,
BeAnObject,
IModelOptions,
ReturnModelType,
} from '@typegoose/typegoose/lib/types'
let mongod: MongoMemoryServer
const dbMap = new Map<string, typeof mongoose>()
/**
* Connect to mock memory db.
*/
const connect = async () => {
mongod = await MongoMemoryServer.create()
const uri = mongod.getUri()
const mongooseInstance = await mongoose.connect(uri, {
autoIndex: true,
maxPoolSize: 10,
})
const id = await nanoid()
dbMap.set(id, mongooseInstance)
return id
}
/**
* Close db connection
*/
const closeDatabase = async (id: string) => {
const mongoose = dbMap.get(id)
if (!mongoose) {
return
}
await mongoose.connection.dropDatabase()
await mongoose.connection.close()
dbMap.delete(id)
if (dbMap.size === 0) await mongod.stop()
}
/**
* Delete db collections
*/
const clearDatabase = async (id: string) => {
const mongoose = dbMap.get(id)
if (!mongoose) {
return
}
const collections = mongoose.connection.collections
for (const key in collections) {
const collection = collections[key]
await collection.deleteMany({})
}
}
export const dbHelper = {
connect,
close: () => closeDatabase(),
clear: () => clearDatabase(),
getModel<U extends AnyParamConstructor<any>, QueryHelpers = BeAnObject>(
cl: U,
options?: IModelOptions,
): ReturnModelType<U, QueryHelpers> {
return getModelForClass(cl, options)
},
}

View File

@@ -55,6 +55,10 @@ export const dbHelper = {
cl: U, cl: U,
options?: IModelOptions, options?: IModelOptions,
): ReturnModelType<U, QueryHelpers> { ): ReturnModelType<U, QueryHelpers> {
return getModelForClass(cl, options) return getModelForClass(cl, {
existingMongoose: mongoose,
existingConnection: mongoose.connection,
...options,
})
}, },
} }

View File

@@ -0,0 +1,12 @@
export interface Provider<T = unknown> {
provide: new (...args: any[]) => T
useValue: Partial<T>
}
export const defineProvider = <T>(provider: Provider<T>) => {
return provider
}
export const defineProviders = (providers: Provider[]) => {
return providers
}

View File

@@ -1,23 +0,0 @@
import { ValidationPipe } from '@nestjs/common'
import { NestFastifyApplication } from '@nestjs/platform-fastify'
import { TestingModule } from '@nestjs/testing'
import { fastifyApp } from '~/common/adapters/fastify.adapter'
export const setupE2EApp = async (module: TestingModule) => {
const app = module.createNestApplication<NestFastifyApplication>(fastifyApp)
app.useGlobalPipes(
new ValidationPipe({
transform: true,
whitelist: true,
errorHttpStatusCode: 422,
forbidUnknownValues: true,
enableDebugMessages: isDev,
stopAtFirstError: true,
}),
)
await app.init()
await app.getHttpAdapter().getInstance().ready()
return app
}

31
test/helper/setup-e2e.ts Normal file
View File

@@ -0,0 +1,31 @@
import { ModuleMetadata, ValidationPipe } from '@nestjs/common'
import { NestFastifyApplication } from '@nestjs/platform-fastify'
import { Test, TestingModule } from '@nestjs/testing'
import { fastifyApp } from '~/common/adapters/fastify.adapter'
export const setupE2EApp = async (module: TestingModule | ModuleMetadata) => {
let nextModule: TestingModule
if (module instanceof TestingModule) {
nextModule = module
} else {
nextModule = await Test.createTestingModule(module).compile()
}
const app =
nextModule.createNestApplication<NestFastifyApplication>(fastifyApp)
app.useGlobalPipes(
new ValidationPipe({
transform: true,
whitelist: true,
errorHttpStatusCode: 422,
forbidUnknownValues: true,
enableDebugMessages: isDev,
stopAtFirstError: true,
}),
)
await app.init()
await app.getHttpAdapter().getInstance().ready()
return app
}

View File

@@ -0,0 +1,8 @@
import { defineProvider } from 'test/helper/defineProvider'
import { AuthService } from '~/modules/auth/auth.service'
export const authProvider = defineProvider({
useValue: {},
provide: AuthService,
})

View File

@@ -0,0 +1,12 @@
import { dbHelper } from 'test/helper/db-mock.helper'
import { defineProvider } from 'test/helper/defineProvider'
import { CommentModel } from '~/modules/comment/comment.model'
import { CommentService } from '~/modules/comment/comment.service'
export const commentProvider = defineProvider({
provide: CommentService,
useValue: {
model: dbHelper.getModel(CommentModel) as any,
},
})

View File

@@ -0,0 +1,20 @@
import { defineProvider } from 'test/helper/defineProvider'
import { generateDefaultConfig } from '~/modules/configs/configs.default'
import { ConfigsService } from '~/modules/configs/configs.service'
export const configProvider = defineProvider({
provide: ConfigsService,
useValue: {
defaultConfig: generateDefaultConfig(),
async get(key) {
return this.defaultConfig[key]
},
async getConfig() {
return this.defaultConfig
},
async waitForConfigReady() {
return this.defaultConfig
},
},
})

View File

@@ -0,0 +1,20 @@
import { defineProviders } from 'test/helper/defineProvider'
import { AdminEventsGateway } from '~/processors/gateway/admin/events.gateway'
import { SystemEventsGateway } from '~/processors/gateway/system/events.gateway'
import { WebEventsGateway } from '~/processors/gateway/web/events.gateway'
export const gatewayProviders = defineProviders([
{
provide: WebEventsGateway,
useValue: {},
},
{
provide: AdminEventsGateway,
useValue: {},
},
{
provide: SystemEventsGateway,
useValue: {},
},
])

View File

@@ -0,0 +1,18 @@
import { defineProvider } from 'test/helper/defineProvider'
import { CountingService } from '~/processors/helper/helper.counting.service'
export const countingServiceProvider = defineProvider({
useValue: {
async updateLikeCount() {
return true
},
async getThisRecordIsLiked() {
return true
},
async updateReadCount() {
return
},
},
provide: CountingService,
})

View File

@@ -0,0 +1,12 @@
import { defineProvider } from 'test/helper/defineProvider'
import { TextMacroService } from '~/processors/helper/helper.macro.service'
export const textMacroProvider = defineProvider({
provide: TextMacroService,
useValue: {
async replaceTextMacro(text) {
return text
},
},
})

View File

@@ -1,7 +1,29 @@
import { register } from '~/global/index.global' import { mkdirSync } from 'fs-extra'
import { chalk } from 'zx'
import { Logger } from '@nestjs/common'
import {
DATA_DIR,
LOG_DIR,
STATIC_FILE_DIR,
TEMP_DIR,
THEME_DIR,
USER_ASSET_DIR,
} from '~/constants/path.constant'
export async function setup() { export async function setup() {
await register() mkdirSync(DATA_DIR, { recursive: true })
Logger.log(chalk.blue(`数据目录已经建好:${DATA_DIR}`))
mkdirSync(TEMP_DIR, { recursive: true })
Logger.log(chalk.blue(`临时目录已经建好:${TEMP_DIR}`))
mkdirSync(LOG_DIR, { recursive: true })
Logger.log(chalk.blue(`日志目录已经建好:${LOG_DIR}`))
mkdirSync(USER_ASSET_DIR, { recursive: true })
Logger.log(chalk.blue(`资源目录已经建好:${USER_ASSET_DIR}`))
mkdirSync(STATIC_FILE_DIR, { recursive: true })
Logger.log(chalk.blue(`文件存放目录已经建好:${STATIC_FILE_DIR}`))
mkdirSync(THEME_DIR, { recursive: true })
} }
export async function teardown() {} export async function teardown() {}

View File

@@ -1,20 +0,0 @@
// @ts-nocheck
import { beforeAll } from 'vitest'
import 'zx/globals'
import consola from 'consola'
beforeAll(async () => {
await import('zx/globals')
global.isDev = true
global.cwd = process.cwd()
global.consola = consola
})
beforeEach(() => {
global.isDev = true
global.cwd = process.cwd()
global.consola = consola
})

View File

@@ -0,0 +1,37 @@
// @ts-nocheck
import { beforeAll } from 'vitest'
import 'zx/globals'
import consola from 'consola'
import { dbHelper } from 'test/helper/db-mock.helper'
import { redisHelper } from 'test/helper/redis-mock.helper'
import { registerJSONGlobal } from '~/global/json.global'
beforeAll(async () => {
await import('zx/globals')
global.isDev = true
global.cwd = process.cwd()
global.consola = consola
registerJSONGlobal()
})
afterAll(async () => {
await dbHelper.clear()
await dbHelper.close()
await (await redisHelper).close()
})
beforeAll(async () => {
await dbHelper.connect()
await redisHelper
})
beforeEach(() => {
global.isDev = true
global.cwd = process.cwd()
global.consola = consola
})

View File

@@ -24,7 +24,6 @@ describe('AppController (e2e)', () => {
}) })
.overrideProvider(CacheService) .overrideProvider(CacheService)
.useValue({}) .useValue({})
.compile() .compile()
app = moduleRef.createNestApplication<NestFastifyApplication>(fastifyApp) app = moduleRef.createNestApplication<NestFastifyApplication>(fastifyApp)

View File

@@ -1,4 +1,3 @@
import { dbHelper } from 'test/helper/db-mock.helper'
import { MockCacheService, redisHelper } from 'test/helper/redis-mock.helper' import { MockCacheService, redisHelper } from 'test/helper/redis-mock.helper'
import { vi } from 'vitest' import { vi } from 'vitest'
@@ -20,11 +19,6 @@ describe('Test ConfigsService', () => {
let service: ConfigsService let service: ConfigsService
let redisService: MockCacheService let redisService: MockCacheService
afterAll(async () => {
await dbHelper.clear()
await dbHelper.close()
await (await redisHelper).close()
})
const optionModel = getModelForClass(OptionModel) const optionModel = getModelForClass(OptionModel)
const mockEmitFn = vi.fn() const mockEmitFn = vi.fn()
@@ -32,7 +26,6 @@ describe('Test ConfigsService', () => {
const { CacheService: redisService$ } = await redisHelper const { CacheService: redisService$ } = await redisHelper
redisService = redisService$ redisService = redisService$
await dbHelper.connect()
const moduleRef = await Test.createTestingModule({ const moduleRef = await Test.createTestingModule({
imports: [], imports: [],

View File

@@ -0,0 +1,302 @@
// Vitest Snapshot v1
exports[`NoteController (e2e) > GET /latest 1`] = `
{
"data": {
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-20T00:00:00.000Z",
"hide": false,
"images": [],
"modified": null,
"music": [],
"nid": 20,
"text": "Content 20",
"title": "Note 20",
"topic": null,
},
"next": {
"nid": 19,
"topic": null,
},
}
`;
exports[`NoteController (e2e) > GET /list/:id 1`] = `
{
"data": [
{
"created": "2023-01-17T11:01:57.851Z",
"nid": 21,
"title": "Note 2 (updated)",
"topic": null,
},
{
"created": "2021-03-20T00:00:00.000Z",
"nid": 20,
"title": "Note 20",
"topic": null,
},
{
"created": "2021-03-19T00:00:00.000Z",
"nid": 19,
"title": "Note 19",
"topic": null,
},
{
"created": "2021-03-18T00:00:00.000Z",
"nid": 18,
"title": "Note 18",
"topic": null,
},
{
"created": "2021-03-17T00:00:00.000Z",
"nid": 17,
"title": "Note 17",
"topic": null,
},
],
"size": 5,
}
`;
exports[`NoteController (e2e) > GET /notes 1`] = `
{
"data": [
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-20T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 20,
"text": "Content 20",
"title": "Note 20",
"topic": null,
},
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-19T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 19,
"text": "Content 19",
"title": "Note 19",
"topic": null,
},
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-18T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 18,
"text": "Content 18",
"title": "Note 18",
"topic": null,
},
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-17T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 17,
"text": "Content 17",
"title": "Note 17",
"topic": null,
},
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-16T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 16,
"text": "Content 16",
"title": "Note 16",
"topic": null,
},
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-15T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 15,
"text": "Content 15",
"title": "Note 15",
"topic": null,
},
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-14T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 14,
"text": "Content 14",
"title": "Note 14",
"topic": null,
},
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-13T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 13,
"text": "Content 13",
"title": "Note 13",
"topic": null,
},
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-12T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 12,
"text": "Content 12",
"title": "Note 12",
"topic": null,
},
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2021-03-11T00:00:00.000Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 11,
"text": "Content 11",
"title": "Note 11",
"topic": null,
},
],
"pagination": {
"current_page": 1,
"has_next_page": true,
"has_prev_page": false,
"size": 10,
"total": 20,
"total_page": 2,
},
}
`;
exports[`NoteController (e2e) > Get patched note 1`] = `
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2023-01-17T11:01:57.851Z",
"hide": false,
"images": [],
"modified": null,
"mood": "happy",
"music": [],
"nid": 21,
"text": "Content 2 (updated)",
"title": "Note 2 (updated)",
"topic": null,
"weather": "sunny",
}
`;
exports[`NoteController (e2e) > POST /notes 1`] = `
{
"allow_comment": true,
"comments_index": 0,
"count": {
"like": 0,
"read": 0,
},
"created": "2023-01-17T11:01:57.851Z",
"hide": false,
"images": [],
"meta": null,
"modified": null,
"music": [],
"nid": 21,
"text": "Content 2",
"title": "Note 2",
}
`;

View File

@@ -0,0 +1,202 @@
import { createE2EApp } from 'test/helper/create-e2e-app'
import { authProvider } from 'test/mock/modules/auth.mock'
import { commentProvider } from 'test/mock/modules/comment.mock'
import { configProvider } from 'test/mock/modules/config.mock'
import { gatewayProviders } from 'test/mock/modules/gateway.mock'
import { countingServiceProvider } from 'test/mock/processors/counting.mock'
import { EventEmitter2 } from '@nestjs/event-emitter'
import { ReturnModelType } from '@typegoose/typegoose'
import { OptionModel } from '~/modules/configs/configs.model'
import { NoteController } from '~/modules/note/note.controller'
import { NoteModel } from '~/modules/note/note.model'
import { NoteService } from '~/modules/note/note.service'
import { UserModel } from '~/modules/user/user.model'
import { UserService } from '~/modules/user/user.service'
import { CountingService } from '~/processors/helper/helper.counting.service'
import { EventManagerService } from '~/processors/helper/helper.event.service'
import { HttpService } from '~/processors/helper/helper.http.service'
import { ImageService } from '~/processors/helper/helper.image.service'
import { TextMacroService } from '~/processors/helper/helper.macro.service'
import { SubPubBridgeService } from '~/processors/redis/subpub.service'
import MockDbData from './note.e2e-mock.db'
describe('NoteController (e2e)', () => {
let model: ReturnModelType<typeof NoteModel>
const proxy = createE2EApp({
controllers: [NoteController],
providers: [
NoteService,
ImageService,
EventManagerService,
commentProvider,
{
provide: TextMacroService,
useValue: {
async replaceTextMacro(text) {
return text
},
},
},
HttpService,
configProvider,
EventEmitter2,
UserService,
SubPubBridgeService,
...gatewayProviders,
authProvider,
CountingService,
countingServiceProvider,
],
imports: [],
models: [NoteModel, OptionModel, UserModel],
async pourData(modelMap) {
// @ts-ignore
const { model: _model } = modelMap.get(NoteModel) as {
model: ReturnModelType<typeof NoteModel>
}
model = _model
for await (const data of MockDbData) {
await _model.create(data)
}
},
})
afterAll(async () => {
await model.deleteMany({})
})
test('GET /notes', async () => {
const { app } = proxy
const res = await app.inject({
method: 'GET',
url: '/notes',
})
const data = res.json()
expect(res.statusCode).toBe(200)
data.data.forEach((d) => {
delete d.id
delete d._id
})
expect(data).toMatchSnapshot()
})
const createdNoteData: Partial<NoteModel> = {
title: 'Note 2',
text: 'Content 2',
allowComment: true,
// use cutsom date
created: new Date('2023-01-17T11:01:57.851Z'),
}
test('POST /notes', async () => {
const { app } = proxy
const res = await app.inject({
method: 'POST',
url: '/notes',
payload: createdNoteData,
})
const data = res.json()
expect(res.statusCode).toBe(201)
createdNoteData.id = data.id
createdNoteData.nid = data.nid
delete data.id
expect(data).toMatchSnapshot()
})
test('PATCH /notes/:id', async () => {
const { app } = proxy
const res = await app.inject({
method: 'PATCH',
url: `/notes/${createdNoteData.id}`,
payload: {
title: 'Note 2 (updated)',
text: `Content 2 (updated)`,
mood: 'happy',
weather: 'sunny',
},
})
expect(res.statusCode).toBe(204)
})
test('Get patched note', async () => {
const { app } = proxy
const res = await app.inject({
method: 'GET',
url: `/notes/${createdNoteData.id}`,
})
expect(res.statusCode).toBe(200)
const data = res.json()
delete data.id
expect(data).toMatchSnapshot()
})
test('GET /list/:id', async () => {
const { app } = proxy
const res = await app.inject({
method: 'GET',
url: `/notes/list/${createdNoteData.id}`,
})
expect(res.statusCode).toBe(200)
const data = res.json()
data.data.forEach((note) => {
delete note.id
})
expect(data).toMatchSnapshot()
})
test('DEL /notes/:id', async () => {
const { app } = proxy
const res = await app.inject({
method: 'DELETE',
url: `/notes/${createdNoteData.id}`,
})
expect(res.statusCode).toBe(204)
})
it('should got 404 when get deleted note', async () => {
const { app } = proxy
{
const res = await app.inject({
method: 'GET',
url: `/notes/${createdNoteData.id}`,
})
expect(res.statusCode).toBe(404)
}
{
const res = await app.inject({
method: 'GET',
url: `/notes/nid/${createdNoteData.nid}`,
})
expect(res.statusCode).toBe(404)
}
})
test('GET /latest', async () => {
const { app } = proxy
const res = await app.inject({
method: 'GET',
url: '/notes/latest',
})
expect(res.statusCode).toBe(200)
const data = res.json()
delete data.data.id
delete data.next.id
expect(data).toMatchSnapshot()
})
})

View File

@@ -0,0 +1,15 @@
import { NoteModel } from '~/modules/note/note.model'
export default Array.from({ length: 20 }).map((_, _i) => {
const i = _i + 1
return {
title: 'Note ' + i,
text: 'Content ' + i,
created: new Date(`2021-03-${i.toFixed().padStart(2, '0')}T00:00:00.000Z`),
modified: null,
allowComment: true,
hide: false,
commentsIndex: 0,
}
}) as NoteModel[]

View File

@@ -1,34 +1,15 @@
import { NestFastifyApplication } from '@nestjs/platform-fastify' import { createE2EApp } from 'test/helper/create-e2e-app'
import { Test } from '@nestjs/testing' import { configProvider } from 'test/mock/modules/config.mock'
import { fastifyApp } from '~/common/adapters/fastify.adapter'
import { generateDefaultConfig } from '~/modules/configs/configs.default'
import { ConfigsService } from '~/modules/configs/configs.service'
import { BaseOptionController } from '~/modules/option/controllers/base.option.controller' import { BaseOptionController } from '~/modules/option/controllers/base.option.controller'
describe('OptionController (e2e)', () => { describe('OptionController (e2e)', () => {
let app: NestFastifyApplication const proxy = createE2EApp({
controllers: [BaseOptionController],
beforeAll(async () => { providers: [configProvider],
const moduleRef = await Test.createTestingModule({
controllers: [BaseOptionController],
providers: [
{
provide: ConfigsService,
useValue: {
defaultConfig: generateDefaultConfig(),
},
},
],
}).compile()
app = moduleRef.createNestApplication<NestFastifyApplication>(fastifyApp)
await app.init()
await app.getHttpAdapter().getInstance().ready()
}) })
test('GET /config/jsonschema', () => { test('GET /config/jsonschema', () => {
return app return proxy.app
.inject({ .inject({
method: 'GET', method: 'GET',
url: '/config/jsonschema', url: '/config/jsonschema',

View File

@@ -1,4 +1,4 @@
import { dbHelper } from 'test/helper/db-mock.helper' import mongoose from 'mongoose'
import { redisHelper } from 'test/helper/redis-mock.helper' import { redisHelper } from 'test/helper/redis-mock.helper'
import { Test } from '@nestjs/testing' import { Test } from '@nestjs/testing'
@@ -17,9 +17,6 @@ describe('test serverless function service', () => {
let service: ServerlessService let service: ServerlessService
beforeAll(async () => { beforeAll(async () => {
const connection = await dbHelper.connect()
await (await redisHelper).connect()
const moduleRef = Test.createTestingModule({ const moduleRef = Test.createTestingModule({
providers: [ providers: [
ServerlessService, ServerlessService,
@@ -32,15 +29,13 @@ describe('test serverless function service', () => {
{ {
provide: DatabaseService, provide: DatabaseService,
useValue: { useValue: {
db: connection.connection.db, db: mongoose.connection.db,
}, },
}, },
{ {
provide: getModelToken('SnippetModel'), provide: getModelToken('SnippetModel'),
useValue: getModelForClass(SnippetModel, { useValue: getModelForClass(SnippetModel),
existingConnection: connection.connection,
}),
}, },
], ],
}) })
@@ -50,12 +45,6 @@ describe('test serverless function service', () => {
service = app.get(ServerlessService) service = app.get(ServerlessService)
}) })
afterAll(async () => {
await dbHelper.clear()
await dbHelper.close()
;(await redisHelper).close()
})
describe('run serverless function', () => { describe('run serverless function', () => {
test('case-1', async () => { test('case-1', async () => {
const model = new SnippetModel() const model = new SnippetModel()

View File

@@ -1,70 +1,42 @@
import { dbHelper } from 'test/helper/db-mock.helper' import { createE2EApp } from 'test/helper/create-e2e-app'
import { MockCacheService, redisHelper } from 'test/helper/redis-mock.helper'
import { setupE2EApp } from 'test/helper/register-app.helper'
import { NestFastifyApplication } from '@nestjs/platform-fastify' import { NestFastifyApplication } from '@nestjs/platform-fastify'
import { Test } from '@nestjs/testing'
import { getModelForClass } from '@typegoose/typegoose'
import { ServerlessService } from '~/modules/serverless/serverless.service' import { ServerlessService } from '~/modules/serverless/serverless.service'
import { SnippetController } from '~/modules/snippet/snippet.controller' import { SnippetController } from '~/modules/snippet/snippet.controller'
import { SnippetModel, SnippetType } from '~/modules/snippet/snippet.model' import { SnippetModel, SnippetType } from '~/modules/snippet/snippet.model'
import { SnippetService } from '~/modules/snippet/snippet.service' import { SnippetService } from '~/modules/snippet/snippet.service'
import { DatabaseService } from '~/processors/database/database.service' import { DatabaseService } from '~/processors/database/database.service'
import { CacheService } from '~/processors/redis/cache.service'
import { getModelToken } from '~/transformers/model.transformer'
describe('test /snippets', () => { describe('test /snippets', () => {
let app: NestFastifyApplication let app: NestFastifyApplication
const proxy = createE2EApp({
controllers: [SnippetController],
providers: [
SnippetService,
{ provide: DatabaseService, useValue: {} },
beforeAll(async () => { {
await dbHelper.connect() provide: ServerlessService,
useValue: {
isValidServerlessFunction() {
return true
},
},
},
],
models: [SnippetModel],
}) })
afterAll(async () => {
await dbHelper.clear()
await dbHelper.close()
})
const model = getModelForClass(SnippetModel)
const mockPayload1: Partial<SnippetModel> = Object.freeze({ const mockPayload1: Partial<SnippetModel> = Object.freeze({
name: 'Snippet_1', name: 'Snippet_1',
private: false, private: false,
raw: JSON.stringify({ foo: 'bar' }), raw: JSON.stringify({ foo: 'bar' }),
type: SnippetType.JSON, type: SnippetType.JSON,
}) })
let redisService: MockCacheService
afterAll(async () => { beforeEach(() => {
await (await redisHelper).close() app = proxy.app
})
beforeAll(async () => {
const { CacheService: redisService$ } = await redisHelper
redisService = redisService$
const ref = await Test.createTestingModule({
controllers: [SnippetController],
providers: [
SnippetService,
{ provide: DatabaseService, useValue: {} },
{ provide: CacheService, useValue: redisService },
{
provide: ServerlessService,
useValue: {
isValidServerlessFunction() {
return true
},
},
},
{
provide: getModelToken(SnippetModel.name),
useValue: model,
},
],
}).compile()
app = await setupE2EApp(ref)
}) })
test('POST /snippets, should 422 with wrong name', async () => { test('POST /snippets, should 422 with wrong name', async () => {

View File

@@ -1,4 +1,3 @@
import { dbHelper } from 'test/helper/db-mock.helper'
import { redisHelper } from 'test/helper/redis-mock.helper' import { redisHelper } from 'test/helper/redis-mock.helper'
import { BadRequestException, NotFoundException } from '@nestjs/common' import { BadRequestException, NotFoundException } from '@nestjs/common'
@@ -14,12 +13,8 @@ import { getModelToken } from '~/transformers/model.transformer'
describe('test Snippet Service', () => { describe('test Snippet Service', () => {
let service: SnippetService let service: SnippetService
afterAll(async () => {
await (await redisHelper).close()
})
beforeAll(async () => {
await dbHelper.connect()
beforeAll(async () => {
const redis = await redisHelper const redis = await redisHelper
const moduleRef = Test.createTestingModule({ const moduleRef = Test.createTestingModule({
providers: [ providers: [
@@ -40,10 +35,6 @@ describe('test Snippet Service', () => {
service = app.get(SnippetService) service = app.get(SnippetService)
}) })
afterAll(async () => {
await dbHelper.close()
})
const snippet = { const snippet = {
name: 'test', name: 'test',
raw: '{"foo": "bar"}', raw: '{"foo": "bar"}',

View File

@@ -14,13 +14,7 @@ import { getModelToken } from '~/transformers/model.transformer'
describe('AppController (e2e)', () => { describe('AppController (e2e)', () => {
let app: NestFastifyApplication let app: NestFastifyApplication
afterAll(async () => {
await dbHelper.close()
await (await redisHelper).close()
})
beforeAll(async () => { beforeAll(async () => {
await dbHelper.connect()
const { CacheService, token } = await redisHelper const { CacheService, token } = await redisHelper
const moduleRef = await Test.createTestingModule({ const moduleRef = await Test.createTestingModule({
controllers: [UserController], controllers: [UserController],

View File

@@ -8,10 +8,6 @@ import { CacheService } from '~/processors/redis/cache.service'
describe('test jwt service', () => { describe('test jwt service', () => {
let service: JWTService let service: JWTService
afterAll(async () => {
await (await redisHelper).close()
})
beforeAll(async () => { beforeAll(async () => {
const { CacheService: MCacheService } = await redisHelper const { CacheService: MCacheService } = await redisHelper
const moduleRef = Test.createTestingModule({ const moduleRef = Test.createTestingModule({

View File

@@ -30,5 +30,12 @@
"./src/*" "./src/*"
] ]
} }
} },
"include": [
"./src/**/*.ts",
"./src/**/*.tsx",
"./src/**/*.js",
"./src/**/*.jsx",
"./**/*.ts",
],
} }

View File

@@ -66,7 +66,7 @@ export default defineConfig({
name: 'a-vitest-plugin-that-changes-config', name: 'a-vitest-plugin-that-changes-config',
config: () => ({ config: () => ({
test: { test: {
setupFiles: ['./setupFiles/add-something-to-global.ts'], setupFiles: ['./setupFiles/lifecycle.ts'],
}, },
}), }),
}, },