mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-03 23:14:13 +00:00 
			
		
		
		
	* test(storybook): add `components/Mk[D-E].*` stories * fix: mock instance name * fix: invalid `reactionAcceptance` value * style: missing trailing commas
This commit is contained in:
		
							parent
							
								
									5c42a0e439
								
							
						
					
					
						commit
						c7354c5e30
					
				
					 17 changed files with 597 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -47,18 +47,7 @@ export function clip(id = 'someclipid', name = 'Some Clip'): entities.Clip {
 | 
			
		|||
		createdAt: '2016-12-28T22:49:51.000Z',
 | 
			
		||||
		lastClippedAt: null,
 | 
			
		||||
		userId: 'someuserid',
 | 
			
		||||
		user: {
 | 
			
		||||
			id: 'someuserid',
 | 
			
		||||
			name: 'Misskey User',
 | 
			
		||||
			username: 'miskist',
 | 
			
		||||
			host: 'misskey-hub.net',
 | 
			
		||||
			avatarUrl: 'https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/about-icon.png?raw=true',
 | 
			
		||||
			avatarBlurhash: 'eQFRshof5NWBRi},juayfPju53WB?0ofs;s*a{ofjuay^SoMEJR%ay',
 | 
			
		||||
			avatarDecorations: [],
 | 
			
		||||
			emojis: {},
 | 
			
		||||
			badgeRoles: [],
 | 
			
		||||
			onlineStatus: 'unknown',
 | 
			
		||||
		},
 | 
			
		||||
		user: userLite(),
 | 
			
		||||
		notesCount: undefined,
 | 
			
		||||
		name,
 | 
			
		||||
		description: 'Some clip description',
 | 
			
		||||
| 
						 | 
				
			
			@ -125,6 +114,15 @@ export function file(isSensitive = false) {
 | 
			
		|||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function folder(id = 'somefolderid', name = 'Some Folder', parentId: string | null = null): entities.DriveFolder {
 | 
			
		||||
	return {
 | 
			
		||||
		id,
 | 
			
		||||
		createdAt: '2016-12-28T22:49:51.000Z',
 | 
			
		||||
		name,
 | 
			
		||||
		parentId,
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function federationInstance(): entities.FederationInstance {
 | 
			
		||||
	return {
 | 
			
		||||
		id: 'someinstanceid',
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +152,27 @@ export function federationInstance(): entities.FederationInstance {
 | 
			
		|||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function userDetailed(id = 'someuserid', username = 'miskist', host:entities.UserDetailed['host'] = 'misskey-hub.net', name:entities.UserDetailed['name'] = 'Misskey User'): entities.UserDetailed {
 | 
			
		||||
export function note(id = 'somenoteid'): entities.Note {
 | 
			
		||||
	return {
 | 
			
		||||
		id,
 | 
			
		||||
		createdAt: '2016-12-28T22:49:51.000Z',
 | 
			
		||||
		deletedAt: null,
 | 
			
		||||
		text: 'some note',
 | 
			
		||||
		cw: null,
 | 
			
		||||
		userId: 'someuserid',
 | 
			
		||||
		user: userLite(),
 | 
			
		||||
		visibility: 'public',
 | 
			
		||||
		reactionAcceptance: 'nonSensitiveOnly',
 | 
			
		||||
		reactionEmojis: {},
 | 
			
		||||
		reactions: {},
 | 
			
		||||
		myReaction: null,
 | 
			
		||||
		reactionCount: 0,
 | 
			
		||||
		renoteCount: 0,
 | 
			
		||||
		repliesCount: 0,
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function userLite(id = 'someuserid', username = 'miskist', host: entities.UserDetailed['host'] = 'misskey-hub.net', name: entities.UserDetailed['name'] = 'Misskey User'): entities.UserLite {
 | 
			
		||||
	return {
 | 
			
		||||
		id,
 | 
			
		||||
		username,
 | 
			
		||||
| 
						 | 
				
			
			@ -165,6 +183,12 @@ export function userDetailed(id = 'someuserid', username = 'miskist', host:entit
 | 
			
		|||
		avatarBlurhash: 'eQFRshof5NWBRi},juayfPju53WB?0ofs;s*a{ofjuay^SoMEJR%ay',
 | 
			
		||||
		avatarDecorations: [],
 | 
			
		||||
		emojis: {},
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function userDetailed(id = 'someuserid', username = 'miskist', host: entities.UserDetailed['host'] = 'misskey-hub.net', name: entities.UserDetailed['name'] = 'Misskey User'): entities.UserDetailed {
 | 
			
		||||
	return {
 | 
			
		||||
		...userLite(id, username, host, name),
 | 
			
		||||
		bannerBlurhash: 'eQA^IW^-MH8w9tE8I=S^o{$*R4RikXtSxutRozjEnNR.RQadoyozog',
 | 
			
		||||
		bannerUrl: 'https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/fedi.jpg?raw=true',
 | 
			
		||||
		birthday: '2014-06-20',
 | 
			
		||||
| 
						 | 
				
			
			@ -215,7 +239,7 @@ export function userDetailed(id = 'someuserid', username = 'miskist', host:entit
 | 
			
		|||
		movedTo: null,
 | 
			
		||||
		alsoKnownAs: null,
 | 
			
		||||
		notify: 'none',
 | 
			
		||||
		memo: null
 | 
			
		||||
		memo: null,
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -397,8 +397,7 @@ function toStories(component: string): Promise<string> {
 | 
			
		|||
	const globs = await Promise.all([
 | 
			
		||||
		glob('src/components/global/Mk*.vue'),
 | 
			
		||||
		glob('src/components/global/RouterView.vue'),
 | 
			
		||||
		glob('src/components/Mk[A-C]*.vue'),
 | 
			
		||||
		glob('src/components/MkDigitalClock.vue'),
 | 
			
		||||
		glob('src/components/Mk[A-E]*.vue'),
 | 
			
		||||
		glob('src/components/MkGalleryPostPreview.vue'),
 | 
			
		||||
		glob('src/components/MkSignupServerRules.vue'),
 | 
			
		||||
		glob('src/components/MkUserSetupDialog.vue'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import MkDateSeparatedList from './MkDateSeparatedList.vue';
 | 
			
		||||
void MkDateSeparatedList;
 | 
			
		||||
							
								
								
									
										159
									
								
								packages/frontend/src/components/MkDialog.stories.impl.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								packages/frontend/src/components/MkDialog.stories.impl.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,159 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { action } from '@storybook/addon-actions';
 | 
			
		||||
import { expect, userEvent, waitFor, within } from '@storybook/test';
 | 
			
		||||
import { StoryObj } from '@storybook/vue3';
 | 
			
		||||
import { i18n } from '@/i18n.js';
 | 
			
		||||
import MkDialog from './MkDialog.vue';
 | 
			
		||||
const Base = {
 | 
			
		||||
	render(args) {
 | 
			
		||||
		return {
 | 
			
		||||
			components: {
 | 
			
		||||
				MkDialog,
 | 
			
		||||
			},
 | 
			
		||||
			setup() {
 | 
			
		||||
				return {
 | 
			
		||||
					args,
 | 
			
		||||
				};
 | 
			
		||||
			},
 | 
			
		||||
			computed: {
 | 
			
		||||
				props() {
 | 
			
		||||
					return {
 | 
			
		||||
						...this.args,
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
				events() {
 | 
			
		||||
					return {
 | 
			
		||||
						done: action('done'),
 | 
			
		||||
						closed: action('closed'),
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			template: '<MkDialog v-bind="props" v-on="events" />',
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	args: {
 | 
			
		||||
		text: 'Hello, world!',
 | 
			
		||||
	},
 | 
			
		||||
	parameters: {
 | 
			
		||||
		layout: 'centered',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
export const Success = {
 | 
			
		||||
	...Base,
 | 
			
		||||
	args: {
 | 
			
		||||
		...Base.args,
 | 
			
		||||
		type: 'success',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
export const Error = {
 | 
			
		||||
	...Base,
 | 
			
		||||
	args: {
 | 
			
		||||
		...Base.args,
 | 
			
		||||
		type: 'error',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
export const Warning = {
 | 
			
		||||
	...Base,
 | 
			
		||||
	args: {
 | 
			
		||||
		...Base.args,
 | 
			
		||||
		type: 'warning',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
export const Info = {
 | 
			
		||||
	...Base,
 | 
			
		||||
	args: {
 | 
			
		||||
		...Base.args,
 | 
			
		||||
		type: 'info',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
export const Question = {
 | 
			
		||||
	...Base,
 | 
			
		||||
	args: {
 | 
			
		||||
		...Base.args,
 | 
			
		||||
		type: 'question',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
export const Waiting = {
 | 
			
		||||
	...Base,
 | 
			
		||||
	args: {
 | 
			
		||||
		...Base.args,
 | 
			
		||||
		type: 'waiting',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
export const DialogWithActions = {
 | 
			
		||||
	...Question,
 | 
			
		||||
	args: {
 | 
			
		||||
		...Question.args,
 | 
			
		||||
		text: i18n.ts.areYouSure,
 | 
			
		||||
		actions: [
 | 
			
		||||
			{
 | 
			
		||||
				text: i18n.ts.yes,
 | 
			
		||||
				primary: true,
 | 
			
		||||
				callback() {
 | 
			
		||||
					action('YES')();
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				text: i18n.ts.no,
 | 
			
		||||
				callback() {
 | 
			
		||||
					action('NO')();
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		],
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
export const DialogWithDangerActions = {
 | 
			
		||||
	...Warning,
 | 
			
		||||
	args: {
 | 
			
		||||
		...Warning.args,
 | 
			
		||||
		text: i18n.ts.resetAreYouSure,
 | 
			
		||||
		actions: [
 | 
			
		||||
			{
 | 
			
		||||
				text: i18n.ts.yes,
 | 
			
		||||
				danger: true,
 | 
			
		||||
				primary: true,
 | 
			
		||||
				callback() {
 | 
			
		||||
					action('YES')();
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				text: i18n.ts.no,
 | 
			
		||||
				callback() {
 | 
			
		||||
					action('NO')();
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		],
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
export const DialogWithInput = {
 | 
			
		||||
	...Question,
 | 
			
		||||
	args: {
 | 
			
		||||
		...Question.args,
 | 
			
		||||
		title: 'Hello, world!',
 | 
			
		||||
		text: undefined,
 | 
			
		||||
		input: {
 | 
			
		||||
			placeholder: i18n.ts.inputMessageHere,
 | 
			
		||||
			type: 'text',
 | 
			
		||||
			default: null,
 | 
			
		||||
			minLength: 2,
 | 
			
		||||
			maxLength: 3,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	async play({ canvasElement }) {
 | 
			
		||||
		const canvas = within(canvasElement);
 | 
			
		||||
		await expect(canvasElement).toHaveTextContent(i18n.tsx._dialog.charactersBelow({ current: 0, min: 2 }));
 | 
			
		||||
		const okButton = canvas.getByRole('button', { name: i18n.ts.ok });
 | 
			
		||||
		await expect(okButton).toBeDisabled();
 | 
			
		||||
		const input = canvas.getByRole<HTMLInputElement>('combobox');
 | 
			
		||||
		await waitFor(() => userEvent.hover(input));
 | 
			
		||||
		await waitFor(() => userEvent.click(input));
 | 
			
		||||
		await waitFor(() => userEvent.type(input, 'M'));
 | 
			
		||||
		await expect(canvasElement).toHaveTextContent(i18n.tsx._dialog.charactersBelow({ current: 1, min: 2 }));
 | 
			
		||||
		await waitFor(() => userEvent.type(input, 'i'));
 | 
			
		||||
		await expect(okButton).toBeEnabled();
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDialog>;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import MkDivider from './MkDivider.vue';
 | 
			
		||||
void MkDivider;
 | 
			
		||||
							
								
								
									
										54
									
								
								packages/frontend/src/components/MkDonation.stories.impl.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								packages/frontend/src/components/MkDonation.stories.impl.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { action } from '@storybook/addon-actions';
 | 
			
		||||
import { StoryObj } from '@storybook/vue3';
 | 
			
		||||
import { onBeforeUnmount } from 'vue';
 | 
			
		||||
import MkDonation from './MkDonation.vue';
 | 
			
		||||
import { instance } from '@/instance.js';
 | 
			
		||||
export const Default = {
 | 
			
		||||
	render(args) {
 | 
			
		||||
		return {
 | 
			
		||||
			components: {
 | 
			
		||||
				MkDonation,
 | 
			
		||||
			},
 | 
			
		||||
			setup() {
 | 
			
		||||
				return {
 | 
			
		||||
					args,
 | 
			
		||||
				};
 | 
			
		||||
			},
 | 
			
		||||
			computed: {
 | 
			
		||||
				props() {
 | 
			
		||||
					return {
 | 
			
		||||
						...this.args,
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
				events() {
 | 
			
		||||
					return {
 | 
			
		||||
						closed: action('closed'),
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			template: '<MkDonation v-bind="props" v-on="events" />',
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	args: {
 | 
			
		||||
		// @ts-expect-error name is used for mocking instance
 | 
			
		||||
		name: 'Misskey Hub',
 | 
			
		||||
	},
 | 
			
		||||
	decorators: [
 | 
			
		||||
		(_, { args }) => ({
 | 
			
		||||
			setup() {
 | 
			
		||||
				// @ts-expect-error name is used for mocking instance
 | 
			
		||||
				instance.name = args.name;
 | 
			
		||||
				onBeforeUnmount(() => instance.name = null);
 | 
			
		||||
			},
 | 
			
		||||
			template: '<story/>',
 | 
			
		||||
		}),
 | 
			
		||||
	],
 | 
			
		||||
	parameters: {
 | 
			
		||||
		layout: 'centered',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDonation>;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { action } from '@storybook/addon-actions';
 | 
			
		||||
import { StoryObj } from '@storybook/vue3';
 | 
			
		||||
import MkDrive_file from './MkDrive.file.vue';
 | 
			
		||||
import { file } from '../../.storybook/fakes.js';
 | 
			
		||||
export const Default = {
 | 
			
		||||
	render(args) {
 | 
			
		||||
		return {
 | 
			
		||||
			components: {
 | 
			
		||||
				MkDrive_file,
 | 
			
		||||
			},
 | 
			
		||||
			setup() {
 | 
			
		||||
				return {
 | 
			
		||||
					args,
 | 
			
		||||
				};
 | 
			
		||||
			},
 | 
			
		||||
			computed: {
 | 
			
		||||
				props() {
 | 
			
		||||
					return {
 | 
			
		||||
						...this.args,
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
				events() {
 | 
			
		||||
					return {
 | 
			
		||||
						chosen: action('chosen'),
 | 
			
		||||
						dragstart: action('dragstart'),
 | 
			
		||||
						dragend: action('dragend'),
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			template: '<MkDrive_file v-bind="props" v-on="events" />',
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	args: {
 | 
			
		||||
		file: file(),
 | 
			
		||||
	},
 | 
			
		||||
	parameters: {
 | 
			
		||||
		chromatic: {
 | 
			
		||||
			// NOTE: ロードが終わるまで待つ
 | 
			
		||||
			delay: 3000,
 | 
			
		||||
		},
 | 
			
		||||
		layout: 'centered',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDrive_file>;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,70 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { action } from '@storybook/addon-actions';
 | 
			
		||||
import { StoryObj } from '@storybook/vue3';
 | 
			
		||||
import { http, HttpResponse } from 'msw';
 | 
			
		||||
import * as Misskey from 'misskey-js';
 | 
			
		||||
import MkDrive_folder from './MkDrive.folder.vue';
 | 
			
		||||
import { folder } from '../../.storybook/fakes.js';
 | 
			
		||||
import { commonHandlers } from '../../.storybook/mocks.js';
 | 
			
		||||
export const Default = {
 | 
			
		||||
	render(args) {
 | 
			
		||||
		return {
 | 
			
		||||
			components: {
 | 
			
		||||
				MkDrive_folder,
 | 
			
		||||
			},
 | 
			
		||||
			setup() {
 | 
			
		||||
				return {
 | 
			
		||||
					args,
 | 
			
		||||
				};
 | 
			
		||||
			},
 | 
			
		||||
			computed: {
 | 
			
		||||
				props() {
 | 
			
		||||
					return {
 | 
			
		||||
						...this.args,
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
				events() {
 | 
			
		||||
					return {
 | 
			
		||||
						chosen: action('chosen'),
 | 
			
		||||
						move: action('move'),
 | 
			
		||||
						upload: action('upload'),
 | 
			
		||||
						removeFile: action('removeFile'),
 | 
			
		||||
						removeFolder: action('removeFolder'),
 | 
			
		||||
						dragstart: action('dragstart'),
 | 
			
		||||
						dragend: action('dragend'),
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			template: '<MkDrive_folder v-bind="props" v-on="events" />',
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	args: {
 | 
			
		||||
		folder: folder(),
 | 
			
		||||
	},
 | 
			
		||||
	parameters: {
 | 
			
		||||
		layout: 'centered',
 | 
			
		||||
		msw: {
 | 
			
		||||
			handlers: [
 | 
			
		||||
				...commonHandlers,
 | 
			
		||||
				http.post('/api/drive/folders/delete', async ({ request }) => {
 | 
			
		||||
					action('POST /api/drive/folders/delete')(await request.json());
 | 
			
		||||
					return HttpResponse.json(undefined, { status: 204 });
 | 
			
		||||
				}),
 | 
			
		||||
				http.post('/api/drive/folders/update', async ({ request }) => {
 | 
			
		||||
					const req = await request.json() as Misskey.entities.DriveFoldersUpdateRequest;
 | 
			
		||||
					action('POST /api/drive/folders/update')(req);
 | 
			
		||||
					return HttpResponse.json({
 | 
			
		||||
						...folder(),
 | 
			
		||||
						id: req.folderId,
 | 
			
		||||
						name: req.name ?? folder().name,
 | 
			
		||||
						parentId: req.parentId ?? folder().parentId,
 | 
			
		||||
					});
 | 
			
		||||
				}),
 | 
			
		||||
			],
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDrive_folder>;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import MkDrive_navFolder from './MkDrive.navFolder.vue';
 | 
			
		||||
void MkDrive_navFolder;
 | 
			
		||||
							
								
								
									
										82
									
								
								packages/frontend/src/components/MkDrive.stories.impl.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								packages/frontend/src/components/MkDrive.stories.impl.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { action } from '@storybook/addon-actions';
 | 
			
		||||
import { StoryObj } from '@storybook/vue3';
 | 
			
		||||
import { http, HttpResponse } from 'msw';
 | 
			
		||||
import * as Misskey from 'misskey-js';
 | 
			
		||||
import MkDrive from './MkDrive.vue';
 | 
			
		||||
import { file, folder } from '../../.storybook/fakes.js';
 | 
			
		||||
import { commonHandlers } from '../../.storybook/mocks.js';
 | 
			
		||||
export const Default = {
 | 
			
		||||
	render(args) {
 | 
			
		||||
		return {
 | 
			
		||||
			components: {
 | 
			
		||||
				MkDrive,
 | 
			
		||||
			},
 | 
			
		||||
			setup() {
 | 
			
		||||
				return {
 | 
			
		||||
					args,
 | 
			
		||||
				};
 | 
			
		||||
			},
 | 
			
		||||
			computed: {
 | 
			
		||||
				props() {
 | 
			
		||||
					return {
 | 
			
		||||
						...this.args,
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
				events() {
 | 
			
		||||
					return {
 | 
			
		||||
						selected: action('selected'),
 | 
			
		||||
						'change-selection': action('change-selection'),
 | 
			
		||||
						'move-root': action('move-root'),
 | 
			
		||||
						cd: action('cd'),
 | 
			
		||||
						'open-folder': action('open-folder'),
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			template: '<MkDrive v-bind="props" v-on="events" />',
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	parameters: {
 | 
			
		||||
		chromatic: {
 | 
			
		||||
			// NOTE: ロードが終わるまで待つ
 | 
			
		||||
			delay: 3000,
 | 
			
		||||
		},
 | 
			
		||||
		layout: 'centered',
 | 
			
		||||
		msw: {
 | 
			
		||||
			handlers: [
 | 
			
		||||
				...commonHandlers,
 | 
			
		||||
				http.post('/api/drive/files', async ({ request }) => {
 | 
			
		||||
					action('POST /api/drive/files')(await request.json());
 | 
			
		||||
					return HttpResponse.json([file()]);
 | 
			
		||||
				}),
 | 
			
		||||
				http.post('/api/drive/folders', async ({ request }) => {
 | 
			
		||||
					action('POST /api/drive/folders')(await request.json());
 | 
			
		||||
					return HttpResponse.json([folder(crypto.randomUUID())]);
 | 
			
		||||
				}),
 | 
			
		||||
				http.post('/api/drive/folders/create', async ({ request }) => {
 | 
			
		||||
					const req = await request.json() as Misskey.entities.DriveFoldersCreateRequest;
 | 
			
		||||
					action('POST /api/drive/folders/create')(req);
 | 
			
		||||
					return HttpResponse.json(folder(crypto.randomUUID(), req.name, req.parentId));
 | 
			
		||||
				}),
 | 
			
		||||
				http.post('/api/drive/folders/delete', async ({ request }) => {
 | 
			
		||||
					action('POST /api/drive/folders/delete')(await request.json());
 | 
			
		||||
					return HttpResponse.json(undefined, { status: 204 });
 | 
			
		||||
				}),
 | 
			
		||||
				http.post('/api/drive/folders/update', async ({ request }) => {
 | 
			
		||||
					const req = await request.json() as Misskey.entities.DriveFoldersUpdateRequest;
 | 
			
		||||
					action('POST /api/drive/folders/update')(req);
 | 
			
		||||
					return HttpResponse.json({
 | 
			
		||||
						...folder(),
 | 
			
		||||
						id: req.folderId,
 | 
			
		||||
						name: req.name ?? folder().name,
 | 
			
		||||
						parentId: req.parentId ?? folder().parentId,
 | 
			
		||||
					});
 | 
			
		||||
				}),
 | 
			
		||||
			]
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDrive>;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { StoryObj } from '@storybook/vue3';
 | 
			
		||||
import MkDriveFileThumbnail from './MkDriveFileThumbnail.vue';
 | 
			
		||||
import { file } from '../../.storybook/fakes.js';
 | 
			
		||||
export const Default = {
 | 
			
		||||
	render(args) {
 | 
			
		||||
		return {
 | 
			
		||||
			components: {
 | 
			
		||||
				MkDriveFileThumbnail,
 | 
			
		||||
			},
 | 
			
		||||
			setup() {
 | 
			
		||||
				return {
 | 
			
		||||
					args,
 | 
			
		||||
				};
 | 
			
		||||
			},
 | 
			
		||||
			computed: {
 | 
			
		||||
				props() {
 | 
			
		||||
					return {
 | 
			
		||||
						...this.args,
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			template: '<MkDriveFileThumbnail v-bind="props" />',
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	args: {
 | 
			
		||||
		file: file(),
 | 
			
		||||
		fit: 'contain',
 | 
			
		||||
	},
 | 
			
		||||
	parameters: {
 | 
			
		||||
		chromatic: {
 | 
			
		||||
			// NOTE: ロードが終わるまで待つ
 | 
			
		||||
			delay: 3000,
 | 
			
		||||
		},
 | 
			
		||||
		layout: 'centered',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkDriveFileThumbnail>;
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
 | 
			
		|||
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
	file: Misskey.entities.DriveFile;
 | 
			
		||||
	fit: string;
 | 
			
		||||
	fit: 'cover' | 'contain';
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const is = computed(() => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import MkDriveSelectDialog from './MkDriveSelectDialog.vue';
 | 
			
		||||
void MkDriveSelectDialog;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import MkDriveWindow from './MkDriveWindow.vue';
 | 
			
		||||
void MkDriveWindow;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import MkEmojiPicker_section from './MkEmojiPicker.section.vue';
 | 
			
		||||
void MkEmojiPicker_section;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { action } from '@storybook/addon-actions';
 | 
			
		||||
import { expect, userEvent, waitFor, within } from '@storybook/test';
 | 
			
		||||
import { StoryObj } from '@storybook/vue3';
 | 
			
		||||
import { i18n } from '@/i18n.js';
 | 
			
		||||
import MkEmojiPicker from './MkEmojiPicker.vue';
 | 
			
		||||
export const Default = {
 | 
			
		||||
	render(args) {
 | 
			
		||||
		return {
 | 
			
		||||
			components: {
 | 
			
		||||
				MkEmojiPicker,
 | 
			
		||||
			},
 | 
			
		||||
			setup() {
 | 
			
		||||
				return {
 | 
			
		||||
					args,
 | 
			
		||||
				};
 | 
			
		||||
			},
 | 
			
		||||
			computed: {
 | 
			
		||||
				props() {
 | 
			
		||||
					return {
 | 
			
		||||
						...this.args,
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
				events() {
 | 
			
		||||
					return {
 | 
			
		||||
						chosen: action('chosen'),
 | 
			
		||||
					};
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			template: '<MkEmojiPicker v-bind="props" v-on="events" />',
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	async play({ canvasElement }) {
 | 
			
		||||
		const canvas = within(canvasElement);
 | 
			
		||||
		const faceSection = canvas.getByText(/face/i);
 | 
			
		||||
		await waitFor(() => userEvent.click(faceSection));
 | 
			
		||||
		const grinning = canvasElement.querySelector('[data-emoji="😀"]');
 | 
			
		||||
		await expect(grinning).toBeInTheDocument();
 | 
			
		||||
		if (grinning == null) throw new Error(); // NOTE: not called
 | 
			
		||||
		await waitFor(() => userEvent.click(grinning));
 | 
			
		||||
		const recentUsedSection = canvas.getByText(new RegExp(i18n.ts.recentUsed)).parentElement;
 | 
			
		||||
		await expect(recentUsedSection).toBeInTheDocument();
 | 
			
		||||
		if (recentUsedSection == null) throw new Error(); // NOTE: not called
 | 
			
		||||
		await expect(within(recentUsedSection).getByAltText('😀')).toBeInTheDocument();
 | 
			
		||||
		await expect(within(recentUsedSection).queryByAltText('😬')).toEqual(null);
 | 
			
		||||
	},
 | 
			
		||||
	parameters: {
 | 
			
		||||
		layout: 'centered',
 | 
			
		||||
	},
 | 
			
		||||
} satisfies StoryObj<typeof MkEmojiPicker>;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: syuilo and misskey-project
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import MkEmojiPickerDialog from './MkEmojiPickerDialog.vue';
 | 
			
		||||
void MkEmojiPickerDialog;
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue