Merge branch 'develop' into upstream/2025.5.0
This commit is contained in:
commit
3ebf9c4a71
317 changed files with 6144 additions and 2603 deletions
|
|
@ -367,8 +367,10 @@ describe('AbuseReportNotificationService', () => {
|
|||
id: idService.gen(),
|
||||
targetUserId: alice.id,
|
||||
targetUser: alice,
|
||||
targetUserInstance: null,
|
||||
reporterId: bob.id,
|
||||
reporter: bob,
|
||||
reporterInstance: null,
|
||||
assigneeId: null,
|
||||
assignee: null,
|
||||
resolved: false,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { GlobalModule } from '@/GlobalModule.js';
|
|||
import { DI } from '@/di-symbols.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { CoreModule } from '@/core/CoreModule.js';
|
||||
import { MetasRepository } from '@/models/_.js';
|
||||
import type { TestingModule } from '@nestjs/testing';
|
||||
import type { DataSource } from 'typeorm';
|
||||
|
||||
|
|
@ -39,8 +40,8 @@ describe('MetaService', () => {
|
|||
});
|
||||
|
||||
test('fetch (cache)', async () => {
|
||||
const db = app.get<DataSource>(DI.db);
|
||||
const spy = jest.spyOn(db, 'transaction');
|
||||
const metasRepository = app.get<MetasRepository>(DI.metasRepository);
|
||||
const spy = jest.spyOn(metasRepository, 'createQueryBuilder');
|
||||
|
||||
const result = await metaService.fetch();
|
||||
|
||||
|
|
@ -49,12 +50,12 @@ describe('MetaService', () => {
|
|||
});
|
||||
|
||||
test('fetch (force)', async () => {
|
||||
const db = app.get<DataSource>(DI.db);
|
||||
const spy = jest.spyOn(db, 'transaction');
|
||||
const metasRepository = app.get<MetasRepository>(DI.metasRepository);
|
||||
const spy = jest.spyOn(metasRepository, 'createQueryBuilder');
|
||||
|
||||
const result = await metaService.fetch(true);
|
||||
|
||||
expect(result.id).toBe('x');
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -57,10 +57,13 @@ describe('NoteCreateService', () => {
|
|||
channelId: null,
|
||||
channel: null,
|
||||
userHost: null,
|
||||
userInstance: null,
|
||||
replyUserId: null,
|
||||
replyUserHost: null,
|
||||
replyUserInstance: null,
|
||||
renoteUserId: null,
|
||||
renoteUserHost: null,
|
||||
renoteUserInstance: null,
|
||||
processErrors: [],
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import type { MockFunctionMetadata } from 'jest-mock';
|
|||
import { GlobalModule } from '@/GlobalModule.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import {
|
||||
InstancesRepository,
|
||||
MiMeta,
|
||||
MiRole,
|
||||
MiRoleAssignment,
|
||||
|
|
@ -39,6 +40,7 @@ const moduleMocker = new ModuleMocker(global);
|
|||
describe('RoleService', () => {
|
||||
let app: TestingModule;
|
||||
let roleService: RoleService;
|
||||
let instancesRepository: InstancesRepository;
|
||||
let usersRepository: UsersRepository;
|
||||
let rolesRepository: RolesRepository;
|
||||
let roleAssignmentsRepository: RoleAssignmentsRepository;
|
||||
|
|
@ -47,6 +49,19 @@ describe('RoleService', () => {
|
|||
let clock: lolex.InstalledClock;
|
||||
|
||||
async function createUser(data: Partial<MiUser> = {}) {
|
||||
if (data.host != null) {
|
||||
await instancesRepository
|
||||
.createQueryBuilder('instance')
|
||||
.insert()
|
||||
.values({
|
||||
id: genAidx(Date.now()),
|
||||
firstRetrievedAt: new Date(),
|
||||
host: data.host,
|
||||
})
|
||||
.orIgnore()
|
||||
.execute();
|
||||
}
|
||||
|
||||
const un = secureRndstr(16);
|
||||
const x = await usersRepository.insert({
|
||||
id: genAidx(Date.now()),
|
||||
|
|
@ -145,6 +160,7 @@ describe('RoleService', () => {
|
|||
app.enableShutdownHooks();
|
||||
|
||||
roleService = app.get<RoleService>(RoleService);
|
||||
instancesRepository = app.get<InstancesRepository>(DI.instancesRepository);
|
||||
usersRepository = app.get<UsersRepository>(DI.usersRepository);
|
||||
rolesRepository = app.get<RolesRepository>(DI.rolesRepository);
|
||||
roleAssignmentsRepository = app.get<RoleAssignmentsRepository>(DI.roleAssignmentsRepository);
|
||||
|
|
|
|||
|
|
@ -7,16 +7,18 @@ import { Test, TestingModule } from '@nestjs/testing';
|
|||
import { describe, jest, test } from '@jest/globals';
|
||||
import { In } from 'typeorm';
|
||||
import { UserSearchService } from '@/core/UserSearchService.js';
|
||||
import { FollowingsRepository, MiUser, UserProfilesRepository, UsersRepository } from '@/models/_.js';
|
||||
import { FollowingsRepository, InstancesRepository, MiUser, UserProfilesRepository, UsersRepository } from '@/models/_.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { GlobalModule } from '@/GlobalModule.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { genAidx } from '@/misc/id/aidx.js';
|
||||
|
||||
describe('UserSearchService', () => {
|
||||
let app: TestingModule;
|
||||
let service: UserSearchService;
|
||||
|
||||
let instancesRepository: InstancesRepository;
|
||||
let usersRepository: UsersRepository;
|
||||
let followingsRepository: FollowingsRepository;
|
||||
let idService: IdService;
|
||||
|
|
@ -35,6 +37,19 @@ describe('UserSearchService', () => {
|
|||
let bobby: MiUser;
|
||||
|
||||
async function createUser(data: Partial<MiUser> = {}) {
|
||||
if (data.host != null) {
|
||||
await instancesRepository
|
||||
.createQueryBuilder('instance')
|
||||
.insert()
|
||||
.values({
|
||||
id: genAidx(Date.now()),
|
||||
firstRetrievedAt: new Date(),
|
||||
host: data.host,
|
||||
})
|
||||
.orIgnore()
|
||||
.execute();
|
||||
}
|
||||
|
||||
const user = await usersRepository
|
||||
.insert({
|
||||
id: idService.gen(),
|
||||
|
|
@ -104,6 +119,7 @@ describe('UserSearchService', () => {
|
|||
|
||||
await app.init();
|
||||
|
||||
instancesRepository = app.get<InstancesRepository>(DI.instancesRepository);
|
||||
usersRepository = app.get(DI.usersRepository);
|
||||
userProfilesRepository = app.get(DI.userProfilesRepository);
|
||||
followingsRepository = app.get(DI.followingsRepository);
|
||||
|
|
|
|||
|
|
@ -103,6 +103,25 @@ describe('ActivityPub', () => {
|
|||
let config: Config;
|
||||
|
||||
const metaInitial = {
|
||||
id: 'x',
|
||||
name: 'Test Instance',
|
||||
shortName: 'Test Instance',
|
||||
description: 'Test Instance',
|
||||
langs: [] as string[],
|
||||
pinnedUsers: [] as string[],
|
||||
hiddenTags: [] as string[],
|
||||
prohibitedWordsForNameOfUser: [] as string[],
|
||||
silencedHosts: [] as string[],
|
||||
mediaSilencedHosts: [] as string[],
|
||||
policies: {},
|
||||
serverRules: [] as string[],
|
||||
bannedEmailDomains: [] as string[],
|
||||
preservedUsernames: [] as string[],
|
||||
bubbleInstances: [] as string[],
|
||||
trustedLinkUrlPatterns: [] as string[],
|
||||
federation: 'all',
|
||||
federationHosts: [] as string[],
|
||||
allowUnsignedFetch: 'always',
|
||||
cacheRemoteFiles: true,
|
||||
cacheRemoteSensitiveFiles: true,
|
||||
enableFanoutTimeline: true,
|
||||
|
|
|
|||
91
packages/backend/test/unit/misc/diff-arrays.ts
Normal file
91
packages/backend/test/unit/misc/diff-arrays.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { diffArrays, diffArraysSimple } from '@/misc/diff-arrays.js';
|
||||
|
||||
describe(diffArrays, () => {
|
||||
it('should return empty result when both inputs are null', () => {
|
||||
const result = diffArrays(null, null);
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should return empty result when both inputs are empty', () => {
|
||||
const result = diffArrays([], []);
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should remove before when after is empty', () => {
|
||||
const result = diffArrays([1, 2, 3], []);
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it('should deduplicate before when after is empty', () => {
|
||||
const result = diffArrays([1, 1, 2, 2, 3], []);
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it('should add after when before is empty', () => {
|
||||
const result = diffArrays([], [1, 2, 3]);
|
||||
expect(result.added).toEqual([1, 2, 3]);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should deduplicate after when before is empty', () => {
|
||||
const result = diffArrays([], [1, 1, 2, 2, 3]);
|
||||
expect(result.added).toEqual([1, 2, 3]);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should return diff when both have values', () => {
|
||||
const result = diffArrays(
|
||||
['a', 'b', 'c', 'd'],
|
||||
['a', 'c', 'e', 'f'],
|
||||
);
|
||||
expect(result.added).toEqual(['e', 'f']);
|
||||
expect(result.removed).toEqual(['b', 'd']);
|
||||
});
|
||||
});
|
||||
|
||||
describe(diffArraysSimple, () => {
|
||||
it('should return false when both inputs are null', () => {
|
||||
const result = diffArraysSimple(null, null);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when both inputs are empty', () => {
|
||||
const result = diffArraysSimple([], []);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when before is populated and after is empty', () => {
|
||||
const result = diffArraysSimple([1, 2, 3], []);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when before is empty and after is populated', () => {
|
||||
const result = diffArraysSimple([], [1, 2, 3]);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when values have changed', () => {
|
||||
const result = diffArraysSimple(
|
||||
['a', 'a', 'b', 'c'],
|
||||
['a', 'b', 'c', 'd'],
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when values have not changed', () => {
|
||||
const result = diffArraysSimple(
|
||||
['a', 'a', 'b', 'c'],
|
||||
['a', 'b', 'c', 'c'],
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -40,10 +40,13 @@ const base: MiNote = {
|
|||
channelId: null,
|
||||
channel: null,
|
||||
userHost: null,
|
||||
userInstance: null,
|
||||
replyUserId: null,
|
||||
replyUserHost: null,
|
||||
replyUserInstance: null,
|
||||
renoteUserId: null,
|
||||
renoteUserHost: null,
|
||||
renoteUserInstance: null,
|
||||
processErrors: [],
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import { AbortError } from 'node-fetch';
|
|||
import { isRetryableError } from '@/misc/is-retryable-error.js';
|
||||
import { StatusError } from '@/misc/status-error.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { CaptchaError, captchaErrorCodes } from '@/core/CaptchaService.js';
|
||||
import { FastifyReplyError } from '@/misc/fastify-reply-error.js';
|
||||
import { ConflictError } from '@/server/SkRateLimiterService.js';
|
||||
|
||||
describe(isRetryableError, () => {
|
||||
it('should return true for retryable StatusError', () => {
|
||||
|
|
@ -55,6 +58,78 @@ describe(isRetryableError, () => {
|
|||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false for CaptchaError with verificationFailed', () => {
|
||||
const error = new CaptchaError(captchaErrorCodes.verificationFailed, 'verificationFailed');
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false for CaptchaError with invalidProvider', () => {
|
||||
const error = new CaptchaError(captchaErrorCodes.invalidProvider, 'invalidProvider');
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false for CaptchaError with invalidParameters', () => {
|
||||
const error = new CaptchaError(captchaErrorCodes.invalidParameters, 'invalidParameters');
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return true for CaptchaError with noResponseProvided', () => {
|
||||
const error = new CaptchaError(captchaErrorCodes.noResponseProvided, 'noResponseProvided');
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true for CaptchaError with requestFailed', () => {
|
||||
const error = new CaptchaError(captchaErrorCodes.requestFailed, 'requestFailed');
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true for CaptchaError with unknown', () => {
|
||||
const error = new CaptchaError(captchaErrorCodes.unknown, 'unknown');
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true for CaptchaError with any other', () => {
|
||||
const error = new CaptchaError(Symbol('temp'), 'unknown');
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false for FastifyReplyError', () => {
|
||||
const error = new FastifyReplyError(400, 'test error');
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return true for ConflictError', () => {
|
||||
const error = new ConflictError('test error');
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true for AggregateError when all inners are retryable', () => {
|
||||
const error = new AggregateError([
|
||||
new ConflictError(),
|
||||
new ConflictError(),
|
||||
]);
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true for AggregateError when any error is not retryable', () => {
|
||||
const error = new AggregateError([
|
||||
new ConflictError(),
|
||||
new StatusError('test err', 400),
|
||||
]);
|
||||
const result = isRetryableError(error);
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
const nonErrorInputs = [
|
||||
[null, 'null'],
|
||||
[undefined, 'undefined'],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue