Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Sharkey
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Dima Krasner
Sharkey
Commits
8571c692
Unverified
Commit
8571c692
authored
2 years ago
by
Nanashia
Committed by
GitHub
2 years ago
Browse files
Options
Downloads
Patches
Plain Diff
test(backend): Add tests for web resources (#10341)
parent
3757d3ab
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
packages/backend/test/e2e/fetch-resource.ts
+383
-125
383 additions, 125 deletions
packages/backend/test/e2e/fetch-resource.ts
packages/backend/test/utils.ts
+85
-4
85 additions, 4 deletions
packages/backend/test/utils.ts
with
468 additions
and
129 deletions
packages/backend/test/e2e/fetch-resource.ts
+
383
−
125
View file @
8571c692
process
.
env
.
NODE_ENV
=
'
test
'
;
import
*
as
assert
from
'
assert
'
;
import
{
startServer
,
signup
,
post
,
api
,
simpleGet
}
from
'
../utils.js
'
;
import
{
startServer
,
channel
,
clip
,
cookie
,
galleryPost
,
signup
,
page
,
play
,
post
,
simpleGet
,
uploadFile
}
from
'
../utils.js
'
;
import
type
{
SimpleGetResponse
}
from
'
../utils.js
'
;
import
type
{
INestApplicationContext
}
from
'
@nestjs/common
'
;
// Request Accept
...
...
@@ -15,189 +16,446 @@ const AP = 'application/activity+json; charset=utf-8';
const
HTML
=
'
text/html; charset=utf-8
'
;
const
JSON_UTF8
=
'
application/json; charset=utf-8
'
;
describe
(
'
Fetch resource
'
,
()
=>
{
describe
(
'
Webリソース
'
,
()
=>
{
let
app
:
INestApplicationContext
;
let
alice
:
any
;
let
aliceUploadedFile
:
any
;
let
alicesPost
:
any
;
let
alicePage
:
any
;
let
alicePlay
:
any
;
let
aliceClip
:
any
;
let
aliceGalleryPost
:
any
;
let
aliceChannel
:
any
;
type
Request
=
{
path
:
string
,
accept
?:
string
,
cookie
?:
string
,
};
const
ok
=
async
(
param
:
Request
&
{
type
?:
string
,
}):
Promise
<
SimpleGetResponse
>
=>
{
const
{
path
,
accept
,
cookie
,
type
}
=
param
;
const
res
=
await
simpleGet
(
path
,
accept
,
cookie
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
type
??
HTML
);
return
res
;
};
const
notOk
=
async
(
param
:
Request
&
{
status
?:
number
,
code
?:
string
,
}):
Promise
<
SimpleGetResponse
>
=>
{
const
{
path
,
accept
,
cookie
,
status
,
code
}
=
param
;
const
res
=
await
simpleGet
(
path
,
accept
,
cookie
);
assert
.
notStrictEqual
(
res
.
status
,
200
);
if
(
status
!=
null
)
{
assert
.
strictEqual
(
res
.
status
,
status
);
}
if
(
code
!=
null
)
{
assert
.
strictEqual
(
res
.
body
.
error
.
code
,
code
);
}
return
res
;
};
const
notFound
=
async
(
param
:
Request
):
Promise
<
SimpleGetResponse
>
=>
{
return
await
notOk
({
...
param
,
status
:
404
,
});
};
const
metaTag
=
(
res
:
SimpleGetResponse
,
key
:
string
,
superkey
=
'
name
'
):
string
=>
{
return
res
.
body
.
window
.
document
.
querySelector
(
'
meta[
'
+
superkey
+
'
="
'
+
key
+
'
"]
'
)?.
content
;
};
beforeAll
(
async
()
=>
{
app
=
await
startServer
();
alice
=
await
signup
({
username
:
'
alice
'
});
aliceUploadedFile
=
await
uploadFile
(
alice
);
alicesPost
=
await
post
(
alice
,
{
text
:
'
test
'
,
});
alicePage
=
await
page
(
alice
,
{});
alicePlay
=
await
play
(
alice
,
{});
aliceClip
=
await
clip
(
alice
,
{});
aliceGalleryPost
=
await
galleryPost
(
alice
,
{
fileIds
:
[
aliceUploadedFile
.
body
.
id
],
});
aliceChannel
=
await
channel
(
alice
,
{});
},
1000
*
60
*
2
);
afterAll
(
async
()
=>
{
await
app
.
close
();
});
describe
(
'
Common
'
,
()
=>
{
test
(
'
meta
'
,
async
()
=>
{
const
res
=
await
api
(
'
/meta
'
,
{
});
describe
.
each
([
{
path
:
'
/
'
,
type
:
HTML
},
{
path
:
'
/docs/ja-JP/about
'
,
type
:
HTML
},
// "指定されたURLに該当するページはありませんでした。"
// fastify-static gives charset=UTF-8 instead of utf-8 and that's okay
{
path
:
'
/api-doc
'
,
type
:
'
text/html; charset=UTF-8
'
},
{
path
:
'
/api.json
'
,
type
:
JSON_UTF8
},
{
path
:
'
/api-console
'
,
type
:
HTML
},
{
path
:
'
/_info_card_
'
,
type
:
HTML
},
{
path
:
'
/bios
'
,
type
:
HTML
},
{
path
:
'
/cli
'
,
type
:
HTML
},
{
path
:
'
/flush
'
,
type
:
HTML
},
{
path
:
'
/robots.txt
'
,
type
:
'
text/plain; charset=UTF-8
'
},
{
path
:
'
/favicon.ico
'
,
type
:
'
image/vnd.microsoft.icon
'
},
{
path
:
'
/opensearch.xml
'
,
type
:
'
application/opensearchdescription+xml
'
},
{
path
:
'
/apple-touch-icon.png
'
,
type
:
'
image/png
'
},
{
path
:
'
/twemoji/2764.svg
'
,
type
:
'
image/svg+xml
'
},
{
path
:
'
/twemoji/2764-fe0f-200d-1f525.svg
'
,
type
:
'
image/svg+xml
'
},
{
path
:
'
/twemoji-badge/2764.png
'
,
type
:
'
image/png
'
},
{
path
:
'
/twemoji-badge/2764-fe0f-200d-1f525.png
'
,
type
:
'
image/png
'
},
{
path
:
'
/fluent-emoji/2764.png
'
,
type
:
'
image/png
'
},
{
path
:
'
/fluent-emoji/2764-fe0f-200d-1f525.png
'
,
type
:
'
image/png
'
},
])(
'
$path
'
,
(
p
)
=>
{
test
(
'
がGETできる。
'
,
async
()
=>
await
ok
({
...
p
}));
// 注意: Webページが200で取得できても、実際のHTMLが正しく表示できるとは限らない
// 例えば、 /@xxx/pages/yyy に存在しないIDを渡した場合、HTTPレスポンスではエラーを区別できない
// こういったアサーションはフロントエンドE2EやAPI Endpointのテストで担保する。
});
assert
.
strictEqual
(
res
.
status
,
200
);
});
describe
.
each
([
{
path
:
'
/twemoji/2764.png
'
},
{
path
:
'
/twemoji/2764-fe0f-200d-1f525.png
'
},
{
path
:
'
/twemoji-badge/2764.svg
'
},
{
path
:
'
/twemoji-badge/2764-fe0f-200d-1f525.svg
'
},
{
path
:
'
/fluent-emoji/2764.svg
'
},
{
path
:
'
/fluent-emoji/2764-fe0f-200d-1f525.svg
'
},
])(
'
$path
'
,
({
path
})
=>
{
test
(
'
はGETできない。
'
,
async
()
=>
await
notFound
({
path
}));
});
test
(
'
GET root
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/
'
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
HTML
);
});
describe
.
each
([
{
ext
:
'
rss
'
,
type
:
'
application/rss+xml; charset=utf-8
'
},
{
ext
:
'
atom
'
,
type
:
'
application/atom+xml; charset=utf-8
'
},
{
ext
:
'
json
'
,
type
:
'
application/json; charset=utf-8
'
},
])(
'
/@:username.$ext
'
,
({
ext
,
type
})
=>
{
const
path
=
(
username
:
string
):
string
=>
`/@
${
username
}
.
${
ext
}
`
;
test
(
'
がGETできる。
'
,
async
()
=>
await
ok
({
path
:
path
(
alice
.
username
),
type
,
}));
test
(
'
は存在しないユーザーはGETできない。
'
,
async
()
=>
await
notOk
({
path
:
path
(
'
nonexisting
'
),
status
:
404
,
}));
});
test
(
'
GET docs
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/docs/ja-JP/about
'
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
HTML
);
});
describe
.
each
([{
path
:
'
/api/foo
'
}])(
'
$path
'
,
({
path
})
=>
{
test
(
'
はGETできない。
'
,
async
()
=>
await
notOk
({
path
,
status
:
404
,
code
:
'
UNKNOWN_API_ENDPOINT
'
,
}));
});
test
(
'
GET api-doc
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/api-doc
'
);
assert
.
strictEqual
(
res
.
status
,
200
);
// fastify-static gives charset=UTF-8 instead of utf-8 and that's okay
assert
.
strictEqual
(
res
.
type
?.
toLowerCase
(),
HTML
);
});
describe
.
each
([{
path
:
'
/queue
'
}])(
'
$path
'
,
({
path
})
=>
{
test
(
'
はadminでなければGETできない。
'
,
async
()
=>
await
notOk
({
path
,
status
:
500
,
// FIXME? 403ではない。
}));
test
(
'
はadminならGETできる。
'
,
async
()
=>
await
ok
({
path
,
cookie
:
cookie
(
alice
),
}));
});
test
(
'
GET api.json
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/api.json
'
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
JSON_UTF8
);
});
describe
.
each
([{
path
:
'
/streaming
'
}])(
'
$path
'
,
({
path
})
=>
{
test
(
'
はGETできない。
'
,
async
()
=>
await
notOk
({
path
,
status
:
503
,
}));
});
test
(
'
GET api/foo (存在しない)
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/api/foo
'
);
assert
.
strictEqual
(
res
.
status
,
404
);
assert
.
strictEqual
(
res
.
body
.
error
.
code
,
'
UNKNOWN_API_ENDPOINT
'
);
describe
(
'
/@:username
'
,
()
=>
{
const
path
=
(
username
:
string
):
string
=>
`/@
${
username
}
`
;
describe
.
each
([
{
accept
:
PREFER_HTML
},
{
accept
:
UNSPECIFIED
},
])(
'
(Acceptヘッダ: $accept)
'
,
({
accept
})
=>
{
test
(
'
はHTMLとしてGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
alice
.
username
),
accept
,
type
:
HTML
,
});
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-username
'
),
alice
.
username
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-id
'
),
alice
.
id
);
// TODO ogタグの検証
// TODO profile.noCrawleの検証
// TODO twitter:creatorの検証
// TODO <link rel="me" ...>の検証
});
test
(
'
はHTMLとしてGETできる。(存在しないIDでも。)
'
,
async
()
=>
await
ok
({
path
:
path
(
'
xxxxxxxxxx
'
),
type
:
HTML
,
}));
});
test
(
'
GET api-console (client page)
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/api-console
'
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
HTML
);
describe
.
each
([
{
accept
:
ONLY_AP
},
{
accept
:
PREFER_AP
},
])(
'
(Acceptヘッダ: $accept)
'
,
({
accept
})
=>
{
test
(
'
はActivityPubとしてGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
alice
.
username
),
accept
,
type
:
AP
,
});
assert
.
strictEqual
(
res
.
body
.
type
,
'
Person
'
);
});
test
(
'
は存在しないIDのときActivityPubとしてGETできない。
'
,
async
()
=>
await
notFound
({
path
:
path
(
'
xxxxxxxxxx
'
),
accept
,
}));
});
});
test
(
'
GET favicon.ico
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/favicon.ico
'
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
'
image/vnd.microsoft.icon
'
);
describe
.
each
([
// 実際のハンドルはフロントエンド(index.vue)で行われる
{
sub
:
'
home
'
},
{
sub
:
'
notes
'
},
{
sub
:
'
activity
'
},
{
sub
:
'
achievements
'
},
{
sub
:
'
reactions
'
},
{
sub
:
'
clips
'
},
{
sub
:
'
pages
'
},
{
sub
:
'
gallery
'
},
])(
'
/@:username/$sub
'
,
({
sub
})
=>
{
const
path
=
(
username
:
string
):
string
=>
`/@
${
username
}
/
${
sub
}
`
;
test
(
'
はHTMLとしてGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
alice
.
username
),
});
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-username
'
),
alice
.
username
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-id
'
),
alice
.
id
);
});
});
describe
(
'
/@:user/pages/:page
'
,
()
=>
{
const
path
=
(
username
:
string
,
pagename
:
string
):
string
=>
`/@
${
username
}
/pages/
${
pagename
}
`
;
test
(
'
GET apple-touch-icon.png
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/apple-touch-icon.png
'
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
'
image/png
'
);
test
(
'
はHTMLとしてGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
alice
.
username
,
alicePage
.
name
),
});
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-username
'
),
alice
.
username
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-id
'
),
alice
.
id
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:page-id
'
),
alicePage
.
id
);
// TODO ogタグの検証
// TODO profile.noCrawleの検証
// TODO twitter:creatorの検証
});
test
(
'
はGETできる。(存在しないIDでも。)
'
,
async
()
=>
await
ok
({
path
:
path
(
alice
.
username
,
'
xxxxxxxxxx
'
),
}));
});
test
(
'
GET twemoji svg
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/twemoji/2764.svg
'
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
'
image/svg+xml
'
);
describe
(
'
/users/:id
'
,
()
=>
{
const
path
=
(
id
:
string
):
string
=>
`/users/
${
id
}
`
;
describe
.
each
([
{
accept
:
PREFER_HTML
},
{
accept
:
UNSPECIFIED
},
])(
'
(Acceptヘッダ: $accept)
'
,
({
accept
})
=>
{
test
(
'
は/@:usernameにリダイレクトする
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
path
(
alice
.
id
),
accept
);
assert
.
strictEqual
(
res
.
status
,
302
);
assert
.
strictEqual
(
res
.
location
,
`/@
${
alice
.
username
}
`
);
});
test
(
'
は存在しないユーザーはGETできない。
'
,
async
()
=>
await
notFound
({
path
:
path
(
'
xxxxxxxx
'
),
}));
});
test
(
'
GET twemoji svg with hyphen
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
'
/twemoji/2764-fe0f-200d-1f525.svg
'
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
'
image/svg+xml
'
);
describe
.
each
([
{
accept
:
ONLY_AP
},
{
accept
:
PREFER_AP
},
])(
'
(Acceptヘッダ: $accept)
'
,
({
accept
})
=>
{
test
(
'
はActivityPubとしてGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
alice
.
id
),
accept
,
type
:
AP
,
});
assert
.
strictEqual
(
res
.
body
.
type
,
'
Person
'
);
});
test
(
'
は存在しないIDのときActivityPubとしてGETできない。
'
,
async
()
=>
await
notOk
({
path
:
path
(
'
xxxxxxxx
'
),
accept
,
status
:
404
,
}));
});
});
describe
(
'
/users/inbox
'
,
()
=>
{
test
(
'
がGETできる。(POST専用だけど4xx/5xxにならずHTMLが返ってくる)
'
,
async
()
=>
await
ok
({
path
:
'
/inbox
'
,
}));
describe
(
'
/@:username
'
,
()
=>
{
test
(
'
Only AP => AP
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/@
${
alice
.
username
}
`
,
ONLY_AP
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
AP
);
});
// test.todo('POSTできる?');
});
test
(
'
Prefer AP => AP
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/@
${
alice
.
username
}
`
,
PREFER_AP
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
AP
);
});
describe
(
'
/users/:id/inbox
'
,
()
=>
{
const
path
=
(
id
:
string
):
string
=>
`/users/
${
id
}
/inbox`
;
test
(
'
Prefer HTML => HTML
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/@
${
alice
.
username
}
`
,
PREFER_HTML
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
HTML
);
});
test
(
'
がGETできる。(POST専用だけど4xx/5xxにならずHTMLが返ってくる)
'
,
async
()
=>
await
ok
({
path
:
path
(
alice
.
id
),
}));
test
(
'
Unspecified => HTML
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/@
${
alice
.
username
}
`
,
UNSPECIFIED
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
HTML
);
});
// test.todo('POSTできる?');
});
describe
(
'
/users/:id
'
,
()
=>
{
test
(
'
Only AP => AP
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/users/
${
alice
.
id
}
`
,
ONLY_AP
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
AP
);
});
describe
(
'
/users/:id/outbox
'
,
()
=>
{
const
path
=
(
id
:
string
):
string
=>
`/users/
${
id
}
/outbox`
;
test
(
'
Prefer AP => AP
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/users/
${
alice
.
id
}
`
,
PREFER_AP
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
AP
);
test
(
'
がGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
alice
.
id
),
type
:
AP
,
});
assert
.
strictEqual
(
res
.
body
.
type
,
'
OrderedCollection
'
);
});
});
describe
(
'
/notes/:id
'
,
()
=>
{
const
path
=
(
noteId
:
string
):
string
=>
`/notes/
${
noteId
}
`
;
describe
.
each
([
{
accept
:
PREFER_HTML
},
{
accept
:
UNSPECIFIED
},
])(
'
(Acceptヘッダ: $accept)
'
,
({
accept
})
=>
{
test
(
'
はHTMLとしてGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
alicesPost
.
id
),
accept
,
type
:
HTML
,
});
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-username
'
),
alice
.
username
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-id
'
),
alice
.
id
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:note-id
'
),
alicesPost
.
id
);
// TODO ogタグの検証
// TODO profile.noCrawleの検証
// TODO twitter:creatorの検証
});
test
(
'
Prefer HTML => Redirect to /@:username
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/users/
${
alice
.
id
}
`
,
PREFER_HTML
);
assert
.
strictEqual
(
res
.
status
,
302
);
assert
.
strictEqual
(
res
.
location
,
`/@
${
alice
.
username
}
`
);
test
(
'
はHTMLとしてGETできる。(存在しないIDでも。)
'
,
async
()
=>
await
ok
({
path
:
path
(
'
xxxxxxxxxx
'
),
}));
});
test
(
'
Undecided => HTML
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/users/
${
alice
.
id
}
`
,
UNSPECIFIED
);
assert
.
strictEqual
(
res
.
status
,
302
);
assert
.
strictEqual
(
res
.
location
,
`/@
${
alice
.
username
}
`
);
describe
.
each
([
{
accept
:
ONLY_AP
},
{
accept
:
PREFER_AP
},
])(
'
(Acceptヘッダ: $accept)
'
,
({
accept
})
=>
{
test
(
'
はActivityPubとしてGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
alicesPost
.
id
),
accept
,
type
:
AP
,
});
assert
.
strictEqual
(
res
.
body
.
type
,
'
Note
'
);
});
test
(
'
は存在しないIDのときActivityPubとしてGETできない。
'
,
async
()
=>
await
notFound
({
path
:
path
(
'
xxxxxxxxxx
'
),
accept
,
}));
});
});
describe
(
'
/play/:id
'
,
()
=>
{
const
path
=
(
playid
:
string
):
string
=>
`/play/
${
playid
}
`
;
describe
(
'
/notes/:id
'
,
()
=>
{
test
(
'
Only AP => AP
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/notes/
${
alicesPost
.
id
}
`
,
ONLY_AP
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
AP
);
test
(
'
がGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
alicePlay
.
id
),
});
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-username
'
),
alice
.
username
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-id
'
),
alice
.
id
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:flash-id
'
),
alicePlay
.
id
);
// TODO ogタグの検証
// TODO profile.noCrawleの検証
// TODO twitter:creatorの検証
});
test
(
'
Prefer AP => AP
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/notes/
${
alicesPost
.
id
}
`
,
PREFER_AP
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
AP
);
});
test
(
'
がGETできる。(存在しないIDでも。)
'
,
async
()
=>
await
ok
({
path
:
path
(
'
xxxxxxxxxx
'
),
}));
});
describe
(
'
/clips/:clip
'
,
()
=>
{
const
path
=
(
clip
:
string
):
string
=>
`/clips/
${
clip
}
`
;
test
(
'
Prefer HTML => HTML
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/notes/
${
alicesPost
.
id
}
`
,
PREFER_HTML
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
HTML
);
});
test
(
'
がGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
aliceClip
.
id
),
});
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-username
'
),
alice
.
username
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-id
'
),
alice
.
id
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:clip-id
'
),
aliceClip
.
id
);
test
(
'
Unspecified => HTML
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/notes/
${
alicesPost
.
id
}
`
,
UNSPECIFIED
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
HTML
);
// TODO ogタグの検証
// TODO profile.noCrawleの検証
});
test
(
'
がGETできる。(存在しないIDでも。)
'
,
async
()
=>
await
ok
({
path
:
path
(
'
xxxxxxxxxx
'
),
}));
});
describe
(
'
Feeds
'
,
()
=>
{
test
(
'
RSS
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/@
${
alice
.
username
}
.rss`
,
UNSPECIFIED
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
'
application/rss+xml; charset=utf-8
'
);
});
describe
(
'
/gallery/:post
'
,
()
=>
{
const
path
=
(
post
:
string
):
string
=>
`/gallery/
${
post
}
`
;
test
(
'
がGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
aliceGalleryPost
.
id
),
});
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-username
'
),
alice
.
username
);
assert
.
strictEqual
(
metaTag
(
res
,
'
misskey:user-id
'
),
alice
.
id
);
test
(
'
ATOM
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/@
${
alice
.
username
}
.atom`
,
UNSPECIFIED
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
'
application/atom+xml; charset=utf-8
'
);
// FIXME: misskey:gallery-post-idみたいなmetaタグの設定がない
// TODO profile.noCrawleの検証
// TODO twitter:creatorの検証
});
test
(
'
がGETできる。(存在しないIDでも。)
'
,
async
()
=>
await
ok
({
path
:
path
(
'
xxxxxxxxxx
'
),
}));
});
describe
(
'
/channels/:channel
'
,
()
=>
{
const
path
=
(
channel
:
string
):
string
=>
`/channels/
${
channel
}
`
;
test
(
'
はGETできる。
'
,
async
()
=>
{
const
res
=
await
ok
({
path
:
path
(
aliceChannel
.
id
),
});
test
(
'
JSON
'
,
async
()
=>
{
const
res
=
await
simpleGet
(
`/@
${
alice
.
username
}
.json`
,
UNSPECIFIED
);
assert
.
strictEqual
(
res
.
status
,
200
);
assert
.
strictEqual
(
res
.
type
,
'
application/json; charset=utf-8
'
);
// FIXME: misskey関連のmetaタグの設定がない
// TODO ogタグの検証
});
test
(
'
がGETできる。(存在しないIDでも。)
'
,
async
()
=>
await
ok
({
path
:
path
(
'
xxxxxxxxxx
'
),
}));
});
});
This diff is collapsed.
Click to expand it.
packages/backend/test/utils.ts
+
85
−
4
View file @
8571c692
...
...
@@ -3,6 +3,7 @@ import { isAbsolute, basename } from 'node:path';
import
WebSocket
from
'
ws
'
;
import
fetch
,
{
Blob
,
File
,
RequestInit
}
from
'
node-fetch
'
;
import
{
DataSource
}
from
'
typeorm
'
;
import
{
JSDOM
}
from
'
jsdom
'
;
import
{
entities
}
from
'
../src/postgres.js
'
;
import
{
loadConfig
}
from
'
../src/config.js
'
;
import
type
*
as
misskey
from
'
misskey-js
'
;
...
...
@@ -12,6 +13,10 @@ export { server as startServer } from '@/boot/common.js';
const
config
=
loadConfig
();
export
const
port
=
config
.
port
;
export
const
cookie
=
(
me
:
any
):
string
=>
{
return
`token=
${
me
.
token
}
;`
;
};
export
const
api
=
async
(
endpoint
:
string
,
params
:
any
,
me
?:
any
)
=>
{
const
normalized
=
endpoint
.
replace
(
/^
\/
/
,
''
);
return
await
request
(
`api/
${
normalized
}
`
,
params
,
me
);
...
...
@@ -71,6 +76,71 @@ export const react = async (user: any, note: any, reaction: string): Promise<any
},
user
);
};
export
const
page
=
async
(
user
:
any
,
page
:
any
=
{}):
Promise
<
any
>
=>
{
const
res
=
await
api
(
'
pages/create
'
,
{
alignCenter
:
false
,
content
:
[
{
id
:
'
2be9a64b-5ada-43a3-85f3-ec3429551ded
'
,
text
:
'
Hello World!
'
,
type
:
'
text
'
,
},
],
eyeCatchingImageId
:
null
,
font
:
'
sans-serif
'
,
hideTitleWhenPinned
:
false
,
name
:
'
1678594845072
'
,
script
:
''
,
summary
:
null
,
title
:
''
,
variables
:
[],
...
page
,
},
user
);
return
res
.
body
;
};
export
const
play
=
async
(
user
:
any
,
play
:
any
=
{}):
Promise
<
any
>
=>
{
const
res
=
await
api
(
'
flash/create
'
,
{
permissions
:
[],
script
:
'
test
'
,
summary
:
''
,
title
:
'
test
'
,
...
play
,
},
user
);
return
res
.
body
;
};
export
const
clip
=
async
(
user
:
any
,
clip
:
any
=
{}):
Promise
<
any
>
=>
{
const
res
=
await
api
(
'
clips/create
'
,
{
description
:
null
,
isPublic
:
true
,
name
:
'
test
'
,
...
clip
,
},
user
);
return
res
.
body
;
};
export
const
galleryPost
=
async
(
user
:
any
,
channel
:
any
=
{}):
Promise
<
any
>
=>
{
const
res
=
await
api
(
'
gallery/posts/create
'
,
{
description
:
null
,
fileIds
:
[],
isSensitive
:
false
,
title
:
'
test
'
,
...
channel
,
},
user
);
return
res
.
body
;
};
export
const
channel
=
async
(
user
:
any
,
channel
:
any
=
{}):
Promise
<
any
>
=>
{
const
res
=
await
api
(
'
channels/create
'
,
{
bannerId
:
null
,
description
:
null
,
name
:
'
test
'
,
...
channel
,
},
user
);
return
res
.
body
;
};
interface
UploadOptions
{
/** Optional, absolute path or relative from ./resources/ */
path
?:
string
|
URL
;
...
...
@@ -196,10 +266,17 @@ export const waitFire = async (user: any, channel: string, trgr: () => any, cond
});
};
export
const
simpleGet
=
async
(
path
:
string
,
accept
=
'
*/*
'
):
Promise
<
{
status
:
number
,
body
:
any
,
type
:
string
|
null
,
location
:
string
|
null
}
>
=>
{
export
type
SimpleGetResponse
=
{
status
:
number
,
body
:
any
|
JSDOM
|
null
,
type
:
string
|
null
,
location
:
string
|
null
};
export
const
simpleGet
=
async
(
path
:
string
,
accept
=
'
*/*
'
,
cookie
:
any
=
undefined
):
Promise
<
SimpleGetResponse
>
=>
{
const
res
=
await
relativeFetch
(
path
,
{
headers
:
{
Accept
:
accept
,
Cookie
:
cookie
,
},
redirect
:
'
manual
'
,
});
...
...
@@ -208,10 +285,14 @@ export const simpleGet = async (path: string, accept = '*/*'): Promise<{ status:
'
application/json; charset=utf-8
'
,
'
application/activity+json; charset=utf-8
'
,
];
const
htmlTypes
=
[
'
text/html; charset=utf-8
'
,
];
const
body
=
jsonTypes
.
includes
(
res
.
headers
.
get
(
'
content-type
'
)
??
''
)
?
await
res
.
json
()
:
null
;
const
body
=
jsonTypes
.
includes
(
res
.
headers
.
get
(
'
content-type
'
)
??
''
)
?
await
res
.
json
()
:
htmlTypes
.
includes
(
res
.
headers
.
get
(
'
content-type
'
)
??
''
)
?
new
JSDOM
(
await
res
.
text
())
:
null
;
return
{
status
:
res
.
status
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment