Merge branch 'develop' into mkusername-empty
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { signup, request, post, startServer, shutdownServer } from '../utils.js';
|
||||
import { signup, api, post, startServer } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('API visibility', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
|
||||
beforeAll(async () => {
|
||||
p = await startServer();
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
describe('Note visibility', () => {
|
||||
@@ -60,7 +60,7 @@ describe('API visibility', () => {
|
||||
//#endregion
|
||||
|
||||
const show = async (noteId: any, by: any) => {
|
||||
return await request('/notes/show', {
|
||||
return await api('/notes/show', {
|
||||
noteId,
|
||||
}, by);
|
||||
};
|
||||
@@ -75,7 +75,7 @@ describe('API visibility', () => {
|
||||
target2 = await signup({ username: 'target2' });
|
||||
|
||||
// follow alice <= follower
|
||||
await request('/following/create', { userId: alice.id }, follower);
|
||||
await api('/following/create', { userId: alice.id }, follower);
|
||||
|
||||
// normal posts
|
||||
pub = await post(alice, { text: 'x', visibility: 'public' });
|
||||
@@ -413,21 +413,21 @@ describe('API visibility', () => {
|
||||
|
||||
//#region HTL
|
||||
test('[HTL] public-post が 自分が見れる', async () => {
|
||||
const res = await request('/notes/timeline', { limit: 100 }, alice);
|
||||
const res = await api('/notes/timeline', { limit: 100 }, alice);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const notes = res.body.filter((n: any) => n.id === pub.id);
|
||||
assert.strictEqual(notes[0].text, 'x');
|
||||
});
|
||||
|
||||
test('[HTL] public-post が 非フォロワーから見れない', async () => {
|
||||
const res = await request('/notes/timeline', { limit: 100 }, other);
|
||||
const res = await api('/notes/timeline', { limit: 100 }, other);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const notes = res.body.filter((n: any) => n.id === pub.id);
|
||||
assert.strictEqual(notes.length, 0);
|
||||
});
|
||||
|
||||
test('[HTL] followers-post が フォロワーから見れる', async () => {
|
||||
const res = await request('/notes/timeline', { limit: 100 }, follower);
|
||||
const res = await api('/notes/timeline', { limit: 100 }, follower);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const notes = res.body.filter((n: any) => n.id === fol.id);
|
||||
assert.strictEqual(notes[0].text, 'x');
|
||||
@@ -436,21 +436,21 @@ describe('API visibility', () => {
|
||||
|
||||
//#region RTL
|
||||
test('[replies] followers-reply が フォロワーから見れる', async () => {
|
||||
const res = await request('/notes/replies', { noteId: tgt.id, limit: 100 }, follower);
|
||||
const res = await api('/notes/replies', { noteId: tgt.id, limit: 100 }, follower);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const notes = res.body.filter((n: any) => n.id === folR.id);
|
||||
assert.strictEqual(notes[0].text, 'x');
|
||||
});
|
||||
|
||||
test('[replies] followers-reply が 非フォロワー (リプライ先ではない) から見れない', async () => {
|
||||
const res = await request('/notes/replies', { noteId: tgt.id, limit: 100 }, other);
|
||||
const res = await api('/notes/replies', { noteId: tgt.id, limit: 100 }, other);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const notes = res.body.filter((n: any) => n.id === folR.id);
|
||||
assert.strictEqual(notes.length, 0);
|
||||
});
|
||||
|
||||
test('[replies] followers-reply が 非フォロワー (リプライ先である) から見れる', async () => {
|
||||
const res = await request('/notes/replies', { noteId: tgt.id, limit: 100 }, target);
|
||||
const res = await api('/notes/replies', { noteId: tgt.id, limit: 100 }, target);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const notes = res.body.filter((n: any) => n.id === folR.id);
|
||||
assert.strictEqual(notes[0].text, 'x');
|
||||
@@ -459,14 +459,14 @@ describe('API visibility', () => {
|
||||
|
||||
//#region MTL
|
||||
test('[mentions] followers-reply が 非フォロワー (リプライ先である) から見れる', async () => {
|
||||
const res = await request('/notes/mentions', { limit: 100 }, target);
|
||||
const res = await api('/notes/mentions', { limit: 100 }, target);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const notes = res.body.filter((n: any) => n.id === folR.id);
|
||||
assert.strictEqual(notes[0].text, 'x');
|
||||
});
|
||||
|
||||
test('[mentions] followers-mention が 非フォロワー (メンション先である) から見れる', async () => {
|
||||
const res = await request('/notes/mentions', { limit: 100 }, target);
|
||||
const res = await api('/notes/mentions', { limit: 100 }, target);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const notes = res.body.filter((n: any) => n.id === folM.id);
|
||||
assert.strictEqual(notes[0].text, '@target x');
|
||||
@@ -474,4 +474,4 @@ describe('API visibility', () => {
|
||||
//#endregion
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
@@ -1,11 +1,11 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { async, signup, request, post, react, uploadFile, startServer, shutdownServer } from '../utils.js';
|
||||
import { signup, api, startServer } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('API', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
let alice: any;
|
||||
let bob: any;
|
||||
let carol: any;
|
||||
@@ -15,69 +15,69 @@ describe('API', () => {
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
carol = await signup({ username: 'carol' });
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
describe('General validation', () => {
|
||||
test('wrong type', async(async () => {
|
||||
const res = await request('/test', {
|
||||
test('wrong type', async () => {
|
||||
const res = await api('/test', {
|
||||
required: true,
|
||||
string: 42,
|
||||
});
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('missing require param', async(async () => {
|
||||
const res = await request('/test', {
|
||||
test('missing require param', async () => {
|
||||
const res = await api('/test', {
|
||||
string: 'a',
|
||||
});
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('invalid misskey:id (empty string)', async(async () => {
|
||||
const res = await request('/test', {
|
||||
test('invalid misskey:id (empty string)', async () => {
|
||||
const res = await api('/test', {
|
||||
required: true,
|
||||
id: '',
|
||||
});
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('valid misskey:id', async(async () => {
|
||||
const res = await request('/test', {
|
||||
test('valid misskey:id', async () => {
|
||||
const res = await api('/test', {
|
||||
required: true,
|
||||
id: '8wvhjghbxu',
|
||||
});
|
||||
assert.strictEqual(res.status, 200);
|
||||
}));
|
||||
});
|
||||
|
||||
test('default value', async(async () => {
|
||||
const res = await request('/test', {
|
||||
test('default value', async () => {
|
||||
const res = await api('/test', {
|
||||
required: true,
|
||||
string: 'a',
|
||||
});
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.body.default, 'hello');
|
||||
}));
|
||||
});
|
||||
|
||||
test('can set null even if it has default value', async(async () => {
|
||||
const res = await request('/test', {
|
||||
test('can set null even if it has default value', async () => {
|
||||
const res = await api('/test', {
|
||||
required: true,
|
||||
nullableDefault: null,
|
||||
});
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.body.nullableDefault, null);
|
||||
}));
|
||||
});
|
||||
|
||||
test('cannot set undefined if it has default value', async(async () => {
|
||||
const res = await request('/test', {
|
||||
test('cannot set undefined if it has default value', async () => {
|
||||
const res = await api('/test', {
|
||||
required: true,
|
||||
nullableDefault: undefined,
|
||||
});
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.body.nullableDefault, 'hello');
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
@@ -1,11 +1,11 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { signup, request, post, startServer, shutdownServer } from '../utils.js';
|
||||
import { signup, api, post, startServer } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('Block', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
|
||||
// alice blocks bob
|
||||
let alice: any;
|
||||
@@ -17,14 +17,14 @@ describe('Block', () => {
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
carol = await signup({ username: 'carol' });
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
test('Block作成', async () => {
|
||||
const res = await request('/blocking/create', {
|
||||
const res = await api('/blocking/create', {
|
||||
userId: bob.id,
|
||||
}, alice);
|
||||
|
||||
@@ -32,7 +32,7 @@ describe('Block', () => {
|
||||
});
|
||||
|
||||
test('ブロックされているユーザーをフォローできない', async () => {
|
||||
const res = await request('/following/create', { userId: alice.id }, bob);
|
||||
const res = await api('/following/create', { userId: alice.id }, bob);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
assert.strictEqual(res.body.error.id, 'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0');
|
||||
@@ -41,7 +41,7 @@ describe('Block', () => {
|
||||
test('ブロックされているユーザーにリアクションできない', async () => {
|
||||
const note = await post(alice, { text: 'hello' });
|
||||
|
||||
const res = await request('/notes/reactions/create', { noteId: note.id, reaction: '👍' }, bob);
|
||||
const res = await api('/notes/reactions/create', { noteId: note.id, reaction: '👍' }, bob);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
assert.strictEqual(res.body.error.id, '20ef5475-9f38-4e4c-bd33-de6d979498ec');
|
||||
@@ -50,7 +50,7 @@ describe('Block', () => {
|
||||
test('ブロックされているユーザーに返信できない', async () => {
|
||||
const note = await post(alice, { text: 'hello' });
|
||||
|
||||
const res = await request('/notes/create', { replyId: note.id, text: 'yo' }, bob);
|
||||
const res = await api('/notes/create', { replyId: note.id, text: 'yo' }, bob);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
assert.strictEqual(res.body.error.id, 'b390d7e1-8a5e-46ed-b625-06271cafd3d3');
|
||||
@@ -59,7 +59,7 @@ describe('Block', () => {
|
||||
test('ブロックされているユーザーのノートをRenoteできない', async () => {
|
||||
const note = await post(alice, { text: 'hello' });
|
||||
|
||||
const res = await request('/notes/create', { renoteId: note.id, text: 'yo' }, bob);
|
||||
const res = await api('/notes/create', { renoteId: note.id, text: 'yo' }, bob);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
assert.strictEqual(res.body.error.id, 'b390d7e1-8a5e-46ed-b625-06271cafd3d3');
|
||||
@@ -74,7 +74,7 @@ describe('Block', () => {
|
||||
const bobNote = await post(bob);
|
||||
const carolNote = await post(carol);
|
||||
|
||||
const res = await request('/notes/local-timeline', {}, bob);
|
||||
const res = await api('/notes/local-timeline', {}, bob);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
@@ -1,29 +1,35 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import * as openapi from '@redocly/openapi-core';
|
||||
import { startServer, signup, post, request, simpleGet, port, shutdownServer, api } from '../utils.js';
|
||||
// node-fetch only supports it's own Blob yet
|
||||
// https://github.com/node-fetch/node-fetch/pull/1664
|
||||
import { Blob } from 'node-fetch';
|
||||
import { startServer, signup, post, api, uploadFile } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('Endpoints', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
|
||||
let alice: any;
|
||||
let bob: any;
|
||||
let carol: any;
|
||||
let dave: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
}, 1000 * 30);
|
||||
carol = await signup({ username: 'carol' });
|
||||
dave = await signup({ username: 'dave' });
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
describe('signup', () => {
|
||||
test('不正なユーザー名でアカウントが作成できない', async () => {
|
||||
const res = await request('api/signup', {
|
||||
const res = await api('signup', {
|
||||
username: 'test.',
|
||||
password: 'test',
|
||||
});
|
||||
@@ -31,7 +37,7 @@ describe('Endpoints', () => {
|
||||
});
|
||||
|
||||
test('空のパスワードでアカウントが作成できない', async () => {
|
||||
const res = await request('api/signup', {
|
||||
const res = await api('signup', {
|
||||
username: 'test',
|
||||
password: '',
|
||||
});
|
||||
@@ -44,7 +50,7 @@ describe('Endpoints', () => {
|
||||
password: 'test1',
|
||||
};
|
||||
|
||||
const res = await request('api/signup', me);
|
||||
const res = await api('signup', me);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
@@ -52,7 +58,7 @@ describe('Endpoints', () => {
|
||||
});
|
||||
|
||||
test('同じユーザー名のアカウントは作成できない', async () => {
|
||||
const res = await request('api/signup', {
|
||||
const res = await api('signup', {
|
||||
username: 'test1',
|
||||
password: 'test1',
|
||||
});
|
||||
@@ -63,7 +69,7 @@ describe('Endpoints', () => {
|
||||
|
||||
describe('signin', () => {
|
||||
test('間違ったパスワードでサインインできない', async () => {
|
||||
const res = await request('api/signin', {
|
||||
const res = await api('signin', {
|
||||
username: 'test1',
|
||||
password: 'bar',
|
||||
});
|
||||
@@ -72,7 +78,7 @@ describe('Endpoints', () => {
|
||||
});
|
||||
|
||||
test('クエリをインジェクションできない', async () => {
|
||||
const res = await request('api/signin', {
|
||||
const res = await api('signin', {
|
||||
username: 'test1',
|
||||
password: {
|
||||
$gt: '',
|
||||
@@ -83,7 +89,7 @@ describe('Endpoints', () => {
|
||||
});
|
||||
|
||||
test('正しい情報でサインインできる', async () => {
|
||||
const res = await request('api/signin', {
|
||||
const res = await api('signin', {
|
||||
username: 'test1',
|
||||
password: 'test1',
|
||||
});
|
||||
@@ -111,11 +117,12 @@ describe('Endpoints', () => {
|
||||
assert.strictEqual(res.body.birthday, myBirthday);
|
||||
});
|
||||
|
||||
test('名前を空白にできない', async () => {
|
||||
test('名前を空白にできる', async () => {
|
||||
const res = await api('/i/update', {
|
||||
name: ' ',
|
||||
}, alice);
|
||||
assert.strictEqual(res.status, 400);
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.body.name, ' ');
|
||||
});
|
||||
|
||||
test('誕生日の設定を削除できる', async () => {
|
||||
@@ -201,7 +208,6 @@ describe('Endpoints', () => {
|
||||
test('リアクションできる', async () => {
|
||||
const bobPost = await post(bob);
|
||||
|
||||
const alice = await signup({ username: 'alice' });
|
||||
const res = await api('/notes/reactions/create', {
|
||||
noteId: bobPost.id,
|
||||
reaction: '🚀',
|
||||
@@ -214,7 +220,7 @@ describe('Endpoints', () => {
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(resNote.status, 200);
|
||||
assert.strictEqual(resNote.body.reactions['🚀'], [alice.id]);
|
||||
assert.strictEqual(resNote.body.reactions['🚀'], 1);
|
||||
});
|
||||
|
||||
test('自分の投稿にもリアクションできる', async () => {
|
||||
@@ -228,7 +234,7 @@ describe('Endpoints', () => {
|
||||
assert.strictEqual(res.status, 204);
|
||||
});
|
||||
|
||||
test('二重にリアクションできない', async () => {
|
||||
test('二重にリアクションすると上書きされる', async () => {
|
||||
const bobPost = await post(bob);
|
||||
|
||||
await api('/notes/reactions/create', {
|
||||
@@ -241,7 +247,14 @@ describe('Endpoints', () => {
|
||||
reaction: '🚀',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
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 () => {
|
||||
@@ -369,57 +382,22 @@ describe('Endpoints', () => {
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
describe('/i', () => {
|
||||
test('', async () => {
|
||||
});
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
/*
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { async, signup, request, post, react, uploadFile, startServer, shutdownServer } from './utils.js';
|
||||
|
||||
describe('API: Endpoints', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let alice: any;
|
||||
let bob: any;
|
||||
let carol: any;
|
||||
|
||||
before(async () => {
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
carol = await signup({ username: 'carol' });
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await shutdownServer(p);
|
||||
});
|
||||
|
||||
describe('drive', () => {
|
||||
test('ドライブ情報を取得できる', async () => {
|
||||
await uploadFile({
|
||||
userId: alice.id,
|
||||
size: 256
|
||||
await uploadFile(alice, {
|
||||
blob: new Blob([new Uint8Array(256)]),
|
||||
});
|
||||
await uploadFile({
|
||||
userId: alice.id,
|
||||
size: 512
|
||||
await uploadFile(alice, {
|
||||
blob: new Blob([new Uint8Array(512)]),
|
||||
});
|
||||
await uploadFile({
|
||||
userId: alice.id,
|
||||
size: 1024
|
||||
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).have.property('usage').eql(1792);
|
||||
}));
|
||||
expect(res.body).toHaveProperty('usage', 1792);
|
||||
});
|
||||
});
|
||||
|
||||
describe('drive/files/create', () => {
|
||||
@@ -428,397 +406,400 @@ describe('API: Endpoints', () => {
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
assert.strictEqual(res.body.name, 'Lenna.png');
|
||||
}));
|
||||
assert.strictEqual(res.body.name, 'Lenna.jpg');
|
||||
});
|
||||
|
||||
test('ファイルに名前を付けられる', async () => {
|
||||
const res = await assert.request(server)
|
||||
.post('/drive/files/create')
|
||||
.field('i', alice.token)
|
||||
.field('name', 'Belmond.png')
|
||||
.attach('file', fs.readFileSync(__dirname + '/resources/Lenna.png'), 'Lenna.png');
|
||||
const res = await uploadFile(alice, { name: 'Belmond.jpg' });
|
||||
|
||||
expect(res).have.status(200);
|
||||
expect(res.body).be.a('object');
|
||||
expect(res.body).have.property('name').eql('Belmond.png');
|
||||
}));
|
||||
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 () => {
|
||||
const res = await api('/drive/files/create', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('SVGファイルを作成できる', async () => {
|
||||
const res = await uploadFile(alice, __dirname + '/resources/image.svg');
|
||||
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');
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('drive/files/update', () => {
|
||||
test('名前を更新できる', async () => {
|
||||
const file = await uploadFile(alice);
|
||||
const file = (await uploadFile(alice)).body;
|
||||
const newName = 'いちごパスタ.png';
|
||||
|
||||
const res = await api('/drive/files/update', {
|
||||
fileId: file.id,
|
||||
name: newName
|
||||
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(bob);
|
||||
const file = (await uploadFile(alice)).body;
|
||||
|
||||
const res = await api('/drive/files/update', {
|
||||
fileId: file.id,
|
||||
name: 'いちごパスタ.png'
|
||||
}, alice);
|
||||
name: 'いちごパスタ.png',
|
||||
}, bob);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('親フォルダを更新できる', async () => {
|
||||
const file = await uploadFile(alice);
|
||||
const file = (await uploadFile(alice)).body;
|
||||
const folder = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
|
||||
const res = await api('/drive/files/update', {
|
||||
fileId: file.id,
|
||||
folderId: folder.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);
|
||||
const file = (await uploadFile(alice)).body;
|
||||
|
||||
const folder = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
|
||||
await api('/drive/files/update', {
|
||||
fileId: file.id,
|
||||
folderId: folder.id
|
||||
folderId: folder.id,
|
||||
}, alice);
|
||||
|
||||
const res = await api('/drive/files/update', {
|
||||
fileId: file.id,
|
||||
folderId: null
|
||||
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);
|
||||
const file = (await uploadFile(alice)).body;
|
||||
const folder = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, bob)).body;
|
||||
|
||||
const res = await api('/drive/files/update', {
|
||||
fileId: file.id,
|
||||
folderId: folder.id
|
||||
folderId: folder.id,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('存在しないフォルダで怒られる', async () => {
|
||||
const file = await uploadFile(alice);
|
||||
const file = (await uploadFile(alice)).body;
|
||||
|
||||
const res = await api('/drive/files/update', {
|
||||
fileId: file.id,
|
||||
folderId: '000000000000000000000000'
|
||||
folderId: '000000000000000000000000',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('不正なフォルダIDで怒られる', async () => {
|
||||
const file = await uploadFile(alice);
|
||||
const file = (await uploadFile(alice)).body;
|
||||
|
||||
const res = await api('/drive/files/update', {
|
||||
fileId: file.id,
|
||||
folderId: 'foo'
|
||||
folderId: 'foo',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('ファイルが存在しなかったら怒る', async () => {
|
||||
const res = await api('/drive/files/update', {
|
||||
fileId: '000000000000000000000000',
|
||||
name: 'いちごパスタ.png'
|
||||
name: 'いちごパスタ.png',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('間違ったIDで怒られる', async () => {
|
||||
const res = await api('/drive/files/update', {
|
||||
fileId: 'kyoppie',
|
||||
name: 'いちごパスタ.png'
|
||||
name: 'いちごパスタ.png',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('drive/folders/create', () => {
|
||||
test('フォルダを作成できる', async () => {
|
||||
const res = await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
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'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folder.id,
|
||||
name: 'new name'
|
||||
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'
|
||||
name: 'test',
|
||||
}, bob)).body;
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folder.id,
|
||||
name: 'new name'
|
||||
name: 'new name',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('親フォルダを更新できる', async () => {
|
||||
const folder = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
const parentFolder = (await api('/drive/folders/create', {
|
||||
name: 'parent'
|
||||
name: 'parent',
|
||||
}, alice)).body;
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folder.id,
|
||||
parentId: parentFolder.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'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
const parentFolder = (await api('/drive/folders/create', {
|
||||
name: 'parent'
|
||||
name: 'parent',
|
||||
}, alice)).body;
|
||||
await api('/drive/folders/update', {
|
||||
folderId: folder.id,
|
||||
parentId: parentFolder.id
|
||||
parentId: parentFolder.id,
|
||||
}, alice);
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folder.id,
|
||||
parentId: null
|
||||
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'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
const parentFolder = (await api('/drive/folders/create', {
|
||||
name: 'parent'
|
||||
name: 'parent',
|
||||
}, bob)).body;
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folder.id,
|
||||
parentId: parentFolder.id
|
||||
parentId: parentFolder.id,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('フォルダが循環するような構造にできない', async () => {
|
||||
const folder = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
const parentFolder = (await api('/drive/folders/create', {
|
||||
name: 'parent'
|
||||
name: 'parent',
|
||||
}, alice)).body;
|
||||
await api('/drive/folders/update', {
|
||||
folderId: parentFolder.id,
|
||||
parentId: folder.id
|
||||
parentId: folder.id,
|
||||
}, alice);
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folder.id,
|
||||
parentId: parentFolder.id
|
||||
parentId: parentFolder.id,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('フォルダが循環するような構造にできない(再帰的)', async () => {
|
||||
const folderA = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
const folderB = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
const folderC = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
await api('/drive/folders/update', {
|
||||
folderId: folderB.id,
|
||||
parentId: folderA.id
|
||||
parentId: folderA.id,
|
||||
}, alice);
|
||||
await api('/drive/folders/update', {
|
||||
folderId: folderC.id,
|
||||
parentId: folderB.id
|
||||
parentId: folderB.id,
|
||||
}, alice);
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folderA.id,
|
||||
parentId: folderC.id
|
||||
parentId: folderC.id,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('フォルダが循環するような構造にできない(自身)', async () => {
|
||||
const folderA = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folderA.id,
|
||||
parentId: folderA.id
|
||||
parentId: folderA.id,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('存在しない親フォルダを設定できない', async () => {
|
||||
const folder = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folder.id,
|
||||
parentId: '000000000000000000000000'
|
||||
parentId: '000000000000000000000000',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('不正な親フォルダIDで怒られる', async () => {
|
||||
const folder = (await api('/drive/folders/create', {
|
||||
name: 'test'
|
||||
name: 'test',
|
||||
}, alice)).body;
|
||||
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: folder.id,
|
||||
parentId: 'foo'
|
||||
parentId: 'foo',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('存在しないフォルダを更新できない', async () => {
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: '000000000000000000000000'
|
||||
folderId: '000000000000000000000000',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
|
||||
test('不正なフォルダIDで怒られる', async () => {
|
||||
const res = await api('/drive/folders/update', {
|
||||
folderId: 'foo'
|
||||
folderId: 'foo',
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 400);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('notes/replies', () => {
|
||||
test('自分に閲覧権限のない投稿は含まれない', async () => {
|
||||
const alicePost = await post(alice, {
|
||||
text: 'foo'
|
||||
text: 'foo',
|
||||
});
|
||||
|
||||
await post(bob, {
|
||||
replyId: alicePost.id,
|
||||
text: 'bar',
|
||||
visibility: 'specified',
|
||||
visibleUserIds: [alice.id]
|
||||
visibleUserIds: [alice.id],
|
||||
});
|
||||
|
||||
const res = await api('/notes/replies', {
|
||||
noteId: alicePost.id
|
||||
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: alice.id
|
||||
}, bob);
|
||||
userId: carol.id,
|
||||
}, dave);
|
||||
|
||||
const alicePost = await post(alice, {
|
||||
const carolPost = await post(carol, {
|
||||
text: 'foo',
|
||||
visibility: 'followers'
|
||||
visibility: 'followers',
|
||||
});
|
||||
|
||||
const res = await api('/notes/timeline', {}, bob);
|
||||
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, alicePost.id);
|
||||
}));
|
||||
assert.strictEqual(res.body[0].id, carolPost.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
*/
|
@@ -1,9 +1,8 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import * as openapi from '@redocly/openapi-core';
|
||||
import { startServer, signup, post, request, simpleGet, port, shutdownServer } from '../utils.js';
|
||||
import { startServer, signup, post, api, simpleGet } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
// Request Accept
|
||||
const ONLY_AP = 'application/activity+json';
|
||||
@@ -13,11 +12,10 @@ const UNSPECIFIED = '*/*';
|
||||
|
||||
// Response Content-Type
|
||||
const AP = 'application/activity+json; charset=utf-8';
|
||||
const JSON = 'application/json; charset=utf-8';
|
||||
const HTML = 'text/html; charset=utf-8';
|
||||
|
||||
describe('Fetch resource', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
|
||||
let alice: any;
|
||||
let alicesPost: any;
|
||||
@@ -28,15 +26,15 @@ describe('Fetch resource', () => {
|
||||
alicesPost = await post(alice, {
|
||||
text: 'test',
|
||||
});
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
describe('Common', () => {
|
||||
test('meta', async () => {
|
||||
const res = await request('/meta', {
|
||||
const res = await api('/meta', {
|
||||
});
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
@@ -54,36 +52,26 @@ describe('Fetch resource', () => {
|
||||
assert.strictEqual(res.type, HTML);
|
||||
});
|
||||
|
||||
test('GET api-doc', async () => {
|
||||
test('GET api-doc (廃止)', async () => {
|
||||
const res = await simpleGet('/api-doc');
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.type, HTML);
|
||||
assert.strictEqual(res.status, 404);
|
||||
});
|
||||
|
||||
test('GET api.json', async () => {
|
||||
test('GET api.json (廃止)', async () => {
|
||||
const res = await simpleGet('/api.json');
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.type, JSON);
|
||||
assert.strictEqual(res.status, 404);
|
||||
});
|
||||
|
||||
test('Validate api.json', async () => {
|
||||
const config = await openapi.loadConfig();
|
||||
const result = await openapi.bundle({
|
||||
config,
|
||||
ref: `http://localhost:${port}/api.json`,
|
||||
});
|
||||
|
||||
for (const problem of result.problems) {
|
||||
console.log(`${problem.message} - ${problem.location[0]?.pointer}`);
|
||||
}
|
||||
|
||||
assert.strictEqual(result.problems.length, 0);
|
||||
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');
|
||||
});
|
||||
|
||||
test('GET favicon.ico', async () => {
|
||||
const res = await simpleGet('/favicon.ico');
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.type, 'image/x-icon');
|
||||
assert.strictEqual(res.type, 'image/vnd.microsoft.icon');
|
||||
});
|
||||
|
||||
test('GET apple-touch-icon.png', async () => {
|
@@ -1,36 +1,34 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { signup, request, post, react, connectStream, startServer, shutdownServer, simpleGet } from '../utils.js';
|
||||
import { signup, api, startServer, simpleGet } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('FF visibility', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
|
||||
let alice: any;
|
||||
let bob: any;
|
||||
let carol: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
p = await startServer();
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
carol = await signup({ username: 'carol' });
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
test('ffVisibility が public なユーザーのフォロー/フォロワーを誰でも見れる', async () => {
|
||||
await request('/i/update', {
|
||||
await api('/i/update', {
|
||||
ffVisibility: 'public',
|
||||
}, alice);
|
||||
|
||||
const followingRes = await request('/users/following', {
|
||||
const followingRes = await api('/users/following', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
const followersRes = await request('/users/followers', {
|
||||
const followersRes = await api('/users/followers', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
|
||||
@@ -41,14 +39,14 @@ describe('FF visibility', () => {
|
||||
});
|
||||
|
||||
test('ffVisibility が followers なユーザーのフォロー/フォロワーを自分で見れる', async () => {
|
||||
await request('/i/update', {
|
||||
await api('/i/update', {
|
||||
ffVisibility: 'followers',
|
||||
}, alice);
|
||||
|
||||
const followingRes = await request('/users/following', {
|
||||
const followingRes = await api('/users/following', {
|
||||
userId: alice.id,
|
||||
}, alice);
|
||||
const followersRes = await request('/users/followers', {
|
||||
const followersRes = await api('/users/followers', {
|
||||
userId: alice.id,
|
||||
}, alice);
|
||||
|
||||
@@ -59,14 +57,14 @@ describe('FF visibility', () => {
|
||||
});
|
||||
|
||||
test('ffVisibility が followers なユーザーのフォロー/フォロワーを非フォロワーが見れない', async () => {
|
||||
await request('/i/update', {
|
||||
await api('/i/update', {
|
||||
ffVisibility: 'followers',
|
||||
}, alice);
|
||||
|
||||
const followingRes = await request('/users/following', {
|
||||
const followingRes = await api('/users/following', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
const followersRes = await request('/users/followers', {
|
||||
const followersRes = await api('/users/followers', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
|
||||
@@ -75,18 +73,18 @@ describe('FF visibility', () => {
|
||||
});
|
||||
|
||||
test('ffVisibility が followers なユーザーのフォロー/フォロワーをフォロワーが見れる', async () => {
|
||||
await request('/i/update', {
|
||||
await api('/i/update', {
|
||||
ffVisibility: 'followers',
|
||||
}, alice);
|
||||
|
||||
await request('/following/create', {
|
||||
await api('/following/create', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
|
||||
const followingRes = await request('/users/following', {
|
||||
const followingRes = await api('/users/following', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
const followersRes = await request('/users/followers', {
|
||||
const followersRes = await api('/users/followers', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
|
||||
@@ -97,14 +95,14 @@ describe('FF visibility', () => {
|
||||
});
|
||||
|
||||
test('ffVisibility が private なユーザーのフォロー/フォロワーを自分で見れる', async () => {
|
||||
await request('/i/update', {
|
||||
await api('/i/update', {
|
||||
ffVisibility: 'private',
|
||||
}, alice);
|
||||
|
||||
const followingRes = await request('/users/following', {
|
||||
const followingRes = await api('/users/following', {
|
||||
userId: alice.id,
|
||||
}, alice);
|
||||
const followersRes = await request('/users/followers', {
|
||||
const followersRes = await api('/users/followers', {
|
||||
userId: alice.id,
|
||||
}, alice);
|
||||
|
||||
@@ -115,14 +113,14 @@ describe('FF visibility', () => {
|
||||
});
|
||||
|
||||
test('ffVisibility が private なユーザーのフォロー/フォロワーを他人が見れない', async () => {
|
||||
await request('/i/update', {
|
||||
await api('/i/update', {
|
||||
ffVisibility: 'private',
|
||||
}, alice);
|
||||
|
||||
const followingRes = await request('/users/following', {
|
||||
const followingRes = await api('/users/following', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
const followersRes = await request('/users/followers', {
|
||||
const followersRes = await api('/users/followers', {
|
||||
userId: alice.id,
|
||||
}, bob);
|
||||
|
||||
@@ -133,7 +131,7 @@ describe('FF visibility', () => {
|
||||
describe('AP', () => {
|
||||
test('ffVisibility が public 以外ならばAPからは取得できない', async () => {
|
||||
{
|
||||
await request('/i/update', {
|
||||
await api('/i/update', {
|
||||
ffVisibility: 'public',
|
||||
}, alice);
|
||||
|
||||
@@ -143,22 +141,22 @@ describe('FF visibility', () => {
|
||||
assert.strictEqual(followersRes.status, 200);
|
||||
}
|
||||
{
|
||||
await request('/i/update', {
|
||||
await api('/i/update', {
|
||||
ffVisibility: 'followers',
|
||||
}, alice);
|
||||
|
||||
const followingRes = await simpleGet(`/users/${alice.id}/following`, 'application/activity+json').catch(res => ({ status: res.statusCode }));
|
||||
const followersRes = await simpleGet(`/users/${alice.id}/followers`, 'application/activity+json').catch(res => ({ status: res.statusCode }));
|
||||
const followingRes = await simpleGet(`/users/${alice.id}/following`, 'application/activity+json');
|
||||
const followersRes = await simpleGet(`/users/${alice.id}/followers`, 'application/activity+json');
|
||||
assert.strictEqual(followingRes.status, 403);
|
||||
assert.strictEqual(followersRes.status, 403);
|
||||
}
|
||||
{
|
||||
await request('/i/update', {
|
||||
await api('/i/update', {
|
||||
ffVisibility: 'private',
|
||||
}, alice);
|
||||
|
||||
const followingRes = await simpleGet(`/users/${alice.id}/following`, 'application/activity+json').catch(res => ({ status: res.statusCode }));
|
||||
const followersRes = await simpleGet(`/users/${alice.id}/followers`, 'application/activity+json').catch(res => ({ status: res.statusCode }));
|
||||
const followingRes = await simpleGet(`/users/${alice.id}/following`, 'application/activity+json');
|
||||
const followersRes = await simpleGet(`/users/${alice.id}/followers`, 'application/activity+json');
|
||||
assert.strictEqual(followingRes.status, 403);
|
||||
assert.strictEqual(followersRes.status, 403);
|
||||
}
|
@@ -1,11 +1,11 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { signup, request, post, react, startServer, shutdownServer, waitFire } from '../utils.js';
|
||||
import { signup, api, post, react, startServer, waitFire } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('Mute', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
|
||||
// alice mutes carol
|
||||
let alice: any;
|
||||
@@ -17,14 +17,14 @@ describe('Mute', () => {
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
carol = await signup({ username: 'carol' });
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
test('ミュート作成', async () => {
|
||||
const res = await request('/mute/create', {
|
||||
const res = await api('/mute/create', {
|
||||
userId: carol.id,
|
||||
}, alice);
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('Mute', () => {
|
||||
const bobNote = await post(bob, { text: '@alice hi' });
|
||||
const carolNote = await post(carol, { text: '@alice hi' });
|
||||
|
||||
const res = await request('/notes/mentions', {}, alice);
|
||||
const res = await api('/notes/mentions', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
@@ -45,11 +45,11 @@ describe('Mute', () => {
|
||||
|
||||
test('ミュートしているユーザーからメンションされても、hasUnreadMentions が true にならない', async () => {
|
||||
// 状態リセット
|
||||
await request('/i/read-all-unread-notes', {}, alice);
|
||||
await api('/i/read-all-unread-notes', {}, alice);
|
||||
|
||||
await post(carol, { text: '@alice hi' });
|
||||
|
||||
const res = await request('/i', {}, alice);
|
||||
const res = await api('/i', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.body.hasUnreadMentions, false);
|
||||
@@ -57,7 +57,7 @@ describe('Mute', () => {
|
||||
|
||||
test('ミュートしているユーザーからメンションされても、ストリームに unreadMention イベントが流れてこない', async () => {
|
||||
// 状態リセット
|
||||
await request('/i/read-all-unread-notes', {}, alice);
|
||||
await api('/i/read-all-unread-notes', {}, alice);
|
||||
|
||||
const fired = await waitFire(alice, 'main', () => post(carol, { text: '@alice hi' }), msg => msg.type === 'unreadMention');
|
||||
|
||||
@@ -66,8 +66,8 @@ describe('Mute', () => {
|
||||
|
||||
test('ミュートしているユーザーからメンションされても、ストリームに unreadNotification イベントが流れてこない', async () => {
|
||||
// 状態リセット
|
||||
await request('/i/read-all-unread-notes', {}, alice);
|
||||
await request('/notifications/mark-all-as-read', {}, alice);
|
||||
await api('/i/read-all-unread-notes', {}, alice);
|
||||
await api('/notifications/mark-all-as-read', {}, alice);
|
||||
|
||||
const fired = await waitFire(alice, 'main', () => post(carol, { text: '@alice hi' }), msg => msg.type === 'unreadNotification');
|
||||
|
||||
@@ -80,7 +80,7 @@ describe('Mute', () => {
|
||||
const bobNote = await post(bob);
|
||||
const carolNote = await post(carol);
|
||||
|
||||
const res = await request('/notes/local-timeline', {}, alice);
|
||||
const res = await api('/notes/local-timeline', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
@@ -96,7 +96,7 @@ describe('Mute', () => {
|
||||
renoteId: carolNote.id,
|
||||
});
|
||||
|
||||
const res = await request('/notes/local-timeline', {}, alice);
|
||||
const res = await api('/notes/local-timeline', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
@@ -112,7 +112,7 @@ describe('Mute', () => {
|
||||
await react(bob, aliceNote, 'like');
|
||||
await react(carol, aliceNote, 'like');
|
||||
|
||||
const res = await request('/i/notifications', {}, alice);
|
||||
const res = await api('/i/notifications', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
@@ -1,12 +1,12 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { Note } from '../../src/models/entities/note.js';
|
||||
import { async, signup, request, post, uploadUrl, startServer, shutdownServer, initTestDb, api } from '../utils.js';
|
||||
import { Note } from '@/models/entities/Note.js';
|
||||
import { signup, post, uploadUrl, startServer, initTestDb, api, uploadFile } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('Note', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
let Notes: any;
|
||||
|
||||
let alice: any;
|
||||
@@ -18,10 +18,10 @@ describe('Note', () => {
|
||||
Notes = connection.getRepository(Note);
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
test('投稿できる', async () => {
|
||||
@@ -29,7 +29,7 @@ describe('Note', () => {
|
||||
text: 'test',
|
||||
};
|
||||
|
||||
const res = await request('/notes/create', post, alice);
|
||||
const res = await api('/notes/create', post, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
@@ -39,7 +39,7 @@ describe('Note', () => {
|
||||
test('ファイルを添付できる', async () => {
|
||||
const file = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg');
|
||||
|
||||
const res = await request('/notes/create', {
|
||||
const res = await api('/notes/create', {
|
||||
fileIds: [file.id],
|
||||
}, alice);
|
||||
|
||||
@@ -48,37 +48,37 @@ describe('Note', () => {
|
||||
assert.deepStrictEqual(res.body.createdNote.fileIds, [file.id]);
|
||||
}, 1000 * 10);
|
||||
|
||||
test('他人のファイルは無視', async () => {
|
||||
test('他人のファイルで怒られる', async () => {
|
||||
const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg');
|
||||
|
||||
const res = await request('/notes/create', {
|
||||
const res = await api('/notes/create', {
|
||||
text: 'test',
|
||||
fileIds: [file.id],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
assert.deepStrictEqual(res.body.createdNote.fileIds, []);
|
||||
assert.strictEqual(res.status, 400);
|
||||
assert.strictEqual(res.body.error.code, 'NO_SUCH_FILE');
|
||||
assert.strictEqual(res.body.error.id, 'b6992544-63e7-67f0-fa7f-32444b1b5306');
|
||||
}, 1000 * 10);
|
||||
|
||||
test('存在しないファイルは無視', async () => {
|
||||
const res = await request('/notes/create', {
|
||||
test('存在しないファイルで怒られる', async () => {
|
||||
const res = await api('/notes/create', {
|
||||
text: 'test',
|
||||
fileIds: ['000000000000000000000000'],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
assert.deepStrictEqual(res.body.createdNote.fileIds, []);
|
||||
assert.strictEqual(res.status, 400);
|
||||
assert.strictEqual(res.body.error.code, 'NO_SUCH_FILE');
|
||||
assert.strictEqual(res.body.error.id, 'b6992544-63e7-67f0-fa7f-32444b1b5306');
|
||||
});
|
||||
|
||||
test('不正なファイルIDは無視', async () => {
|
||||
const res = await request('/notes/create', {
|
||||
test('不正なファイルIDで怒られる', async () => {
|
||||
const res = await api('/notes/create', {
|
||||
fileIds: ['kyoppie'],
|
||||
}, alice);
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
assert.deepStrictEqual(res.body.createdNote.fileIds, []);
|
||||
assert.strictEqual(res.status, 400);
|
||||
assert.strictEqual(res.body.error.code, 'NO_SUCH_FILE');
|
||||
assert.strictEqual(res.body.error.id, 'b6992544-63e7-67f0-fa7f-32444b1b5306');
|
||||
});
|
||||
|
||||
test('返信できる', async () => {
|
||||
@@ -91,7 +91,7 @@ describe('Note', () => {
|
||||
replyId: bobPost.id,
|
||||
};
|
||||
|
||||
const res = await request('/notes/create', alicePost, alice);
|
||||
const res = await api('/notes/create', alicePost, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
@@ -109,7 +109,7 @@ describe('Note', () => {
|
||||
renoteId: bobPost.id,
|
||||
};
|
||||
|
||||
const res = await request('/notes/create', alicePost, alice);
|
||||
const res = await api('/notes/create', alicePost, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
@@ -127,7 +127,7 @@ describe('Note', () => {
|
||||
renoteId: bobPost.id,
|
||||
};
|
||||
|
||||
const res = await request('/notes/create', alicePost, alice);
|
||||
const res = await api('/notes/create', alicePost, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
@@ -140,7 +140,7 @@ describe('Note', () => {
|
||||
const post = {
|
||||
text: '!'.repeat(3000),
|
||||
};
|
||||
const res = await request('/notes/create', post, alice);
|
||||
const res = await api('/notes/create', post, alice);
|
||||
assert.strictEqual(res.status, 200);
|
||||
});
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('Note', () => {
|
||||
const post = {
|
||||
text: '!'.repeat(3001),
|
||||
};
|
||||
const res = await request('/notes/create', post, alice);
|
||||
const res = await api('/notes/create', post, alice);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
@@ -157,7 +157,7 @@ describe('Note', () => {
|
||||
text: 'test',
|
||||
replyId: '000000000000000000000000',
|
||||
};
|
||||
const res = await request('/notes/create', post, alice);
|
||||
const res = await api('/notes/create', post, alice);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
@@ -165,7 +165,7 @@ describe('Note', () => {
|
||||
const post = {
|
||||
renoteId: '000000000000000000000000',
|
||||
};
|
||||
const res = await request('/notes/create', post, alice);
|
||||
const res = await api('/notes/create', post, alice);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
@@ -174,7 +174,7 @@ describe('Note', () => {
|
||||
text: 'test',
|
||||
replyId: 'foo',
|
||||
};
|
||||
const res = await request('/notes/create', post, alice);
|
||||
const res = await api('/notes/create', post, alice);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
@@ -182,7 +182,7 @@ describe('Note', () => {
|
||||
const post = {
|
||||
renoteId: 'foo',
|
||||
};
|
||||
const res = await request('/notes/create', post, alice);
|
||||
const res = await api('/notes/create', post, alice);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
@@ -191,7 +191,7 @@ describe('Note', () => {
|
||||
text: '@ghost yo',
|
||||
};
|
||||
|
||||
const res = await request('/notes/create', post, alice);
|
||||
const res = await api('/notes/create', post, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
@@ -203,7 +203,7 @@ describe('Note', () => {
|
||||
text: '@bob @bob @bob yo',
|
||||
};
|
||||
|
||||
const res = await request('/notes/create', post, alice);
|
||||
const res = await api('/notes/create', post, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
@@ -213,9 +213,125 @@ describe('Note', () => {
|
||||
assert.deepStrictEqual(noteDoc.mentions, [bob.id]);
|
||||
});
|
||||
|
||||
describe('添付ファイル情報', () => {
|
||||
test('ファイルを添付した場合、投稿成功時にファイル情報入りのレスポンスが帰ってくる', async () => {
|
||||
const file = await uploadFile(alice);
|
||||
const res = await api('/notes/create', {
|
||||
fileIds: [file.body.id],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true);
|
||||
assert.strictEqual(res.body.createdNote.files.length, 1);
|
||||
assert.strictEqual(res.body.createdNote.files[0].id, file.body.id);
|
||||
});
|
||||
|
||||
test('ファイルを添付した場合、タイムラインでファイル情報入りのレスポンスが帰ってくる', async () => {
|
||||
const file = await uploadFile(alice);
|
||||
const createdNote = await api('/notes/create', {
|
||||
fileIds: [file.body.id],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(createdNote.status, 200);
|
||||
|
||||
const res = await api('/notes', {
|
||||
withFiles: true,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
const myNote = res.body.find((note: { id: string; files: { id: string }[] }) => note.id === createdNote.body.createdNote.id);
|
||||
assert.notEqual(myNote, null);
|
||||
assert.strictEqual(myNote.files.length, 1);
|
||||
assert.strictEqual(myNote.files[0].id, file.body.id);
|
||||
});
|
||||
|
||||
test('ファイルが添付されたノートをリノートした場合、タイムラインでファイル情報入りのレスポンスが帰ってくる', async () => {
|
||||
const file = await uploadFile(alice);
|
||||
const createdNote = await api('/notes/create', {
|
||||
fileIds: [file.body.id],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(createdNote.status, 200);
|
||||
|
||||
const renoted = await api('/notes/create', {
|
||||
renoteId: createdNote.body.createdNote.id,
|
||||
}, alice);
|
||||
assert.strictEqual(renoted.status, 200);
|
||||
|
||||
const res = await api('/notes', {
|
||||
renote: true,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
const myNote = res.body.find((note: { id: string }) => note.id === renoted.body.createdNote.id);
|
||||
assert.notEqual(myNote, null);
|
||||
assert.strictEqual(myNote.renote.files.length, 1);
|
||||
assert.strictEqual(myNote.renote.files[0].id, file.body.id);
|
||||
});
|
||||
|
||||
test('ファイルが添付されたノートに返信した場合、タイムラインでファイル情報入りのレスポンスが帰ってくる', async () => {
|
||||
const file = await uploadFile(alice);
|
||||
const createdNote = await api('/notes/create', {
|
||||
fileIds: [file.body.id],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(createdNote.status, 200);
|
||||
|
||||
const reply = await api('/notes/create', {
|
||||
replyId: createdNote.body.createdNote.id,
|
||||
text: 'this is reply',
|
||||
}, alice);
|
||||
assert.strictEqual(reply.status, 200);
|
||||
|
||||
const res = await api('/notes', {
|
||||
reply: true,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
const myNote = res.body.find((note: { id: string }) => note.id === reply.body.createdNote.id);
|
||||
assert.notEqual(myNote, null);
|
||||
assert.strictEqual(myNote.reply.files.length, 1);
|
||||
assert.strictEqual(myNote.reply.files[0].id, file.body.id);
|
||||
});
|
||||
|
||||
test('ファイルが添付されたノートへの返信をリノートした場合、タイムラインでファイル情報入りのレスポンスが帰ってくる', async () => {
|
||||
const file = await uploadFile(alice);
|
||||
const createdNote = await api('/notes/create', {
|
||||
fileIds: [file.body.id],
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(createdNote.status, 200);
|
||||
|
||||
const reply = await api('/notes/create', {
|
||||
replyId: createdNote.body.createdNote.id,
|
||||
text: 'this is reply',
|
||||
}, alice);
|
||||
assert.strictEqual(reply.status, 200);
|
||||
|
||||
const renoted = await api('/notes/create', {
|
||||
renoteId: reply.body.createdNote.id,
|
||||
}, alice);
|
||||
assert.strictEqual(renoted.status, 200);
|
||||
|
||||
const res = await api('/notes', {
|
||||
renote: true,
|
||||
}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
const myNote = res.body.find((note: { id: string }) => note.id === renoted.body.createdNote.id);
|
||||
assert.notEqual(myNote, null);
|
||||
assert.strictEqual(myNote.renote.reply.files.length, 1);
|
||||
assert.strictEqual(myNote.renote.reply.files[0].id, file.body.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('notes/create', () => {
|
||||
test('投票を添付できる', async () => {
|
||||
const res = await request('/notes/create', {
|
||||
const res = await api('/notes/create', {
|
||||
text: 'test',
|
||||
poll: {
|
||||
choices: ['foo', 'bar'],
|
||||
@@ -228,14 +344,14 @@ describe('Note', () => {
|
||||
});
|
||||
|
||||
test('投票の選択肢が無くて怒られる', async () => {
|
||||
const res = await request('/notes/create', {
|
||||
const res = await api('/notes/create', {
|
||||
poll: {},
|
||||
}, alice);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
test('投票の選択肢が無くて怒られる (空の配列)', async () => {
|
||||
const res = await request('/notes/create', {
|
||||
const res = await api('/notes/create', {
|
||||
poll: {
|
||||
choices: [],
|
||||
},
|
||||
@@ -244,7 +360,7 @@ describe('Note', () => {
|
||||
});
|
||||
|
||||
test('投票の選択肢が1つで怒られる', async () => {
|
||||
const res = await request('/notes/create', {
|
||||
const res = await api('/notes/create', {
|
||||
poll: {
|
||||
choices: ['Strawberry Pasta'],
|
||||
},
|
||||
@@ -253,14 +369,14 @@ describe('Note', () => {
|
||||
});
|
||||
|
||||
test('投票できる', async () => {
|
||||
const { body } = await request('/notes/create', {
|
||||
const { body } = await api('/notes/create', {
|
||||
text: 'test',
|
||||
poll: {
|
||||
choices: ['sakura', 'izumi', 'ako'],
|
||||
},
|
||||
}, alice);
|
||||
|
||||
const res = await request('/notes/polls/vote', {
|
||||
const res = await api('/notes/polls/vote', {
|
||||
noteId: body.createdNote.id,
|
||||
choice: 1,
|
||||
}, alice);
|
||||
@@ -269,19 +385,19 @@ describe('Note', () => {
|
||||
});
|
||||
|
||||
test('複数投票できない', async () => {
|
||||
const { body } = await request('/notes/create', {
|
||||
const { body } = await api('/notes/create', {
|
||||
text: 'test',
|
||||
poll: {
|
||||
choices: ['sakura', 'izumi', 'ako'],
|
||||
},
|
||||
}, alice);
|
||||
|
||||
await request('/notes/polls/vote', {
|
||||
await api('/notes/polls/vote', {
|
||||
noteId: body.createdNote.id,
|
||||
choice: 0,
|
||||
}, alice);
|
||||
|
||||
const res = await request('/notes/polls/vote', {
|
||||
const res = await api('/notes/polls/vote', {
|
||||
noteId: body.createdNote.id,
|
||||
choice: 2,
|
||||
}, alice);
|
||||
@@ -290,7 +406,7 @@ describe('Note', () => {
|
||||
});
|
||||
|
||||
test('許可されている場合は複数投票できる', async () => {
|
||||
const { body } = await request('/notes/create', {
|
||||
const { body } = await api('/notes/create', {
|
||||
text: 'test',
|
||||
poll: {
|
||||
choices: ['sakura', 'izumi', 'ako'],
|
||||
@@ -298,17 +414,17 @@ describe('Note', () => {
|
||||
},
|
||||
}, alice);
|
||||
|
||||
await request('/notes/polls/vote', {
|
||||
await api('/notes/polls/vote', {
|
||||
noteId: body.createdNote.id,
|
||||
choice: 0,
|
||||
}, alice);
|
||||
|
||||
await request('/notes/polls/vote', {
|
||||
await api('/notes/polls/vote', {
|
||||
noteId: body.createdNote.id,
|
||||
choice: 1,
|
||||
}, alice);
|
||||
|
||||
const res = await request('/notes/polls/vote', {
|
||||
const res = await api('/notes/polls/vote', {
|
||||
noteId: body.createdNote.id,
|
||||
choice: 2,
|
||||
}, alice);
|
||||
@@ -317,7 +433,7 @@ describe('Note', () => {
|
||||
});
|
||||
|
||||
test('締め切られている場合は投票できない', async () => {
|
||||
const { body } = await request('/notes/create', {
|
||||
const { body } = await api('/notes/create', {
|
||||
text: 'test',
|
||||
poll: {
|
||||
choices: ['sakura', 'izumi', 'ako'],
|
||||
@@ -327,7 +443,7 @@ describe('Note', () => {
|
||||
|
||||
await new Promise(x => setTimeout(x, 2));
|
||||
|
||||
const res = await request('/notes/polls/vote', {
|
||||
const res = await api('/notes/polls/vote', {
|
||||
noteId: body.createdNote.id,
|
||||
choice: 1,
|
||||
}, alice);
|
@@ -1,12 +1,12 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { Following } from '../../src/models/entities/following.js';
|
||||
import { connectStream, signup, api, post, startServer, shutdownServer, initTestDb, waitFire } from '../utils.js';
|
||||
import { Following } from '@/models/entities/Following.js';
|
||||
import { connectStream, signup, api, post, startServer, initTestDb, waitFire } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('Streaming', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
let Followings: any;
|
||||
|
||||
const follow = async (follower: any, followee: any) => {
|
||||
@@ -71,10 +71,10 @@ describe('Streaming', () => {
|
||||
listId: list.id,
|
||||
userId: kyoko.id,
|
||||
}, chitose);
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
describe('Events', () => {
|
||||
@@ -404,43 +404,45 @@ describe('Streaming', () => {
|
||||
});
|
||||
}));
|
||||
|
||||
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);
|
||||
}));
|
||||
// XXX: QueryFailedError: duplicate key value violates unique constraint "IDX_347fec870eafea7b26c8a73bac"
|
||||
|
||||
// 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);
|
||||
// }));
|
||||
|
||||
test('指定したハッシュタグの投稿が流れる (OR)', () => new Promise<void>(async done => {
|
||||
let fooCount = 0;
|
@@ -1,11 +1,11 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { signup, request, post, react, connectStream, startServer, shutdownServer } from '../utils.js';
|
||||
import { signup, api, post, connectStream, startServer } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('Note thread mute', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
|
||||
let alice: any;
|
||||
let bob: any;
|
||||
@@ -16,22 +16,22 @@ describe('Note thread mute', () => {
|
||||
alice = await signup({ username: 'alice' });
|
||||
bob = await signup({ username: 'bob' });
|
||||
carol = await signup({ username: 'carol' });
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async () => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
test('notes/mentions にミュートしているスレッドの投稿が含まれない', async () => {
|
||||
const bobNote = await post(bob, { text: '@alice @carol root note' });
|
||||
const aliceReply = await post(alice, { replyId: bobNote.id, text: '@bob @carol child note' });
|
||||
|
||||
await request('/notes/thread-muting/create', { noteId: bobNote.id }, alice);
|
||||
await api('/notes/thread-muting/create', { noteId: bobNote.id }, alice);
|
||||
|
||||
const carolReply = await post(carol, { replyId: bobNote.id, text: '@bob @alice child note' });
|
||||
const carolReplyWithoutMention = await post(carol, { replyId: aliceReply.id, text: 'child note' });
|
||||
|
||||
const res = await request('/notes/mentions', {}, alice);
|
||||
const res = await api('/notes/mentions', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
||||
@@ -42,27 +42,27 @@ describe('Note thread mute', () => {
|
||||
|
||||
test('ミュートしているスレッドからメンションされても、hasUnreadMentions が true にならない', async () => {
|
||||
// 状態リセット
|
||||
await request('/i/read-all-unread-notes', {}, alice);
|
||||
await api('/i/read-all-unread-notes', {}, alice);
|
||||
|
||||
const bobNote = await post(bob, { text: '@alice @carol root note' });
|
||||
|
||||
await request('/notes/thread-muting/create', { noteId: bobNote.id }, alice);
|
||||
await api('/notes/thread-muting/create', { noteId: bobNote.id }, alice);
|
||||
|
||||
const carolReply = await post(carol, { replyId: bobNote.id, text: '@bob @alice child note' });
|
||||
|
||||
const res = await request('/i', {}, alice);
|
||||
const res = await api('/i', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.body.hasUnreadMentions, false);
|
||||
});
|
||||
|
||||
test('ミュートしているスレッドからメンションされても、ストリームに unreadMention イベントが流れてこない', () => new Promise(async done => {
|
||||
test('ミュートしているスレッドからメンションされても、ストリームに unreadMention イベントが流れてこない', () => new Promise<void>(async done => {
|
||||
// 状態リセット
|
||||
await request('/i/read-all-unread-notes', {}, alice);
|
||||
await api('/i/read-all-unread-notes', {}, alice);
|
||||
|
||||
const bobNote = await post(bob, { text: '@alice @carol root note' });
|
||||
|
||||
await request('/notes/thread-muting/create', { noteId: bobNote.id }, alice);
|
||||
await api('/notes/thread-muting/create', { noteId: bobNote.id }, alice);
|
||||
|
||||
let fired = false;
|
||||
|
||||
@@ -86,12 +86,12 @@ describe('Note thread mute', () => {
|
||||
const bobNote = await post(bob, { text: '@alice @carol root note' });
|
||||
const aliceReply = await post(alice, { replyId: bobNote.id, text: '@bob @carol child note' });
|
||||
|
||||
await request('/notes/thread-muting/create', { noteId: bobNote.id }, alice);
|
||||
await api('/notes/thread-muting/create', { noteId: bobNote.id }, alice);
|
||||
|
||||
const carolReply = await post(carol, { replyId: bobNote.id, text: '@bob @alice child note' });
|
||||
const carolReplyWithoutMention = await post(carol, { replyId: aliceReply.id, text: 'child note' });
|
||||
|
||||
const res = await request('/i/notifications', {}, alice);
|
||||
const res = await api('/i/notifications', {}, alice);
|
||||
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(Array.isArray(res.body), true);
|
@@ -1,11 +1,11 @@
|
||||
process.env.NODE_ENV = 'test';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as childProcess from 'child_process';
|
||||
import { signup, request, post, uploadUrl, startServer, shutdownServer } from '../utils.js';
|
||||
import { signup, api, post, uploadUrl, startServer } from '../utils.js';
|
||||
import type { INestApplicationContext } from '@nestjs/common';
|
||||
|
||||
describe('users/notes', () => {
|
||||
let p: childProcess.ChildProcess;
|
||||
let p: INestApplicationContext;
|
||||
|
||||
let alice: any;
|
||||
let jpgNote: any;
|
||||
@@ -26,14 +26,14 @@ describe('users/notes', () => {
|
||||
jpgPngNote = await post(alice, {
|
||||
fileIds: [jpg.id, png.id],
|
||||
});
|
||||
}, 1000 * 30);
|
||||
}, 1000 * 60 * 2);
|
||||
|
||||
afterAll(async() => {
|
||||
await shutdownServer(p);
|
||||
await p.close();
|
||||
});
|
||||
|
||||
test('ファイルタイプ指定 (jpg)', async () => {
|
||||
const res = await request('/users/notes', {
|
||||
const res = await api('/users/notes', {
|
||||
userId: alice.id,
|
||||
fileType: ['image/jpeg'],
|
||||
}, alice);
|
||||
@@ -46,7 +46,7 @@ describe('users/notes', () => {
|
||||
});
|
||||
|
||||
test('ファイルタイプ指定 (jpg or png)', async () => {
|
||||
const res = await request('/users/notes', {
|
||||
const res = await api('/users/notes', {
|
||||
userId: alice.id,
|
||||
fileType: ['image/jpeg', 'image/png'],
|
||||
}, alice);
|
11
packages/backend/test/prelude/get-api-validator.ts
Normal file
11
packages/backend/test/prelude/get-api-validator.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Schema } from '@/misc/schema';
|
||||
import Ajv from 'ajv';
|
||||
|
||||
export const getValidator = (paramDef: Schema) => {
|
||||
const ajv = new Ajv({
|
||||
useDefaults: true,
|
||||
});
|
||||
ajv.addFormat('misskey:id', /^[a-zA-Z0-9]+$/);
|
||||
|
||||
return ajv.compile(paramDef);
|
||||
}
|
7
packages/backend/test/resources/misskey.svg
Normal file
7
packages/backend/test/resources/misskey.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 9.2 KiB |
@@ -33,11 +33,12 @@
|
||||
"lib": [
|
||||
"esnext"
|
||||
],
|
||||
"types": ["jest"]
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"include": [
|
||||
"./**/*.ts",
|
||||
"../src/**/*.test.ts",
|
||||
"../src/@types/**/*.ts",
|
||||
]
|
||||
}
|
||||
|
@@ -3,16 +3,18 @@ process.env.NODE_ENV = 'test';
|
||||
import { jest } from '@jest/globals';
|
||||
import { ModuleMocker } from 'jest-mock';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { DataSource } from 'typeorm';
|
||||
import * as lolex from '@sinonjs/fake-timers';
|
||||
import rndstr from 'rndstr';
|
||||
import { GlobalModule } from '@/GlobalModule.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import type { Role, RolesRepository, RoleAssignmentsRepository, UsersRepository, User } from '@/models/index.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { CoreModule } from '@/core/CoreModule.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { genAid } from '@/misc/id/aid.js';
|
||||
import { UserCacheService } from '@/core/UserCacheService.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
import { sleep } from '../utils.js';
|
||||
import type { TestingModule } from '@nestjs/testing';
|
||||
import type { MockFunctionMetadata } from 'jest-mock';
|
||||
|
||||
@@ -25,6 +27,7 @@ describe('RoleService', () => {
|
||||
let rolesRepository: RolesRepository;
|
||||
let roleAssignmentsRepository: RoleAssignmentsRepository;
|
||||
let metaService: jest.Mocked<MetaService>;
|
||||
let clock: lolex.InstalledClock;
|
||||
|
||||
function createUser(data: Partial<User> = {}) {
|
||||
const un = rndstr('a-z0-9', 16);
|
||||
@@ -50,16 +53,12 @@ describe('RoleService', () => {
|
||||
.then(x => rolesRepository.findOneByOrFail(x.identifiers[0]));
|
||||
}
|
||||
|
||||
async function assign(roleId: Role['id'], userId: User['id']) {
|
||||
await roleAssignmentsRepository.insert({
|
||||
id: genAid(new Date()),
|
||||
createdAt: new Date(),
|
||||
roleId,
|
||||
userId,
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
clock = lolex.install({
|
||||
now: new Date(),
|
||||
shouldClearNativeTimers: true,
|
||||
});
|
||||
|
||||
app = await Test.createTestingModule({
|
||||
imports: [
|
||||
GlobalModule,
|
||||
@@ -67,6 +66,8 @@ describe('RoleService', () => {
|
||||
providers: [
|
||||
RoleService,
|
||||
UserCacheService,
|
||||
IdService,
|
||||
GlobalEventService,
|
||||
],
|
||||
})
|
||||
.useMocker((token) => {
|
||||
@@ -92,12 +93,15 @@ describe('RoleService', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
clock.uninstall();
|
||||
|
||||
await Promise.all([
|
||||
app.get(DI.metasRepository).delete({}),
|
||||
usersRepository.delete({}),
|
||||
rolesRepository.delete({}),
|
||||
roleAssignmentsRepository.delete({}),
|
||||
]);
|
||||
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -115,7 +119,7 @@ describe('RoleService', () => {
|
||||
expect(result.canManageCustomEmojis).toBe(false);
|
||||
});
|
||||
|
||||
test('instance default policies 2', async () => {
|
||||
test('instance default policies 2', async () => {
|
||||
const user = await createUser();
|
||||
metaService.fetch.mockResolvedValue({
|
||||
policies: {
|
||||
@@ -128,7 +132,7 @@ describe('RoleService', () => {
|
||||
expect(result.canManageCustomEmojis).toBe(true);
|
||||
});
|
||||
|
||||
test('with role', async () => {
|
||||
test('with role', async () => {
|
||||
const user = await createUser();
|
||||
const role = await createRole({
|
||||
name: 'a',
|
||||
@@ -140,7 +144,7 @@ describe('RoleService', () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
await assign(role.id, user.id);
|
||||
await roleService.assign(user.id, role.id);
|
||||
metaService.fetch.mockResolvedValue({
|
||||
policies: {
|
||||
canManageCustomEmojis: false,
|
||||
@@ -152,7 +156,7 @@ describe('RoleService', () => {
|
||||
expect(result.canManageCustomEmojis).toBe(true);
|
||||
});
|
||||
|
||||
test('priority', async () => {
|
||||
test('priority', async () => {
|
||||
const user = await createUser();
|
||||
const role1 = await createRole({
|
||||
name: 'role1',
|
||||
@@ -174,8 +178,8 @@ describe('RoleService', () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
await assign(role1.id, user.id);
|
||||
await assign(role2.id, user.id);
|
||||
await roleService.assign(user.id, role1.id);
|
||||
await roleService.assign(user.id, role2.id);
|
||||
metaService.fetch.mockResolvedValue({
|
||||
policies: {
|
||||
driveCapacityMb: 50,
|
||||
@@ -187,7 +191,7 @@ describe('RoleService', () => {
|
||||
expect(result.driveCapacityMb).toBe(100);
|
||||
});
|
||||
|
||||
test('conditional role', async () => {
|
||||
test('conditional role', async () => {
|
||||
const user1 = await createUser({
|
||||
createdAt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 365)),
|
||||
});
|
||||
@@ -228,5 +232,42 @@ describe('RoleService', () => {
|
||||
expect(user1Policies.canManageCustomEmojis).toBe(false);
|
||||
expect(user2Policies.canManageCustomEmojis).toBe(true);
|
||||
});
|
||||
|
||||
test('expired role', async () => {
|
||||
const user = await createUser();
|
||||
const role = await createRole({
|
||||
name: 'a',
|
||||
policies: {
|
||||
canManageCustomEmojis: {
|
||||
useDefault: false,
|
||||
priority: 0,
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
await roleService.assign(user.id, role.id, new Date(Date.now() + (1000 * 60 * 60 * 24)));
|
||||
metaService.fetch.mockResolvedValue({
|
||||
policies: {
|
||||
canManageCustomEmojis: false,
|
||||
},
|
||||
} as any);
|
||||
|
||||
const result = await roleService.getUserPolicies(user.id);
|
||||
expect(result.canManageCustomEmojis).toBe(true);
|
||||
|
||||
clock.tick('25:00:00');
|
||||
|
||||
const resultAfter25h = await roleService.getUserPolicies(user.id);
|
||||
expect(resultAfter25h.canManageCustomEmojis).toBe(false);
|
||||
|
||||
await roleService.assign(user.id, role.id);
|
||||
|
||||
// ストリーミング経由で反映されるまでちょっと待つ
|
||||
clock.uninstall();
|
||||
await sleep(100);
|
||||
|
||||
const resultAfter25hAgain = await roleService.getUserPolicies(user.id);
|
||||
expect(resultAfter25hAgain.canManageCustomEmojis).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
42
packages/backend/test/unit/misc/others.ts
Normal file
42
packages/backend/test/unit/misc/others.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { describe, test, expect } from '@jest/globals';
|
||||
import { contentDisposition } from '@/misc/content-disposition.js';
|
||||
import { correctFilename } from '@/misc/correct-filename.js';
|
||||
|
||||
describe('misc:content-disposition', () => {
|
||||
test('inline', () => {
|
||||
expect(contentDisposition('inline', 'foo bar')).toBe('inline; filename=\"foo_bar\"; filename*=UTF-8\'\'foo%20bar');
|
||||
});
|
||||
test('attachment', () => {
|
||||
expect(contentDisposition('attachment', 'foo bar')).toBe('attachment; filename=\"foo_bar\"; filename*=UTF-8\'\'foo%20bar');
|
||||
});
|
||||
test('non ascii', () => {
|
||||
expect(contentDisposition('attachment', 'ファイル名')).toBe('attachment; filename=\"_____\"; filename*=UTF-8\'\'%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D');
|
||||
});
|
||||
});
|
||||
|
||||
describe('misc:correct-filename', () => {
|
||||
test('simple', () => {
|
||||
expect(correctFilename('filename', 'jpg')).toBe('filename.jpg');
|
||||
});
|
||||
test('with same ext', () => {
|
||||
expect(correctFilename('filename.jpg', 'jpg')).toBe('filename.jpg');
|
||||
});
|
||||
test('.ext', () => {
|
||||
expect(correctFilename('filename.jpg', '.jpg')).toBe('filename.jpg');
|
||||
});
|
||||
test('with different ext', () => {
|
||||
expect(correctFilename('filename.webp', 'jpg')).toBe('filename.webp.jpg');
|
||||
});
|
||||
test('non ascii with space', () => {
|
||||
expect(correctFilename('ファイル 名前', 'jpg')).toBe('ファイル 名前.jpg');
|
||||
});
|
||||
test('jpeg', () => {
|
||||
expect(correctFilename('filename.jpeg', 'jpg')).toBe('filename.jpeg');
|
||||
});
|
||||
test('tiff', () => {
|
||||
expect(correctFilename('filename.tiff', 'tif')).toBe('filename.tiff');
|
||||
});
|
||||
test('null ext', () => {
|
||||
expect(correctFilename('filename', null)).toBe('filename.unknown');
|
||||
});
|
||||
});
|
@@ -1,87 +1,50 @@
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname } from 'node:path';
|
||||
import * as childProcess from 'child_process';
|
||||
import * as http from 'node:http';
|
||||
import { SIGKILL } from 'constants';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { isAbsolute, basename } from 'node:path';
|
||||
import WebSocket from 'ws';
|
||||
import fetch from 'node-fetch';
|
||||
import FormData from 'form-data';
|
||||
import fetch, { Blob, File, RequestInit } from 'node-fetch';
|
||||
import { DataSource } from 'typeorm';
|
||||
import got, { RequestError } from 'got';
|
||||
import loadConfig from '../src/config/load.js';
|
||||
import { entities } from '@/postgres.js';
|
||||
import { entities } from '../src/postgres.js';
|
||||
import { loadConfig } from '../src/config.js';
|
||||
import type * as misskey from 'misskey-js';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
export { server as startServer } from '@/boot/common.js';
|
||||
|
||||
const config = loadConfig();
|
||||
export const port = config.port;
|
||||
|
||||
export const api = async (endpoint: string, params: any, me?: any) => {
|
||||
endpoint = endpoint.replace(/^\//, '');
|
||||
|
||||
const auth = me ? {
|
||||
i: me.token,
|
||||
} : {};
|
||||
|
||||
try {
|
||||
const res = await got<string>(`http://localhost:${port}/api/${endpoint}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(Object.assign(auth, params)),
|
||||
retry: {
|
||||
limit: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const status = res.statusCode;
|
||||
const body = res.statusCode !== 204 ? await JSON.parse(res.body) : null;
|
||||
|
||||
return {
|
||||
status,
|
||||
body,
|
||||
};
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof RequestError && err.response) {
|
||||
const status = err.response.statusCode;
|
||||
const body = await JSON.parse(err.response.body as string);
|
||||
|
||||
return {
|
||||
status,
|
||||
body,
|
||||
};
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
const normalized = endpoint.replace(/^\//, '');
|
||||
return await request(`api/${normalized}`, params, me);
|
||||
};
|
||||
|
||||
export const request = async (path: string, params: any, me?: any): Promise<{ body: any, status: number }> => {
|
||||
const request = async (path: string, params: any, me?: any): Promise<{ body: any, status: number }> => {
|
||||
const auth = me ? {
|
||||
i: me.token,
|
||||
} : {};
|
||||
|
||||
const res = await fetch(`http://localhost:${port}/${path}`, {
|
||||
const res = await relativeFetch(path, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(Object.assign(auth, params)),
|
||||
redirect: 'manual',
|
||||
});
|
||||
|
||||
const status = res.status;
|
||||
const body = res.status === 200 ? await res.json().catch() : null;
|
||||
const body = res.headers.get('content-type') === 'application/json; charset=utf-8'
|
||||
? await res.json()
|
||||
: null;
|
||||
|
||||
return {
|
||||
body, status,
|
||||
};
|
||||
};
|
||||
|
||||
const relativeFetch = async (path: string, init?: RequestInit | undefined) => {
|
||||
return await fetch(new URL(path, `http://127.0.0.1:${port}/`).toString(), init);
|
||||
};
|
||||
|
||||
export const signup = async (params?: any): Promise<any> => {
|
||||
const q = Object.assign({
|
||||
username: 'test',
|
||||
@@ -110,30 +73,46 @@ export const react = async (user: any, note: any, reaction: string): Promise<any
|
||||
}, user);
|
||||
};
|
||||
|
||||
interface UploadOptions {
|
||||
/** Optional, absolute path or relative from ./resources/ */
|
||||
path?: string | URL;
|
||||
/** The name to be used for the file upload */
|
||||
name?: string;
|
||||
/** A Blob can be provided instead of path */
|
||||
blob?: Blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file
|
||||
* @param user User
|
||||
* @param _path Optional, absolute path or relative from ./resources/
|
||||
*/
|
||||
export const uploadFile = async (user: any, _path?: string): Promise<any> => {
|
||||
const absPath = _path == null ? `${_dirname}/resources/Lenna.jpg` : path.isAbsolute(_path) ? _path : `${_dirname}/resources/${_path}`;
|
||||
export const uploadFile = async (user: any, { path, name, blob }: UploadOptions = {}): Promise<any> => {
|
||||
const absPath = path == null
|
||||
? new URL('resources/Lenna.jpg', import.meta.url)
|
||||
: isAbsolute(path.toString())
|
||||
? new URL(path)
|
||||
: new URL(path, new URL('resources/', import.meta.url));
|
||||
|
||||
const formData = new FormData() as any;
|
||||
const formData = new FormData();
|
||||
formData.append('i', user.token);
|
||||
formData.append('file', fs.createReadStream(absPath));
|
||||
formData.append('file', blob ??
|
||||
new File([await readFile(absPath)], basename(absPath.toString())));
|
||||
formData.append('force', 'true');
|
||||
if (name) {
|
||||
formData.append('name', name);
|
||||
}
|
||||
|
||||
const res = await got<string>(`http://localhost:${port}/api/drive/files/create`, {
|
||||
const res = await relativeFetch('api/drive/files/create', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
retry: {
|
||||
limit: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const body = res.statusCode !== 204 ? await JSON.parse(res.body) : null;
|
||||
const body = res.status !== 204 ? await res.json() : null;
|
||||
|
||||
return body;
|
||||
return {
|
||||
status: res.status,
|
||||
body,
|
||||
};
|
||||
};
|
||||
|
||||
export const uploadUrl = async (user: any, url: string) => {
|
||||
@@ -160,7 +139,7 @@ export const uploadUrl = async (user: any, url: string) => {
|
||||
|
||||
export function connectStream(user: any, channel: string, listener: (message: Record<string, any>) => any, params?: any): Promise<WebSocket> {
|
||||
return new Promise((res, rej) => {
|
||||
const ws = new WebSocket(`ws://localhost:${port}/streaming?i=${user.token}`);
|
||||
const ws = new WebSocket(`ws://127.0.0.1:${port}/streaming?i=${user.token}`);
|
||||
|
||||
ws.on('open', () => {
|
||||
ws.on('message', data => {
|
||||
@@ -187,7 +166,7 @@ export function connectStream(user: any, channel: string, listener: (message: Re
|
||||
|
||||
export const waitFire = async (user: any, channel: string, trgr: () => any, cond: (msg: Record<string, any>) => boolean, params?: any) => {
|
||||
return new Promise<boolean>(async (res, rej) => {
|
||||
let timer: NodeJS.Timeout;
|
||||
let timer: NodeJS.Timeout | null = null;
|
||||
|
||||
let ws: WebSocket;
|
||||
try {
|
||||
@@ -219,41 +198,25 @@ export const waitFire = async (user: any, channel: string, trgr: () => any, cond
|
||||
});
|
||||
};
|
||||
|
||||
export const simpleGet = async (path: string, accept = '*/*'): Promise<{ status?: number, type?: string, location?: string }> => {
|
||||
// node-fetchだと3xxを取れない
|
||||
return await new Promise((resolve, reject) => {
|
||||
const req = http.request(`http://localhost:${port}${path}`, {
|
||||
headers: {
|
||||
Accept: accept,
|
||||
},
|
||||
}, res => {
|
||||
if (res.statusCode! >= 400) {
|
||||
reject(res);
|
||||
} else {
|
||||
resolve({
|
||||
status: res.statusCode,
|
||||
type: res.headers['content-type'],
|
||||
location: res.headers.location,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
req.end();
|
||||
export const simpleGet = async (path: string, accept = '*/*'): Promise<{ status: number, body: any, type: string | null, location: string | null }> => {
|
||||
const res = await relativeFetch(path, {
|
||||
headers: {
|
||||
Accept: accept,
|
||||
},
|
||||
redirect: 'manual',
|
||||
});
|
||||
};
|
||||
|
||||
export function launchServer(callbackSpawnedProcess: (p: childProcess.ChildProcess) => void, moreProcess: () => Promise<void> = async () => {}) {
|
||||
return (done: (err?: Error) => any) => {
|
||||
const p = childProcess.spawn('node', [_dirname + '/../index.js'], {
|
||||
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
||||
env: { NODE_ENV: 'test', PATH: process.env.PATH },
|
||||
});
|
||||
callbackSpawnedProcess(p);
|
||||
p.on('message', message => {
|
||||
if (message === 'ok') moreProcess().then(() => done()).catch(e => done(e));
|
||||
});
|
||||
const body = res.headers.get('content-type') === 'application/json; charset=utf-8'
|
||||
? await res.json()
|
||||
: null;
|
||||
|
||||
return {
|
||||
status: res.status,
|
||||
body,
|
||||
type: res.headers.get('content-type'),
|
||||
location: res.headers.get('location'),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export async function initTestDb(justBorrow = false, initEntities?: any[]) {
|
||||
if (process.env.NODE_ENV !== 'test') throw 'NODE_ENV is not a test';
|
||||
@@ -275,46 +238,6 @@ export async function initTestDb(justBorrow = false, initEntities?: any[]) {
|
||||
return db;
|
||||
}
|
||||
|
||||
export function startServer(timeout = 60 * 1000): Promise<childProcess.ChildProcess> {
|
||||
return new Promise((res, rej) => {
|
||||
const t = setTimeout(() => {
|
||||
p.kill(SIGKILL);
|
||||
rej('timeout to start');
|
||||
}, timeout);
|
||||
|
||||
const p = childProcess.spawn('node', [_dirname + '/../built/index.js'], {
|
||||
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
||||
env: { NODE_ENV: 'test', PATH: process.env.PATH },
|
||||
});
|
||||
|
||||
p.on('error', e => rej(e));
|
||||
|
||||
p.on('message', message => {
|
||||
if (message === 'ok') {
|
||||
clearTimeout(t);
|
||||
res(p);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function shutdownServer(p: childProcess.ChildProcess | undefined, timeout = 20 * 1000) {
|
||||
if (p == null) return Promise.resolve('nop');
|
||||
return new Promise((res, rej) => {
|
||||
const t = setTimeout(() => {
|
||||
p.kill(SIGKILL);
|
||||
res('force exit');
|
||||
}, timeout);
|
||||
|
||||
p.once('exit', () => {
|
||||
clearTimeout(t);
|
||||
res('exited');
|
||||
});
|
||||
|
||||
p.kill();
|
||||
});
|
||||
}
|
||||
|
||||
export function sleep(msec: number) {
|
||||
return new Promise<void>(res => {
|
||||
setTimeout(() => {
|
||||
|
Reference in New Issue
Block a user