Skip to content

Commit 9bb6c53

Browse files
authored
test(#10336): add components/Mk[A-B].* stories (#10475)
* chore(#10336): register snippets * test(#10336): add `components/Mk[A-B].*` stories * build: desynced lockfile * ci(#10336): preload assets * ci(#10336): use pull_request * build: update lockfile * fix: reactivity transform * chore: track upstream changes * refactor: avoid temporary previous tapping declarations * revert: avoid temporary previous tapping declarations This reverts commit e649b1b. * test: flaky snapshots * style: import
1 parent 2a7ba37 commit 9bb6c53

21 files changed

+617
-245
lines changed

CONTRIBUTING.md

-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ You can override the default story by creating a impl story file (`MyComponent.s
245245

246246
```ts
247247
/* eslint-disable @typescript-eslint/explicit-function-return-type */
248-
/* eslint-disable import/no-duplicates */
249248
import { StoryObj } from '@storybook/vue3';
250249
import MyComponent from './MyComponent.vue';
251250
export const Default = {

packages/frontend/.storybook/generate.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ function toStories(component: string): string {
118118
.replace(/[-.]|^(?=\d)/g, '_')
119119
.replace(/(?<=^[^A-Z_]*$)/, '_')}
120120
/> as estree.Identifier;
121-
const parameters = (
121+
const parameters =
122122
<object-expression
123123
properties={[
124124
<property
@@ -137,9 +137,8 @@ function toStories(component: string): string {
137137
]
138138
: []),
139139
]}
140-
/>
141-
) as estree.ObjectExpression;
142-
const program = (
140+
/> as estree.ObjectExpression;
141+
const program =
143142
<program
144143
body={[
145144
<import-declaration
@@ -379,11 +378,11 @@ function toStories(component: string): string {
379378
declaration={(<identifier name='meta' />) as estree.Identifier}
380379
/> as estree.ExportDefaultDeclaration,
381380
]}
382-
/>
383-
) as estree.Program;
381+
/> as estree.Program;
384382
return format(
385383
'/* eslint-disable @typescript-eslint/explicit-function-return-type */\n' +
386384
'/* eslint-disable import/no-default-export */\n' +
385+
'/* eslint-disable import/no-duplicates */\n' +
387386
generate(program, { generator }) +
388387
(hasImplStories ? readFileSync(`${implStories}.ts`, 'utf-8') : ''),
389388
{
@@ -397,6 +396,7 @@ function toStories(component: string): string {
397396
// glob('src/{components,pages,ui,widgets}/**/*.vue')
398397
Promise.all([
399398
glob('src/components/global/*.vue'),
399+
glob('src/components/Mk{A,B}*.vue'),
400400
glob('src/components/MkGalleryPostPreview.vue'),
401401
glob('src/pages/user/home.vue'),
402402
])

packages/frontend/.storybook/mocks.ts

+10
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ export const onUnhandledRequest = ((req, print) => {
88
}) satisfies SharedOptions['onUnhandledRequest'];
99

1010
export const commonHandlers = [
11+
rest.get('/fluent-emoji/:codepoints.png', async (req, res, ctx) => {
12+
const { codepoints } = req.params;
13+
const value = await fetch(`https://raw.githubusercontent.com/misskey-dev/emojis/main/dist/${codepoints}.png`).then((response) => response.blob());
14+
return res(ctx.set('Content-Type', 'image/png'), ctx.body(value));
15+
}),
16+
rest.get('/fluent-emojis/:codepoints.png', async (req, res, ctx) => {
17+
const { codepoints } = req.params;
18+
const value = await fetch(`https://raw.githubusercontent.com/misskey-dev/emojis/main/dist/${codepoints}.png`).then((response) => response.blob());
19+
return res(ctx.set('Content-Type', 'image/png'), ctx.body(value));
20+
}),
1121
rest.get('/twemoji/:codepoints.svg', async (req, res, ctx) => {
1222
const { codepoints } = req.params;
1323
const value = await fetch(`https://unpkg.com/@discordapp/[email protected]/dist/svg/${codepoints}.svg`).then((response) => response.blob());

packages/frontend/.storybook/preview-head.html

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<link rel="preload" href="https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/about-icon.png?raw=true" as="image" type="image/png" crossorigin="anonymous">
2+
<link rel="preload" href="https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/fedi.jpg?raw=true" as="image" type="image/jpeg" crossorigin="anonymous">
13
<link rel="stylesheet" href="https://unpkg.com/@tabler/[email protected]/tabler-icons.min.css">
24
<link rel="stylesheet" href="https://unpkg.com/@fontsource/m-plus-rounded-1c/index.css">
35
<style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
{
2+
"Storybook Story Impl File": {
3+
"scope": "typescript",
4+
"prefix": "storyimpl",
5+
"body": [
6+
"/* eslint-disable @typescript-eslint/explicit-function-return-type */",
7+
"import { StoryObj } from '@storybook/vue3';",
8+
"import $1 from './$1.vue';",
9+
"export const Default = {",
10+
"\trender(args) {",
11+
"\t\treturn {",
12+
"\t\t\tcomponents: {",
13+
"\t\t\t\t$1,",
14+
"\t\t\t},",
15+
"\t\t\tsetup() {",
16+
"\t\t\t\treturn {",
17+
"\t\t\t\t\targs,",
18+
"\t\t\t\t};",
19+
"\t\t\t},",
20+
"\t\t\tcomputed: {",
21+
"\t\t\t\tprops() {",
22+
"\t\t\t\t\treturn {",
23+
"\t\t\t\t\t\t...this.args,",
24+
"\t\t\t\t\t};",
25+
"\t\t\t\t},",
26+
"\t\t\t},",
27+
"\t\t\ttemplate: '<$1 v-bind=\"props\" />',",
28+
"\t\t};",
29+
"\t},",
30+
"\targs: {",
31+
"\t\t$2",
32+
"\t},",
33+
"\tparameters: {",
34+
"\t\tlayout: 'centered',",
35+
"\t},",
36+
"} satisfies StoryObj<typeof $1>;",
37+
""
38+
]
39+
},
40+
"Storybook Story Impl File (w/ events)": {
41+
"scope": "typescript",
42+
"prefix": "storyimplevent",
43+
"body": [
44+
"/* eslint-disable @typescript-eslint/explicit-function-return-type */",
45+
"import { action } from '@storybook/addon-actions';",
46+
"import { StoryObj } from '@storybook/vue3';",
47+
"import $1 from './$1.vue';",
48+
"export const Default = {",
49+
"\trender(args) {",
50+
"\t\treturn {",
51+
"\t\t\tcomponents: {",
52+
"\t\t\t\t$1,",
53+
"\t\t\t},",
54+
"\t\t\tsetup() {",
55+
"\t\t\t\treturn {",
56+
"\t\t\t\t\targs,",
57+
"\t\t\t\t};",
58+
"\t\t\t},",
59+
"\t\t\tcomputed: {",
60+
"\t\t\t\tprops() {",
61+
"\t\t\t\t\treturn {",
62+
"\t\t\t\t\t\t...this.args,",
63+
"\t\t\t\t\t};",
64+
"\t\t\t\t},",
65+
"\t\t\t\tevents() {",
66+
"\t\t\t\t\treturn {",
67+
"\t\t\t\t\t\t$3",
68+
"\t\t\t\t\t};",
69+
"\t\t\t\t},",
70+
"\t\t\t},",
71+
"\t\t\ttemplate: '<$1 v-bind=\"props\" v-on=\"events\" />',",
72+
"\t\t};",
73+
"\t},",
74+
"\targs: {",
75+
"\t\t$2",
76+
"\t},",
77+
"\tparameters: {",
78+
"\t\tlayout: 'centered',",
79+
"\t},",
80+
"} satisfies StoryObj<typeof $1>;",
81+
""
82+
]
83+
}
84+
}

packages/frontend/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
"vuedraggable": "next"
7575
},
7676
"devDependencies": {
77+
"@storybook/addon-actions": "7.0.2",
7778
"@storybook/addon-essentials": "7.0.2",
7879
"@storybook/addon-interactions": "7.0.2",
7980
"@storybook/addon-links": "7.0.2",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
2+
import { action } from '@storybook/addon-actions';
3+
import { StoryObj } from '@storybook/vue3';
4+
import { rest } from 'msw';
5+
import { abuseUserReport } from '../../.storybook/fakes';
6+
import { commonHandlers } from '../../.storybook/mocks';
7+
import MkAbuseReport from './MkAbuseReport.vue';
8+
export const Default = {
9+
render(args) {
10+
return {
11+
components: {
12+
MkAbuseReport,
13+
},
14+
setup() {
15+
return {
16+
args,
17+
};
18+
},
19+
computed: {
20+
props() {
21+
return {
22+
...this.args,
23+
};
24+
},
25+
events() {
26+
return {
27+
resolved: action('resolved'),
28+
};
29+
},
30+
},
31+
template: '<MkAbuseReport v-bind="props" v-on="events" />',
32+
};
33+
},
34+
args: {
35+
report: abuseUserReport(),
36+
},
37+
parameters: {
38+
layout: 'fullscreen',
39+
msw: {
40+
handlers: [
41+
...commonHandlers,
42+
rest.post('/api/admin/resolve-abuse-user-report', async (req, res, ctx) => {
43+
action('POST /api/admin/resolve-abuse-user-report')(await req.json());
44+
return res(ctx.json({}));
45+
}),
46+
],
47+
},
48+
},
49+
} satisfies StoryObj<typeof MkAbuseReport>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
2+
import { action } from '@storybook/addon-actions';
3+
import { StoryObj } from '@storybook/vue3';
4+
import { rest } from 'msw';
5+
import { userDetailed } from '../../.storybook/fakes';
6+
import { commonHandlers } from '../../.storybook/mocks';
7+
import MkAbuseReportWindow from './MkAbuseReportWindow.vue';
8+
export const Default = {
9+
render(args) {
10+
return {
11+
components: {
12+
MkAbuseReportWindow,
13+
},
14+
setup() {
15+
return {
16+
args,
17+
};
18+
},
19+
computed: {
20+
props() {
21+
return {
22+
...this.args,
23+
};
24+
},
25+
events() {
26+
return {
27+
'closed': action('closed'),
28+
};
29+
},
30+
},
31+
template: '<MkAbuseReportWindow v-bind="props" v-on="events" />',
32+
};
33+
},
34+
args: {
35+
user: userDetailed(),
36+
},
37+
parameters: {
38+
layout: 'centered',
39+
msw: {
40+
handlers: [
41+
...commonHandlers,
42+
rest.post('/api/users/report-abuse', async (req, res, ctx) => {
43+
action('POST /api/users/report-abuse')(await req.json());
44+
return res(ctx.json({}));
45+
}),
46+
],
47+
},
48+
},
49+
} satisfies StoryObj<typeof MkAbuseReportWindow>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
2+
import { StoryObj } from '@storybook/vue3';
3+
import { userDetailed } from '../../.storybook/fakes';
4+
import MkAccountMoved from './MkAccountMoved.vue';
5+
export const Default = {
6+
render(args) {
7+
return {
8+
components: {
9+
MkAccountMoved,
10+
},
11+
setup() {
12+
return {
13+
args,
14+
};
15+
},
16+
computed: {
17+
props() {
18+
return {
19+
...this.args,
20+
};
21+
},
22+
},
23+
template: '<MkAccountMoved v-bind="props" />',
24+
};
25+
},
26+
args: {
27+
username: userDetailed().username,
28+
host: userDetailed().host,
29+
},
30+
parameters: {
31+
layout: 'centered',
32+
},
33+
} satisfies StoryObj<typeof MkAccountMoved>;

packages/frontend/src/components/MkAccountMoved.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div :class="$style.root">
33
<i class="ti ti-plane-departure" style="margin-right: 8px;"></i>
44
{{ i18n.ts.accountMoved }}
5-
<MkMention :class="$style.link" :username="acct" :host="host ?? localHost"/>
5+
<MkMention :class="$style.link" :username="username" :host="host ?? localHost"/>
66
</div>
77
</template>
88

@@ -12,7 +12,7 @@ import { i18n } from '@/i18n';
1212
import { host as localHost } from '@/config';
1313
1414
defineProps<{
15-
acct: string;
15+
username: string;
1616
host: string;
1717
}>();
1818
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
2+
import { StoryObj } from '@storybook/vue3';
3+
import { rest } from 'msw';
4+
import { userDetailed } from '../../.storybook/fakes';
5+
import { commonHandlers } from '../../.storybook/mocks';
6+
import MkAchievements from './MkAchievements.vue';
7+
import { ACHIEVEMENT_TYPES } from '@/scripts/achievements';
8+
export const Empty = {
9+
render(args) {
10+
return {
11+
components: {
12+
MkAchievements,
13+
},
14+
setup() {
15+
return {
16+
args,
17+
};
18+
},
19+
computed: {
20+
props() {
21+
return {
22+
...this.args,
23+
};
24+
},
25+
},
26+
template: '<MkAchievements v-bind="props" />',
27+
};
28+
},
29+
args: {
30+
user: userDetailed(),
31+
},
32+
parameters: {
33+
layout: 'fullscreen',
34+
msw: {
35+
handlers: [
36+
...commonHandlers,
37+
rest.post('/api/users/achievements', (req, res, ctx) => {
38+
return res(ctx.json([]));
39+
}),
40+
],
41+
},
42+
},
43+
} satisfies StoryObj<typeof MkAchievements>;
44+
export const All = {
45+
...Empty,
46+
parameters: {
47+
msw: {
48+
handlers: [
49+
...commonHandlers,
50+
rest.post('/api/users/achievements', (req, res, ctx) => {
51+
return res(ctx.json(ACHIEVEMENT_TYPES.map((name) => ({ name, unlockedAt: 0 }))));
52+
}),
53+
],
54+
},
55+
},
56+
} satisfies StoryObj<typeof MkAchievements>;

packages/frontend/src/components/MkAnalogClock.stories.impl.ts

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable @typescript-eslint/explicit-function-return-type */
22
import { StoryObj } from '@storybook/vue3';
33
import MkAnalogClock from './MkAnalogClock.vue';
4+
import isChromatic from 'chromatic';
45
export const Default = {
56
render(args) {
67
return {
@@ -22,6 +23,14 @@ export const Default = {
2223
template: '<MkAnalogClock v-bind="props" />',
2324
};
2425
},
26+
args: {
27+
now: isChromatic() ? () => new Date('2023-01-01T10:10:30') : undefined,
28+
},
29+
decorators: [
30+
() => ({
31+
template: '<div style="container-type:inline-size;height:100%"><div style="height:100cqmin;margin:auto;width:100cqmin"><story/></div></div>',
32+
}),
33+
],
2534
parameters: {
2635
layout: 'fullscreen',
2736
},

0 commit comments

Comments
 (0)