/* * SPDX-FileCopyrightText: syuilo and other misskey contributors * SPDX-License-Identifier: AGPL-3.0-only */ process.env.NODE_ENV = 'test'; import { jest } from '@jest/globals'; import { ModuleMocker } from 'jest-mock'; import { Test } from '@nestjs/testing'; import * as Redis from 'ioredis'; import { GlobalModule } from '@/GlobalModule.js'; import type { UsersRepository, MiUser, NotesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { genAidx } from '@/misc/id/aidx.js'; import { CacheService } from '@/core/CacheService.js'; import { IdService } from '@/core/IdService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { NoteCreateService } from '@/core/NoteCreateService.js'; import { CoreModule } from '@/core/CoreModule.js'; import { MetaService } from '@/core/MetaService.js'; import { RoleService } from '@/core/RoleService.js'; import NotesChart from '@/core/chart/charts/notes.js'; import PerUserNotesChart from '@/core/chart/charts/per-user-notes.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { HashtagService } from '@/core/HashtagService.js'; import { AntennaService } from '@/core/AntennaService.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { sleep } from '../utils.js'; import type { TestingModule } from '@nestjs/testing'; import type { MockFunctionMetadata } from 'jest-mock'; const moduleMocker = new ModuleMocker(global); describe('NoteCreateService', () => { let app: TestingModule; let noteCreateService: NoteCreateService; let usersRepository: UsersRepository; let notesRepository: NotesRepository; let globalEventService: jest.Mocked; let redisForTimelines: jest.Mocked; function createUser(data: Partial = {}) { const un = secureRndstr(16); return usersRepository.insert({ id: genAidx(new Date()), createdAt: new Date(), username: un, usernameLower: un, ...data, }) .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); } beforeEach(async () => { app = await Test.createTestingModule({ imports: [ GlobalModule, //CoreModule, ], providers: [ UtilityService, ApPersonService, MetaService, CacheService, IdService, RoleService, NotesChart, PerUserNotesChart, ActiveUsersChart, UserEntityService, NoteEntityService, HashtagService, AntennaService, NoteCreateService, ], }) .useMocker((token) => { if (token === GlobalEventService) { return { publishNotesStream: jest.fn(), publishMainStream: jest.fn(), }; } else if (token === DI.redisForTimelines) { return { xadd: jest.fn(), }; } else if (typeof token === 'function') { const mockMetadata = moduleMocker.getMetadata(token) as MockFunctionMetadata; const Mock = moduleMocker.generateFromMetadata(mockMetadata); return new Mock(); } }) .compile(); await app.init(); app.enableShutdownHooks(); noteCreateService = app.get(NoteCreateService); usersRepository = app.get(DI.usersRepository); globalEventService = app.get(GlobalEventService) as jest.Mocked; redisForTimelines = app.get(DI.redisForTimelines) as jest.Mocked; }); afterEach(async () => { await Promise.all([ app.get(DI.metasRepository).delete({}), usersRepository.delete({}), notesRepository.delete({}), ]); await app.close(); }); describe('create', () => { test('text', async () => { const me = await createUser(); const follower = await createUser(); await app.get(DI.followingsRepository).insert({ id: genAidx(new Date()), followerId: follower.id, followeeId: me.id, createdAt: new Date(), }); const result = await noteCreateService.create(me, { text: 'Hello, Misskey!', }); expect(result.text).toBe('Hello, Misskey!'); await sleep(100); expect(globalEventService.publishNotesStream).toHaveBeenCalled(); expect(globalEventService.publishNotesStream.mock.lastCall![0].id).toBe(result.id); expect(redisForTimelines.xadd).toHaveBeenCalled(); expect(redisForTimelines.xadd.mock.calls.some(call => call[0] === `homeTimeline:${follower.id}`)).toBe(true); }); }); });