diff --git a/src/processors/helper/helper.counting.service.ts b/src/processors/helper/helper.counting.service.ts index b74fb071..2b4d82e9 100644 --- a/src/processors/helper/helper.counting.service.ts +++ b/src/processors/helper/helper.counting.service.ts @@ -2,9 +2,6 @@ import { Injectable, Logger } from '@nestjs/common' import { ArticleType } from '~/constants/article.constant' import { RedisKeys } from '~/constants/cache.constant' -import { NoteModel } from '~/modules/note/note.model' -import { PostModel } from '~/modules/post/post.model' -import { InjectModel } from '~/transformers/model.transformer' import { getRedisKey } from '~/utils/redis.util' import { DatabaseService } from '../database/database.service' @@ -14,10 +11,6 @@ import { CacheService } from '../redis/cache.service' export class CountingService { private logger: Logger constructor( - @InjectModel(PostModel) - private readonly postModel: MongooseModel, - @InjectModel(NoteModel) - private readonly noteModel: MongooseModel, private readonly redis: CacheService, private readonly databaseService: DatabaseService, ) { diff --git a/test/helper/defineProvider.ts b/test/helper/defineProvider.ts index 99958c15..00ad0b56 100644 --- a/test/helper/defineProvider.ts +++ b/test/helper/defineProvider.ts @@ -7,6 +7,14 @@ export const defineProvider = (provider: Provider) => { return provider } -export const defineProviders = (providers: Provider[]) => { +export function defineProviders(providers: [Provider]): [Provider] +export function defineProviders( + providers: [Provider, Provider], +): [Provider, Provider] +export function defineProviders( + providers: [Provider, Provider, Provider], +): [Provider, Provider, Provider] + +export function defineProviders(providers: Provider[]) { return providers } diff --git a/test/mock/interceptors/counting.interceptor.ts b/test/mock/interceptors/counting.interceptor.ts new file mode 100644 index 00000000..f27050da --- /dev/null +++ b/test/mock/interceptors/counting.interceptor.ts @@ -0,0 +1,41 @@ +import { map } from 'rxjs' + +import { + CallHandler, + ExecutionContext, + Inject, + Injectable, + NestInterceptor, +} from '@nestjs/common' +import { Reflector } from '@nestjs/core' + +import { HTTP_RES_UPDATE_DOC_COUNT_TYPE } from '~/constants/meta.constant' +import { REFLECTOR } from '~/constants/system.constant' +import { CountingService } from '~/processors/helper/helper.counting.service' + +@Injectable() +export class MockingCountingInterceptor implements NestInterceptor { + constructor( + @Inject(REFLECTOR) private readonly reflector: Reflector, + private readonly countingService: CountingService, + ) {} + + intercept(context: ExecutionContext, next: CallHandler) { + const handler = context.getHandler() + return next.handle().pipe( + map((data) => { + // 计数处理 + const documentType = this.reflector.get( + HTTP_RES_UPDATE_DOC_COUNT_TYPE, + handler, + ) + if (documentType && data) { + // @ts-ignore + this.countingService.updateReadCount() + } + + return data + }), + ) + } +} diff --git a/test/mock/processors/counting.mock.ts b/test/mock/processors/counting.mock.ts index 4d878e7d..ff123214 100644 --- a/test/mock/processors/counting.mock.ts +++ b/test/mock/processors/counting.mock.ts @@ -10,9 +10,9 @@ export const countingServiceProvider = defineProvider({ async getThisRecordIsLiked() { return true }, - async updateReadCount() { + updateReadCount: vi.fn().mockImplementation(async () => { return - }, + }), }, provide: CountingService, }) diff --git a/test/mock/processors/email.mock.ts b/test/mock/processors/email.mock.ts new file mode 100644 index 00000000..df4b9ca4 --- /dev/null +++ b/test/mock/processors/email.mock.ts @@ -0,0 +1,16 @@ +import { defineProvider } from 'test/helper/defineProvider' + +import { EmailService } from '~/processors/helper/helper.email.service' + +export const emailProvider = defineProvider({ + provide: EmailService, + useValue: { + async send(options) {}, + render(template, source) { + return '' + }, + sendTestEmail() { + return Promise.resolve() + }, + }, +}) diff --git a/test/mock/processors/event.mock.ts b/test/mock/processors/event.mock.ts new file mode 100644 index 00000000..3eade36d --- /dev/null +++ b/test/mock/processors/event.mock.ts @@ -0,0 +1,40 @@ +import { defineProviders } from 'test/helper/defineProvider' + +import { EventEmitter2 } from '@nestjs/event-emitter' + +import { EventManagerService } from '~/processors/helper/helper.event.service' +import { SubPubBridgeService } from '~/processors/redis/subpub.service' + +export const eventEmitterProvider = defineProviders([ + { + provide: EventEmitter2, + useValue: { + emit(event, data) { + return true + }, + }, + }, + { + provide: SubPubBridgeService, + useValue: { + async publish(event, data) {}, + async subscribe(event, callback) {}, + async unsubscribe(event, callback) {}, + }, + }, + { + provide: EventManagerService, + useValue: { + async broadcast(event, data) {}, + async emit() {}, + on() { + return noop + }, + registerHandler() { + return noop + }, + }, + }, +]) + +const noop = () => {} diff --git a/test/src/modules/link/link.controller.e2e-spec.ts b/test/src/modules/link/link.controller.e2e-spec.ts index 9221c899..64643cea 100644 --- a/test/src/modules/link/link.controller.e2e-spec.ts +++ b/test/src/modules/link/link.controller.e2e-spec.ts @@ -1,8 +1,9 @@ import { createE2EApp } from 'test/helper/create-e2e-app' import { gatewayProviders } from 'test/mock/modules/gateway.mock' import { userProvider } from 'test/mock/modules/user.mock' +import { emailProvider } from 'test/mock/processors/email.mock' +import { eventEmitterProvider } from 'test/mock/processors/event.mock' -import { EventEmitter2 } from '@nestjs/event-emitter' import { ReturnModelType } from '@typegoose/typegoose' import { OptionModel } from '~/modules/configs/configs.model' @@ -13,11 +14,7 @@ import { } from '~/modules/link/link.controller' import { LinkModel, LinkState } from '~/modules/link/link.model' import { LinkService } from '~/modules/link/link.service' -import { AssetService } from '~/processors/helper/helper.asset.service' -import { EmailService } from '~/processors/helper/helper.email.service' -import { EventManagerService } from '~/processors/helper/helper.event.service' import { HttpService } from '~/processors/helper/helper.http.service' -import { SubPubBridgeService } from '~/processors/redis/subpub.service' describe('Test LinkController(E2E)', () => { const proxy = createE2EApp({ @@ -26,14 +23,14 @@ describe('Test LinkController(E2E)', () => { providers: [ ...gatewayProviders, LinkService, - ConfigsService, - EmailService, + + emailProvider, HttpService, - EventManagerService, + userProvider, - SubPubBridgeService, - AssetService, - EventEmitter2, + + ConfigsService, + ...eventEmitterProvider, ], async pourData(modelMap) { const linkModel = modelMap.get(LinkModel) diff --git a/test/src/modules/note/__snapshots__/note.controller.e2e-spec.ts.snap b/test/src/modules/note/__snapshots__/note.controller.e2e-spec.ts.snap index 9bc6a9ac..b12ba6bd 100644 --- a/test/src/modules/note/__snapshots__/note.controller.e2e-spec.ts.snap +++ b/test/src/modules/note/__snapshots__/note.controller.e2e-spec.ts.snap @@ -259,6 +259,39 @@ exports[`NoteController (e2e) > GET /notes 1`] = ` } `; +exports[`NoteController (e2e) > GET /notes/nid/:nid 1`] = ` +{ + "data": { + "allow_comment": true, + "comments_index": 0, + "count": { + "like": 0, + "read": 0, + }, + "created": "2023-01-17T11:01:57.851Z", + "hide": false, + "images": [], + "liked": true, + "modified": null, + "mood": "happy", + "music": [], + "nid": 21, + "text": "Content 2 (updated)", + "title": "Note 2 (updated)", + "topic": null, + "weather": "sunny", + }, + "next": { + "created": "2021-03-20T00:00:00.000Z", + "modified": null, + "nid": 20, + "title": "Note 20", + "topic": null, + }, + "prev": null, +} +`; + exports[`NoteController (e2e) > Get patched note 1`] = ` { "allow_comment": true, diff --git a/test/src/modules/note/note.controller.e2e-spec.ts b/test/src/modules/note/note.controller.e2e-spec.ts index c0f4431f..9ade8239 100644 --- a/test/src/modules/note/note.controller.e2e-spec.ts +++ b/test/src/modules/note/note.controller.e2e-spec.ts @@ -1,11 +1,13 @@ import { createE2EApp } from 'test/helper/create-e2e-app' +import { MockingCountingInterceptor } from 'test/mock/interceptors/counting.interceptor' 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 { eventEmitterProvider } from 'test/mock/processors/event.mock' -import { EventEmitter2 } from '@nestjs/event-emitter' +import { APP_INTERCEPTOR } from '@nestjs/core' import { ReturnModelType } from '@typegoose/typegoose' import { OptionModel } from '~/modules/configs/configs.model' @@ -14,12 +16,9 @@ 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' @@ -30,7 +29,12 @@ describe('NoteController (e2e)', () => { providers: [ NoteService, ImageService, - EventManagerService, + + { + provide: APP_INTERCEPTOR, + useClass: MockingCountingInterceptor, + }, + commentProvider, { @@ -43,12 +47,12 @@ describe('NoteController (e2e)', () => { }, HttpService, configProvider, - EventEmitter2, + UserService, - SubPubBridgeService, + ...eventEmitterProvider, ...gatewayProviders, authProvider, - CountingService, + countingServiceProvider, ], imports: [], @@ -156,6 +160,29 @@ describe('NoteController (e2e)', () => { expect(data).toMatchSnapshot() }) + test('GET /notes/nid/:nid', async () => { + const { app } = proxy + const res = await app.inject({ + method: 'GET', + url: `/notes/nid/${createdNoteData.nid}`, + }) + + expect(res.statusCode).toBe(200) + const data = res.json() + delete data.id + delete data.data.id + if (data.prev) { + delete data.prev.id + } + if (data.next) { + delete data.next.id + } + + expect(data).toMatchSnapshot() + + expect(countingServiceProvider.useValue.updateReadCount).toBeCalled() + }) + test('DEL /notes/:id', async () => { const { app } = proxy const res = await app.inject({