mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-20 01:15:29 +02:00
Merge branch 'develop' into renovate/major-backend-update-dependencies
This commit is contained in:
@@ -69,6 +69,9 @@ describe('アンテナ', () => {
|
||||
let userMutingAlice: User;
|
||||
let userMutedByAlice: User;
|
||||
|
||||
let testChannel: misskey.entities.Channel;
|
||||
let testMutedChannel: misskey.entities.Channel;
|
||||
|
||||
beforeAll(async () => {
|
||||
root = await signup({ username: 'root' });
|
||||
alice = await signup({ username: 'alice' });
|
||||
@@ -120,6 +123,10 @@ describe('アンテナ', () => {
|
||||
userMutedByAlice = await signup({ username: 'userMutedByAlice' });
|
||||
await post(userMutedByAlice, { text: 'test' });
|
||||
await api('mute/create', { userId: userMutedByAlice.id }, alice);
|
||||
|
||||
testChannel = (await api('channels/create', { name: 'test' }, root)).body;
|
||||
testMutedChannel = (await api('channels/create', { name: 'test-muted' }, root)).body;
|
||||
await api('channels/mute/create', { channelId: testMutedChannel.id }, alice);
|
||||
}, 1000 * 60 * 10);
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -605,6 +612,20 @@ describe('アンテナ', () => {
|
||||
{ note: (): Promise<Note> => post(bob, { text: `${keyword}` }), included: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'チャンネルノートも含む',
|
||||
parameters: () => ({ src: 'all' }),
|
||||
posts: [
|
||||
{ note: (): Promise<Note> => post(bob, { text: `test ${keyword}`, channelId: testChannel.id }), included: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'ミュートしてるチャンネルは含まない',
|
||||
parameters: () => ({ src: 'all' }),
|
||||
posts: [
|
||||
{ note: (): Promise<Note> => post(bob, { text: `test ${keyword}`, channelId: testMutedChannel.id }) },
|
||||
],
|
||||
},
|
||||
])('が取得できること($label)', async ({ parameters, posts }) => {
|
||||
const antenna = await successfulApiCall({
|
||||
endpoint: 'antennas/create',
|
||||
|
||||
@@ -506,10 +506,10 @@ describe('クリップ', () => {
|
||||
});
|
||||
};
|
||||
|
||||
const myFavorites = async (request: Partial<ApiRequest<'clips/my-favorites'>> = {}): Promise<Misskey.entities.Clip[]> => {
|
||||
const myFavorites = async (parameters: Misskey.entities.ClipsMyFavoritesRequest, request: Partial<ApiRequest<'clips/my-favorites'>> = {}): Promise<Misskey.entities.Clip[]> => {
|
||||
return successfulApiCall({
|
||||
endpoint: 'clips/my-favorites',
|
||||
parameters: {},
|
||||
parameters,
|
||||
user: alice,
|
||||
...request,
|
||||
});
|
||||
@@ -562,8 +562,9 @@ describe('クリップ', () => {
|
||||
await favorite({ clipId: clip.id });
|
||||
}
|
||||
|
||||
// pagenationはない。全部一気にとれる。
|
||||
const favorited = await myFavorites();
|
||||
const favorited = await myFavorites({
|
||||
limit: 30,
|
||||
});
|
||||
assert.strictEqual(favorited.length, clips.length);
|
||||
for (const clip of favorited) {
|
||||
assert.strictEqual(clip.favoritedCount, 1);
|
||||
@@ -617,7 +618,7 @@ describe('クリップ', () => {
|
||||
const clip = await show({ clipId: aliceClip.id });
|
||||
assert.strictEqual(clip.favoritedCount, 0);
|
||||
assert.strictEqual(clip.isFavorited, false);
|
||||
assert.deepStrictEqual(await myFavorites(), []);
|
||||
assert.deepStrictEqual(await myFavorites({}), []);
|
||||
});
|
||||
|
||||
test.each([
|
||||
@@ -651,13 +652,13 @@ describe('クリップ', () => {
|
||||
|
||||
test('を取得できる。', async () => {
|
||||
await favorite({ clipId: aliceClip.id });
|
||||
const favorited = await myFavorites();
|
||||
const favorited = await myFavorites({});
|
||||
assert.deepStrictEqual(favorited, [await show({ clipId: aliceClip.id })]);
|
||||
});
|
||||
|
||||
test('を取得したとき他人のお気に入りは含まない。', async () => {
|
||||
await favorite({ clipId: aliceClip.id });
|
||||
const favorited = await myFavorites({ user: bob });
|
||||
const favorited = await myFavorites({}, { user: bob });
|
||||
assert.deepStrictEqual(favorited, []);
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
10
packages/backend/test/jest.setup.unit.cjs
Normal file
10
packages/backend/test/jest.setup.unit.cjs
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
module.exports = async () => {
|
||||
// DBはUTC(っぽい)ので、テスト側も合わせておく
|
||||
process.env.TZ = 'UTC';
|
||||
process.env.NODE_ENV = 'test';
|
||||
};
|
||||
235
packages/backend/test/unit/ChannelFollowingService.ts
Normal file
235
packages/backend/test/unit/ChannelFollowingService.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
import { afterEach, beforeEach, describe, expect } from '@jest/globals';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { GlobalModule } from '@/GlobalModule.js';
|
||||
import { CoreModule } from '@/core/CoreModule.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import {
|
||||
type ChannelFollowingsRepository,
|
||||
ChannelsRepository,
|
||||
DriveFilesRepository,
|
||||
MiChannel,
|
||||
MiChannelFollowing,
|
||||
MiDriveFile,
|
||||
MiUser,
|
||||
UserProfilesRepository,
|
||||
UsersRepository,
|
||||
} from '@/models/_.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ChannelFollowingService } from "@/core/ChannelFollowingService.js";
|
||||
import { MiLocalUser } from "@/models/User.js";
|
||||
|
||||
describe('ChannelFollowingService', () => {
|
||||
let app: TestingModule;
|
||||
let service: ChannelFollowingService;
|
||||
let channelsRepository: ChannelsRepository;
|
||||
let channelFollowingsRepository: ChannelFollowingsRepository;
|
||||
let usersRepository: UsersRepository;
|
||||
let userProfilesRepository: UserProfilesRepository;
|
||||
let driveFilesRepository: DriveFilesRepository;
|
||||
let idService: IdService;
|
||||
|
||||
let alice: MiLocalUser;
|
||||
let bob: MiLocalUser;
|
||||
let channel1: MiChannel;
|
||||
let channel2: MiChannel;
|
||||
let channel3: MiChannel;
|
||||
let driveFile1: MiDriveFile;
|
||||
let driveFile2: MiDriveFile;
|
||||
|
||||
async function createUser(data: Partial<MiUser> = {}) {
|
||||
const user = await usersRepository
|
||||
.insert({
|
||||
id: idService.gen(),
|
||||
username: 'username',
|
||||
usernameLower: 'username',
|
||||
...data,
|
||||
})
|
||||
.then(x => usersRepository.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
await userProfilesRepository.insert({
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
async function createChannel(data: Partial<MiChannel> = {}) {
|
||||
return await channelsRepository
|
||||
.insert({
|
||||
id: idService.gen(),
|
||||
...data,
|
||||
})
|
||||
.then(x => channelsRepository.findOneByOrFail(x.identifiers[0]));
|
||||
}
|
||||
|
||||
async function createChannelFollowing(data: Partial<MiChannelFollowing> = {}) {
|
||||
return await channelFollowingsRepository
|
||||
.insert({
|
||||
id: idService.gen(),
|
||||
...data,
|
||||
})
|
||||
.then(x => channelFollowingsRepository.findOneByOrFail(x.identifiers[0]));
|
||||
}
|
||||
|
||||
async function fetchChannelFollowing() {
|
||||
return await channelFollowingsRepository.findBy({});
|
||||
}
|
||||
|
||||
async function createDriveFile(data: Partial<MiDriveFile> = {}) {
|
||||
return await driveFilesRepository
|
||||
.insert({
|
||||
id: idService.gen(),
|
||||
md5: 'md5',
|
||||
name: 'name',
|
||||
size: 0,
|
||||
type: 'type',
|
||||
storedInternal: false,
|
||||
url: 'url',
|
||||
...data,
|
||||
})
|
||||
.then(x => driveFilesRepository.findOneByOrFail(x.identifiers[0]));
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
app = await Test.createTestingModule({
|
||||
imports: [
|
||||
GlobalModule,
|
||||
CoreModule,
|
||||
],
|
||||
providers: [
|
||||
GlobalEventService,
|
||||
IdService,
|
||||
ChannelFollowingService,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
app.enableShutdownHooks();
|
||||
|
||||
service = app.get<ChannelFollowingService>(ChannelFollowingService);
|
||||
idService = app.get<IdService>(IdService);
|
||||
channelsRepository = app.get<ChannelsRepository>(DI.channelsRepository);
|
||||
channelFollowingsRepository = app.get<ChannelFollowingsRepository>(DI.channelFollowingsRepository);
|
||||
usersRepository = app.get<UsersRepository>(DI.usersRepository);
|
||||
userProfilesRepository = app.get<UserProfilesRepository>(DI.userProfilesRepository);
|
||||
driveFilesRepository = app.get<DriveFilesRepository>(DI.driveFilesRepository);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
alice = { ...await createUser({ username: 'alice' }), host: null, uri: null };
|
||||
bob = { ...await createUser({ username: 'bob' }), host: null, uri: null };
|
||||
driveFile1 = await createDriveFile();
|
||||
driveFile2 = await createDriveFile();
|
||||
channel1 = await createChannel({ name: 'channel1', userId: alice.id, bannerId: driveFile1.id });
|
||||
channel2 = await createChannel({ name: 'channel2', userId: alice.id, bannerId: driveFile2.id });
|
||||
channel3 = await createChannel({ name: 'channel3', userId: alice.id, bannerId: driveFile2.id });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await channelFollowingsRepository.deleteAll();
|
||||
await channelsRepository.deleteAll();
|
||||
await userProfilesRepository.deleteAll();
|
||||
await usersRepository.deleteAll();
|
||||
});
|
||||
|
||||
describe('list', () => {
|
||||
test('default', async () => {
|
||||
await createChannelFollowing({ followerId: alice.id, followeeId: channel1.id });
|
||||
await createChannelFollowing({ followerId: alice.id, followeeId: channel2.id });
|
||||
await createChannelFollowing({ followerId: bob.id, followeeId: channel3.id });
|
||||
|
||||
const followings = await service.list({ requestUserId: alice.id });
|
||||
|
||||
expect(followings).toHaveLength(2);
|
||||
expect(followings[0].id).toBe(channel1.id);
|
||||
expect(followings[0].userId).toBe(alice.id);
|
||||
expect(followings[0].user).toBeFalsy();
|
||||
expect(followings[0].bannerId).toBe(driveFile1.id);
|
||||
expect(followings[0].banner).toBeFalsy();
|
||||
expect(followings[1].id).toBe(channel2.id);
|
||||
expect(followings[1].userId).toBe(alice.id);
|
||||
expect(followings[1].user).toBeFalsy();
|
||||
expect(followings[1].bannerId).toBe(driveFile2.id);
|
||||
expect(followings[1].banner).toBeFalsy();
|
||||
});
|
||||
|
||||
test('idOnly', async () => {
|
||||
await createChannelFollowing({ followerId: alice.id, followeeId: channel1.id });
|
||||
await createChannelFollowing({ followerId: alice.id, followeeId: channel2.id });
|
||||
await createChannelFollowing({ followerId: bob.id, followeeId: channel3.id });
|
||||
|
||||
const followings = await service.list({ requestUserId: alice.id }, { idOnly: true });
|
||||
|
||||
expect(followings).toHaveLength(2);
|
||||
expect(followings[0].id).toBe(channel1.id);
|
||||
expect(followings[1].id).toBe(channel2.id);
|
||||
});
|
||||
|
||||
test('joinUser', async () => {
|
||||
await createChannelFollowing({ followerId: alice.id, followeeId: channel1.id });
|
||||
await createChannelFollowing({ followerId: alice.id, followeeId: channel2.id });
|
||||
await createChannelFollowing({ followerId: bob.id, followeeId: channel3.id });
|
||||
|
||||
const followings = await service.list({ requestUserId: alice.id }, { joinUser: true });
|
||||
|
||||
expect(followings).toHaveLength(2);
|
||||
expect(followings[0].id).toBe(channel1.id);
|
||||
expect(followings[0].user).toEqual(alice);
|
||||
expect(followings[0].banner).toBeFalsy();
|
||||
expect(followings[1].id).toBe(channel2.id);
|
||||
expect(followings[1].user).toEqual(alice);
|
||||
expect(followings[1].banner).toBeFalsy();
|
||||
});
|
||||
|
||||
test('joinBannerFile', async () => {
|
||||
await createChannelFollowing({ followerId: alice.id, followeeId: channel1.id });
|
||||
await createChannelFollowing({ followerId: alice.id, followeeId: channel2.id });
|
||||
await createChannelFollowing({ followerId: bob.id, followeeId: channel3.id });
|
||||
|
||||
const followings = await service.list({ requestUserId: alice.id }, { joinBannerFile: true });
|
||||
|
||||
expect(followings).toHaveLength(2);
|
||||
expect(followings[0].id).toBe(channel1.id);
|
||||
expect(followings[0].user).toBeFalsy();
|
||||
expect(followings[0].banner).toEqual(driveFile1);
|
||||
expect(followings[1].id).toBe(channel2.id);
|
||||
expect(followings[1].user).toBeFalsy();
|
||||
expect(followings[1].banner).toEqual(driveFile2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('follow', () => {
|
||||
test('default', async () => {
|
||||
await service.follow(alice, channel1);
|
||||
|
||||
const followings = await fetchChannelFollowing();
|
||||
|
||||
expect(followings).toHaveLength(1);
|
||||
expect(followings[0].followeeId).toBe(channel1.id);
|
||||
expect(followings[0].followerId).toBe(alice.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('unfollow', () => {
|
||||
test('default', async () => {
|
||||
await createChannelFollowing({ followerId: alice.id, followeeId: channel1.id });
|
||||
|
||||
await service.unfollow(alice, channel1);
|
||||
|
||||
const followings = await fetchChannelFollowing();
|
||||
|
||||
expect(followings).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
336
packages/backend/test/unit/ChannelMutingService.ts
Normal file
336
packages/backend/test/unit/ChannelMutingService.ts
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
import { afterEach, beforeEach, describe, expect } from '@jest/globals';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { GlobalModule } from '@/GlobalModule.js';
|
||||
import { CoreModule } from '@/core/CoreModule.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { ChannelMutingService } from '@/core/ChannelMutingService.js';
|
||||
import {
|
||||
ChannelMutingRepository,
|
||||
ChannelsRepository,
|
||||
DriveFilesRepository,
|
||||
MiChannel,
|
||||
MiChannelMuting,
|
||||
MiDriveFile,
|
||||
MiUser,
|
||||
UserProfilesRepository,
|
||||
UsersRepository,
|
||||
} from '@/models/_.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
|
||||
describe('ChannelMutingService', () => {
|
||||
let app: TestingModule;
|
||||
let service: ChannelMutingService;
|
||||
let channelsRepository: ChannelsRepository;
|
||||
let channelMutingRepository: ChannelMutingRepository;
|
||||
let usersRepository: UsersRepository;
|
||||
let userProfilesRepository: UserProfilesRepository;
|
||||
let driveFilesRepository: DriveFilesRepository;
|
||||
let idService: IdService;
|
||||
|
||||
let alice: MiUser;
|
||||
let bob: MiUser;
|
||||
let channel1: MiChannel;
|
||||
let channel2: MiChannel;
|
||||
let channel3: MiChannel;
|
||||
let driveFile1: MiDriveFile;
|
||||
let driveFile2: MiDriveFile;
|
||||
|
||||
async function createUser(data: Partial<MiUser> = {}) {
|
||||
const user = await usersRepository
|
||||
.insert({
|
||||
id: idService.gen(),
|
||||
username: 'username',
|
||||
usernameLower: 'username',
|
||||
...data,
|
||||
})
|
||||
.then(x => usersRepository.findOneByOrFail(x.identifiers[0]));
|
||||
|
||||
await userProfilesRepository.insert({
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
async function createChannel(data: Partial<MiChannel> = {}) {
|
||||
return await channelsRepository
|
||||
.insert({
|
||||
id: idService.gen(),
|
||||
...data,
|
||||
})
|
||||
.then(x => channelsRepository.findOneByOrFail(x.identifiers[0]));
|
||||
}
|
||||
|
||||
async function createChannelMuting(data: Partial<MiChannelMuting> = {}) {
|
||||
return await channelMutingRepository
|
||||
.insert({
|
||||
id: idService.gen(),
|
||||
...data,
|
||||
})
|
||||
.then(x => channelMutingRepository.findOneByOrFail(x.identifiers[0]));
|
||||
}
|
||||
|
||||
async function fetchChannelMuting() {
|
||||
return await channelMutingRepository.findBy({});
|
||||
}
|
||||
|
||||
async function createDriveFile(data: Partial<MiDriveFile> = {}) {
|
||||
return await driveFilesRepository
|
||||
.insert({
|
||||
id: idService.gen(),
|
||||
md5: 'md5',
|
||||
name: 'name',
|
||||
size: 0,
|
||||
type: 'type',
|
||||
storedInternal: false,
|
||||
url: 'url',
|
||||
...data,
|
||||
})
|
||||
.then(x => driveFilesRepository.findOneByOrFail(x.identifiers[0]));
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
app = await Test.createTestingModule({
|
||||
imports: [
|
||||
GlobalModule,
|
||||
CoreModule,
|
||||
],
|
||||
providers: [
|
||||
GlobalEventService,
|
||||
IdService,
|
||||
ChannelMutingService,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
app.enableShutdownHooks();
|
||||
|
||||
service = app.get<ChannelMutingService>(ChannelMutingService);
|
||||
idService = app.get<IdService>(IdService);
|
||||
channelsRepository = app.get<ChannelsRepository>(DI.channelsRepository);
|
||||
channelMutingRepository = app.get<ChannelMutingRepository>(DI.channelMutingRepository);
|
||||
usersRepository = app.get<UsersRepository>(DI.usersRepository);
|
||||
userProfilesRepository = app.get<UserProfilesRepository>(DI.userProfilesRepository);
|
||||
driveFilesRepository = app.get<DriveFilesRepository>(DI.driveFilesRepository);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
alice = await createUser({ username: 'alice' });
|
||||
bob = await createUser({ username: 'bob' });
|
||||
driveFile1 = await createDriveFile();
|
||||
driveFile2 = await createDriveFile();
|
||||
channel1 = await createChannel({ name: 'channel1', userId: alice.id, bannerId: driveFile1.id });
|
||||
channel2 = await createChannel({ name: 'channel2', userId: alice.id, bannerId: driveFile2.id });
|
||||
channel3 = await createChannel({ name: 'channel3', userId: alice.id, bannerId: driveFile2.id });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await channelMutingRepository.deleteAll();
|
||||
await channelsRepository.deleteAll();
|
||||
await userProfilesRepository.deleteAll();
|
||||
await usersRepository.deleteAll();
|
||||
});
|
||||
|
||||
describe('list', () => {
|
||||
test('default', async () => {
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel1.id });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel2.id });
|
||||
await createChannelMuting({ userId: bob.id, channelId: channel3.id });
|
||||
|
||||
const mutings = await service.list({ requestUserId: alice.id });
|
||||
|
||||
expect(mutings).toHaveLength(2);
|
||||
expect(mutings[0].id).toBe(channel1.id);
|
||||
expect(mutings[0].userId).toBe(alice.id);
|
||||
expect(mutings[0].user).toBeFalsy();
|
||||
expect(mutings[0].bannerId).toBe(driveFile1.id);
|
||||
expect(mutings[0].banner).toBeFalsy();
|
||||
expect(mutings[1].id).toBe(channel2.id);
|
||||
expect(mutings[1].userId).toBe(alice.id);
|
||||
expect(mutings[1].user).toBeFalsy();
|
||||
expect(mutings[1].bannerId).toBe(driveFile2.id);
|
||||
expect(mutings[1].banner).toBeFalsy();
|
||||
});
|
||||
|
||||
test('withoutExpires', async () => {
|
||||
const now = new Date();
|
||||
const past = new Date(now);
|
||||
const future = new Date(now);
|
||||
past.setMinutes(past.getMinutes() - 1);
|
||||
future.setMinutes(future.getMinutes() + 1);
|
||||
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel1.id, expiresAt: past });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel2.id, expiresAt: null });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel3.id, expiresAt: future });
|
||||
|
||||
const mutings = await service.list({ requestUserId: alice.id });
|
||||
|
||||
expect(mutings).toHaveLength(2);
|
||||
expect(mutings[0].id).toBe(channel2.id);
|
||||
expect(mutings[1].id).toBe(channel3.id);
|
||||
});
|
||||
|
||||
test('idOnly', async () => {
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel1.id });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel2.id });
|
||||
await createChannelMuting({ userId: bob.id, channelId: channel3.id });
|
||||
|
||||
const mutings = await service.list({ requestUserId: alice.id }, { idOnly: true });
|
||||
|
||||
expect(mutings).toHaveLength(2);
|
||||
expect(mutings[0].id).toBe(channel1.id);
|
||||
expect(mutings[1].id).toBe(channel2.id);
|
||||
});
|
||||
|
||||
test('withoutExpires-idOnly', async () => {
|
||||
const now = new Date();
|
||||
const past = new Date(now);
|
||||
const future = new Date(now);
|
||||
past.setMinutes(past.getMinutes() - 1);
|
||||
future.setMinutes(future.getMinutes() + 1);
|
||||
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel1.id, expiresAt: past });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel2.id, expiresAt: null });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel3.id, expiresAt: future });
|
||||
|
||||
const mutings = await service.list({ requestUserId: alice.id }, { idOnly: true });
|
||||
|
||||
expect(mutings).toHaveLength(2);
|
||||
expect(mutings[0].id).toBe(channel2.id);
|
||||
expect(mutings[1].id).toBe(channel3.id);
|
||||
});
|
||||
|
||||
test('joinUser', async () => {
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel1.id });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel2.id });
|
||||
await createChannelMuting({ userId: bob.id, channelId: channel3.id });
|
||||
|
||||
const mutings = await service.list({ requestUserId: alice.id }, { joinUser: true });
|
||||
|
||||
expect(mutings).toHaveLength(2);
|
||||
expect(mutings[0].id).toBe(channel1.id);
|
||||
expect(mutings[0].user).toEqual(alice);
|
||||
expect(mutings[0].banner).toBeFalsy();
|
||||
expect(mutings[1].id).toBe(channel2.id);
|
||||
expect(mutings[1].user).toEqual(alice);
|
||||
expect(mutings[1].banner).toBeFalsy();
|
||||
});
|
||||
|
||||
test('joinBannerFile', async () => {
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel1.id });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel2.id });
|
||||
await createChannelMuting({ userId: bob.id, channelId: channel3.id });
|
||||
|
||||
const mutings = await service.list({ requestUserId: alice.id }, { joinBannerFile: true });
|
||||
|
||||
expect(mutings).toHaveLength(2);
|
||||
expect(mutings[0].id).toBe(channel1.id);
|
||||
expect(mutings[0].user).toBeFalsy();
|
||||
expect(mutings[0].banner).toEqual(driveFile1);
|
||||
expect(mutings[1].id).toBe(channel2.id);
|
||||
expect(mutings[1].user).toBeFalsy();
|
||||
expect(mutings[1].banner).toEqual(driveFile2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findExpiredMutings', () => {
|
||||
test('default', async () => {
|
||||
const now = new Date();
|
||||
const future = new Date(now);
|
||||
const past = new Date(now);
|
||||
future.setMinutes(now.getMinutes() + 1);
|
||||
past.setMinutes(now.getMinutes() - 1);
|
||||
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel1.id, expiresAt: past });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel2.id, expiresAt: future });
|
||||
await createChannelMuting({ userId: bob.id, channelId: channel3.id, expiresAt: past });
|
||||
|
||||
const mutings = await service.findExpiredMutings();
|
||||
|
||||
expect(mutings).toHaveLength(2);
|
||||
expect(mutings[0].channelId).toBe(channel1.id);
|
||||
expect(mutings[1].channelId).toBe(channel3.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isMuted', () => {
|
||||
test('isMuted: true', async () => {
|
||||
// キャッシュを読むのでServiceの機能を使って登録し、キャッシュを作成する
|
||||
await service.mute({ requestUserId: alice.id, targetChannelId: channel1.id });
|
||||
await service.mute({ requestUserId: alice.id, targetChannelId: channel2.id });
|
||||
|
||||
await setTimeout(500);
|
||||
|
||||
const result = await service.isMuted({ requestUserId: alice.id, targetChannelId: channel1.id });
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
test('isMuted: false', async () => {
|
||||
await service.mute({ requestUserId: alice.id, targetChannelId: channel2.id });
|
||||
|
||||
await setTimeout(500);
|
||||
|
||||
const result = await service.isMuted({ requestUserId: alice.id, targetChannelId: channel1.id });
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mute', () => {
|
||||
test('default', async () => {
|
||||
await service.mute({ requestUserId: alice.id, targetChannelId: channel1.id });
|
||||
|
||||
const muting = await fetchChannelMuting();
|
||||
expect(muting).toHaveLength(1);
|
||||
expect(muting[0].channelId).toBe(channel1.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('unmute', () => {
|
||||
test('default', async () => {
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel1.id });
|
||||
|
||||
let muting = await fetchChannelMuting();
|
||||
expect(muting).toHaveLength(1);
|
||||
expect(muting[0].channelId).toBe(channel1.id);
|
||||
|
||||
await service.unmute({ requestUserId: alice.id, targetChannelId: channel1.id });
|
||||
|
||||
muting = await fetchChannelMuting();
|
||||
expect(muting).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('eraseExpiredMutings', () => {
|
||||
test('default', async () => {
|
||||
const now = new Date();
|
||||
const future = new Date(now);
|
||||
const past = new Date(now);
|
||||
future.setMinutes(now.getMinutes() + 1);
|
||||
past.setMinutes(now.getMinutes() - 1);
|
||||
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel1.id, expiresAt: past });
|
||||
await createChannelMuting({ userId: alice.id, channelId: channel2.id, expiresAt: future });
|
||||
await createChannelMuting({ userId: bob.id, channelId: channel3.id, expiresAt: past });
|
||||
|
||||
await service.eraseExpiredMutings();
|
||||
|
||||
const mutings = await fetchChannelMuting();
|
||||
expect(mutings).toHaveLength(1);
|
||||
expect(mutings[0].channelId).toBe(channel2.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -61,6 +61,7 @@ describe('NoteCreateService', () => {
|
||||
replyUserHost: null,
|
||||
renoteUserId: null,
|
||||
renoteUserHost: null,
|
||||
renoteChannelId: null,
|
||||
};
|
||||
|
||||
const poll: IPoll = {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
import { jest } from '@jest/globals';
|
||||
import { describe, jest } from '@jest/globals';
|
||||
import { ModuleMocker } from 'jest-mock';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as lolex from '@sinonjs/fake-timers';
|
||||
@@ -160,16 +160,75 @@ describe('RoleService', () => {
|
||||
afterEach(async () => {
|
||||
clock.uninstall();
|
||||
|
||||
/**
|
||||
* Delete meta and roleAssignment first to avoid deadlock due to schema dependencies
|
||||
* https://github.com/misskey-dev/misskey/issues/16783
|
||||
*/
|
||||
await app.get(DI.metasRepository).createQueryBuilder().delete().execute();
|
||||
await roleAssignmentsRepository.createQueryBuilder().delete().execute();
|
||||
await Promise.all([
|
||||
app.get(DI.metasRepository).createQueryBuilder().delete().execute(),
|
||||
usersRepository.createQueryBuilder().delete().execute(),
|
||||
rolesRepository.createQueryBuilder().delete().execute(),
|
||||
roleAssignmentsRepository.createQueryBuilder().delete().execute(),
|
||||
]);
|
||||
|
||||
await app.close();
|
||||
});
|
||||
|
||||
describe('getUserAssigns', () => {
|
||||
test('アサインされたロールを取得できる', async () => {
|
||||
const user = await createUser();
|
||||
const role1 = await createRole({ name: 'a' });
|
||||
const role2 = await createRole({ name: 'b' });
|
||||
|
||||
await roleService.assign(user.id, role1.id);
|
||||
await roleService.assign(user.id, role2.id);
|
||||
|
||||
const assigns = await roleService.getUserAssigns(user.id);
|
||||
expect(assigns).toHaveLength(2);
|
||||
expect(assigns.some(a => a.roleId === role1.id)).toBe(true);
|
||||
expect(assigns.some(a => a.roleId === role2.id)).toBe(true);
|
||||
});
|
||||
|
||||
test('アサインされたロールの有効/期限切れパターンを取得できる', async () => {
|
||||
const user = await createUser();
|
||||
const roleNoExpiry = await createRole({ name: 'no-expires' });
|
||||
const roleNotExpired = await createRole({ name: 'not-expired' });
|
||||
const roleExpired = await createRole({ name: 'expired' });
|
||||
|
||||
// expiresAtなし
|
||||
await roleService.assign(user.id, roleNoExpiry.id);
|
||||
|
||||
// expiresAtあり(期限切れでない)
|
||||
const future = new Date(Date.now() + 1000 * 60 * 60); // +1 hour
|
||||
await roleService.assign(user.id, roleNotExpired.id, future);
|
||||
|
||||
// expiresAtあり(期限切れ)
|
||||
await assignRole({ userId: user.id, roleId: roleExpired.id, expiresAt: new Date(Date.now() - 1000) });
|
||||
|
||||
const assigns = await roleService.getUserAssigns(user.id);
|
||||
expect(assigns.some(a => a.roleId === roleNoExpiry.id)).toBe(true);
|
||||
expect(assigns.some(a => a.roleId === roleNotExpired.id)).toBe(true);
|
||||
expect(assigns.some(a => a.roleId === roleExpired.id)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserRoles', () => {
|
||||
test('アサインされたロールとコンディショナルロールの両方が取得できる', async () => {
|
||||
const user = await createUser();
|
||||
const manualRole = await createRole({ name: 'manual role' });
|
||||
const conditionalRole = await createConditionalRole({
|
||||
id: aidx(),
|
||||
type: 'isBot',
|
||||
});
|
||||
await roleService.assign(user.id, manualRole.id);
|
||||
await roleService.assign(user.id, conditionalRole.id);
|
||||
|
||||
const roles = await roleService.getUserRoles(user.id);
|
||||
expect(roles.some(r => r.id === manualRole.id)).toBe(true);
|
||||
expect(roles.some(r => r.id === conditionalRole.id)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserPolicies', () => {
|
||||
test('instance default policies', async () => {
|
||||
const user = await createUser();
|
||||
@@ -282,6 +341,112 @@ describe('RoleService', () => {
|
||||
const resultAfter25hAgain = await roleService.getUserPolicies(user.id);
|
||||
expect(resultAfter25hAgain.canManageCustomEmojis).toBe(true);
|
||||
});
|
||||
|
||||
test('role with no policy set', async () => {
|
||||
const user = await createUser();
|
||||
const roleWithPolicy = await createRole({
|
||||
name: 'roleWithPolicy',
|
||||
policies: {
|
||||
pinLimit: {
|
||||
useDefault: false,
|
||||
priority: 0,
|
||||
value: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
const roleWithoutPolicy = await createRole({
|
||||
name: 'roleWithoutPolicy',
|
||||
policies: {}, // ポリシーが空
|
||||
});
|
||||
await roleService.assign(user.id, roleWithPolicy.id);
|
||||
await roleService.assign(user.id, roleWithoutPolicy.id);
|
||||
meta.policies = {
|
||||
pinLimit: 5,
|
||||
};
|
||||
|
||||
const result = await roleService.getUserPolicies(user.id);
|
||||
|
||||
// roleWithoutPolicy は default 値 (5) を使い、roleWithPolicy の 10 と比較して大きい方が採用される
|
||||
expect(result.pinLimit).toBe(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserBadgeRoles', () => {
|
||||
test('手動アサイン済みのバッジロールのみが返る', async () => {
|
||||
const user = await createUser();
|
||||
const badgeRole = await createRole({ name: 'badge', asBadge: true });
|
||||
const normalRole = await createRole({ name: 'normal', asBadge: false });
|
||||
|
||||
await roleService.assign(user.id, badgeRole.id);
|
||||
await roleService.assign(user.id, normalRole.id);
|
||||
|
||||
const roles = await roleService.getUserBadgeRoles(user.id);
|
||||
expect(roles.some(r => r.id === badgeRole.id)).toBe(true);
|
||||
expect(roles.some(r => r.id === normalRole.id)).toBe(false);
|
||||
});
|
||||
|
||||
test('コンディショナルなバッジロールが条件一致で返る', async () => {
|
||||
const user = await createUser({ isBot: true });
|
||||
const condBadgeRole = await createConditionalRole({
|
||||
id: aidx(),
|
||||
type: 'isBot',
|
||||
}, { asBadge: true, name: 'cond-badge' });
|
||||
const condNonBadgeRole = await createConditionalRole({
|
||||
id: aidx(),
|
||||
type: 'isBot',
|
||||
}, { asBadge: false, name: 'cond-non-badge' });
|
||||
|
||||
const roles = await roleService.getUserBadgeRoles(user.id);
|
||||
expect(roles.some(r => r.id === condBadgeRole.id)).toBe(true);
|
||||
expect(roles.some(r => r.id === condNonBadgeRole.id)).toBe(false);
|
||||
});
|
||||
|
||||
test('roleAssignedTo 条件のバッジロール: アサイン有無で変化する', async () => {
|
||||
const [user1, user2] = await Promise.all([createUser(), createUser()]);
|
||||
const manualRole = await createRole({ name: 'manual' });
|
||||
const condBadgeRole = await createConditionalRole({
|
||||
id: aidx(),
|
||||
type: 'roleAssignedTo',
|
||||
roleId: manualRole.id,
|
||||
}, { asBadge: true, name: 'assigned-badge' });
|
||||
|
||||
await roleService.assign(user2.id, manualRole.id);
|
||||
|
||||
const [roles1, roles2] = await Promise.all([
|
||||
roleService.getUserBadgeRoles(user1.id),
|
||||
roleService.getUserBadgeRoles(user2.id),
|
||||
]);
|
||||
expect(roles1.some(r => r.id === condBadgeRole.id)).toBe(false);
|
||||
expect(roles2.some(r => r.id === condBadgeRole.id)).toBe(true);
|
||||
});
|
||||
|
||||
test('期限切れのバッジロールは除外される', async () => {
|
||||
const user = await createUser();
|
||||
const roleNoExpiry = await createRole({ name: 'no-exp', asBadge: true });
|
||||
const roleNotExpired = await createRole({ name: 'not-expired', asBadge: true });
|
||||
const roleExpired = await createRole({ name: 'expired', asBadge: true });
|
||||
|
||||
// expiresAt なし
|
||||
await roleService.assign(user.id, roleNoExpiry.id);
|
||||
|
||||
// expiresAt あり(期限切れでない)
|
||||
const future = new Date(Date.now() + 1000 * 60 * 60); // +1 hour
|
||||
await roleService.assign(user.id, roleNotExpired.id, future);
|
||||
|
||||
// expiresAt あり(期限切れ)
|
||||
await assignRole({ userId: user.id, roleId: roleExpired.id, expiresAt: new Date(Date.now() - 1000) });
|
||||
|
||||
const rolesBefore = await roleService.getUserBadgeRoles(user.id);
|
||||
expect(rolesBefore.some(r => r.id === roleNoExpiry.id)).toBe(true);
|
||||
expect(rolesBefore.some(r => r.id === roleNotExpired.id)).toBe(true);
|
||||
expect(rolesBefore.some(r => r.id === roleExpired.id)).toBe(false);
|
||||
|
||||
// 時間経過で roleNotExpired を失効させる
|
||||
clock.tick('02:00:00');
|
||||
const rolesAfter = await roleService.getUserBadgeRoles(user.id);
|
||||
expect(rolesAfter.some(r => r.id === roleNoExpiry.id)).toBe(true);
|
||||
expect(rolesAfter.some(r => r.id === roleNotExpired.id)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getModeratorIds', () => {
|
||||
@@ -415,9 +580,9 @@ describe('RoleService', () => {
|
||||
expect(result).toEqual([modeUser1.id, modeUser2.id, rootUser.id]);
|
||||
});
|
||||
|
||||
test('root has moderator role', async () => {
|
||||
const [adminUser1, modeUser1, normalUser1, rootUser] = await Promise.all([
|
||||
createUser(), createUser(), createUser(), createRoot(),
|
||||
test('includeAdmins = false, includeRoot = true, excludeExpire = true', async () => {
|
||||
const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([
|
||||
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createRoot(),
|
||||
]);
|
||||
|
||||
const role1 = await createRole({ name: 'admin', isAdministrator: true });
|
||||
@@ -426,9 +591,11 @@ describe('RoleService', () => {
|
||||
|
||||
await Promise.all([
|
||||
assignRole({ userId: adminUser1.id, roleId: role1.id }),
|
||||
assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
assignRole({ userId: modeUser1.id, roleId: role2.id }),
|
||||
assignRole({ userId: rootUser.id, roleId: role2.id }),
|
||||
assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
assignRole({ userId: normalUser1.id, roleId: role3.id }),
|
||||
assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
]);
|
||||
|
||||
const result = await roleService.getModeratorIds({
|
||||
@@ -436,12 +603,12 @@ describe('RoleService', () => {
|
||||
includeRoot: true,
|
||||
excludeExpire: false,
|
||||
});
|
||||
expect(result).toEqual([modeUser1.id, rootUser.id]);
|
||||
expect(result).toEqual([modeUser1.id, modeUser2.id, rootUser.id]);
|
||||
});
|
||||
|
||||
test('root has administrator role', async () => {
|
||||
const [adminUser1, modeUser1, normalUser1, rootUser] = await Promise.all([
|
||||
createUser(), createUser(), createUser(), createRoot(),
|
||||
test('includeAdmins = true, includeRoot = true, excludeExpire = false', async () => {
|
||||
const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([
|
||||
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createRoot(),
|
||||
]);
|
||||
|
||||
const role1 = await createRole({ name: 'admin', isAdministrator: true });
|
||||
@@ -450,9 +617,11 @@ describe('RoleService', () => {
|
||||
|
||||
await Promise.all([
|
||||
assignRole({ userId: adminUser1.id, roleId: role1.id }),
|
||||
assignRole({ userId: rootUser.id, roleId: role1.id }),
|
||||
assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
assignRole({ userId: modeUser1.id, roleId: role2.id }),
|
||||
assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
assignRole({ userId: normalUser1.id, roleId: role3.id }),
|
||||
assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
]);
|
||||
|
||||
const result = await roleService.getModeratorIds({
|
||||
@@ -460,12 +629,12 @@ describe('RoleService', () => {
|
||||
includeRoot: true,
|
||||
excludeExpire: false,
|
||||
});
|
||||
expect(result).toEqual([adminUser1.id, modeUser1.id, rootUser.id]);
|
||||
expect(result).toEqual([adminUser1.id, adminUser2.id, modeUser1.id, modeUser2.id, rootUser.id]);
|
||||
});
|
||||
|
||||
test('root has moderator role(expire)', async () => {
|
||||
const [adminUser1, modeUser1, normalUser1, rootUser] = await Promise.all([
|
||||
createUser(), createUser(), createUser(), createRoot(),
|
||||
test('includeAdmins = true, includeRoot = true, excludeExpire = true', async () => {
|
||||
const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2, rootUser] = await Promise.all([
|
||||
createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), createRoot(),
|
||||
]);
|
||||
|
||||
const role1 = await createRole({ name: 'admin', isAdministrator: true });
|
||||
@@ -474,17 +643,71 @@ describe('RoleService', () => {
|
||||
|
||||
await Promise.all([
|
||||
assignRole({ userId: adminUser1.id, roleId: role1.id }),
|
||||
assignRole({ userId: modeUser1.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
assignRole({ userId: rootUser.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
assignRole({ userId: modeUser1.id, roleId: role2.id }),
|
||||
assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
assignRole({ userId: normalUser1.id, roleId: role3.id }),
|
||||
assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }),
|
||||
]);
|
||||
|
||||
const result = await roleService.getModeratorIds({
|
||||
includeAdmins: false,
|
||||
includeAdmins: true,
|
||||
includeRoot: true,
|
||||
excludeExpire: true,
|
||||
});
|
||||
expect(result).toEqual([rootUser.id]);
|
||||
expect(result).toEqual([adminUser1.id, modeUser1.id, rootUser.id]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAdministratorIds', () => {
|
||||
test('should return only user IDs with administrator roles', async () => {
|
||||
const adminUser1 = await createUser();
|
||||
const adminUser2 = await createUser();
|
||||
const normalUser = await createUser();
|
||||
const moderatorUser = await createUser();
|
||||
|
||||
const adminRole = await createRole({ name: 'admin', isAdministrator: true, isModerator: false });
|
||||
const moderatorRole = await createRole({ name: 'moderator', isModerator: true, isAdministrator: false });
|
||||
const normalRole = await createRole({ name: 'normal', isAdministrator: false, isModerator: false });
|
||||
|
||||
await roleService.assign(adminUser1.id, adminRole.id);
|
||||
await roleService.assign(adminUser2.id, adminRole.id);
|
||||
await roleService.assign(moderatorUser.id, moderatorRole.id);
|
||||
await roleService.assign(normalUser.id, normalRole.id);
|
||||
|
||||
const adminIds = await roleService.getAdministratorIds();
|
||||
|
||||
// sort for deterministic order
|
||||
adminIds.sort();
|
||||
const expectedIds = [adminUser1.id, adminUser2.id].sort();
|
||||
|
||||
expect(adminIds).toEqual(expectedIds);
|
||||
});
|
||||
|
||||
test('should return an empty array if no users have administrator roles', async () => {
|
||||
const normalUser = await createUser();
|
||||
const normalRole = await createRole({ name: 'normal', isAdministrator: false });
|
||||
await roleService.assign(normalUser.id, normalRole.id);
|
||||
|
||||
const adminIds = await roleService.getAdministratorIds();
|
||||
|
||||
expect(adminIds).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('should return an empty array if there are no administrator roles defined', async () => {
|
||||
await createUser(); // create user to ensure not empty db
|
||||
const adminIds = await roleService.getAdministratorIds();
|
||||
expect(adminIds).toHaveLength(0);
|
||||
});
|
||||
|
||||
// TODO: rootユーザーは現在実装に含まれていないため、テストもそれに倣う
|
||||
test('should not include the root user', async () => {
|
||||
const rootUser = await createUser();
|
||||
meta.rootUserId = rootUser.id;
|
||||
|
||||
const adminIds = await roleService.getAdministratorIds();
|
||||
|
||||
expect(adminIds).not.toContain(rootUser.id);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ const base: MiNote = {
|
||||
replyUserHost: null,
|
||||
renoteUserId: null,
|
||||
renoteUserHost: null,
|
||||
renoteChannelId: null,
|
||||
};
|
||||
|
||||
describe('misc:is-renote', () => {
|
||||
|
||||
Reference in New Issue
Block a user