Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
Svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148<script module lang="ts"> import { defineMeta, type StoryContext } from "@storybook/addon-svelte-csf"; import { expect, screen, userEvent, waitFor } from "storybook/test"; import FollowButton from "$lib/components/profile/FollowButton.svelte";
// the toggle (create/delete) goes through the mock agent's handler, so a story // that needs a successful toggle passes `respond` on the auth parameter. const respond = (pathname: string): Response => { if (pathname.includes("createRecord")) { return Response.json({ uri: "at://did:plc:alice/sh.tangled.graph.follow/3lknew", cid: "bafyreibfko5xzzdptcimcaql4tmsaffgr6jhreyjz3tv6nlh34si6k4u7e" }); } if (pathname.includes("deleteRecord")) { return Response.json({}); } return new Response(null, { status: 404 }); };
// a never-settling respond keeps the toggle in its loading state so the // busy state can be asserted const hang = () => new Promise<Response>(() => {});
type PlayContext = Pick<StoryContext<Record<string, unknown>>, "canvas">;
const subject = "did:plc:subject";
const notFollowing = async ({ canvas }: PlayContext) => { const button = await canvas.findByRole("button", { name: "Follow" }); await waitFor(() => expect(button).toBeEnabled()); };
const following = async ({ canvas }: PlayContext) => { const button = await canvas.findByRole("button", { name: "Unfollow" }); await waitFor(() => expect(button).toBeEnabled()); };
// clicking follow: the button goes busy while the write is in flight, then // settles on "Unfollow" with the minus icon const followingNow = async ({ canvas }: PlayContext) => { const button = await canvas.findByRole("button", { name: "Follow" }); await userEvent.click(button); await waitFor(() => expect(canvas.getByRole("button", { name: "Unfollow" })).toBeVisible()); };
// a hung write: the button stays on "Follow", disabled and marked busy const followingLoading = async ({ canvas }: PlayContext) => { const button = await canvas.findByRole("button", { name: "Follow" }); await userEvent.click(button); await waitFor(() => expect(button).toHaveAttribute("aria-busy", "true")); await expect(button).toHaveTextContent("Follow"); await expect(button).toBeDisabled(); };
const unfollowing = async ({ canvas }: PlayContext) => { const button = await canvas.findByRole("button", { name: "Unfollow" }); await userEvent.click(button); await waitFor(() => expect(canvas.getByRole("button", { name: "Follow" })).toBeVisible()); };
// the toggle failed: the button turns red with a triangle-alert icon, and // hovering shows the error in a tooltip. the error clears itself after 2s. const toggleError = async ({ canvas }: PlayContext) => { const button = await canvas.findByRole("button", { name: "Follow" }); await waitFor(() => expect(button).toBeEnabled()); await userEvent.click(button); await waitFor(() => expect(canvas.getByRole("button", { name: "Follow" })).toHaveAttribute( "data-variant", "danger" ) ); await userEvent.hover(button); await waitFor(() => expect(screen.getByRole("tooltip")).toHaveTextContent("Something went wrong") ); await waitFor( () => expect(canvas.getByRole("button", { name: "Follow" })).not.toHaveAttribute( "data-variant", "danger" ), { timeout: 3000 } ); await waitFor(() => expect(canvas.queryByRole("tooltip")).toBeNull()); };
const signedOutFollow = async ({ canvas }: PlayContext) => { const [follow] = await canvas.findAllByRole("link", { name: "Follow" }); expect(follow.getAttribute("href")).toContain("/login"); };
const { Story } = defineMeta({ title: "Profile/FollowButton", component: FollowButton, tags: ["autodocs"], args: { profileDid: subject } });</script>
<Story name="Not following" asChild play={notFollowing} parameters={{ auth: true }}> <div class="w-48"> <FollowButton profileDid={subject} initialRkey={null} /> </div></Story>
<Story name="Following" asChild play={following} parameters={{ auth: true }}> <div class="w-48"> <FollowButton profileDid={subject} initialRkey="3jkfollow" /> </div></Story>
<Story name="Following now" asChild play={followingNow} parameters={{ auth: { respond } }}> <div class="w-48"> <FollowButton profileDid={subject} initialRkey={null} /> </div></Story>
<Story name="Following (loading)" asChild play={followingLoading} parameters={{ auth: { respond: hang } }}> <div class="w-48"> <FollowButton profileDid={subject} initialRkey={null} /> </div></Story>
<Story name="Unfollowing" asChild play={unfollowing} parameters={{ auth: { respond } }}> <div class="w-48"> <FollowButton profileDid={subject} initialRkey="3jkfollow" /> </div></Story>
<Story name="Toggle error" asChild play={toggleError} parameters={{ auth: true }}> <div class="w-48"> <FollowButton profileDid={subject} initialRkey={null} /> </div></Story>
<Story name="Signed out" asChild play={signedOutFollow} parameters={{ auth: false }}> <div class="w-48"> <FollowButton profileDid={subject} initialRkey={null} /> </div></Story>