From afda15260f4f97ec00b3e7fdf63bd13013daae40 Mon Sep 17 00:00:00 2001 From: Mar0xy Date: Sun, 24 Sep 2023 01:44:53 +0200 Subject: upd: megalodon to v7 --- packages/megalodon/test/integration/cancel.spec.ts | 38 ++++ .../megalodon/test/integration/cancelWorker.ts | 5 + .../megalodon/test/integration/detector.spec.ts | 67 +++++++ .../megalodon/test/integration/mastodon.spec.ts | 218 ++++++++++++++++++++ .../test/integration/mastodon/api_client.spec.ts | 176 ++++++++++++++++ .../megalodon/test/integration/megalodon.spec.ts | 27 --- .../megalodon/test/integration/misskey.spec.ts | 34 +++- .../megalodon/test/integration/pleroma.spec.ts | 222 +++++++++++++++++++++ 8 files changed, 750 insertions(+), 37 deletions(-) create mode 100644 packages/megalodon/test/integration/cancel.spec.ts create mode 100644 packages/megalodon/test/integration/cancelWorker.ts create mode 100644 packages/megalodon/test/integration/detector.spec.ts create mode 100644 packages/megalodon/test/integration/mastodon.spec.ts create mode 100644 packages/megalodon/test/integration/mastodon/api_client.spec.ts delete mode 100644 packages/megalodon/test/integration/megalodon.spec.ts create mode 100644 packages/megalodon/test/integration/pleroma.spec.ts (limited to 'packages/megalodon/test/integration') diff --git a/packages/megalodon/test/integration/cancel.spec.ts b/packages/megalodon/test/integration/cancel.spec.ts new file mode 100644 index 0000000000..efc9d49770 --- /dev/null +++ b/packages/megalodon/test/integration/cancel.spec.ts @@ -0,0 +1,38 @@ +import MastodonAPI from '@/mastodon/api_client' +import { Worker } from 'jest-worker' + +jest.mock('axios', () => { + const mockAxios = jest.requireActual('axios') + mockAxios.get = (_path: string) => { + return new Promise(resolve => { + setTimeout(() => { + console.log('hoge') + resolve({ + data: 'hoge', + status: 200, + statusText: '200OK', + headers: [], + config: {} + }) + }, 5000) + }) + } + return mockAxios +}) + +const worker = async (client: MastodonAPI.Client) => { + const w: any = new Worker(require.resolve('./cancelWorker.ts')) + await w.cancel(client) +} + +// Could not use jest-worker under typescript. +// I'm waiting for resolve this issue. +// https://github.com/facebook/jest/issues/8872 +describe.skip('cancel', () => { + const client = new MastodonAPI.Client('testToken', 'https://pleroma.io/api/v1') + it('should be raised', async () => { + const getPromise = client.get<{}>('/timelines/home') + worker(client) + await expect(getPromise).rejects.toThrow() + }) +}) diff --git a/packages/megalodon/test/integration/cancelWorker.ts b/packages/megalodon/test/integration/cancelWorker.ts new file mode 100644 index 0000000000..17a0722780 --- /dev/null +++ b/packages/megalodon/test/integration/cancelWorker.ts @@ -0,0 +1,5 @@ +import MastodonAPI from '@/mastodon/api_client' + +export function cancel(client: MastodonAPI.Client) { + return client.cancel() +} diff --git a/packages/megalodon/test/integration/detector.spec.ts b/packages/megalodon/test/integration/detector.spec.ts new file mode 100644 index 0000000000..86c32622e9 --- /dev/null +++ b/packages/megalodon/test/integration/detector.spec.ts @@ -0,0 +1,67 @@ +import { detector } from '../../src/index' + +describe('detector', () => { + describe('mastodon', () => { + const url = 'https://mastodon.social' + it('should be mastodon', async () => { + const mastodon = await detector(url) + expect(mastodon).toEqual('mastodon') + }) + }) + + describe('pleroma', () => { + const url = 'https://pleroma.io' + it('should be pleroma', async () => { + const pleroma = await detector(url) + expect(pleroma).toEqual('pleroma') + }) + }) + + describe('misskey', () => { + const url = 'https://misskey.io' + it('should be misskey', async () => { + const misskey = await detector(url) + expect(misskey).toEqual('misskey') + }) + }) + + describe('fedibird', () => { + const url = 'https://fedibird.com' + it('should be mastodon', async () => { + const fedibird = await detector(url) + expect(fedibird).toEqual('mastodon') + }, 20000) + }) + + describe('friendica', () => { + const url = 'https://squeet.me' + it('should be friendica', async () => { + const friendica = await detector(url) + expect(friendica).toEqual('friendica') + }) + }) + + describe('akkoma', () => { + const url = 'https://pleroma.noellabo.jp' + it('should be akkoma', async () => { + const akkoma = await detector(url) + expect(akkoma).toEqual('pleroma') + }) + }) + + describe('wildebeest', () => { + const url = 'https://wildebeest.mirror-kt.dev' + it('should be mastodon', async () => { + const wildebeest = await detector(url) + expect(wildebeest).toEqual('mastodon') + }) + }) + + describe('unknown', () => { + const url = 'https://google.com' + it('should be null', async () => { + const unknown = detector(url) + await expect(unknown).rejects.toThrow() + }) + }) +}) diff --git a/packages/megalodon/test/integration/mastodon.spec.ts b/packages/megalodon/test/integration/mastodon.spec.ts new file mode 100644 index 0000000000..172d11a863 --- /dev/null +++ b/packages/megalodon/test/integration/mastodon.spec.ts @@ -0,0 +1,218 @@ +import MastodonEntity from '@/mastodon/entity' +import MastodonNotificationType from '@/mastodon/notification' +import Mastodon from '@/mastodon' +import MegalodonNotificationType from '@/notification' +import axios, { AxiosResponse, InternalAxiosRequestConfig, AxiosHeaders } from 'axios' + +jest.mock('axios') + +const account: MastodonEntity.Account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + group: false, + noindex: false, + suspended: false, + limited: false, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false, + source: { + privacy: null, + sensitive: false, + language: null, + note: 'test', + fields: [] + } +} + +const status: MastodonEntity.Status = { + id: '1', + uri: 'http://example.com', + url: 'http://example.com', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: 'hoge', + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + } as MastodonEntity.Application, + language: null, + pinned: null, + bookmarked: false +} + +const follow: MastodonEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '1', + type: MastodonNotificationType.Follow +} + +const favourite: MastodonEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '2', + status: status, + type: MastodonNotificationType.Favourite +} + +const mention: MastodonEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '3', + status: status, + type: MastodonNotificationType.Mention +} + +const reblog: MastodonEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '4', + status: status, + type: MastodonNotificationType.Reblog +} + +const poll: MastodonEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '5', + type: MastodonNotificationType.Poll +} + +const followRequest: MastodonEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '6', + type: MastodonNotificationType.FollowRequest +} + +const toot: MastodonEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '7', + status: status, + type: MastodonNotificationType.Status +} + +const unknownEvent: MastodonEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '8', + type: 'unknown' +} + +;(axios.CancelToken.source as any).mockImplementation(() => { + return { + token: { + throwIfRequested: () => {}, + promise: { + then: () => {}, + catch: () => {} + } + } + } +}) + +describe('getNotifications', () => { + const client = new Mastodon('http://localhost', 'sample token') + const cases: Array<{ event: MastodonEntity.Notification; expected: Entity.NotificationType; title: string }> = [ + { + event: follow, + expected: MegalodonNotificationType.Follow, + title: 'follow' + }, + { + event: favourite, + expected: MegalodonNotificationType.Favourite, + title: 'favourite' + }, + { + event: mention, + expected: MegalodonNotificationType.Mention, + title: 'mention' + }, + { + event: reblog, + expected: MegalodonNotificationType.Reblog, + title: 'reblog' + }, + { + event: poll, + expected: MegalodonNotificationType.PollExpired, + title: 'poll' + }, + { + event: followRequest, + expected: MegalodonNotificationType.FollowRequest, + title: 'followRequest' + }, + { + event: toot, + expected: MegalodonNotificationType.Status, + title: 'status' + } + ] + cases.forEach(c => { + it(`should be ${c.title} event`, async () => { + const config: InternalAxiosRequestConfig = { + headers: new AxiosHeaders() + } + const mockResponse: AxiosResponse> = { + data: [c.event], + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + ;(axios.get as any).mockResolvedValue(mockResponse) + const res = await client.getNotifications() + expect(res.data[0].type).toEqual(c.expected) + }) + }) + it('UnknownEvent should be ignored', async () => { + const config: InternalAxiosRequestConfig = { + headers: new AxiosHeaders() + } + const mockResponse: AxiosResponse> = { + data: [unknownEvent], + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + ;(axios.get as any).mockResolvedValue(mockResponse) + const res = await client.getNotifications() + expect(res.data).toEqual([]) + }) +}) diff --git a/packages/megalodon/test/integration/mastodon/api_client.spec.ts b/packages/megalodon/test/integration/mastodon/api_client.spec.ts new file mode 100644 index 0000000000..950105152c --- /dev/null +++ b/packages/megalodon/test/integration/mastodon/api_client.spec.ts @@ -0,0 +1,176 @@ +import MastodonAPI from '@/mastodon/api_client' +import Entity from '@/entity' +import Response from '@/response' +import axios, { AxiosResponse, InternalAxiosRequestConfig, AxiosHeaders } from 'axios' + +jest.mock('axios') + +const account: Entity.Account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + group: false, + noindex: false, + suspended: false, + limited: false, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false, + source: { + privacy: null, + sensitive: false, + language: null, + note: 'test', + fields: [] + } +} + +const status: Entity.Status = { + id: '1', + uri: 'http://example.com', + url: 'http://example.com', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: 'hoge', + plain_content: null, + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + } as Entity.Application, + language: null, + pinned: null, + emoji_reactions: [], + bookmarked: false, + quote: false +} +;(axios.CancelToken.source as any).mockImplementation(() => { + return { + token: { + throwIfRequested: () => {}, + promise: { + then: () => {}, + catch: () => {} + } + } + } +}) + +const config: InternalAxiosRequestConfig = { + headers: new AxiosHeaders() +} + +describe('get', () => { + const client = new MastodonAPI.Client('testToken', 'https://pleroma.io/api/v1') + const mockResponse: AxiosResponse> = { + data: [status], + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + it('should be responsed', async () => { + ;(axios.get as any).mockResolvedValue(mockResponse) + const response: Response> = await client.get>('/timelines/home') + expect(response.data).toEqual([status]) + }) +}) + +describe('put', () => { + const client = new MastodonAPI.Client('testToken', 'https://pleroma.io/api/v1') + const mockResponse: AxiosResponse = { + data: account, + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + it('should be responsed', async () => { + ;(axios.put as any).mockResolvedValue(mockResponse) + const response: Response = await client.put('/accounts/update_credentials', { + display_name: 'hoge' + }) + expect(response.data).toEqual(account) + }) +}) + +describe('patch', () => { + const client = new MastodonAPI.Client('testToken', 'https://pleroma.io/api/v1') + const mockResponse: AxiosResponse = { + data: account, + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + it('should be responsed', async () => { + ;(axios.patch as any).mockResolvedValue(mockResponse) + const response: Response = await client.patch('/accounts/update_credentials', { + display_name: 'hoge' + }) + expect(response.data).toEqual(account) + }) +}) + +describe('post', () => { + const client = new MastodonAPI.Client('testToken', 'https://pleroma.io/api/v1') + const mockResponse: AxiosResponse = { + data: status, + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + it('should be responsed', async () => { + ;(axios.post as any).mockResolvedValue(mockResponse) + const response: Response = await client.post('/statuses', { + status: 'hoge' + }) + expect(response.data).toEqual(status) + }) +}) + +describe('del', () => { + const client = new MastodonAPI.Client('testToken', 'https://pleroma.io/api/v1') + const mockResponse: AxiosResponse<{}> = { + data: {}, + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + it('should be responsed', async () => { + ;(axios.delete as any).mockResolvedValue(mockResponse) + const response: Response<{}> = await client.del<{}>('/statuses/12asdf34') + expect(response.data).toEqual({}) + }) +}) diff --git a/packages/megalodon/test/integration/megalodon.spec.ts b/packages/megalodon/test/integration/megalodon.spec.ts deleted file mode 100644 index 8964535509..0000000000 --- a/packages/megalodon/test/integration/megalodon.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { detector } from '../../src/index' - -describe('detector', () => { - describe('mastodon', () => { - const url = 'https://fedibird.com' - it('should be mastodon', async () => { - const mastodon = await detector(url) - expect(mastodon).toEqual('mastodon') - }) - }) - - describe('pleroma', () => { - const url = 'https://pleroma.soykaf.com' - it('should be pleroma', async () => { - const pleroma = await detector(url) - expect(pleroma).toEqual('pleroma') - }) - }) - - describe('misskey', () => { - const url = 'https://misskey.io' - it('should be misskey', async () => { - const misskey = await detector(url) - expect(misskey).toEqual('misskey') - }) - }) -}) diff --git a/packages/megalodon/test/integration/misskey.spec.ts b/packages/megalodon/test/integration/misskey.spec.ts index 0ec1288428..ed3b9a40f2 100644 --- a/packages/megalodon/test/integration/misskey.spec.ts +++ b/packages/megalodon/test/integration/misskey.spec.ts @@ -2,7 +2,7 @@ import MisskeyEntity from '@/misskey/entity' import MisskeyNotificationType from '@/misskey/notification' import Misskey from '@/misskey' import MegalodonNotificationType from '@/notification' -import axios, { AxiosResponse } from 'axios' +import axios, { AxiosHeaders, AxiosResponse, InternalAxiosRequestConfig } from 'axios' jest.mock('axios') @@ -27,6 +27,7 @@ const note: MisskeyEntity.Note = { renoteCount: 0, repliesCount: 0, reactions: {}, + reactionEmojis: {}, emojis: [], fileIds: [], files: [], @@ -93,7 +94,7 @@ const pollVote: MisskeyEntity.Notification = { createdAt: '2021-02-01T01:49:29', userId: user.id, user: user, - type: MisskeyNotificationType.PollEnded, + type: MisskeyNotificationType.PollVote, note: note } @@ -163,12 +164,12 @@ describe('getNotifications', () => { }, { event: reaction, - expected: MegalodonNotificationType.Reaction, + expected: MegalodonNotificationType.EmojiReaction, title: 'reaction' }, { event: pollVote, - expected: MegalodonNotificationType.Poll, + expected: MegalodonNotificationType.PollVote, title: 'pollVote' }, { @@ -180,25 +181,38 @@ describe('getNotifications', () => { event: followRequestAccepted, expected: MegalodonNotificationType.Follow, title: 'followRequestAccepted' - }, - { - event: groupInvited, - expected: MisskeyNotificationType.GroupInvited, - title: 'groupInvited' } ] cases.forEach(c => { it(`should be ${c.title} event`, async () => { + const config: InternalAxiosRequestConfig = { + headers: new AxiosHeaders() + } const mockResponse: AxiosResponse> = { data: [c.event], status: 200, statusText: '200OK', headers: {}, - config: {} + config: config } ;(axios.post as any).mockResolvedValue(mockResponse) const res = await client.getNotifications() expect(res.data[0].type).toEqual(c.expected) }) }) + it('groupInvited event should be ignored', async () => { + const config: InternalAxiosRequestConfig = { + headers: new AxiosHeaders() + } + const mockResponse: AxiosResponse> = { + data: [groupInvited], + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + ;(axios.post as any).mockResolvedValue(mockResponse) + const res = await client.getNotifications() + expect(res.data).toEqual([]) + }) }) diff --git a/packages/megalodon/test/integration/pleroma.spec.ts b/packages/megalodon/test/integration/pleroma.spec.ts new file mode 100644 index 0000000000..1e1f449e17 --- /dev/null +++ b/packages/megalodon/test/integration/pleroma.spec.ts @@ -0,0 +1,222 @@ +import PleromaEntity from '@/pleroma/entity' +import Pleroma from '@/pleroma' +import MegalodonNotificationType from '@/notification' +import PleromaNotificationType from '@/pleroma/notification' +import axios, { AxiosResponse, InternalAxiosRequestConfig, AxiosHeaders } from 'axios' + +jest.mock('axios') + +const account: PleromaEntity.Account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + noindex: null, + suspended: null, + limited: null, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false, + source: { + privacy: null, + sensitive: false, + language: null, + note: 'test', + fields: [] + } +} + +const status: PleromaEntity.Status = { + id: '1', + uri: 'http://example.com', + url: 'http://example.com', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: 'hoge', + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + } as MastodonEntity.Application, + language: null, + pinned: null, + bookmarked: false, + pleroma: { + local: false + } +} + +const follow: PleromaEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '1', + type: PleromaNotificationType.Follow +} + +const favourite: PleromaEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '2', + type: PleromaNotificationType.Favourite, + status: status +} + +const mention: PleromaEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '3', + type: PleromaNotificationType.Mention, + status: status +} + +const reblog: PleromaEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '4', + type: PleromaNotificationType.Reblog, + status: status +} + +const poll: PleromaEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '5', + type: PleromaNotificationType.Poll, + status: status +} + +const emojiReaction: PleromaEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '6', + type: PleromaNotificationType.PleromaEmojiReaction, + status: status, + emoji: '♥' +} + +const unknownEvent: PleromaEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '8', + type: 'unknown' +} + +const followRequest: PleromaEntity.Notification = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '7', + type: PleromaNotificationType.FollowRequest +} + +;(axios.CancelToken.source as any).mockImplementation(() => { + return { + token: { + throwIfRequested: () => {}, + promise: { + then: () => {}, + catch: () => {} + } + } + } +}) + +describe('getNotifications', () => { + const client = new Pleroma('http://localhost', 'sample token') + const cases: Array<{ event: PleromaEntity.Notification; expected: Entity.NotificationType; title: string }> = [ + { + event: follow, + expected: MegalodonNotificationType.Follow, + title: 'follow' + }, + { + event: favourite, + expected: MegalodonNotificationType.Favourite, + title: 'favourite' + }, + { + event: mention, + expected: MegalodonNotificationType.Mention, + title: 'mention' + }, + { + event: reblog, + expected: MegalodonNotificationType.Reblog, + title: 'reblog' + }, + { + event: poll, + expected: MegalodonNotificationType.PollExpired, + title: 'poll' + }, + { + event: emojiReaction, + expected: MegalodonNotificationType.EmojiReaction, + title: 'emojiReaction' + }, + { + event: followRequest, + expected: MegalodonNotificationType.FollowRequest, + title: 'followRequest' + } + ] + cases.forEach(c => { + it(`should be ${c.title} event`, async () => { + const config: InternalAxiosRequestConfig = { + headers: new AxiosHeaders() + } + const mockResponse: AxiosResponse> = { + data: [c.event], + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + ;(axios.get as any).mockResolvedValue(mockResponse) + const res = await client.getNotifications() + expect(res.data[0].type).toEqual(c.expected) + }) + }) + it('UnknownEvent should be ignored', async () => { + const config: InternalAxiosRequestConfig = { + headers: new AxiosHeaders() + } + const mockResponse: AxiosResponse> = { + data: [unknownEvent], + status: 200, + statusText: '200OK', + headers: {}, + config: config + } + ;(axios.get as any).mockResolvedValue(mockResponse) + const res = await client.getNotifications() + expect(res.data).toEqual([]) + }) +}) -- cgit v1.2.3-freya