From 60792019f30753b612fb2abd85f47d214fae0b6e Mon Sep 17 00:00:00 2001 From: Ryo Igarashi Date: Thu, 20 Jul 2023 09:48:46 +0900 Subject: [PATCH] chore(test): Improve test readability --- .github/workflows/ci-e2e.yml | 2 +- tests/streaming/errors.spec.ts | 51 +++++--- tests/streaming/events.spec.ts | 97 ++++++-------- tests/streaming/timelines.spec.ts | 206 +++++++++++++----------------- 4 files changed, 160 insertions(+), 196 deletions(-) diff --git a/.github/workflows/ci-e2e.yml b/.github/workflows/ci-e2e.yml index ab9e7f856..269198ecf 100644 --- a/.github/workflows/ci-e2e.yml +++ b/.github/workflows/ci-e2e.yml @@ -84,7 +84,7 @@ jobs: run: yarn install --frozen-lockfile - name: Run tests - run: yarn run test:e2e --max-workers=1 + run: yarn run test:e2e --max-workers=2 - name: Codecov uses: codecov/codecov-action@v3 diff --git a/tests/streaming/errors.spec.ts b/tests/streaming/errors.spec.ts index da354c9bc..bec849c9e 100644 --- a/tests/streaming/errors.spec.ts +++ b/tests/streaming/errors.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable unicorn/no-array-callback-reference */ import { type mastodon } from "../../src"; import { MastoUnexpectedError } from "../../src/adapters/errors"; import { sleep } from "../../src/utils"; @@ -28,37 +29,47 @@ it("supports multiplex subscription", () => { const s2 = alice.ws.public.local.subscribe(); const s1 = alice.ws.hashtag.subscribe({ tag: "test" }); - let id!: string; + const e1Promise = s1 + .values() + .filter(isUpdate) + .filter(isFrom(alice.id)) + .take(1) + .toArray(); + const e2Promise = s2 + .values() + .filter(isUpdate) + .filter(isFrom(alice.id)) + .take(1) + .toArray(); + const e3Promise = s3 + .values() + .filter(isUpdate) + .filter(isFrom(alice.id)) + .take(1) + .toArray(); - const dispatch = async () => { - await sleep(1000); + await sleep(1000); - const status = await alice.rest.v1.statuses.create({ - status: "#test", - visibility: "public", - }); - - id = status.id; - }; + const status = await alice.rest.v1.statuses.create({ + status: "#test", + visibility: "public", + }); try { - /* eslint-disable unicorn/no-array-callback-reference */ const [[e1], [e2], [e3]] = await Promise.all([ - s1.values().filter(isUpdate).filter(isFrom(alice.id)).take(1).toArray(), - s2.values().filter(isUpdate).filter(isFrom(alice.id)).take(1).toArray(), - s3.values().filter(isUpdate).filter(isFrom(alice.id)).take(1).toArray(), - dispatch(), + e1Promise, + e2Promise, + e3Promise, ]); - /* eslint-enable unicorn/no-array-callback-reference */ - expect(e1.payload.id).toBe(id); - expect(e2.payload.id).toBe(id); - expect(e3.payload.id).toBe(id); + expect(e1.payload.id).toBe(status.id); + expect(e2.payload.id).toBe(status.id); + expect(e3.payload.id).toBe(status.id); } finally { s1.unsubscribe(); s2.unsubscribe(); s3.unsubscribe(); - await alice.rest.v1.statuses.$select(id).remove(); + await alice.rest.v1.statuses.$select(status.id).remove(); } }); }); diff --git a/tests/streaming/events.spec.ts b/tests/streaming/events.spec.ts index ffc0f5929..54917ab3b 100644 --- a/tests/streaming/events.spec.ts +++ b/tests/streaming/events.spec.ts @@ -6,36 +6,30 @@ import { sleep } from "../../src/utils"; describe("events", () => { it.concurrent("streams update, status.update, and delete event", () => { return sessions.use(async (session) => { - let id!: string; const tag = `tag_${crypto.randomBytes(4).toString("hex")}`; const subscription = session.ws.hashtag.local.subscribe({ tag }); - const dispatch = async () => { - await sleep(1000); - const status = await session.rest.v1.statuses.create({ - status: `test1 #${tag}`, - }); - id = status.id; - await sleep(1000); - await session.rest.v1.statuses.$select(status.id).update({ - status: `test2 #${tag}`, - }); - await sleep(1000); - await session.rest.v1.statuses.$select(status.id).remove(); - }; + const eventsPromise = subscription.values().take(3).toArray(); - try { - const [[e1, e2, e3]] = await Promise.all([ - subscription.values().take(3).toArray(), - dispatch(), - ]); + await sleep(1000); + const status = await session.rest.v1.statuses.create({ + status: `test1 #${tag}`, + }); + await sleep(1000); + await session.rest.v1.statuses.$select(status.id).update({ + status: `test2 #${tag}`, + }); + await sleep(1000); + await session.rest.v1.statuses.$select(status.id).remove(); + try { + const [e1, e2, e3] = await eventsPromise; assert(e1.event === "update"); expect(e1.payload.content).toMatch(/test1/); assert(e2.event === "status.update"); expect(e2.payload.content).toMatch(/test2/); assert(e3.event === "delete"); - expect(e3.payload).toBe(id); + expect(e3.payload).toBe(status.id); } finally { subscription.unsubscribe(); } @@ -45,23 +39,18 @@ describe("events", () => { it.concurrent("streams filters_changed event", () => { return sessions.use(async (session) => { const subscription = session.ws.user.subscribe(); + const eventsPromise = subscription.values().take(1).toArray(); - const dispatch = async () => { - await sleep(1000); - const filter = await session.rest.v2.filters.create({ - title: "test", - context: ["public"], - keywordsAttributes: [{ keyword: "TypeScript" }], - }); - await session.rest.v2.filters.$select(filter.id).remove(); - }; + await sleep(1000); + const filter = await session.rest.v2.filters.create({ + title: "test", + context: ["public"], + keywordsAttributes: [{ keyword: "TypeScript" }], + }); + await session.rest.v2.filters.$select(filter.id).remove(); try { - const [[e]] = await Promise.all([ - subscription.values().take(1).toArray(), - dispatch(), - ]); - + const [e] = await eventsPromise; assert(e.event === "filters_changed"); expect(e.payload).toBeUndefined(); } finally { @@ -72,23 +61,16 @@ describe("events", () => { it.concurrent("streams notification", () => { return sessions.use(2, async ([alice, bob]) => { - let id!: string; const subscription = alice.ws.user.notification.subscribe(); + const eventsPromise = subscription.values().take(1).toArray(); - const dispatch = async () => { - await sleep(1000); - await bob.rest.v1.accounts.$select(alice.id).follow(); - }; + await sleep(1000); + await bob.rest.v1.accounts.$select(alice.id).follow(); try { - const [[e]] = await Promise.all([ - subscription.values().take(1).toArray(), - dispatch(), - ]); - + const [e] = await eventsPromise; assert(e.event === "notification"); expect(e.payload.account.id).toBe(bob.id); - expect(e.payload.status?.id).toBe(id); } finally { await bob.rest.v1.accounts.$select(alice.id).unfollow(); subscription.unsubscribe(); @@ -98,28 +80,21 @@ describe("events", () => { it.concurrent("streams conversation", () => { return sessions.use(2, async ([alice, bob]) => { - let id!: string; const subscription = alice.ws.direct.subscribe(); + const eventsPromise = subscription.values().take(1).toArray(); - const dispatch = async () => { - await sleep(1000); - const status = await bob.rest.v1.statuses.create({ - status: `@${alice.acct} Hello there`, - visibility: "direct", - }); - id = status.id; - }; + await sleep(1000); + const status = await bob.rest.v1.statuses.create({ + status: `@${alice.acct} Hello there`, + visibility: "direct", + }); try { - const [[e]] = await Promise.all([ - subscription.values().take(1).toArray(), - dispatch(), - ]); - + const [e] = await eventsPromise; assert(e.event === "conversation"); - expect(e.payload.lastStatus?.id).toBe(id); + expect(e.payload.lastStatus?.id).toBe(status.id); } finally { - await bob.rest.v1.statuses.$select(id).remove(); + await bob.rest.v1.statuses.$select(status.id).remove(); subscription.unsubscribe(); } }); diff --git a/tests/streaming/timelines.spec.ts b/tests/streaming/timelines.spec.ts index c176a1e67..dc783ed0b 100644 --- a/tests/streaming/timelines.spec.ts +++ b/tests/streaming/timelines.spec.ts @@ -9,207 +9,188 @@ const TRANSPARENT_1X1_PNG = describe("websocket", () => { it("streams public", () => { return sessions.use(async (session) => { - let id!: string; const random = crypto.randomBytes(16).toString("hex"); const subscription = session.ws.public.subscribe(); - const events = subscription + const eventsPromise = subscription .values() .filter( (e): e is mastodon.streaming.UpdateEvent => e.event === "update", ) .filter((e) => e.payload.content.includes(random)) - .take(1); + .take(1) + .toArray(); - const dispatch = async () => { - await sleep(1000); - const status = await session.rest.v1.statuses.create({ - status: random, - }); - id = status.id; - }; + await sleep(1000); + const status = await session.rest.v1.statuses.create({ + status: random, + }); try { - const [[event]] = await Promise.all([events.toArray(), dispatch()]); - expect(event.payload.id).toBe(id); + const [event] = await eventsPromise; + expect(event.payload.id).toBe(status.id); } finally { subscription.unsubscribe(); - await session.rest.v1.statuses.$select(id).remove(); + await session.rest.v1.statuses.$select(status.id).remove(); } }); }); it("streams public:media", () => { return sessions.use(async (session) => { - let id!: string; const random = crypto.randomBytes(16).toString("hex"); const subscription = session.ws.public.media.subscribe(); - const events = subscription + const eventsPromise = subscription .values() .filter( (e): e is mastodon.streaming.UpdateEvent => e.event === "update", ) .filter((e) => e.payload.content.includes(random)) - .take(1); + .take(1) + .toArray(); - const dispatch = async () => { - await sleep(1000); - const media = await session.rest.v2.media.create({ - file: TRANSPARENT_1X1_PNG, - }); - const status = await session.rest.v1.statuses.create({ - status: random, - mediaIds: [media.id], - visibility: "public", - }); - id = status.id; - }; + await sleep(1000); + const media = await session.rest.v2.media.create({ + file: TRANSPARENT_1X1_PNG, + }); + const status = await session.rest.v1.statuses.create({ + status: random, + mediaIds: [media.id], + visibility: "public", + }); try { - const [[event]] = await Promise.all([events.toArray(), dispatch()]); - expect(event.payload.id).toBe(id); + const [event] = await eventsPromise; + expect(event.payload.id).toBe(status.id); } finally { subscription.unsubscribe(); - await session.rest.v1.statuses.$select(id).remove(); + await session.rest.v1.statuses.$select(status.id).remove(); } }); }); it("streams public:local", () => { return sessions.use(async (session) => { - let id!: string; const random = crypto.randomBytes(16).toString("hex"); const subscription = session.ws.public.local.subscribe(); - const events = subscription + const eventsPromise = subscription .values() .filter( (e): e is mastodon.streaming.UpdateEvent => e.event === "update", ) .filter((e) => e.payload.content.includes(random)) - .take(1); + .take(1) + .toArray(); - const dispatch = async () => { - await sleep(1000); - const status = await session.rest.v1.statuses.create({ - status: random, - visibility: "public", - }); - id = status.id; - }; + await sleep(1000); + const status = await session.rest.v1.statuses.create({ + status: random, + visibility: "public", + }); try { - const [[event]] = await Promise.all([events.toArray(), dispatch()]); - expect(event.payload.id).toBe(id); + const [event] = await eventsPromise; + expect(event.payload.id).toBe(status.id); } finally { subscription.unsubscribe(); - await session.rest.v1.statuses.$select(id).remove(); + await session.rest.v1.statuses.$select(status.id).remove(); } }); }); it("streams public:local:media", () => { return sessions.use(async (session) => { - let id!: string; const random = crypto.randomBytes(16).toString("hex"); const subscription = session.ws.public.local.media.subscribe(); - const events = subscription + const eventsPromise = subscription .values() .filter( (e): e is mastodon.streaming.UpdateEvent => e.event === "update", ) .filter((e) => e.payload.content.includes(random)) - .take(1); - - const dispatch = async () => { - await sleep(1000); - const media = await session.rest.v2.media.create({ - file: TRANSPARENT_1X1_PNG, - }); + .take(1) + .toArray(); - const status = await session.rest.v1.statuses.create({ - status: random, - mediaIds: [media.id], - visibility: "public", - }); + await sleep(1000); + const media = await session.rest.v2.media.create({ + file: TRANSPARENT_1X1_PNG, + }); - id = status.id; - }; + const status = await session.rest.v1.statuses.create({ + status: random, + mediaIds: [media.id], + visibility: "public", + }); try { - const [[event]] = await Promise.all([events.toArray(), dispatch()]); - expect(event.payload.id).toBe(id); + const [event] = await eventsPromise; + expect(event.payload.id).toBe(status.id); } finally { subscription.unsubscribe(); - await session.rest.v1.statuses.$select(id).remove(); + await session.rest.v1.statuses.$select(status.id).remove(); } }); }); it("streams hashtag", () => { return sessions.use(async (session) => { - let id!: string; const hashtag = `tag_${crypto.randomBytes(4).toString("hex")}`; const subscription = session.ws.hashtag.subscribe({ tag: hashtag }); - const events = subscription + const eventsPromise = subscription .values() .filter( (e): e is mastodon.streaming.UpdateEvent => e.event === "update", ) .filter((e) => e.payload.content.includes(hashtag)) - .take(1); + .take(1) + .toArray(); - const dispatch = async () => { - await sleep(1000); - const status = await session.rest.v1.statuses.create({ - status: "#" + hashtag, - }); - id = status.id; - }; + await sleep(1000); + const status = await session.rest.v1.statuses.create({ + status: "#" + hashtag, + }); try { - const [[event]] = await Promise.all([events.toArray(), dispatch()]); - expect(event.payload.id).toBe(id); + const [event] = await eventsPromise; + expect(event.payload.id).toBe(status.id); } finally { subscription.unsubscribe(); - await session.rest.v1.statuses.$select(id).remove(); + await session.rest.v1.statuses.$select(status.id).remove(); } }); }); it("streams hashtag:local", () => { return sessions.use(async (session) => { - let id!: string; const hashtag = `tag_${crypto.randomBytes(4).toString("hex")}`; const subscription = session.ws.hashtag.local.subscribe({ tag: hashtag, }); - const events = subscription + const eventsPromise = subscription .values() .filter( (e): e is mastodon.streaming.UpdateEvent => e.event === "update", ) .filter((e) => e.payload.content.includes(hashtag)) - .take(1); + .take(1) + .toArray(); - const dispatch = async () => { - await sleep(1000); - const status = await session.rest.v1.statuses.create({ - status: "#" + hashtag, - }); - id = status.id; - }; + await sleep(1000); + const status = await session.rest.v1.statuses.create({ + status: "#" + hashtag, + }); try { - const [[event]] = await Promise.all([events.toArray(), dispatch()]); - expect(event.payload.id).toBe(id); + const [event] = await eventsPromise; + expect(event.payload.id).toBe(status.id); } finally { subscription.unsubscribe(); - await session.rest.v1.statuses.$select(id).remove(); + await session.rest.v1.statuses.$select(status.id).remove(); } }); }); @@ -218,22 +199,21 @@ describe("websocket", () => { return sessions.use(2, async ([alice, bob]) => { const subscription = alice.ws.user.subscribe(); - const events = subscription + const eventsPromise = subscription .values() .filter( (e): e is mastodon.streaming.NotificationEvent => e.event === "notification", ) - .take(1); + .take(1) + .toArray(); - const dispatch = async () => { - await sleep(1000); - await bob.rest.v1.accounts.$select(alice.id).unfollow(); - await bob.rest.v1.accounts.$select(alice.id).follow(); - }; + await sleep(1000); + await bob.rest.v1.accounts.$select(alice.id).unfollow(); + await bob.rest.v1.accounts.$select(alice.id).follow(); try { - const [[e1]] = await Promise.all([events.toArray(), dispatch()]); + const [e1] = await eventsPromise; expect(e1.payload.type).toBe("follow"); expect(e1.payload.account.id).toBe(bob.id); } finally { @@ -247,22 +227,21 @@ describe("websocket", () => { return sessions.use(2, async ([alice, bob]) => { const subscription = alice.ws.user.notification.subscribe(); - const events = subscription + const eventsPromise = subscription .values() .filter( (e): e is mastodon.streaming.NotificationEvent => e.event === "notification", ) .filter((e) => e.payload.type === "follow") - .take(1); + .take(1) + .toArray(); - const dispatch = async () => { - await sleep(1000); - await bob.rest.v1.accounts.$select(alice.id).follow(); - }; + await sleep(1000); + await bob.rest.v1.accounts.$select(alice.id).follow(); try { - const [[e1]] = await Promise.all([events.toArray(), dispatch()]); + const [e1] = await eventsPromise; expect(e1.payload.type).toBe("follow"); expect(e1.payload.account.id).toBe(bob.id); } finally { @@ -277,19 +256,18 @@ describe("websocket", () => { const list = await alice.rest.v1.lists.create({ title: "test" }); const subscription = alice.ws.list.subscribe({ list: list.id }); - const events = subscription + const eventsPromise = subscription .values() .filter( (e): e is mastodon.streaming.UpdateEvent => e.event === "update", ) - .take(1); + .take(1) + .toArray(); - const dispatch = async () => { - await sleep(1000); - await bob.rest.v1.statuses.create({ - status: "a post from bob", - }); - }; + await sleep(1000); + await bob.rest.v1.statuses.create({ + status: "a post from bob", + }); try { await alice.rest.v1.accounts.$select(bob.id).follow(); @@ -297,7 +275,7 @@ describe("websocket", () => { accountIds: [bob.id], }); - const [[e1]] = await Promise.all([events.toArray(), dispatch()]); + const [e1] = await eventsPromise; expect(e1.payload.account.id).toBe(bob.id); } finally { subscription.unsubscribe();