update unit tests and mocks
This commit is contained in:
parent
9b843181f8
commit
effdea5658
11 changed files with 123 additions and 121 deletions
|
|
@ -3,9 +3,9 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import type { LimitInfo } from '@/misc/rate-limit-utils.js';
|
||||
import { SkRateLimiterService } from '@/server/SkRateLimiterService.js';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
/**
|
||||
* Fake implementation of SkRateLimiterService that does not enforce any limits.
|
||||
|
|
|
|||
63
packages/backend/test/misc/MockConsole.ts
Normal file
63
packages/backend/test/misc/MockConsole.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { jest } from '@jest/globals';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
/**
|
||||
* Console implementation where all members are jest mocks.
|
||||
*/
|
||||
@Injectable()
|
||||
export class MockConsole implements Console {
|
||||
public readonly Console = MockConsole;
|
||||
|
||||
/**
|
||||
* Resets all mocks in the console.
|
||||
*/
|
||||
@bindThis
|
||||
public mockReset(): void {
|
||||
for (const func of Object.values(this)) {
|
||||
if (typeof(func) === 'function' && 'mockReset' in func) {
|
||||
func.mockReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that no errors and/or warnings have been logged.
|
||||
*/
|
||||
@bindThis
|
||||
public assertNoErrors(opts?: { orWarnings?: boolean }): void {
|
||||
expect(this.error).not.toHaveBeenCalled();
|
||||
|
||||
if (opts?.orWarnings) {
|
||||
expect(this.warn).not.toHaveBeenCalled();
|
||||
}
|
||||
}
|
||||
|
||||
public readonly error = jest.fn<Console['error']>();
|
||||
public readonly warn = jest.fn<Console['warn']>();
|
||||
public readonly info = jest.fn<Console['info']>();
|
||||
public readonly log = jest.fn<Console['log']>();
|
||||
public readonly debug = jest.fn<Console['debug']>();
|
||||
public readonly trace = jest.fn<Console['trace']>();
|
||||
public readonly assert = jest.fn<Console['assert']>();
|
||||
public readonly clear = jest.fn<Console['clear']>();
|
||||
public readonly count = jest.fn<Console['count']>();
|
||||
public readonly countReset = jest.fn<Console['countReset']>();
|
||||
public readonly dir = jest.fn<Console['dir']>();
|
||||
public readonly dirxml = jest.fn<Console['dirxml']>();
|
||||
public readonly group = jest.fn<Console['group']>();
|
||||
public readonly groupCollapsed = jest.fn<Console['groupCollapsed']>();
|
||||
public readonly groupEnd = jest.fn<Console['groupEnd']>();
|
||||
public readonly table = jest.fn<Console['table']>();
|
||||
public readonly time = jest.fn<Console['time']>();
|
||||
public readonly timeEnd = jest.fn<Console['timeEnd']>();
|
||||
public readonly timeLog = jest.fn<Console['timeLog']>();
|
||||
public readonly profile = jest.fn<Console['profile']>();
|
||||
public readonly profileEnd = jest.fn<Console['profileEnd']>();
|
||||
public readonly timeStamp = jest.fn<Console['timeStamp']>();
|
||||
}
|
||||
35
packages/backend/test/misc/MockDependencyService.ts
Normal file
35
packages/backend/test/misc/MockDependencyService.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DependencyService } from '@/global/DependencyService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
/**
|
||||
* Extension of DependencyService that allows version information to be mocked.
|
||||
*/
|
||||
@Injectable()
|
||||
export class MockDependencyService extends DependencyService {
|
||||
/**
|
||||
* Overrides the version for a dependency.
|
||||
* Pass a string or null to override the version, or pass undefined to clear the override and restore the original value.
|
||||
*/
|
||||
@bindThis
|
||||
public setDependencyVersion(dependency: string, version: string | null | undefined) {
|
||||
if (version !== undefined) {
|
||||
this.dependencyVersionCache.set(dependency, version);
|
||||
} else {
|
||||
this.dependencyVersionCache.delete(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the mock to initial values.
|
||||
*/
|
||||
@bindThis
|
||||
public mockReset(): void {
|
||||
this.dependencyVersionCache.clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,6 @@
|
|||
import process from 'node:process';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EnvService } from '@/global/EnvService.js';
|
||||
import { CacheManagementService } from '@/global/CacheManagementService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
/**
|
||||
|
|
@ -15,12 +14,7 @@ import { bindThis } from '@/decorators.js';
|
|||
*/
|
||||
@Injectable()
|
||||
export class MockEnvService extends EnvService {
|
||||
private _env: Partial<Record<string, string>>;
|
||||
|
||||
constructor(cacheManagementService: CacheManagementService) {
|
||||
super(cacheManagementService);
|
||||
this._env = process.env;
|
||||
}
|
||||
private _env: Partial<Record<string, string>> = process.env;
|
||||
|
||||
/**
|
||||
* Gets the mocked environment.
|
||||
|
|
@ -42,25 +36,11 @@ export class MockEnvService extends EnvService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the version for a dependency.
|
||||
* Pass a string or null to override the version, or pass undefined to clear the override and restore the original value.
|
||||
*/
|
||||
@bindThis
|
||||
public setDependencyVersion(dependency: string, version: string | null | undefined) {
|
||||
if (version !== undefined) {
|
||||
this.dependencyVersionCache.set(dependency, version);
|
||||
} else {
|
||||
this.dependencyVersionCache.delete(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the mock to initial values.
|
||||
*/
|
||||
@bindThis
|
||||
public mockReset(): void {
|
||||
this._env = process.env;
|
||||
this.dependencyVersionCache.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { jest } from '@jest/globals';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import type { KEYWORD } from 'color-convert/conversions.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import Logger, { type Console } from '@/logger.js';
|
||||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { NativeTimeService, TimeService } from '@/global/TimeService.js';
|
||||
|
||||
/**
|
||||
* Mocked implementation of LoggerService.
|
||||
* Suppresses all log output to prevent console spam, and records calls for assertions.
|
||||
*/
|
||||
@Injectable()
|
||||
export class MockLoggerService extends LoggerService {
|
||||
/**
|
||||
* Mocked Console implementation.
|
||||
* All logs from all logger instances will be sent here.
|
||||
*/
|
||||
public readonly console: jest.Mocked<Console> = {
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
info: jest.fn(),
|
||||
log: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
};
|
||||
|
||||
/**
|
||||
* Controls the verbose flag for logger instances.
|
||||
* Defaults to false (not verbose).
|
||||
*/
|
||||
public verbose: boolean;
|
||||
|
||||
constructor(config?: Config, timeService?: TimeService) {
|
||||
config ??= { logging: { verbose: false } } as Config;
|
||||
timeService ??= new NativeTimeService();
|
||||
super(config, timeService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the instance to initial state.
|
||||
* Mocks are reset, and verbose flag is cleared.
|
||||
*/
|
||||
@bindThis
|
||||
public reset() {
|
||||
this.console.error.mockReset();
|
||||
this.console.warn.mockReset();
|
||||
this.console.info.mockReset();
|
||||
this.console.log.mockReset();
|
||||
this.console.debug.mockReset();
|
||||
|
||||
this.verbose = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that no errors and/or warnings have been logged.
|
||||
*/
|
||||
@bindThis
|
||||
public assertNoErrors(opts?: { orWarnings?: boolean }): void {
|
||||
expect(this.console.error).not.toHaveBeenCalled();
|
||||
|
||||
if (opts?.orWarnings) {
|
||||
expect(this.console.warn).not.toHaveBeenCalled();
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
getLogger(domain: string, color?: KEYWORD | undefined): Logger {
|
||||
return new Logger(domain, color, this.verbose, this.console);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,14 +4,14 @@
|
|||
*/
|
||||
|
||||
import { Inject } from '@nestjs/common';
|
||||
import { MockLoggerService } from './MockLoggerService.js';
|
||||
import { MockConsole } from './MockConsole.js';
|
||||
import { MockEnvService } from './MockEnvService.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js';
|
||||
import type { ApRendererService } from '@/core/activitypub/ApRendererService.js';
|
||||
import type { ApRequestService } from '@/core/activitypub/ApRequestService.js';
|
||||
import type { IObject, IObjectWithId } from '@/core/activitypub/type.js';
|
||||
import type { HttpRequestService } from '@/core/HttpRequestService.js';
|
||||
import type { LoggerService } from '@/core/LoggerService.js';
|
||||
import type { UtilityService } from '@/core/UtilityService.js';
|
||||
import type {
|
||||
FollowRequestsRepository,
|
||||
|
|
@ -23,6 +23,7 @@ import type {
|
|||
} from '@/models/_.js';
|
||||
import type { CacheService } from '@/core/CacheService.js';
|
||||
import { ApLogService } from '@/core/ApLogService.js';
|
||||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
import { ApUtilityService } from '@/core/activitypub/ApUtilityService.js';
|
||||
import { fromTuple } from '@/misc/from-tuple.js';
|
||||
import { SystemAccountService } from '@/core/SystemAccountService.js';
|
||||
|
|
@ -30,6 +31,7 @@ import { bindThis } from '@/decorators.js';
|
|||
import { Resolver } from '@/core/activitypub/ApResolverService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { NativeTimeService } from '@/global/TimeService.js';
|
||||
|
||||
type MockResponse = {
|
||||
type: string;
|
||||
|
|
@ -88,7 +90,7 @@ export class MockResolver extends Resolver {
|
|||
httpRequestService ?? {} as HttpRequestService,
|
||||
apRendererService ?? {} as ApRendererService,
|
||||
apDbResolverService ?? {} as ApDbResolverService,
|
||||
loggerService ?? new MockLoggerService(),
|
||||
loggerService ?? new LoggerService(new MockConsole(), new NativeTimeService(), new MockEnvService()),
|
||||
apLogService ?? {} as ApLogService,
|
||||
apUtilityService ?? {} as ApUtilityService,
|
||||
cacheService ?? {} as CacheService,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { FakeCacheManagementService } from '../misc/FakeCacheManagementService.js';
|
||||
import type { MiMeta } from '@/models/_.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { SoftwareSuspension } from '@/models/Meta.js';
|
||||
|
|
@ -32,7 +31,7 @@ describe('UtilityService', () => {
|
|||
federation: 'all',
|
||||
} as unknown as MiMeta;
|
||||
|
||||
const envService = new EnvService(new FakeCacheManagementService());
|
||||
const envService = new EnvService();
|
||||
utilityService = new UtilityService(config, meta, envService);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { generateKeyPair } from 'crypto';
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { jest } from '@jest/globals';
|
||||
import { MockApResolverService } from '../misc/MockApResolverService.js';
|
||||
import { MockLoggerService } from '../misc/MockLoggerService.js';
|
||||
import { MockConsole } from '../misc/MockConsole.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { MiLocalUser, MiRemoteUser } from '@/models/User.js';
|
||||
import { ApImageService } from '@/core/activitypub/models/ApImageService.js';
|
||||
|
|
@ -106,7 +106,7 @@ describe('ActivityPub', () => {
|
|||
let usersRepository: UsersRepository;
|
||||
let config: Config;
|
||||
let cacheManagementService: CacheManagementService;
|
||||
let mockLoggerService: MockLoggerService;
|
||||
let mockConsole: MockConsole;
|
||||
let notesRepository: NotesRepository;
|
||||
|
||||
const metaInitial = {
|
||||
|
|
@ -162,7 +162,7 @@ describe('ActivityPub', () => {
|
|||
})
|
||||
.overrideProvider(DI.meta).useValue(meta)
|
||||
.overrideProvider(ApResolverService).useClass(MockApResolverService)
|
||||
.overrideProvider(LoggerService).useClass(MockLoggerService)
|
||||
.overrideProvider(DI.console).useClass(MockConsole)
|
||||
.compile();
|
||||
|
||||
await app.init();
|
||||
|
|
@ -182,7 +182,7 @@ describe('ActivityPub', () => {
|
|||
usersRepository = app.get<UsersRepository>(DI.usersRepository);
|
||||
config = app.get<Config>(DI.config);
|
||||
cacheManagementService = app.get(CacheManagementService);
|
||||
mockLoggerService = app.get<MockLoggerService>(LoggerService);
|
||||
mockConsole = app.get<MockConsole>(DI.console);
|
||||
notesRepository = app.get<NotesRepository>(DI.notesRepository);
|
||||
});
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ describe('ActivityPub', () => {
|
|||
cacheManagementService.clear();
|
||||
|
||||
// Reset mocks
|
||||
mockLoggerService.reset();
|
||||
mockConsole.mockReset();
|
||||
resolver.clear();
|
||||
});
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ describe('ActivityPub', () => {
|
|||
|
||||
const user = await personService.createPerson(actor.id, resolver);
|
||||
|
||||
mockLoggerService.assertNoErrors();
|
||||
mockConsole.assertNoErrors();
|
||||
assert.deepStrictEqual(user.uri, actor.id);
|
||||
assert.deepStrictEqual(user.username, actor.preferredUsername);
|
||||
assert.deepStrictEqual(user.inbox, actor.inbox);
|
||||
|
|
@ -231,7 +231,7 @@ describe('ActivityPub', () => {
|
|||
|
||||
const note = await noteService.createNote(post.id, undefined, resolver, true);
|
||||
|
||||
mockLoggerService.assertNoErrors();
|
||||
mockConsole.assertNoErrors();
|
||||
assert.deepStrictEqual(note?.uri, post.id);
|
||||
assert.deepStrictEqual(note.visibility, 'public');
|
||||
assert.deepStrictEqual(note.text, post.content);
|
||||
|
|
@ -298,7 +298,7 @@ describe('ActivityPub', () => {
|
|||
const user = await personService.createPerson(actor.id, resolver);
|
||||
const userProfile = await userProfilesRepository.findOneByOrFail({ userId: user.id });
|
||||
|
||||
mockLoggerService.assertNoErrors();
|
||||
mockConsole.assertNoErrors();
|
||||
assert.deepStrictEqual(userProfile.followingVisibility, 'public');
|
||||
assert.deepStrictEqual(userProfile.followersVisibility, 'public');
|
||||
};
|
||||
|
|
@ -360,7 +360,7 @@ describe('ActivityPub', () => {
|
|||
assert.strictEqual(note.uri, item.id);
|
||||
}
|
||||
|
||||
mockLoggerService.assertNoErrors();
|
||||
mockConsole.assertNoErrors();
|
||||
});
|
||||
|
||||
test('Fetch featured notes from IActor pointing to another remote server', async () => {
|
||||
|
|
@ -858,7 +858,7 @@ describe('ActivityPub', () => {
|
|||
|
||||
expect(publicKey).not.toBeNull();
|
||||
expect(publicKey?.keyPem).toBe('key material');
|
||||
mockLoggerService.assertNoErrors();
|
||||
mockConsole.assertNoErrors();
|
||||
});
|
||||
|
||||
it('should accept SocialHome actor', async () => {
|
||||
|
|
@ -907,7 +907,7 @@ describe('ActivityPub', () => {
|
|||
|
||||
expect(user.uri).toBe(actor.id);
|
||||
expect(publicKey).not.toBeNull();
|
||||
mockLoggerService.assertNoErrors();
|
||||
mockConsole.assertNoErrors();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { MockConsole } from '../misc/MockConsole.js';
|
||||
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { GodOfTimeService } from '../misc/GodOfTimeService.js';
|
||||
import { MockLoggerService } from '../misc/MockLoggerService.js';
|
||||
import { MockRedis } from '../misc/MockRedis.js';
|
||||
import { GlobalModule } from '@/GlobalModule.js';
|
||||
import TestChart from '@/core/chart/charts/test.js';
|
||||
|
|
@ -46,7 +47,7 @@ describe('Chart', () => {
|
|||
})
|
||||
.overrideProvider(DI.redis).useClass(MockRedis)
|
||||
.overrideProvider(TimeService).useClass(GodOfTimeService)
|
||||
.overrideProvider(LoggerService).useClass(MockLoggerService)
|
||||
.overrideProvider(DI.console).useClass(MockConsole)
|
||||
.compile();
|
||||
|
||||
logger = app.get(LoggerService).getLogger('chart');
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { jest } from '@jest/globals';
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { addHours, addSeconds, subDays, subHours, subSeconds } from 'date-fns';
|
||||
import { GodOfTimeService } from '../../../misc/GodOfTimeService.js';
|
||||
import { MockLoggerService } from '../../../misc/MockLoggerService.js';
|
||||
import { MockConsole } from '../../../misc/MockConsole.js';
|
||||
import { CheckModeratorsActivityProcessorService } from '@/queue/processors/CheckModeratorsActivityProcessorService.js';
|
||||
import { MiSystemWebhook, MiUser, MiUserProfile, UserProfilesRepository, UsersRepository } from '@/models/_.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
|
|
@ -24,7 +24,6 @@ import { CacheManagementService } from '@/global/CacheManagementService.js';
|
|||
import { TimeService } from '@/global/TimeService.js';
|
||||
import { CoreModule } from '@/core/CoreModule.js';
|
||||
import { QueueProcessorModule } from '@/queue/QueueProcessorModule.js';
|
||||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
|
||||
const baseDate = new Date(Date.UTC(2000, 11, 15, 12, 0, 0));
|
||||
|
||||
|
|
@ -109,7 +108,7 @@ describe('CheckModeratorsActivityProcessorService', () => {
|
|||
fetchActiveSystemWebhooks: jest.fn(),
|
||||
enqueueSystemWebhook: jest.fn(),
|
||||
})
|
||||
.overrideProvider(LoggerService).useClass(MockLoggerService)
|
||||
.overrideProvider(DI.console).useClass(MockConsole)
|
||||
.compile();
|
||||
|
||||
await app.init();
|
||||
|
|
|
|||
|
|
@ -27,13 +27,12 @@ describe(SkRateLimiterService, () => {
|
|||
|
||||
beforeAll(() => {
|
||||
mockTimeService = new GodOfTimeService();
|
||||
mockEnvService = new MockEnvService();
|
||||
|
||||
mockRedis = new MockRedis(mockTimeService);
|
||||
const fakeConfig = { host: 'example.com' } as unknown as Config;
|
||||
mockInternalEventService = new MockInternalEventService(fakeConfig);
|
||||
cacheManagementService = new CacheManagementService(mockRedis, mockTimeService, mockInternalEventService);
|
||||
|
||||
mockEnvService = new MockEnvService(cacheManagementService);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue