This repository has no description
1<script module lang="ts">
2 import { defineMeta, type StoryContext } from "@storybook/addon-svelte-csf";
3 import { expect, waitFor } from "storybook/test";
4 import type { RepoBlobView } from "$lib/api/blob";
5 import BlobView from "./BlobView.svelte";
6
7 const lastCommit = {
8 hash: "0123456789abcdef0123456789abcdef01234567",
9 shortHash: "01234567",
10 subject: "add the blob view",
11 body: "",
12 authorName: "dawn",
13 authorEmail: "dawn@example.test",
14 when: "2026-07-28T09:00:00Z"
15 };
16
17 const codeBlob: RepoBlobView = {
18 ref: "main",
19 path: "web/src/main.ts",
20 kind: "code",
21 sizeLabel: "1.2 kB",
22 lines: 3,
23 contents: 'import { serve } from "./server";\n\nserve({ port: 5555 });\n',
24 renderedHtml: null,
25 fileTooLarge: false,
26 defaultView: "code",
27 submodule: null,
28 lastCommit
29 };
30
31 type PlayContext = Pick<
32 StoryContext<Record<string, unknown>>,
33 "canvas" | "canvasElement" | "userEvent"
34 >;
35
36 // pierre renders inside a shadow root, findByText cannot see the code
37 const shadowText = (canvasElement: HTMLElement) =>
38 canvasElement.querySelector("diffs-container")?.shadowRoot?.textContent ?? "";
39
40 const showsCode = async ({ canvas, canvasElement }: PlayContext) => {
41 await expect(canvas.getByText("main.ts")).toBeVisible();
42 await expect(canvas.getByText("3 lines")).toBeVisible();
43 await expect(canvas.getByRole("link", { name: "main" })).toBeVisible();
44 await expect(canvas.getByText("TypeScript")).toBeVisible();
45 await expect(canvas.getByRole("link", { name: "View raw" })).toBeVisible();
46 await waitFor(() => expect(shadowText(canvasElement)).toContain("serve({ port: 5555 })"));
47 };
48
49 const { Story } = defineMeta({
50 title: "Repo/BlobView",
51 component: BlobView,
52 tags: ["autodocs"],
53 args: { ownerHandle: "dawn", repoName: "tangled", blob: codeBlob, language: "TypeScript" }
54 });
55</script>
56
57<Story name="Code file" play={showsCode} />
58
59<Story
60 name="Markdown rendered"
61 args={{
62 blob: {
63 ...codeBlob,
64 path: "docs/guide.md",
65 kind: "markup",
66 lines: 5,
67 contents: "# tangled\n\nsocial code collaboration for the at protocol.\n",
68 renderedHtml: "<h1>tangled</h1><p>social code collaboration for the at protocol.</p>",
69 defaultView: "rendered"
70 }
71 }}
72 play={async ({ canvas, canvasElement, userEvent }: PlayContext) => {
73 await expect(canvas.getByRole("heading", { name: "tangled" })).toBeVisible();
74 await userEvent.click(canvas.getByRole("button", { name: "View code" }));
75 await waitFor(() => expect(shadowText(canvasElement)).toContain("# tangled"));
76 }}
77/>
78
79<Story
80 name="Image"
81 args={{
82 blob: {
83 ...codeBlob,
84 path: "assets/logo.png",
85 kind: "image",
86 sizeLabel: "18 kB",
87 lines: null,
88 contents: null
89 }
90 }}
91 play={async ({ canvas }: PlayContext) => {
92 const image = canvas.getByRole("img", { name: "assets/logo.png" });
93 await expect(image).toHaveAttribute("src", "/dawn/tangled/raw/main/assets/logo.png");
94 }}
95/>
96
97<Story
98 name="Binary unsupported"
99 args={{
100 blob: {
101 ...codeBlob,
102 path: "assets/data.bin",
103 kind: "other",
104 lines: null,
105 contents: null
106 }
107 }}
108 play={async ({ canvas }: PlayContext) => {
109 await expect(canvas.getByText("Previews are not supported for this file type.")).toBeVisible();
110 }}
111/>
112
113<Story
114 name="Submodule"
115 args={{
116 blob: {
117 ...codeBlob,
118 path: "vendor/spindle",
119 kind: "submodule",
120 sizeLabel: null,
121 lines: null,
122 contents: null,
123 submodule: { name: "spindle", url: "https://tangled.org/dawn/spindle" }
124 }
125 }}
126 play={async ({ canvas }: PlayContext) => {
127 const link = canvas.getByRole("link", { name: "https://tangled.org/dawn/spindle" });
128 await expect(link).toBeVisible();
129 await expect(canvas.getByText(/This directory is a git submodule of/)).toBeVisible();
130 }}
131/>
132
133<Story
134 name="File too large"
135 args={{
136 blob: {
137 ...codeBlob,
138 path: "data/dump.sql",
139 sizeLabel: "3.4 MB",
140 lines: null,
141 contents: null,
142 fileTooLarge: true
143 }
144 }}
145 play={async ({ canvas }: PlayContext) => {
146 await expect(canvas.getByText(/This file is too large to render/)).toBeVisible();
147 await expect(canvas.getByRole("link", { name: "View raw." })).toHaveAttribute(
148 "href",
149 "/dawn/tangled/raw/main/data/dump.sql"
150 );
151 }}
152/>