misskey/packages/backend/test/e2e/endpoints.ts

1133 lines
32 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
process.env.NODE_ENV = 'test';
import * as assert from 'assert';
// node-fetch only supports it's own Blob yet
// https://github.com/node-fetch/node-fetch/pull/1664
import { Blob } from 'node-fetch';
import { MiUser } from '@/models/_.js';
import { api, initTestDb, post, signup, simpleGet, uploadFile } from '../utils.js';
import type * as misskey from 'misskey-js';
describe('Endpoints', () => {
let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse;
let carol: misskey.entities.SignupResponse;
let dave: misskey.entities.SignupResponse;
beforeAll(async () => {
alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' });
carol = await signup({ username: 'carol' });
dave = await signup({ username: 'dave' });
}, 1000 * 60 * 2);
describe('signup', () => {
test('不正なユーザー名でアカウントが作成できない', async () => {
const res = await api('signup', {
username: 'test.',
password: 'test',
});
assert.strictEqual(res.status, 400);
});
test('空のパスワードでアカウントが作成できない', async () => {
const res = await api('signup', {
username: 'test',
password: '',
});
assert.strictEqual(res.status, 400);
});
test('正しくアカウントが作成できる', async () => {
const me = {
username: 'test1',
password: 'test1',
};
const res = await api('signup', me);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.username, me.username);
});
test('同じユーザー名のアカウントは作成できない', async () => {
const res = await api('signup', {
username: 'test1',
password: 'test1',
});
assert.strictEqual(res.status, 400);
});
});
describe('signin', () => {
test('間違ったパスワードでサインインできない', async () => {
const res = await api('signin', {
username: 'test1',
password: 'bar',
});
assert.strictEqual(res.status, 403);
});
test('クエリをインジェクションできない', async () => {
const res = await api('signin', {
username: 'test1',
// @ts-expect-error password must be string
password: {
$gt: '',
},
});
assert.strictEqual(res.status, 400);
});
test('正しい情報でサインインできる', async () => {
const res = await api('signin', {
username: 'test1',
password: 'test1',
});
assert.strictEqual(res.status, 200);
});
});
describe('i/update', () => {
test('アカウント設定を更新できる', async () => {
const myName = '大室櫻子';
const myLocation = '七森中';
const myBirthday = '2000-09-07';
const res = await api('i/update', {
name: myName,
location: myLocation,
birthday: myBirthday,
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.name, myName);
assert.strictEqual(res.body.location, myLocation);
assert.strictEqual(res.body.birthday, myBirthday);
});
test('名前を空白のみにした場合nullになる', async () => {
const res = await api('i/update', {
name: ' ',
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(res.body.name, null);
});
test('名前の前後に空白Unicodeのホワイトスペースを入れてもトリムされる', async () => {
const res = await api('i/update', {
name: ' あ い う \u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000',
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(res.body.name, 'あ い う');
});
test('誕生日の設定を削除できる', async () => {
await api('i/update', {
birthday: '2000-09-07',
}, alice);
const res = await api('i/update', {
birthday: null,
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.birthday, null);
});
test('不正な誕生日の形式で怒られる', async () => {
const res = await api('i/update', {
birthday: '2000/09/07',
}, alice);
assert.strictEqual(res.status, 400);
});
});
describe('users/show', () => {
test('ユーザーが取得できる', async () => {
const res = await api('users/show', {
userId: alice.id,
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.id, alice.id);
});
test('ユーザーが存在しなかったら怒る', async () => {
const res = await api('users/show', {
userId: '000000000000000000000000',
});
assert.strictEqual(res.status, 404);
});
test('間違ったIDで怒られる', async () => {
const res = await api('users/show', {
userId: 'kyoppie',
});
assert.strictEqual(res.status, 404);
});
});
describe('notes/show', () => {
test('投稿が取得できる', async () => {
const myPost = await post(alice, {
text: 'test',
});
const res = await api('notes/show', {
noteId: myPost.id,
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.id, myPost.id);
assert.strictEqual(res.body.text, myPost.text);
});
test('投稿が存在しなかったら怒る', async () => {
const res = await api('notes/show', {
noteId: '000000000000000000000000',
});
assert.strictEqual(res.status, 400);
});
test('間違ったIDで怒られる', async () => {
const res = await api('notes/show', {
noteId: 'kyoppie',
});
assert.strictEqual(res.status, 400);
});
});
describe('notes/reactions/create', () => {
test('リアクションできる', async () => {
const bobPost = await post(bob, { text: 'hi' });
const res = await api('notes/reactions/create', {
noteId: bobPost.id,
reaction: '🚀',
}, alice);
assert.strictEqual(res.status, 204);
const resNote = await api('notes/show', {
noteId: bobPost.id,
}, alice);
assert.strictEqual(resNote.status, 200);
assert.strictEqual(resNote.body.reactions['🚀'], 1);
});
test('自分の投稿にもリアクションできる', async () => {
const myPost = await post(alice, { text: 'hi' });
const res = await api('notes/reactions/create', {
noteId: myPost.id,
reaction: '🚀',
}, alice);
assert.strictEqual(res.status, 204);
});
test('二重にリアクションすると上書きされる', async () => {
const bobPost = await post(bob, { text: 'hi' });
await api('notes/reactions/create', {
noteId: bobPost.id,
reaction: '🥰',
}, alice);
const res = await api('notes/reactions/create', {
noteId: bobPost.id,
reaction: '🚀',
}, alice);
assert.strictEqual(res.status, 204);
const resNote = await api('notes/show', {
noteId: bobPost.id,
}, alice);
assert.strictEqual(resNote.status, 200);
assert.deepStrictEqual(resNote.body.reactions, { '🚀': 1 });
});
test('存在しない投稿にはリアクションできない', async () => {
const res = await api('notes/reactions/create', {
noteId: '000000000000000000000000',
reaction: '🚀',
}, alice);
assert.strictEqual(res.status, 400);
});
test('リノートにリアクションできない', async () => {
const bobNote = await post(bob, { text: 'hi' });
const bobRenote = await post(bob, { renoteId: bobNote.id });
const res = await api('notes/reactions/create', {
noteId: bobRenote.id,
reaction: '🚀',
}, alice);
assert.strictEqual(res.status, 400);
assert.strictEqual(res.body.error.code, 'CANNOT_REACT_TO_RENOTE');
});
test('引用にリアクションできる', async () => {
const bobNote = await post(bob, { text: 'hi' });
const bobRenote = await post(bob, { text: 'hi again', renoteId: bobNote.id });
const res = await api('notes/reactions/create', {
noteId: bobRenote.id,
reaction: '🚀',
}, alice);
assert.strictEqual(res.status, 204);
});
test('空文字列のリアクションは\u2764にフォールバックされる', async () => {
const bobNote = await post(bob, { text: 'hi' });
const res = await api('notes/reactions/create', {
noteId: bobNote.id,
reaction: '',
}, alice);
assert.strictEqual(res.status, 204);
const reaction = await api('notes/reactions', {
noteId: bobNote.id,
});
assert.strictEqual(reaction.body.length, 1);
assert.strictEqual(reaction.body[0].type, '\u2764');
});
test('絵文字ではない文字列のリアクションは\u2764にフォールバックされる', async () => {
const bobNote = await post(bob, { text: 'hi' });
const res = await api('notes/reactions/create', {
noteId: bobNote.id,
reaction: 'Hello!',
}, alice);
assert.strictEqual(res.status, 204);
const reaction = await api('notes/reactions', {
noteId: bobNote.id,
});
assert.strictEqual(reaction.body.length, 1);
assert.strictEqual(reaction.body[0].type, '\u2764');
});
test('空のパラメータで怒られる', async () => {
// @ts-expect-error param must not be empty
const res = await api('notes/reactions/create', {}, alice);
assert.strictEqual(res.status, 400);
});
test('間違ったIDで怒られる', async () => {
const res = await api('notes/reactions/create', {
noteId: 'kyoppie',
reaction: '🚀',
}, alice);
assert.strictEqual(res.status, 400);
});
});
describe('following/create', () => {
test('フォローできる', async () => {
const res = await api('following/create', {
userId: alice.id,
}, bob);
assert.strictEqual(res.status, 200);
const connection = await initTestDb(true);
const Users = connection.getRepository(MiUser);
const newBob = await Users.findOneByOrFail({ id: bob.id });
assert.strictEqual(newBob.followersCount, 0);
assert.strictEqual(newBob.followingCount, 1);
const newAlice = await Users.findOneByOrFail({ id: alice.id });
assert.strictEqual(newAlice.followersCount, 1);
assert.strictEqual(newAlice.followingCount, 0);
connection.destroy();
});
test('既にフォローしている場合は怒る', async () => {
const res = await api('following/create', {
userId: alice.id,
}, bob);
assert.strictEqual(res.status, 400);
});
test('存在しないユーザーはフォローできない', async () => {
const res = await api('following/create', {
userId: '000000000000000000000000',
}, alice);
assert.strictEqual(res.status, 400);
});
test('自分自身はフォローできない', async () => {
const res = await api('following/create', {
userId: alice.id,
}, alice);
assert.strictEqual(res.status, 400);
});
test('空のパラメータで怒られる', async () => {
// @ts-expect-error params must not be empty
const res = await api('following/create', {}, alice);
assert.strictEqual(res.status, 400);
});
test('間違ったIDで怒られる', async () => {
const res = await api('following/create', {
userId: 'foo',
}, alice);
assert.strictEqual(res.status, 400);
});
});
describe('following/delete', () => {
test('フォロー解除できる', async () => {
await api('following/create', {
userId: alice.id,
}, bob);
const res = await api('following/delete', {
userId: alice.id,
}, bob);
assert.strictEqual(res.status, 200);
const connection = await initTestDb(true);
const Users = connection.getRepository(MiUser);
const newBob = await Users.findOneByOrFail({ id: bob.id });
assert.strictEqual(newBob.followersCount, 0);
assert.strictEqual(newBob.followingCount, 0);
const newAlice = await Users.findOneByOrFail({ id: alice.id });
assert.strictEqual(newAlice.followersCount, 0);
assert.strictEqual(newAlice.followingCount, 0);
connection.destroy();
});
test('フォローしていない場合は怒る', async () => {
const res = await api('following/delete', {
userId: alice.id,
}, bob);
assert.strictEqual(res.status, 400);
});
test('存在しないユーザーはフォロー解除できない', async () => {
const res = await api('following/delete', {
userId: '000000000000000000000000',
}, alice);
assert.strictEqual(res.status, 400);
});
test('自分自身はフォロー解除できない', async () => {
const res = await api('following/delete', {
userId: alice.id,
}, alice);
assert.strictEqual(res.status, 400);
});
test('空のパラメータで怒られる', async () => {
// @ts-expect-error params must not be empty
const res = await api('following/delete', {}, alice);
assert.strictEqual(res.status, 400);
});
test('間違ったIDで怒られる', async () => {
const res = await api('following/delete', {
userId: 'kyoppie',
}, alice);
assert.strictEqual(res.status, 400);
});
});
describe('channels/search', () => {
test('空白検索で一覧を取得できる', async () => {
await api('channels/create', {
name: 'aaa',
description: 'bbb',
}, bob);
await api('channels/create', {
name: 'ccc1',
description: 'ddd1',
}, bob);
await api('channels/create', {
name: 'ccc2',
description: 'ddd2',
}, bob);
const res = await api('channels/search', {
query: '',
}, bob);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 3);
});
test('名前のみの検索で名前を検索できる', async () => {
const res = await api('channels/search', {
query: 'aaa',
type: 'nameOnly',
}, bob);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 1);
assert.strictEqual(res.body[0].name, 'aaa');
});
test('名前のみの検索で名前を複数検索できる', async () => {
const res = await api('channels/search', {
query: 'ccc',
type: 'nameOnly',
}, bob);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 2);
});
test('名前のみの検索で説明は検索できない', async () => {
const res = await api('channels/search', {
query: 'bbb',
type: 'nameOnly',
}, bob);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 0);
});
test('名前と説明の検索で名前を検索できる', async () => {
const res = await api('channels/search', {
query: 'ccc1',
}, bob);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 1);
assert.strictEqual(res.body[0].name, 'ccc1');
});
test('名前と説明での検索で説明を検索できる', async () => {
const res = await api('channels/search', {
query: 'ddd1',
}, bob);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 1);
assert.strictEqual(res.body[0].name, 'ccc1');
});
test('名前と説明の検索で名前を複数検索できる', async () => {
const res = await api('channels/search', {
query: 'ccc',
}, bob);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 2);
});
test('名前と説明での検索で説明を複数検索できる', async () => {
const res = await api('channels/search', {
query: 'ddd',
}, bob);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 2);
});
});
describe('drive', () => {
test('ドライブ情報を取得できる', async () => {
await uploadFile(alice, {
blob: new Blob([new Uint8Array(256)]),
});
await uploadFile(alice, {
blob: new Blob([new Uint8Array(512)]),
});
await uploadFile(alice, {
blob: new Blob([new Uint8Array(1024)]),
});
const res = await api('drive', {}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
expect(res.body).toHaveProperty('usage', 1792);
});
});
describe('drive/files/create', () => {
test('ファイルを作成できる', async () => {
const res = await uploadFile(alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body!.name, 'Lenna.jpg');
});
test('ファイルに名前を付けられる', async () => {
const res = await uploadFile(alice, { name: 'Belmond.jpg' });
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body!.name, 'Belmond.jpg');
});
test('ファイルに名前を付けられるが、拡張子は正しいものになる', async () => {
const res = await uploadFile(alice, { name: 'Belmond.png' });
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body!.name, 'Belmond.png.jpg');
});
test('ファイル無しで怒られる', async () => {
// @ts-expect-error params must not be empty
const res = await api('drive/files/create', {}, alice);
assert.strictEqual(res.status, 400);
});
test('SVGファイルを作成できる', async () => {
const res = await uploadFile(alice, { path: 'image.svg' });
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body!.name, 'image.svg');
assert.strictEqual(res.body!.type, 'image/svg+xml');
});
for (const type of ['webp', 'avif']) {
const mediaType = `image/${type}`;
const getWebpublicType = async (user: misskey.entities.SignupResponse, fileId: string): Promise<string> => {
// drive/files/create does not expose webpublicType directly, so get it by posting it
const res = await post(user, {
text: mediaType,
fileIds: [fileId],
});
const apRes = await simpleGet(`notes/${res.id}`, 'application/activity+json');
assert.strictEqual(apRes.status, 200);
assert.ok(Array.isArray(apRes.body.attachment));
return apRes.body.attachment[0].mediaType;
};
test(`透明な${type}ファイルを作成できる`, async () => {
const path = `with-alpha.${type}`;
const res = await uploadFile(alice, { path });
assert.strictEqual(res.status, 200);
assert.strictEqual(res.body!.name, path);
assert.strictEqual(res.body!.type, mediaType);
const webpublicType = await getWebpublicType(alice, res.body!.id);
assert.strictEqual(webpublicType, 'image/webp');
});
test(`透明じゃない${type}ファイルを作成できる`, async () => {
const path = `without-alpha.${type}`;
const res = await uploadFile(alice, { path });
assert.strictEqual(res.status, 200);
assert.strictEqual(res.body!.name, path);
assert.strictEqual(res.body!.type, mediaType);
const webpublicType = await getWebpublicType(alice, res.body!.id);
assert.strictEqual(webpublicType, 'image/webp');
});
}
});
describe('drive/files/update', () => {
test('名前を更新できる', async () => {
const file = (await uploadFile(alice)).body;
const newName = 'いちごパスタ.png';
const res = await api('drive/files/update', {
fileId: file!.id,
name: newName,
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.name, newName);
});
test('他人のファイルは更新できない', async () => {
const file = (await uploadFile(alice)).body;
const res = await api('drive/files/update', {
fileId: file!.id,
name: 'いちごパスタ.png',
}, bob);
assert.strictEqual(res.status, 400);
});
test('親フォルダを更新できる', async () => {
const file = (await uploadFile(alice)).body;
const folder = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const res = await api('drive/files/update', {
fileId: file!.id,
folderId: folder.id,
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.folderId, folder.id);
});
test('親フォルダを無しにできる', async () => {
const file = (await uploadFile(alice)).body;
const folder = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
await api('drive/files/update', {
fileId: file!.id,
folderId: folder.id,
}, alice);
const res = await api('drive/files/update', {
fileId: file!.id,
folderId: null,
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.folderId, null);
});
test('他人のフォルダには入れられない', async () => {
const file = (await uploadFile(alice)).body;
const folder = (await api('drive/folders/create', {
name: 'test',
}, bob)).body;
const res = await api('drive/files/update', {
fileId: file!.id,
folderId: folder.id,
}, alice);
assert.strictEqual(res.status, 400);
});
test('存在しないフォルダで怒られる', async () => {
const file = (await uploadFile(alice)).body;
const res = await api('drive/files/update', {
fileId: file!.id,
folderId: '000000000000000000000000',
}, alice);
assert.strictEqual(res.status, 400);
});
test('不正なフォルダIDで怒られる', async () => {
const file = (await uploadFile(alice)).body;
const res = await api('drive/files/update', {
fileId: file!.id,
folderId: 'foo',
}, alice);
assert.strictEqual(res.status, 400);
});
test('ファイルが存在しなかったら怒る', async () => {
const res = await api('drive/files/update', {
fileId: '000000000000000000000000',
name: 'いちごパスタ.png',
}, alice);
assert.strictEqual(res.status, 400);
});
test('不正なファイル名で怒られる', async () => {
const file = (await uploadFile(alice)).body;
const newName = '';
const res = await api('drive/files/update', {
fileId: file!.id,
name: newName,
}, alice);
assert.strictEqual(res.status, 400);
});
test('間違ったIDで怒られる', async () => {
const res = await api('drive/files/update', {
fileId: 'kyoppie',
name: 'いちごパスタ.png',
}, alice);
assert.strictEqual(res.status, 400);
});
});
describe('drive/folders/create', () => {
test('フォルダを作成できる', async () => {
const res = await api('drive/folders/create', {
name: 'test',
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.name, 'test');
});
});
describe('drive/folders/update', () => {
test('名前を更新できる', async () => {
const folder = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const res = await api('drive/folders/update', {
folderId: folder.id,
name: 'new name',
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.name, 'new name');
});
test('他人のフォルダを更新できない', async () => {
const folder = (await api('drive/folders/create', {
name: 'test',
}, bob)).body;
const res = await api('drive/folders/update', {
folderId: folder.id,
name: 'new name',
}, alice);
assert.strictEqual(res.status, 400);
});
test('親フォルダを更新できる', async () => {
const folder = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const parentFolder = (await api('drive/folders/create', {
name: 'parent',
}, alice)).body;
const res = await api('drive/folders/update', {
folderId: folder.id,
parentId: parentFolder.id,
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.parentId, parentFolder.id);
});
test('親フォルダを無しに更新できる', async () => {
const folder = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const parentFolder = (await api('drive/folders/create', {
name: 'parent',
}, alice)).body;
await api('drive/folders/update', {
folderId: folder.id,
parentId: parentFolder.id,
}, alice);
const res = await api('drive/folders/update', {
folderId: folder.id,
parentId: null,
}, alice);
assert.strictEqual(res.status, 200);
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
assert.strictEqual(res.body.parentId, null);
});
test('他人のフォルダを親フォルダに設定できない', async () => {
const folder = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const parentFolder = (await api('drive/folders/create', {
name: 'parent',
}, bob)).body;
const res = await api('drive/folders/update', {
folderId: folder.id,
parentId: parentFolder.id,
}, alice);
assert.strictEqual(res.status, 400);
});
test('フォルダが循環するような構造にできない', async () => {
const folder = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const parentFolder = (await api('drive/folders/create', {
name: 'parent',
}, alice)).body;
await api('drive/folders/update', {
folderId: parentFolder.id,
parentId: folder.id,
}, alice);
const res = await api('drive/folders/update', {
folderId: folder.id,
parentId: parentFolder.id,
}, alice);
assert.strictEqual(res.status, 400);
});
test('フォルダが循環するような構造にできない(再帰的)', async () => {
const folderA = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const folderB = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const folderC = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
await api('drive/folders/update', {
folderId: folderB.id,
parentId: folderA.id,
}, alice);
await api('drive/folders/update', {
folderId: folderC.id,
parentId: folderB.id,
}, alice);
const res = await api('drive/folders/update', {
folderId: folderA.id,
parentId: folderC.id,
}, alice);
assert.strictEqual(res.status, 400);
});
test('フォルダが循環するような構造にできない(自身)', async () => {
const folderA = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const res = await api('drive/folders/update', {
folderId: folderA.id,
parentId: folderA.id,
}, alice);
assert.strictEqual(res.status, 400);
});
test('存在しない親フォルダを設定できない', async () => {
const folder = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const res = await api('drive/folders/update', {
folderId: folder.id,
parentId: '000000000000000000000000',
}, alice);
assert.strictEqual(res.status, 400);
});
test('不正な親フォルダIDで怒られる', async () => {
const folder = (await api('drive/folders/create', {
name: 'test',
}, alice)).body;
const res = await api('drive/folders/update', {
folderId: folder.id,
parentId: 'foo',
}, alice);
assert.strictEqual(res.status, 400);
});
test('存在しないフォルダを更新できない', async () => {
const res = await api('drive/folders/update', {
folderId: '000000000000000000000000',
}, alice);
assert.strictEqual(res.status, 400);
});
test('不正なフォルダIDで怒られる', async () => {
const res = await api('drive/folders/update', {
folderId: 'foo',
}, alice);
assert.strictEqual(res.status, 400);
});
});
describe('notes/replies', () => {
test('自分に閲覧権限のない投稿は含まれない', async () => {
const alicePost = await post(alice, {
text: 'foo',
});
await post(bob, {
replyId: alicePost.id,
text: 'bar',
visibility: 'specified',
visibleUserIds: [alice.id],
});
const res = await api('notes/replies', {
noteId: alicePost.id,
}, carol);
assert.strictEqual(res.status, 200);
assert.strictEqual(Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 0);
});
});
describe('notes/timeline', () => {
test('フォロワー限定投稿が含まれる', async () => {
await api('following/create', {
userId: carol.id,
}, dave);
const carolPost = await post(carol, {
text: 'foo',
visibility: 'followers',
});
const res = await api('notes/timeline', {}, dave);
assert.strictEqual(res.status, 200);
assert.strictEqual(Array.isArray(res.body), true);
assert.strictEqual(res.body.length, 1);
assert.strictEqual(res.body[0].id, carolPost.id);
});
});
describe('URL preview', () => {
test('Error from summaly becomes HTTP 422', async () => {
const res = await simpleGet('/url?url=https://e:xample.com');
assert.strictEqual(res.status, 422);
assert.strictEqual(res.body.error.code, 'URL_PREVIEW_FAILED');
});
});
describe('パーソナルメモ機能のテスト', () => {
test('他者に関するメモを更新できる', async () => {
const memo = '10月まで低浮上とのこと。';
const res1 = await api('users/update-memo', {
memo,
userId: bob.id,
}, alice);
const res2 = await api('users/show', {
userId: bob.id,
}, alice);
assert.strictEqual(res1.status, 204);
assert.strictEqual(res2.body?.memo, memo);
});
test('自分に関するメモを更新できる', async () => {
const memo = 'チケットを月末までに買う。';
const res1 = await api('users/update-memo', {
memo,
userId: alice.id,
}, alice);
const res2 = await api('users/show', {
userId: alice.id,
}, alice);
assert.strictEqual(res1.status, 204);
assert.strictEqual(res2.body?.memo, memo);
});
test('メモを削除できる', async () => {
const memo = '10月まで低浮上とのこと。';
await api('users/update-memo', {
memo,
userId: bob.id,
}, alice);
await api('users/update-memo', {
memo: '',
userId: bob.id,
}, alice);
const res = await api('users/show', {
userId: bob.id,
}, alice);
// memoには常に文字列かnullが入っている(5cac151)
assert.strictEqual(res.body.memo, null);
});
test('メモは個人ごとに独立して保存される', async () => {
const memoAliceToBob = '10月まで低浮上とのこと。';
const memoCarolToBob = '例の件について今度問いただす。';
await Promise.all([
api('users/update-memo', {
memo: memoAliceToBob,
userId: bob.id,
}, alice),
api('users/update-memo', {
memo: memoCarolToBob,
userId: bob.id,
}, carol),
]);
const [resAlice, resCarol] = await Promise.all([
api('users/show', {
userId: bob.id,
}, alice),
api('users/show', {
userId: bob.id,
}, carol),
]);
assert.strictEqual(resAlice.body.memo, memoAliceToBob);
assert.strictEqual(resCarol.body.memo, memoCarolToBob);
});
});
});