From 01b7ce11bab2becd1b7373bdc443918848d3666a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?=
 <root@acid-chicken.com>
Date: Mon, 29 May 2023 04:59:44 +0900
Subject: [PATCH] test: add stories for `MkChannelFollowButton`

---
 packages/frontend/.storybook/fakes.ts         |  46 ++++++++
 packages/frontend/.storybook/generate.tsx     |   2 +-
 .../MkChannelFollowButton.stories.impl.ts     | 109 ++++++++++++++++++
 3 files changed, 156 insertions(+), 1 deletion(-)
 create mode 100644 packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts

diff --git a/packages/frontend/.storybook/fakes.ts b/packages/frontend/.storybook/fakes.ts
index 5fd21cdf0..b9558948a 100644
--- a/packages/frontend/.storybook/fakes.ts
+++ b/packages/frontend/.storybook/fakes.ts
@@ -17,6 +17,27 @@ export function abuseUserReport() {
 	};
 }
 
+export function channel() {
+	return {
+		id: 'somechannelid',
+		createdAt: '2016-12-28T22:49:51.000Z',
+		lastNotedAt: '2023-01-01T00:00:00.000Z',
+		name: 'AKANEā˜†CHANNEL',
+		description: 'sweetie sweet',
+		userId: 'someuserid',
+		bannerUrl: 'https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/fedi.jpg?raw=true',
+		pinnedNoteIds: ['somenoteid'],
+		color: '#eb613f',
+		isArchived: false,
+		usersCount: 16,
+		notesCount: 1024,
+		isFollowing: false,
+		isFavorited: false,
+		hasUnreadNote: false,
+		pinnedNotes: [note()],
+	}
+}
+
 export function galleryPost(isSensitive = false) {
 	return {
 		id: 'somepostid',
@@ -60,6 +81,31 @@ export function file(isSensitive = false) {
 	};
 }
 
+export function note() {
+	return {
+		id: 'somenoteid',
+		createdAt: '2016-12-28T22:49:51.000Z',
+		userId: 'someuserid',
+		user: userDetailed(),
+		text: 'make some noise',
+		cw: 'sing along',
+		visibility: 'public',
+		localOnly: false,
+		reactionAcceptance: null,
+		renoteCount: 4,
+		repliesCount: 2,
+		reactions: {
+			'šŸ‘': 16,
+			':yo@.:': 8,
+		},
+		reactionEmojis: {},
+		fileIds: [],
+		files: [],
+		replyId: null,
+		renoteId: null,
+	}
+}
+
 export function userDetailed(id = 'someuserid', username = 'miskist', host = 'misskey-hub.net', name = 'Misskey User'): entities.UserDetailed {
 	return {
 		id,
diff --git a/packages/frontend/.storybook/generate.tsx b/packages/frontend/.storybook/generate.tsx
index f44242210..4a4fbb76c 100644
--- a/packages/frontend/.storybook/generate.tsx
+++ b/packages/frontend/.storybook/generate.tsx
@@ -396,7 +396,7 @@ function toStories(component: string): string {
 // glob('src/{components,pages,ui,widgets}/**/*.vue')
 Promise.all([
 	glob('src/components/global/*.vue'),
-	glob('src/components/Mk{A,B}*.vue'),
+	glob('src/components/Mk{A,B,C}*.vue'),
 	glob('src/components/MkDigitalClock.vue'),
 	glob('src/components/MkGalleryPostPreview.vue'),
 	glob('src/components/MkSignupServerRules.vue'),
diff --git a/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts b/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts
new file mode 100644
index 000000000..1c856b77b
--- /dev/null
+++ b/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts
@@ -0,0 +1,109 @@
+/* eslint-disable @typescript-eslint/explicit-function-return-type */
+import { action } from '@storybook/addon-actions';
+import { userEvent, waitFor, within } from '@storybook/testing-library';
+import { StoryObj } from '@storybook/vue3';
+import { rest } from 'msw';
+import { channel } from '../../.storybook/fakes';
+import { commonHandlers } from '../../.storybook/mocks';
+import MkChannelFollowButton from './MkChannelFollowButton.vue';
+export const Default = {
+	render(args) {
+		return {
+			components: {
+				MkChannelFollowButton,
+			},
+			setup() {
+				return {
+					args,
+				};
+			},
+			computed: {
+				props() {
+					return {
+						...this.args,
+					};
+				},
+				events() {
+					return {
+						
+					};
+				},
+			},
+			template: '<MkChannelFollowButton v-bind="props" v-on="events" />',
+		};
+	},
+	args: {
+		channel: channel(),
+	},
+	parameters: {
+		layout: 'centered',
+		msw: {
+			handlers: [
+				...commonHandlers,
+				rest.post('/api/channels/follow', async (req, res, ctx) => {
+					action('POST /api/channels/follow')(await req.json());
+					return res(ctx.status(204));
+				}),
+				rest.post('/api/channels/unfollow', async (req, res, ctx) => {
+					action('POST /api/channels/unfollow')(await req.json());
+					return res(ctx.status(204));
+				}),
+			],
+		},
+	},
+} satisfies StoryObj<typeof MkChannelFollowButton>;
+export const Following = {
+	...Default,
+	async play({ canvasElement }) {
+		const canvas = within(canvasElement);
+		const button = canvas.getByRole('button');
+		await waitFor(() => userEvent.click(button));
+	},
+	parameters: {
+		...Default.parameters,
+		msw: {
+			handlers: [
+				...commonHandlers,
+				rest.post('/api/channels/follow', async (req, res, ctx) => {
+					action('POST /api/channels/follow')(await req.json());
+					await new Promise(() => {});
+				}),
+				rest.post('/api/channels/unfollow', async (req, res, ctx) => {
+					action('POST /api/channels/unfollow')(await req.json());
+					await new Promise(() => {});
+				}),
+			],
+		},
+	},
+}
+export const Followed = {
+	...Default,
+	args: {
+		...Default.args,
+		channel: {
+			...channel(),
+			isFollowing: true,
+		},
+	},
+} satisfies StoryObj<typeof MkChannelFollowButton>;
+export const Full = {
+	...Default,
+	args: {
+		...Default.args,
+		full: true,
+	},
+} satisfies StoryObj<typeof MkChannelFollowButton>;
+export const FullFollowing = {
+	...Following,
+	args: {
+		...Following.args,
+		full: true,
+	},
+} satisfies StoryObj<typeof MkChannelFollowButton>;
+export const FullFollowed = {
+	...Followed,
+	args: {
+		...Followed.args,
+		full: true,
+	},
+} satisfies StoryObj<typeof MkChannelFollowButton>;