2023-07-27 08:31:52 +03:00
/ *
2024-02-13 17:59:27 +02:00
* SPDX - FileCopyrightText : syuilo and misskey - project
2023-07-27 08:31:52 +03:00
* SPDX - License - Identifier : AGPL - 3.0 - only
* /
2019-04-07 15:50:36 +03:00
process . env . NODE_ENV = 'test' ;
2019-01-25 12:37:45 +02:00
import * as assert from 'assert' ;
2023-12-27 08:08:59 +02:00
import { WebSocket } from 'ws' ;
2023-09-20 05:33:36 +03:00
import { MiFollowing } from '@/models/Following.js' ;
2024-01-08 10:43:52 +02:00
import { api , createAppToken , initTestDb , port , post , signup , waitFire } from '../utils.js' ;
2023-06-25 02:34:18 +03:00
import type * as misskey from 'misskey-js' ;
2019-01-23 05:15:27 +02:00
2019-04-07 15:50:36 +03:00
describe ( 'Streaming' , ( ) = > {
let Followings : any ;
2019-01-23 05:15:27 +02:00
2019-04-18 08:29:17 +03:00
const follow = async ( follower : any , followee : any ) = > {
2019-04-07 15:50:36 +03:00
await Followings . save ( {
id : 'a' ,
followerId : follower.id ,
followeeId : followee.id ,
followerHost : follower.host ,
followerInbox : null ,
followerSharedInbox : null ,
followeeHost : followee.host ,
followeeInbox : null ,
2022-05-21 16:21:41 +03:00
followeeSharedInbox : null ,
2019-04-07 15:50:36 +03:00
} ) ;
} ;
2019-01-23 05:15:27 +02:00
2022-07-03 14:54:54 +03:00
describe ( 'Streaming' , ( ) = > {
// Local users
2024-01-03 06:41:28 +02:00
let ayano : misskey.entities.SignupResponse ;
let kyoko : misskey.entities.SignupResponse ;
let chitose : misskey.entities.SignupResponse ;
let kanako : misskey.entities.SignupResponse ;
2019-01-23 05:15:27 +02:00
2022-07-03 14:54:54 +03:00
// Remote users
2024-01-03 06:41:28 +02:00
let akari : misskey.entities.SignupResponse ;
let chinatsu : misskey.entities.SignupResponse ;
let takumi : misskey.entities.SignupResponse ;
2019-01-23 05:15:27 +02:00
2024-03-02 18:36:49 +02:00
let kyokoNote : misskey.entities.Note ;
let kanakoNote : misskey.entities.Note ;
let takumiNote : misskey.entities.Note ;
2022-07-03 14:54:54 +03:00
let list : any ;
2019-04-07 15:50:36 +03:00
2022-09-17 21:27:08 +03:00
beforeAll ( async ( ) = > {
2022-07-03 14:54:54 +03:00
const connection = await initTestDb ( true ) ;
2023-08-16 11:51:28 +03:00
Followings = connection . getRepository ( MiFollowing ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
ayano = await signup ( { username : 'ayano' } ) ;
kyoko = await signup ( { username : 'kyoko' } ) ;
chitose = await signup ( { username : 'chitose' } ) ;
2023-12-03 03:19:37 +02:00
kanako = await signup ( { username : 'kanako' } ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
akari = await signup ( { username : 'akari' , host : 'example.com' } ) ;
chinatsu = await signup ( { username : 'chinatsu' , host : 'example.com' } ) ;
2023-12-03 03:19:37 +02:00
takumi = await signup ( { username : 'takumi' , host : 'example.com' } ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
kyokoNote = await post ( kyoko , { text : 'foo' } ) ;
2023-12-03 03:19:37 +02:00
kanakoNote = await post ( kanako , { text : 'hoge' } ) ;
takumiNote = await post ( takumi , { text : 'piyo' } ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
// Follow: ayano => kyoko
await api ( 'following/create' , { userId : kyoko.id } , ayano ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
// Follow: ayano => akari
await follow ( ayano , akari ) ;
2019-04-07 15:50:36 +03:00
2024-03-02 18:36:49 +02:00
// Follow: kyoko => chitose
await api ( 'following/create' , { userId : chitose.id } , kyoko ) ;
2023-12-03 03:19:37 +02:00
// Mute: chitose => kanako
await api ( 'mute/create' , { userId : kanako.id } , chitose ) ;
2022-07-03 14:54:54 +03:00
// List: chitose => ayano, kyoko
list = await api ( 'users/lists/create' , {
name : 'my list' ,
} , chitose ) . then ( x = > x . body ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
await api ( 'users/lists/push' , {
listId : list.id ,
userId : ayano.id ,
} , chitose ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
await api ( 'users/lists/push' , {
listId : list.id ,
userId : kyoko.id ,
} , chitose ) ;
2023-12-03 03:19:37 +02:00
await api ( 'users/lists/push' , {
listId : list.id ,
userId : takumi.id ,
} , chitose ) ;
2023-03-03 04:13:12 +02:00
} , 1000 * 60 * 2 ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
describe ( 'Events' , ( ) = > {
2023-02-02 11:18:25 +02:00
test ( 'mention event' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
kyoko , 'main' , // kyoko:main
( ) = > post ( ayano , { text : 'foo @kyoko bar' } ) , // ayano mention => kyoko
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'mention' && msg . body . userId === ayano . id , // wait ayano
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'renote event' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
kyoko , 'main' , // kyoko:main
( ) = > post ( ayano , { renoteId : kyokoNote.id } ) , // ayano renote
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'renote' && msg . body . renoteId === kyokoNote . id , // wait renote
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2022-07-03 14:54:54 +03:00
} ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
describe ( 'Home Timeline' , ( ) = > {
2023-02-02 11:18:25 +02:00
test ( '自分の投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'homeTimeline' , // ayano:Home
( ) = > api ( 'notes/create' , { text : 'foo' } , ayano ) , // ayano posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . text === 'foo' ,
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
} ) ;
2019-04-07 15:50:36 +03:00
2023-10-20 02:13:20 +03:00
test ( '自分の visibility: followers な投稿が流れる' , async ( ) = > {
const fired = await waitFire (
ayano , 'homeTimeline' , // ayano:Home
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'followers' } , ayano ) , // ayano posts
msg = > msg . type === 'note' && msg . body . text === 'foo' ,
) ;
assert . strictEqual ( fired , true ) ;
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしているユーザーの投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'homeTimeline' , // ayano:home
( ) = > api ( 'notes/create' , { text : 'foo' } , kyoko ) , // kyoko posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2019-01-23 05:15:27 +02:00
2023-10-20 02:13:20 +03:00
test ( 'フォローしているユーザーの visibility: followers な投稿が流れる' , async ( ) = > {
const fired = await waitFire (
ayano , 'homeTimeline' , // ayano:home
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'followers' } , kyoko ) , // kyoko posts
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
) ;
assert . strictEqual ( fired , true ) ;
} ) ;
2023-10-20 07:07:08 +03:00
/ * な ん か 失 敗 す る
2023-10-20 05:58:09 +03:00
test ( 'フォローしているユーザーの visibility: followers な投稿への返信が流れる' , async ( ) = > {
const note = await api ( 'notes/create' , { text : 'foo' , visibility : 'followers' } , kyoko ) ;
const fired = await waitFire (
ayano , 'homeTimeline' , // ayano:home
( ) = > api ( 'notes/create' , { text : 'bar' , visibility : 'followers' , replyId : note.body.id } , kyoko ) , // kyoko posts
msg = > msg . type === 'note' && msg . body . userId === kyoko . id && msg . body . reply . text === 'foo' ,
) ;
assert . strictEqual ( fired , true ) ;
} ) ;
2023-10-20 07:07:08 +03:00
* /
2023-10-20 05:58:09 +03:00
2023-10-23 09:29:42 +03:00
test ( 'フォローしているユーザーのフォローしていないユーザーの visibility: followers な投稿への返信が流れない' , async ( ) = > {
2024-03-02 18:36:49 +02:00
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 ) ;
2023-10-23 09:29:42 +03:00
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしていないユーザーの投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
kyoko , 'homeTimeline' , // kyoko:home
( ) = > api ( 'notes/create' , { text : 'foo' } , ayano ) , // ayano posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === ayano . id , // wait ayano
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
assert . strictEqual ( fired , false ) ;
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしているユーザーのダイレクト投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'homeTimeline' , // ayano:home
2022-09-17 21:27:08 +03:00
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'specified' , visibleUserIds : [ ayano . id ] } , kyoko ) , // kyoko dm => ayano
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
2022-07-03 14:54:54 +03:00
) ;
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2019-01-23 05:15:27 +02:00
2023-02-02 11:18:25 +02:00
test ( 'フォローしているユーザーでも自分が指定されていないダイレクト投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'homeTimeline' , // ayano:home
2022-09-17 21:27:08 +03:00
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'specified' , visibleUserIds : [ chitose . id ] } , kyoko ) , // kyoko dm => chitose
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
2022-07-03 14:54:54 +03:00
) ;
2019-01-23 05:15:27 +02:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , false ) ;
2024-03-02 18:36:49 +02:00
} ) ;
/ * *
* 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 ) ;
2019-01-23 05:15:27 +02:00
} ) ;
2022-07-03 14:54:54 +03:00
} ) ; // Home
2019-01-25 08:56:49 +02:00
2022-07-03 14:54:54 +03:00
describe ( 'Local Timeline' , ( ) = > {
2023-02-02 11:18:25 +02:00
test ( '自分の投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'localTimeline' , // ayano:Local
( ) = > api ( 'notes/create' , { text : 'foo' } , ayano ) , // ayano posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . text === 'foo' ,
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
} ) ;
2019-04-07 15:50:36 +03:00
2023-02-02 11:18:25 +02:00
test ( 'フォローしていないローカルユーザーの投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'localTimeline' , // ayano:Local
( ) = > api ( 'notes/create' , { text : 'foo' } , chitose ) , // chitose posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === chitose . id , // wait chitose
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2019-01-25 09:14:09 +02:00
2023-04-07 14:09:22 +03:00
/ * T O D O
2023-02-02 11:18:25 +02:00
test ( 'リモートユーザーの投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'localTimeline' , // ayano:Local
( ) = > api ( 'notes/create' , { text : 'foo' } , chinatsu ) , // chinatsu posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === chinatsu . id , // wait chinatsu
2022-07-03 14:54:54 +03:00
) ;
2019-01-25 09:14:09 +02:00
2019-04-07 15:50:36 +03:00
assert . strictEqual ( fired , false ) ;
2019-01-25 09:14:09 +02:00
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしてたとしてもリモートユーザーの投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'localTimeline' , // ayano:Local
( ) = > api ( 'notes/create' , { text : 'foo' } , akari ) , // akari posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === akari . id , // wait akari
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
assert . strictEqual ( fired , false ) ;
} ) ;
2023-04-07 14:09:22 +03:00
* /
2019-01-25 09:14:09 +02:00
2023-02-02 11:18:25 +02:00
test ( 'ホーム指定の投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'localTimeline' , // ayano:Local
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'home' } , kyoko ) , // kyoko home posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
assert . strictEqual ( fired , false ) ;
2019-01-25 09:14:09 +02:00
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしているローカルユーザーのダイレクト投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'localTimeline' , // ayano:Local
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'specified' , visibleUserIds : [ ayano . id ] } , kyoko ) , // kyoko DM => ayano
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
2022-07-03 14:54:54 +03:00
) ;
2020-01-09 10:29:03 +02:00
assert . strictEqual ( fired , false ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしていないローカルユーザーのフォロワー宛て投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'localTimeline' , // ayano:Local
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'followers' } , chitose ) ,
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === chitose . id , // wait chitose
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
assert . strictEqual ( fired , false ) ;
} ) ;
2022-07-03 14:54:54 +03:00
} ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
describe ( 'Hybrid Timeline' , ( ) = > {
2023-02-02 11:18:25 +02:00
test ( '自分の投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'hybridTimeline' , // ayano:Hybrid
( ) = > api ( 'notes/create' , { text : 'foo' } , ayano ) , // ayano posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . text === 'foo' ,
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2023-10-20 02:15:31 +03:00
test ( '自分の visibility: followers な投稿が流れる' , async ( ) = > {
const fired = await waitFire (
ayano , 'hybridTimeline' ,
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'followers' } , ayano ) , // ayano posts
msg = > msg . type === 'note' && msg . body . text === 'foo' ,
) ;
assert . strictEqual ( fired , true ) ;
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしていないローカルユーザーの投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'hybridTimeline' , // ayano:Hybrid
( ) = > api ( 'notes/create' , { text : 'foo' } , chitose ) , // chitose posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === chitose . id , // wait chitose
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2023-04-07 14:09:22 +03:00
/ * T O D O
2023-02-02 11:18:25 +02:00
test ( 'フォローしているリモートユーザーの投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'hybridTimeline' , // ayano:Hybrid
( ) = > api ( 'notes/create' , { text : 'foo' } , akari ) , // akari posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === akari . id , // wait akari
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしていないリモートユーザーの投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'hybridTimeline' , // ayano:Hybrid
( ) = > api ( 'notes/create' , { text : 'foo' } , chinatsu ) , // chinatsu posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === chinatsu . id , // wait chinatsu
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
assert . strictEqual ( fired , false ) ;
} ) ;
2023-04-07 14:09:22 +03:00
* /
2019-04-07 15:50:36 +03:00
2023-02-02 11:18:25 +02:00
test ( 'フォローしているユーザーのダイレクト投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'hybridTimeline' , // ayano:Hybrid
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'specified' , visibleUserIds : [ ayano . id ] } , kyoko ) ,
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
2022-07-03 14:54:54 +03:00
) ;
2019-04-18 08:39:49 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-18 08:39:49 +03:00
} ) ;
2019-04-18 08:34:47 +03:00
2023-02-02 11:18:25 +02:00
test ( 'フォローしているユーザーのホーム投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'hybridTimeline' , // ayano:Hybrid
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'home' } , kyoko ) ,
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
2022-07-03 14:54:54 +03:00
) ;
2019-04-18 08:34:47 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-18 08:34:47 +03:00
} ) ;
2023-10-20 02:15:31 +03:00
test ( 'フォローしているユーザーの visibility: followers な投稿が流れる' , async ( ) = > {
const fired = await waitFire (
ayano , 'hybridTimeline' , // ayano:Hybrid
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'followers' } , kyoko ) ,
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
) ;
assert . strictEqual ( fired , true ) ;
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしていないローカルユーザーのホーム投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'hybridTimeline' , // ayano:Hybrid
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'home' } , chitose ) ,
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === chitose . id ,
2022-07-03 14:54:54 +03:00
) ;
2019-04-18 08:34:47 +03:00
assert . strictEqual ( fired , false ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'フォローしていないローカルユーザーのフォロワー宛て投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'hybridTimeline' , // ayano:Hybrid
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'followers' } , chitose ) ,
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === chitose . id ,
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
assert . strictEqual ( fired , false ) ;
} ) ;
2022-07-03 14:54:54 +03:00
} ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
describe ( 'Global Timeline' , ( ) = > {
2023-02-02 11:18:25 +02:00
test ( 'フォローしていないローカルユーザーの投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'globalTimeline' , // ayano:Global
( ) = > api ( 'notes/create' , { text : 'foo' } , chitose ) , // chitose posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === chitose . id , // wait chitose
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2019-04-22 20:50:59 +03:00
2023-04-07 14:09:22 +03:00
/ * T O D O
2023-02-02 11:18:25 +02:00
test ( 'フォローしていないリモートユーザーの投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'globalTimeline' , // ayano:Global
( ) = > api ( 'notes/create' , { text : 'foo' } , chinatsu ) , // chinatsu posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === chinatsu . id , // wait chinatsu
2022-07-03 14:54:54 +03:00
) ;
2019-04-22 20:50:59 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-22 20:50:59 +03:00
} ) ;
2023-04-07 14:09:22 +03:00
* /
2019-04-22 20:50:59 +03:00
2023-02-02 11:18:25 +02:00
test ( 'ホーム投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
ayano , 'globalTimeline' , // ayano:Global
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'home' } , kyoko ) , // kyoko posts
2022-09-17 21:27:08 +03:00
msg = > msg . type === 'note' && msg . body . userId === kyoko . id , // wait kyoko
2022-07-03 14:54:54 +03:00
) ;
2019-04-22 20:50:59 +03:00
assert . strictEqual ( fired , false ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2022-07-03 14:54:54 +03:00
} ) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
describe ( 'UserList Timeline' , ( ) = > {
2023-02-02 11:18:25 +02:00
test ( 'リストに入れているユーザーの投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { text : 'foo' } , ayano ) ,
msg = > msg . type === 'note' && msg . body . userId === ayano . id ,
2022-09-17 21:27:08 +03:00
{ listId : list.id } ,
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2023-02-02 11:18:25 +02:00
test ( 'リストに入れていないユーザーの投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { text : 'foo' } , chinatsu ) ,
msg = > msg . type === 'note' && msg . body . userId === chinatsu . id ,
2022-09-17 21:27:08 +03:00
{ listId : list.id } ,
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
assert . strictEqual ( fired , false ) ;
} ) ;
2022-07-03 14:54:54 +03:00
// #4471
2023-02-02 11:18:25 +02:00
test ( 'リストに入れているユーザーのダイレクト投稿が流れる' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'specified' , visibleUserIds : [ chitose . id ] } , ayano ) ,
msg = > msg . type === 'note' && msg . body . userId === ayano . id ,
2022-09-17 21:27:08 +03:00
{ listId : list.id } ,
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
2022-07-03 14:54:54 +03:00
assert . strictEqual ( fired , true ) ;
2019-04-07 15:50:36 +03:00
} ) ;
2022-07-03 14:54:54 +03:00
// #4335
2023-02-02 11:18:25 +02:00
test ( 'リストに入れているがフォローはしてないユーザーのフォロワー宛て投稿は流れない' , async ( ) = > {
2022-07-03 14:54:54 +03:00
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { text : 'foo' , visibility : 'followers' } , kyoko ) ,
msg = > msg . type === 'note' && msg . body . userId === kyoko . id ,
2022-09-17 21:27:08 +03:00
{ listId : list.id } ,
2022-07-03 14:54:54 +03:00
) ;
2019-04-07 15:50:36 +03:00
assert . strictEqual ( fired , false ) ;
2022-07-03 14:54:54 +03:00
} ) ;
2023-12-03 03:19:37 +02:00
// #10443
test ( 'チャンネル投稿は流れない' , async ( ) = > {
// リスインしている kyoko が 任意のチャンネルに投降した時の動きを見たい
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { text : 'foo' , channelId : 'dummy' } , kyoko ) ,
msg = > msg . type === 'note' && msg . body . userId === kyoko . id ,
{ listId : list.id } ,
) ;
assert . strictEqual ( fired , false ) ;
} ) ;
// #10443
test ( 'ミュートしているユーザへのリプライがリストTLに流れない' , async ( ) = > {
// chitose が kanako をミュートしている状態で、リスインしている kyoko が kanako にリプライした時の動きを見たい
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { text : 'foo' , replyId : kanakoNote.id } , kyoko ) ,
msg = > msg . type === 'note' && msg . body . userId === kyoko . id ,
{ listId : list.id } ,
) ;
assert . strictEqual ( fired , false ) ;
} ) ;
// #10443
test ( 'ミュートしているユーザの投稿をリノ ートしたときリストTLに流れない' , async ( ) = > {
// chitose が kanako をミュートしている状態で、リスインしている kyoko が kanako のノートをリノートした時の動きを見たい
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { renoteId : kanakoNote.id } , kyoko ) ,
msg = > msg . type === 'note' && msg . body . userId === kyoko . id ,
{ listId : list.id } ,
) ;
assert . strictEqual ( fired , false ) ;
} ) ;
// #10443
test ( 'ミュートしているサーバのノ ートがリストTLに流れない' , async ( ) = > {
await api ( '/i/update' , {
mutedInstances : [ 'example.com' ] ,
} , chitose ) ;
// chitose が example.com をミュートしている状態で、リスインしている takumi が ノートした時の動きを見たい
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { text : 'foo' } , takumi ) ,
msg = > msg . type === 'note' && msg . body . userId === kyoko . id ,
{ listId : list.id } ,
) ;
assert . strictEqual ( fired , false ) ;
} ) ;
// #10443
test ( 'ミュートしているサーバのノ ートに対するリプライがリストTLに流れない' , async ( ) = > {
await api ( '/i/update' , {
mutedInstances : [ 'example.com' ] ,
} , chitose ) ;
// chitose が example.com をミュートしている状態で、リスインしている kyoko が takumi のノートにリプライした時の動きを見たい
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { text : 'foo' , replyId : takumiNote.id } , kyoko ) ,
msg = > msg . type === 'note' && msg . body . userId === kyoko . id ,
{ listId : list.id } ,
) ;
assert . strictEqual ( fired , false ) ;
} ) ;
// #10443
test ( 'ミュートしているサーバのノ ートに対するリノ ートがリストTLに流れない' , async ( ) = > {
await api ( '/i/update' , {
mutedInstances : [ 'example.com' ] ,
} , chitose ) ;
// chitose が example.com をミュートしている状態で、リスインしている kyoko が takumi のノートをリノートした時の動きを見たい
const fired = await waitFire (
chitose , 'userList' ,
( ) = > api ( 'notes/create' , { renoteId : takumiNote.id } , kyoko ) ,
msg = > msg . type === 'note' && msg . body . userId === kyoko . id ,
{ listId : list.id } ,
) ;
assert . strictEqual ( fired , false ) ;
} ) ;
2022-07-03 14:54:54 +03:00
} ) ;
2019-04-07 15:50:36 +03:00
2023-12-27 08:08:59 +02:00
test ( 'Authentication' , async ( ) = > {
const application = await createAppToken ( ayano , [ ] ) ;
const application2 = await createAppToken ( ayano , [ 'read:account' ] ) ;
const socket = new WebSocket ( ` ws://127.0.0.1: ${ port } /streaming?i= ${ application } ` ) ;
const established = await new Promise < boolean > ( ( resolve , reject ) = > {
socket . on ( 'error' , ( ) = > resolve ( false ) ) ;
socket . on ( 'unexpected-response' , ( ) = > resolve ( false ) ) ;
setTimeout ( ( ) = > resolve ( true ) , 3000 ) ;
} ) ;
socket . close ( ) ;
assert . strictEqual ( established , false ) ;
const fired = await waitFire (
{ token : application2 } , 'hybridTimeline' ,
( ) = > api ( 'notes/create' , { text : 'Hello, world!' } , ayano ) ,
msg = > msg . type === 'note' && msg . body . userId === ayano . id ,
) ;
assert . strictEqual ( fired , true ) ;
} ) ;
2023-04-08 11:39:44 +03:00
// XXX: QueryFailedError: duplicate key value violates unique constraint "IDX_347fec870eafea7b26c8a73bac"
/ *
2022-07-03 14:54:54 +03:00
describe ( 'Hashtag Timeline' , ( ) = > {
2023-02-02 11:18:25 +02:00
test ( '指定したハッシュタグの投稿が流れる' , ( ) = > new Promise < void > ( async done = > {
2022-07-03 14:54:54 +03:00
const ws = await connectStream ( chitose , 'hashtag' , ( { type , body } ) = > {
2022-09-17 21:27:08 +03:00
if ( type === 'note' ) {
2022-07-03 14:54:54 +03:00
assert . deepStrictEqual ( body . text , '#foo' ) ;
ws . close ( ) ;
done ( ) ;
}
} , {
q : [
[ 'foo' ] ,
] ,
} ) ;
post ( chitose , {
text : '#foo' ,
} ) ;
} ) ) ;
2023-04-08 11:39:44 +03:00
test ( '指定したハッシュタグの投稿が流れる (AND)' , ( ) = > new Promise < void > ( async done = > {
let fooCount = 0 ;
let barCount = 0 ;
let fooBarCount = 0 ;
const ws = await connectStream ( chitose , 'hashtag' , ( { type , body } ) = > {
if ( type === 'note' ) {
if ( body . text === '#foo' ) fooCount ++ ;
if ( body . text === '#bar' ) barCount ++ ;
if ( body . text === '#foo #bar' ) fooBarCount ++ ;
}
} , {
q : [
[ 'foo' , 'bar' ] ,
] ,
} ) ;
post ( chitose , {
text : '#foo' ,
} ) ;
post ( chitose , {
text : '#bar' ,
} ) ;
post ( chitose , {
text : '#foo #bar' ,
} ) ;
setTimeout ( ( ) = > {
assert . strictEqual ( fooCount , 0 ) ;
assert . strictEqual ( barCount , 0 ) ;
assert . strictEqual ( fooBarCount , 1 ) ;
ws . close ( ) ;
done ( ) ;
} , 3000 ) ;
} ) ) ;
2022-07-03 14:54:54 +03:00
2023-02-02 11:18:25 +02:00
test ( '指定したハッシュタグの投稿が流れる (OR)' , ( ) = > new Promise < void > ( async done = > {
2022-07-03 14:54:54 +03:00
let fooCount = 0 ;
let barCount = 0 ;
let fooBarCount = 0 ;
let piyoCount = 0 ;
const ws = await connectStream ( chitose , 'hashtag' , ( { type , body } ) = > {
2022-09-17 21:27:08 +03:00
if ( type === 'note' ) {
2022-07-03 14:54:54 +03:00
if ( body . text === '#foo' ) fooCount ++ ;
if ( body . text === '#bar' ) barCount ++ ;
if ( body . text === '#foo #bar' ) fooBarCount ++ ;
if ( body . text === '#piyo' ) piyoCount ++ ;
}
} , {
q : [
[ 'foo' ] ,
[ 'bar' ] ,
] ,
} ) ;
post ( chitose , {
text : '#foo' ,
} ) ;
post ( chitose , {
text : '#bar' ,
} ) ;
post ( chitose , {
text : '#foo #bar' ,
} ) ;
post ( chitose , {
text : '#piyo' ,
} ) ;
setTimeout ( ( ) = > {
assert . strictEqual ( fooCount , 1 ) ;
assert . strictEqual ( barCount , 1 ) ;
assert . strictEqual ( fooBarCount , 1 ) ;
assert . strictEqual ( piyoCount , 0 ) ;
ws . close ( ) ;
done ( ) ;
} , 3000 ) ;
} ) ) ;
2023-02-02 11:18:25 +02:00
test ( '指定したハッシュタグの投稿が流れる (AND + OR)' , ( ) = > new Promise < void > ( async done = > {
2022-07-03 14:54:54 +03:00
let fooCount = 0 ;
let barCount = 0 ;
let fooBarCount = 0 ;
let piyoCount = 0 ;
let waaaCount = 0 ;
const ws = await connectStream ( chitose , 'hashtag' , ( { type , body } ) = > {
2022-09-17 21:27:08 +03:00
if ( type === 'note' ) {
2022-07-03 14:54:54 +03:00
if ( body . text === '#foo' ) fooCount ++ ;
if ( body . text === '#bar' ) barCount ++ ;
if ( body . text === '#foo #bar' ) fooBarCount ++ ;
if ( body . text === '#piyo' ) piyoCount ++ ;
if ( body . text === '#waaa' ) waaaCount ++ ;
}
} , {
q : [
[ 'foo' , 'bar' ] ,
[ 'piyo' ] ,
] ,
} ) ;
post ( chitose , {
text : '#foo' ,
} ) ;
post ( chitose , {
text : '#bar' ,
} ) ;
post ( chitose , {
text : '#foo #bar' ,
} ) ;
post ( chitose , {
text : '#piyo' ,
} ) ;
post ( chitose , {
text : '#waaa' ,
} ) ;
setTimeout ( ( ) = > {
assert . strictEqual ( fooCount , 0 ) ;
assert . strictEqual ( barCount , 0 ) ;
assert . strictEqual ( fooBarCount , 1 ) ;
assert . strictEqual ( piyoCount , 1 ) ;
assert . strictEqual ( waaaCount , 0 ) ;
ws . close ( ) ;
done ( ) ;
} , 3000 ) ;
} ) ) ;
} ) ;
2023-04-08 11:39:44 +03:00
* /
2019-04-07 15:50:36 +03:00
} ) ;
2019-01-23 05:15:27 +02:00
} ) ;