Merge remote-tracking branch 'misskey-dev/develop' into io
This commit is contained in:
commit
9ab785c48f
94 changed files with 4169 additions and 2564 deletions
|
@ -117,5 +117,185 @@ describe('Mute', () => {
|
|||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからのリプライが含まれない', async () => {
|
||||
const aliceNote = await post(alice, { text: 'hi' });
|
||||
await post(bob, { text: '@alice hi', replyId: aliceNote.id });
|
||||
await post(carol, { text: '@alice hi', replyId: aliceNote.id });
|
||||
|
||||
const res = await api('/i/notifications', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからのリプライが含まれない', async () => {
|
||||
await post(alice, { text: 'hi' });
|
||||
await post(bob, { text: '@alice hi' });
|
||||
await post(carol, { text: '@alice hi' });
|
||||
|
||||
const res = await api('/i/notifications', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからの引用リノートが含まれない', async () => {
|
||||
const aliceNote = await post(alice, { text: 'hi' });
|
||||
await post(bob, { text: 'hi', renoteId: aliceNote.id });
|
||||
await post(carol, { text: 'hi', renoteId: aliceNote.id });
|
||||
|
||||
const res = await api('/i/notifications', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからのリノートが含まれない', async () => {
|
||||
const aliceNote = await post(alice, { text: 'hi' });
|
||||
await post(bob, { renoteId: aliceNote.id });
|
||||
await post(carol, { renoteId: aliceNote.id });
|
||||
|
||||
const res = await api('/i/notifications', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからのフォロー通知が含まれない', async () => {
|
||||
await api('/i/follow', { userId: alice.id }, bob);
|
||||
await api('/i/follow', { userId: alice.id }, carol);
|
||||
|
||||
const res = await api('/i/notifications', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからのフォローリクエストが含まれない', async () => {
|
||||
await api('/i/update/', { isLocked: true }, alice);
|
||||
await api('/following/create', { userId: alice.id }, bob);
|
||||
await api('/following/create', { userId: alice.id }, carol);
|
||||
|
||||
const res = await api('/i/notifications', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Notification (Grouped)', () => {
|
||||
test('通知にミュートしているユーザーの通知が含まれない(リアクション)', async () => {
|
||||
const aliceNote = await post(alice, { text: 'hi' });
|
||||
await react(bob, aliceNote, 'like');
|
||||
await react(carol, aliceNote, 'like');
|
||||
|
||||
const res = await api('/i/notifications-grouped', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
test('通知にミュートしているユーザーからのリプライが含まれない', async () => {
|
||||
const aliceNote = await post(alice, { text: 'hi' });
|
||||
await post(bob, { text: '@alice hi', replyId: aliceNote.id });
|
||||
await post(carol, { text: '@alice hi', replyId: aliceNote.id });
|
||||
|
||||
const res = await api('/i/notifications-grouped', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからのリプライが含まれない', async () => {
|
||||
await post(alice, { text: 'hi' });
|
||||
await post(bob, { text: '@alice hi' });
|
||||
await post(carol, { text: '@alice hi' });
|
||||
|
||||
const res = await api('/i/notifications-grouped', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからの引用リノートが含まれない', async () => {
|
||||
const aliceNote = await post(alice, { text: 'hi' });
|
||||
await post(bob, { text: 'hi', renoteId: aliceNote.id });
|
||||
await post(carol, { text: 'hi', renoteId: aliceNote.id });
|
||||
|
||||
const res = await api('/i/notifications-grouped', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからのリノートが含まれない', async () => {
|
||||
const aliceNote = await post(alice, { text: 'hi' });
|
||||
await post(bob, { renoteId: aliceNote.id });
|
||||
await post(carol, { renoteId: aliceNote.id });
|
||||
|
||||
const res = await api('/i/notifications-grouped', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからのフォロー通知が含まれない', async () => {
|
||||
await api('/i/follow', { userId: alice.id }, bob);
|
||||
await api('/i/follow', { userId: alice.id }, carol);
|
||||
|
||||
const res = await api('/i/notifications-grouped', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
|
||||
test('通知にミュートしているユーザーからのフォローリクエストが含まれない', async () => {
|
||||
await api('/i/update/', { isLocked: true }, alice);
|
||||
await api('/following/create', { userId: alice.id }, bob);
|
||||
await api('/following/create', { userId: alice.id }, carol);
|
||||
|
||||
const res = await api('/i/notifications-grouped', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === bob.id), true);
|
||||
assert.strictEqual(res.body.some((notification: any) => notification.userId === carol.id), false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -178,6 +178,87 @@ describe('Note', () => {
|
|||
assert.strictEqual(deleteRes.status, 204);
|
||||
});
|
||||
|
||||
test('visibility: followersなノートに対してフォロワーはリプライできる', async () => {
|
||||
await api('/following/create', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
|
||||
const aliceNote = await api('/notes/create', {
|
||||
text: 'direct note to bob',
|
||||
visibility: 'followers',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(aliceNote.status, 200);
|
||||
|
||||
const replyId = aliceNote.body.createdNote.id;
|
||||
const bobReply = await api('/notes/create', {
|
||||
text: 'reply to alice note',
|
||||
replyId,
|
||||
}, bob);
|
||||
|
||||
assert.strictEqual(bobReply.status, 200);
|
||||
assert.strictEqual(bobReply.body.createdNote.replyId, replyId);
|
||||
|
||||
await api('/following/delete', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
});
|
||||
|
||||
test('visibility: followersなノートに対してフォロワーでないユーザーがリプライしようとすると怒られる', async () => {
|
||||
const aliceNote = await api('/notes/create', {
|
||||
text: 'direct note to bob',
|
||||
visibility: 'followers',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(aliceNote.status, 200);
|
||||
|
||||
const bobReply = await api('/notes/create', {
|
||||
text: 'reply to alice note',
|
||||
replyId: aliceNote.body.createdNote.id,
|
||||
}, bob);
|
||||
|
||||
assert.strictEqual(bobReply.status, 400);
|
||||
assert.strictEqual(bobReply.body.error.code, 'CANNOT_REPLY_TO_AN_INVISIBLE_NOTE');
|
||||
});
|
||||
|
||||
test('visibility: specifiedなノートに対してvisibility: specifiedで返信できる', async () => {
|
||||
const aliceNote = await api('/notes/create', {
|
||||
text: 'direct note to bob',
|
||||
visibility: 'specified',
|
||||
visibleUserIds: [bob.id],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(aliceNote.status, 200);
|
||||
|
||||
const bobReply = await api('/notes/create', {
|
||||
text: 'reply to alice note',
|
||||
replyId: aliceNote.body.createdNote.id,
|
||||
visibility: 'specified',
|
||||
visibleUserIds: [alice.id],
|
||||
}, bob);
|
||||
|
||||
assert.strictEqual(bobReply.status, 200);
|
||||
});
|
||||
|
||||
test('visibility: specifiedなノートに対してvisibility: follwersで返信しようとすると怒られる', async () => {
|
||||
const aliceNote = await api('/notes/create', {
|
||||
text: 'direct note to bob',
|
||||
visibility: 'specified',
|
||||
visibleUserIds: [bob.id],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(aliceNote.status, 200);
|
||||
|
||||
const bobReply = await api('/notes/create', {
|
||||
text: 'reply to alice note with visibility: followers',
|
||||
replyId: aliceNote.body.createdNote.id,
|
||||
visibility: 'followers',
|
||||
}, bob);
|
||||
|
||||
assert.strictEqual(bobReply.status, 400);
|
||||
assert.strictEqual(bobReply.body.error.code, 'CANNOT_REPLY_TO_SPECIFIED_VISIBILITY_NOTE_WITH_EXTENDED_VISIBILITY');
|
||||
});
|
||||
|
||||
test('文字数ぎりぎりで怒られない', async () => {
|
||||
const post = {
|
||||
text: '!'.repeat(MAX_NOTE_TEXT_LENGTH), // 3000文字
|
||||
|
@ -683,6 +764,171 @@ describe('Note', () => {
|
|||
assert.strictEqual(note3.status, 400);
|
||||
assert.strictEqual(note3.body.error.code, 'CONTAINS_PROHIBITED_WORDS');
|
||||
});
|
||||
|
||||
test('メンションの数が上限を超えるとエラーになる', async () => {
|
||||
const res = await api('admin/roles/create', {
|
||||
name: 'test',
|
||||
description: '',
|
||||
color: null,
|
||||
iconUrl: null,
|
||||
displayOrder: 0,
|
||||
target: 'manual',
|
||||
condFormula: {},
|
||||
isAdministrator: false,
|
||||
isModerator: false,
|
||||
isPublic: false,
|
||||
isExplorable: false,
|
||||
asBadge: false,
|
||||
canEditMembersByModerator: false,
|
||||
policies: {
|
||||
mentionLimit: {
|
||||
useDefault: false,
|
||||
priority: 1,
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
|
||||
await new Promise(x => setTimeout(x, 2));
|
||||
|
||||
const assign = await api('admin/roles/assign', {
|
||||
userId: alice.id,
|
||||
roleId: res.body.id,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(assign.status, 204);
|
||||
|
||||
await new Promise(x => setTimeout(x, 2));
|
||||
|
||||
const note = await api('/notes/create', {
|
||||
text: '@bob potentially annoying text',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(note.status, 400);
|
||||
assert.strictEqual(note.body.error.code, 'CONTAINS_TOO_MANY_MENTIONS');
|
||||
|
||||
await api('admin/roles/unassign', {
|
||||
userId: alice.id,
|
||||
roleId: res.body.id,
|
||||
});
|
||||
|
||||
await api('admin/roles/delete', {
|
||||
roleId: res.body.id,
|
||||
}, alice);
|
||||
});
|
||||
|
||||
test('ダイレクト投稿もエラーになる', async () => {
|
||||
const res = await api('admin/roles/create', {
|
||||
name: 'test',
|
||||
description: '',
|
||||
color: null,
|
||||
iconUrl: null,
|
||||
displayOrder: 0,
|
||||
target: 'manual',
|
||||
condFormula: {},
|
||||
isAdministrator: false,
|
||||
isModerator: false,
|
||||
isPublic: false,
|
||||
isExplorable: false,
|
||||
asBadge: false,
|
||||
canEditMembersByModerator: false,
|
||||
policies: {
|
||||
mentionLimit: {
|
||||
useDefault: false,
|
||||
priority: 1,
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
|
||||
await new Promise(x => setTimeout(x, 2));
|
||||
|
||||
const assign = await api('admin/roles/assign', {
|
||||
userId: alice.id,
|
||||
roleId: res.body.id,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(assign.status, 204);
|
||||
|
||||
await new Promise(x => setTimeout(x, 2));
|
||||
|
||||
const note = await api('/notes/create', {
|
||||
text: 'potentially annoying text',
|
||||
visibility: 'specified',
|
||||
visibleUserIds: [ bob.id ],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(note.status, 400);
|
||||
assert.strictEqual(note.body.error.code, 'CONTAINS_TOO_MANY_MENTIONS');
|
||||
|
||||
await api('admin/roles/unassign', {
|
||||
userId: alice.id,
|
||||
roleId: res.body.id,
|
||||
});
|
||||
|
||||
await api('admin/roles/delete', {
|
||||
roleId: res.body.id,
|
||||
}, alice);
|
||||
});
|
||||
|
||||
test('ダイレクトの宛先とメンションが同じ場合は重複してカウントしない', async () => {
|
||||
const res = await api('admin/roles/create', {
|
||||
name: 'test',
|
||||
description: '',
|
||||
color: null,
|
||||
iconUrl: null,
|
||||
displayOrder: 0,
|
||||
target: 'manual',
|
||||
condFormula: {},
|
||||
isAdministrator: false,
|
||||
isModerator: false,
|
||||
isPublic: false,
|
||||
isExplorable: false,
|
||||
asBadge: false,
|
||||
canEditMembersByModerator: false,
|
||||
policies: {
|
||||
mentionLimit: {
|
||||
useDefault: false,
|
||||
priority: 1,
|
||||
value: 1,
|
||||
},
|
||||
},
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
|
||||
await new Promise(x => setTimeout(x, 2));
|
||||
|
||||
const assign = await api('admin/roles/assign', {
|
||||
userId: alice.id,
|
||||
roleId: res.body.id,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(assign.status, 204);
|
||||
|
||||
await new Promise(x => setTimeout(x, 2));
|
||||
|
||||
const note = await api('/notes/create', {
|
||||
text: '@bob potentially annoying text',
|
||||
visibility: 'specified',
|
||||
visibleUserIds: [ bob.id ],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(note.status, 200);
|
||||
|
||||
await api('admin/roles/unassign', {
|
||||
userId: alice.id,
|
||||
roleId: res.body.id,
|
||||
});
|
||||
|
||||
await api('admin/roles/delete', {
|
||||
roleId: res.body.id,
|
||||
}, alice);
|
||||
});
|
||||
});
|
||||
|
||||
describe('notes/delete', () => {
|
||||
|
|
|
@ -40,9 +40,9 @@ describe('Streaming', () => {
|
|||
let chinatsu: misskey.entities.SignupResponse;
|
||||
let takumi: misskey.entities.SignupResponse;
|
||||
|
||||
let kyokoNote: any;
|
||||
let kanakoNote: any;
|
||||
let takumiNote: any;
|
||||
let kyokoNote: misskey.entities.Note;
|
||||
let kanakoNote: misskey.entities.Note;
|
||||
let takumiNote: misskey.entities.Note;
|
||||
let list: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
|
@ -70,6 +70,9 @@ describe('Streaming', () => {
|
|||
// Follow: ayano => akari
|
||||
await follow(ayano, akari);
|
||||
|
||||
// Follow: kyoko => chitose
|
||||
await api('following/create', { userId: chitose.id }, kyoko);
|
||||
|
||||
// Mute: chitose => kanako
|
||||
await api('mute/create', { userId: kanako.id }, chitose);
|
||||
|
||||
|
@ -172,7 +175,28 @@ describe('Streaming', () => {
|
|||
*/
|
||||
|
||||
test('フォローしているユーザーのフォローしていないユーザーの visibility: followers な投稿への返信が流れない', async () => {
|
||||
// TODO
|
||||
const chitoseNote = await post(chitose, { text: 'followers-only post', visibility: 'followers' });
|
||||
|
||||
const fired = await waitFire(
|
||||
ayano, 'homeTimeline', // ayano:home
|
||||
() => api('notes/create', { text: 'reply to chitose\'s followers-only post', replyId: chitoseNote.id }, kyoko), // kyoko's reply to chitose's followers-only post
|
||||
msg => msg.type === 'note' && msg.body.userId === kyoko.id, // wait kyoko
|
||||
);
|
||||
|
||||
assert.strictEqual(fired, false);
|
||||
});
|
||||
|
||||
test('フォローしているユーザーのフォローしていないユーザーの visibility: followers な投稿への返信のリノートが流れない', async () => {
|
||||
const chitoseNote = await post(chitose, { text: 'followers-only post', visibility: 'followers' });
|
||||
const kyokoReply = await post(kyoko, { text: 'reply to followers-only post', replyId: chitoseNote.id });
|
||||
|
||||
const fired = await waitFire(
|
||||
ayano, 'homeTimeline', // ayano:home
|
||||
() => api('notes/create', { renoteId: kyokoReply.id }, kyoko), // kyoko's renote of kyoko's reply to chitose's followers-only post
|
||||
msg => msg.type === 'note' && msg.body.userId === kyoko.id, // wait kyoko
|
||||
);
|
||||
|
||||
assert.strictEqual(fired, false);
|
||||
});
|
||||
|
||||
test('フォローしていないユーザーの投稿は流れない', async () => {
|
||||
|
@ -204,6 +228,79 @@ describe('Streaming', () => {
|
|||
|
||||
assert.strictEqual(fired, false);
|
||||
});
|
||||
|
||||
/**
|
||||
* TODO: 落ちる
|
||||
* @see https://github.com/misskey-dev/misskey/issues/13474
|
||||
test('visibility: specified なノートで visibleUserIds に自分が含まれているときそのノートへのリプライが流れてくる', async () => {
|
||||
const chitoseToKyokoAndAyano = await post(chitose, { text: 'direct note from chitose to kyoko and ayano', visibility: 'specified', visibleUserIds: [kyoko.id, ayano.id] });
|
||||
|
||||
const fired = await waitFire(
|
||||
ayano, 'homeTimeline', // ayano:home
|
||||
() => api('notes/create', { text: 'direct reply from kyoko to chitose and ayano', replyId: chitoseToKyokoAndAyano.id, visibility: 'specified', visibleUserIds: [chitose.id, ayano.id] }, kyoko),
|
||||
msg => msg.type === 'note' && msg.body.userId === kyoko.id,
|
||||
);
|
||||
|
||||
assert.strictEqual(fired, true);
|
||||
});
|
||||
*/
|
||||
|
||||
test('visibility: specified な投稿に対するリプライで visibleUserIds が拡張されたとき、その拡張されたユーザーの HTL にはそのリプライが流れない', async () => {
|
||||
const chitoseToKyoko = await post(chitose, { text: 'direct note from chitose to kyoko', visibility: 'specified', visibleUserIds: [kyoko.id] });
|
||||
|
||||
const fired = await waitFire(
|
||||
ayano, 'homeTimeline', // ayano:home
|
||||
() => api('notes/create', { text: 'direct reply from kyoko to chitose and ayano', replyId: chitoseToKyoko.id, visibility: 'specified', visibleUserIds: [chitose.id, ayano.id] }, kyoko),
|
||||
msg => msg.type === 'note' && msg.body.userId === kyoko.id,
|
||||
);
|
||||
|
||||
assert.strictEqual(fired, false);
|
||||
});
|
||||
|
||||
test('visibility: specified な投稿に対するリプライで visibleUserIds が収縮されたとき、その収縮されたユーザーの HTL にはそのリプライが流れない', async () => {
|
||||
const chitoseToKyokoAndAyano = await post(chitose, { text: 'direct note from chitose to kyoko and ayano', visibility: 'specified', visibleUserIds: [kyoko.id, ayano.id] });
|
||||
|
||||
const fired = await waitFire(
|
||||
ayano, 'homeTimeline', // ayano:home
|
||||
() => api('notes/create', { text: 'direct reply from kyoko to chitose', replyId: chitoseToKyokoAndAyano.id, visibility: 'specified', visibleUserIds: [chitose.id] }, kyoko),
|
||||
msg => msg.type === 'note' && msg.body.userId === kyoko.id,
|
||||
);
|
||||
|
||||
assert.strictEqual(fired, false);
|
||||
});
|
||||
|
||||
test('withRenotes: false のときリノートが流れない', async () => {
|
||||
const fired = await waitFire(
|
||||
ayano, 'homeTimeline', // ayano:home
|
||||
() => api('notes/create', { renoteId: kyokoNote.id }, kyoko), // kyoko renote
|
||||
msg => msg.type === 'note' && msg.body.userId === kyoko.id, // wait kyoko
|
||||
{ withRenotes: false },
|
||||
);
|
||||
|
||||
assert.strictEqual(fired, false);
|
||||
});
|
||||
|
||||
test('withRenotes: false のとき引用リノートが流れる', async () => {
|
||||
const fired = await waitFire(
|
||||
ayano, 'homeTimeline', // ayano:home
|
||||
() => api('notes/create', { text: 'quote', renoteId: kyokoNote.id }, kyoko), // kyoko quote
|
||||
msg => msg.type === 'note' && msg.body.userId === kyoko.id, // wait kyoko
|
||||
{ withRenotes: false },
|
||||
);
|
||||
|
||||
assert.strictEqual(fired, true);
|
||||
});
|
||||
|
||||
test('withRenotes: false のとき投票のみのリノートが流れる', async () => {
|
||||
const fired = await waitFire(
|
||||
ayano, 'homeTimeline', // ayano:home
|
||||
() => api('notes/create', { poll: { choices: ['kinoko', 'takenoko'] }, renoteId: kyokoNote.id }, kyoko), // kyoko renote with poll
|
||||
msg => msg.type === 'note' && msg.body.userId === kyoko.id, // wait kyoko
|
||||
{ withRenotes: false },
|
||||
);
|
||||
|
||||
assert.strictEqual(fired, true);
|
||||
});
|
||||
}); // Home
|
||||
|
||||
describe('Local Timeline', () => {
|
||||
|
|
|
@ -251,6 +251,34 @@ describe('RoleService', () => {
|
|||
expect(user2Policies.canManageCustomEmojis).toBe(true);
|
||||
});
|
||||
|
||||
test('コンディショナルロール: マニュアルロールにアサイン済み', async () => {
|
||||
const [user1, user2, role1] = await Promise.all([
|
||||
createUser(),
|
||||
createUser(),
|
||||
createRole({
|
||||
name: 'manual role',
|
||||
}),
|
||||
]);
|
||||
const role2 = await createRole({
|
||||
name: 'conditional role',
|
||||
target: 'conditional',
|
||||
condFormula: {
|
||||
// idはバックエンドのロジックに必要ない?
|
||||
id: 'bdc612bd-9d54-4675-ae83-0499c82ea670',
|
||||
type: 'roleAssignedTo',
|
||||
roleId: role1.id,
|
||||
},
|
||||
});
|
||||
await roleService.assign(user2.id, role1.id);
|
||||
|
||||
const [u1role, u2role] = await Promise.all([
|
||||
roleService.getUserRoles(user1.id),
|
||||
roleService.getUserRoles(user2.id),
|
||||
]);
|
||||
expect(u1role.some(r => r.id === role2.id)).toBe(false);
|
||||
expect(u2role.some(r => r.id === role2.id)).toBe(true);
|
||||
});
|
||||
|
||||
test('expired role', async () => {
|
||||
const user = await createUser();
|
||||
const role = await createRole({
|
||||
|
|
|
@ -356,7 +356,7 @@ export const uploadUrl = async (user: UserToken, url: string): Promise<Packed<'D
|
|||
return catcher;
|
||||
};
|
||||
|
||||
export function connectStream(user: UserToken, channel: string, listener: (message: Record<string, any>) => any, params?: any): Promise<WebSocket> {
|
||||
export function connectStream<C extends keyof misskey.Channels>(user: UserToken, channel: C, listener: (message: Record<string, any>) => any, params?: misskey.Channels[C]['params']): Promise<WebSocket> {
|
||||
return new Promise((res, rej) => {
|
||||
const url = new URL(`ws://127.0.0.1:${port}/streaming`);
|
||||
const options: ClientOptions = {};
|
||||
|
@ -391,7 +391,7 @@ export function connectStream(user: UserToken, channel: string, listener: (messa
|
|||
});
|
||||
}
|
||||
|
||||
export const waitFire = async (user: UserToken, channel: string, trgr: () => any, cond: (msg: Record<string, any>) => boolean, params?: any) => {
|
||||
export const waitFire = async <C extends keyof misskey.Channels>(user: UserToken, channel: C, trgr: () => any, cond: (msg: Record<string, any>) => boolean, params?: misskey.Channels[C]['params']) => {
|
||||
return new Promise<boolean>(async (res, rej) => {
|
||||
let timer: NodeJS.Timeout | null = null;
|
||||
|
||||
|
@ -436,7 +436,7 @@ export const waitFire = async (user: UserToken, channel: string, trgr: () => any
|
|||
*/
|
||||
export function makeStreamCatcher<T>(
|
||||
user: UserToken,
|
||||
channel: string,
|
||||
channel: keyof misskey.Channels,
|
||||
cond: (message: Record<string, any>) => boolean,
|
||||
extractor: (message: Record<string, any>) => T,
|
||||
timeout = 60 * 1000): Promise<T> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue