summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzyoshoka <107108195+zyoshoka@users.noreply.github.com>2024-07-02 10:57:20 +0900
committerGitHub <noreply@github.com>2024-07-02 10:57:20 +0900
commitf1b1e2a7cca3d69eb6162d4c16746968d855ea40 (patch)
tree9ca92f0f3a73d4f20d9f742c2bcea4e8981b9620
parentchore(docker-compose): 推奨の名前にする (#14096) (diff)
downloadmisskey-f1b1e2a7cca3d69eb6162d4c16746968d855ea40.tar.gz
misskey-f1b1e2a7cca3d69eb6162d4c16746968d855ea40.tar.bz2
misskey-f1b1e2a7cca3d69eb6162d4c16746968d855ea40.zip
fix(storybook): prevent infinite remount of component (#14101)
* fix(storybook): prevent infinite remount of component * fix: disable flaky `.toMatch()` test
-rw-r--r--packages/frontend/.storybook/preview.ts6
-rw-r--r--packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts6
-rw-r--r--packages/frontend/src/components/MkClickerGame.stories.impl.ts12
-rw-r--r--packages/frontend/src/components/MkCwButton.stories.impl.ts10
-rw-r--r--packages/frontend/src/components/global/MkA.stories.impl.ts2
-rw-r--r--packages/frontend/src/components/global/MkAd.stories.impl.ts87
-rw-r--r--packages/frontend/src/scripts/test-utils.ts10
7 files changed, 41 insertions, 92 deletions
diff --git a/packages/frontend/.storybook/preview.ts b/packages/frontend/.storybook/preview.ts
index 73ee007fb8..d000a28232 100644
--- a/packages/frontend/.storybook/preview.ts
+++ b/packages/frontend/.storybook/preview.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { FORCE_REMOUNT } from '@storybook/core-events';
+import { FORCE_RE_RENDER, FORCE_REMOUNT } from '@storybook/core-events';
import { addons } from '@storybook/preview-api';
import { type Preview, setup } from '@storybook/vue3';
import isChromatic from 'chromatic/isChromatic';
@@ -16,7 +16,7 @@ import '../src/style.scss';
const appInitialized = Symbol();
-let lastStory = null;
+let lastStory: string | null = null;
let moduleInitialized = false;
let unobserve = () => {};
let misskeyOS = null;
@@ -110,7 +110,7 @@ const preview = {
}).catch(() => {});
Promise.all([resetIndexedDBPromise, resetDefaultStorePromise]).then(() => {
initLocalStorage();
- channel.emit(FORCE_REMOUNT, { storyId: context.id });
+ channel.emit(FORCE_RE_RENDER, { storyId: context.id });
});
}
const story = Story();
diff --git a/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts b/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts
index b99620da22..b9770670dc 100644
--- a/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts
+++ b/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts
@@ -12,14 +12,12 @@ import { expect, userEvent, within } from '@storybook/test';
import { channel } from '../../.storybook/fakes.js';
import { commonHandlers } from '../../.storybook/mocks.js';
import MkChannelFollowButton from './MkChannelFollowButton.vue';
-import { semaphore } from '@/scripts/test-utils.js';
import { i18n } from '@/i18n.js';
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
-const s = semaphore();
export const Default = {
render(args) {
return {
@@ -46,17 +44,13 @@ export const Default = {
full: true,
},
async play({ canvasElement }) {
- await s.acquire();
- await sleep(1000);
const canvas = within(canvasElement);
const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
await expect(buttonElement).toHaveTextContent(i18n.ts.follow);
await userEvent.click(buttonElement);
await sleep(1000);
await expect(buttonElement).toHaveTextContent(i18n.ts.unfollow);
- await sleep(100);
await userEvent.click(buttonElement);
- s.release();
},
parameters: {
layout: 'centered',
diff --git a/packages/frontend/src/components/MkClickerGame.stories.impl.ts b/packages/frontend/src/components/MkClickerGame.stories.impl.ts
index 8378010f8b..36313f965d 100644
--- a/packages/frontend/src/components/MkClickerGame.stories.impl.ts
+++ b/packages/frontend/src/components/MkClickerGame.stories.impl.ts
@@ -8,7 +8,7 @@
import { StoryObj } from '@storybook/vue3';
import { HttpResponse, http } from 'msw';
import { action } from '@storybook/addon-actions';
-import { expect, within } from '@storybook/test';
+import { expect, userEvent, within } from '@storybook/test';
import { commonHandlers } from '../../.storybook/mocks.js';
import MkClickerGame from './MkClickerGame.vue';
@@ -41,12 +41,10 @@ export const Default = {
await sleep(1000);
const canvas = within(canvasElement);
const count = canvas.getByTestId('count');
- // NOTE: flaky なので N/A も通しておく
- await expect(count).toHaveTextContent(/^(0|N\/A)$/);
- // FIXME: flaky
- // const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
- // await userEvent.click(buttonElement);
- // await expect(count).toHaveTextContent('1');
+ await expect(count).toHaveTextContent('0');
+ const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
+ await userEvent.click(buttonElement);
+ await expect(count).toHaveTextContent('1');
},
parameters: {
layout: 'centered',
diff --git a/packages/frontend/src/components/MkCwButton.stories.impl.ts b/packages/frontend/src/components/MkCwButton.stories.impl.ts
index 05c6001552..5d6ea56da9 100644
--- a/packages/frontend/src/components/MkCwButton.stories.impl.ts
+++ b/packages/frontend/src/components/MkCwButton.stories.impl.ts
@@ -11,13 +11,6 @@ import { expect, userEvent, within } from '@storybook/test';
import { file } from '../../.storybook/fakes.js';
import MkCwButton from './MkCwButton.vue';
import { i18n } from '@/i18n.js';
-import { semaphore } from '@/scripts/test-utils.js';
-
-function sleep(ms: number) {
- return new Promise(resolve => setTimeout(resolve, ms));
-}
-
-const s = semaphore();
export const Default = {
render(args) {
@@ -54,8 +47,6 @@ export const Default = {
text: 'Some CW content',
},
async play({ canvasElement }) {
- await s.acquire();
- await sleep(1000);
const canvas = within(canvasElement);
const buttonElement = canvas.getByRole<HTMLButtonElement>('button');
await expect(buttonElement).toHaveTextContent(i18n.ts._cw.show);
@@ -63,7 +54,6 @@ export const Default = {
await userEvent.click(buttonElement);
await expect(buttonElement).toHaveTextContent(i18n.ts._cw.hide);
await userEvent.click(buttonElement);
- s.release();
},
parameters: {
chromatic: {
diff --git a/packages/frontend/src/components/global/MkA.stories.impl.ts b/packages/frontend/src/components/global/MkA.stories.impl.ts
index c1d8cf0ca6..02e5a7f98c 100644
--- a/packages/frontend/src/components/global/MkA.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkA.stories.impl.ts
@@ -35,12 +35,10 @@ export const Default = {
// FIXME: 通るけどその後落ちるのでコメントアウト
// await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
await userEvent.pointer({ keys: '[MouseRight]', target: a });
- await tick();
const menu = canvas.getByRole('menu');
await expect(menu).toBeInTheDocument();
await userEvent.click(a);
a.blur();
- await tick();
await expect(menu).not.toBeInTheDocument();
},
args: {
diff --git a/packages/frontend/src/components/global/MkAd.stories.impl.ts b/packages/frontend/src/components/global/MkAd.stories.impl.ts
index aef26ab92d..8c0b7ef52f 100644
--- a/packages/frontend/src/components/global/MkAd.stories.impl.ts
+++ b/packages/frontend/src/components/global/MkAd.stories.impl.ts
@@ -9,12 +9,6 @@ import { StoryObj } from '@storybook/vue3';
import MkAd from './MkAd.vue';
import { i18n } from '@/i18n.js';
-let lock: Promise<undefined> | undefined;
-
-function sleep(ms: number) {
- return new Promise(resolve => setTimeout(resolve, ms));
-}
-
const common = {
render(args) {
return {
@@ -37,56 +31,41 @@ const common = {
};
},
async play({ canvasElement, args }) {
- if (lock) {
- console.warn('This test is unexpectedly running twice in parallel, fix it!');
- console.warn('See also: https://github.com/misskey-dev/misskey/issues/11267');
- await lock;
+ const canvas = within(canvasElement);
+ const a = canvas.getByRole<HTMLAnchorElement>('link');
+ // FIXME: 通るけどその後落ちるのでコメントアウト
+ // await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
+ const img = within(a).getByRole('img');
+ await expect(img).toBeInTheDocument();
+ let buttons = canvas.getAllByRole<HTMLButtonElement>('button');
+ await expect(buttons).toHaveLength(1);
+ const i = buttons[0];
+ await expect(i).toBeInTheDocument();
+ await userEvent.click(i);
+ await expect(canvasElement).toHaveTextContent(i18n.ts._ad.back);
+ await expect(a).not.toBeInTheDocument();
+ await expect(i).not.toBeInTheDocument();
+ buttons = canvas.getAllByRole<HTMLButtonElement>('button');
+ const hasReduceFrequency = args.specify?.ratio !== 0;
+ await expect(buttons).toHaveLength(hasReduceFrequency ? 2 : 1);
+ const reduce = hasReduceFrequency ? buttons[0] : null;
+ const back = buttons[hasReduceFrequency ? 1 : 0];
+ if (reduce) {
+ await expect(reduce).toBeInTheDocument();
+ await expect(reduce).toHaveTextContent(i18n.ts._ad.reduceFrequencyOfThisAd);
}
-
- let resolve: (value?: any) => void;
- lock = new Promise(r => resolve = r);
-
- try {
- // NOTE: sleep しないと何故か落ちる
- await sleep(100);
- const canvas = within(canvasElement);
- const a = canvas.getByRole<HTMLAnchorElement>('link');
- // await expect(a.href).toMatch(/^https?:\/\/.*#test$/);
- const img = within(a).getByRole('img');
- await expect(img).toBeInTheDocument();
- let buttons = canvas.getAllByRole<HTMLButtonElement>('button');
- await expect(buttons).toHaveLength(1);
- const i = buttons[0];
- await expect(i).toBeInTheDocument();
- await userEvent.click(i);
- await expect(canvasElement).toHaveTextContent(i18n.ts._ad.back);
- await expect(a).not.toBeInTheDocument();
- await expect(i).not.toBeInTheDocument();
- buttons = canvas.getAllByRole<HTMLButtonElement>('button');
- const hasReduceFrequency = args.specify?.ratio !== 0;
- await expect(buttons).toHaveLength(hasReduceFrequency ? 2 : 1);
- const reduce = hasReduceFrequency ? buttons[0] : null;
- const back = buttons[hasReduceFrequency ? 1 : 0];
- if (reduce) {
- await expect(reduce).toBeInTheDocument();
- await expect(reduce).toHaveTextContent(i18n.ts._ad.reduceFrequencyOfThisAd);
- }
- await expect(back).toBeInTheDocument();
- await expect(back).toHaveTextContent(i18n.ts._ad.back);
- await userEvent.click(back);
- await waitFor(() => expect(canvas.queryByRole('img')).toBeTruthy());
- if (reduce) {
- await expect(reduce).not.toBeInTheDocument();
- }
- await expect(back).not.toBeInTheDocument();
- const aAgain = canvas.getByRole<HTMLAnchorElement>('link');
- await expect(aAgain).toBeInTheDocument();
- const imgAgain = within(aAgain).getByRole('img');
- await expect(imgAgain).toBeInTheDocument();
- } finally {
- resolve!();
- lock = undefined;
+ await expect(back).toBeInTheDocument();
+ await expect(back).toHaveTextContent(i18n.ts._ad.back);
+ await userEvent.click(back);
+ await waitFor(() => expect(canvas.queryByRole('img')).toBeTruthy());
+ if (reduce) {
+ await expect(reduce).not.toBeInTheDocument();
}
+ await expect(back).not.toBeInTheDocument();
+ const aAgain = canvas.getByRole<HTMLAnchorElement>('link');
+ await expect(aAgain).toBeInTheDocument();
+ const imgAgain = within(aAgain).getByRole('img');
+ await expect(imgAgain).toBeInTheDocument();
},
args: {
prefer: [],
diff --git a/packages/frontend/src/scripts/test-utils.ts b/packages/frontend/src/scripts/test-utils.ts
index a32315f4df..52bb2d94e0 100644
--- a/packages/frontend/src/scripts/test-utils.ts
+++ b/packages/frontend/src/scripts/test-utils.ts
@@ -7,13 +7,3 @@ export async function tick(): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
await new Promise((globalThis.requestIdleCallback ?? setTimeout) as never);
}
-
-/**
- * @see https://github.com/misskey-dev/misskey/issues/11267
- */
-export function semaphore(counter = 0, waiting: (() => void)[] = []) {
- return {
- acquire: () => ++counter > 1 && new Promise<void>(resolve => waiting.push(resolve)),
- release: () => --counter && waiting.pop()?.(),
- };
-}