adf0d17497
publish / version_or_publish (push) Has been cancelled
storybook-build / changes (push) Has been cancelled
storybook-build / :storybook-build (push) Has been cancelled
Sync Gradio Skills to Hugging Face / sync-skills (push) Has been cancelled
functional / changes (push) Has been cancelled
functional / build-frontend (push) Has been cancelled
functional / functional-test-SSR=false (push) Has been cancelled
functional / functional-reload (push) Has been cancelled
js / changes (push) Has been cancelled
js / js-test (push) Has been cancelled
docs-build / changes (push) Has been cancelled
docs-build / docs-build (push) Has been cancelled
docs-build / website-build (push) Has been cancelled
functional / functional-test-SSR=true (push) Has been cancelled
hygiene / hygiene-test (push) Has been cancelled
python / changes (push) Has been cancelled
python / build (push) Has been cancelled
python / test-ubuntu-latest-flaky (push) Has been cancelled
python / test-ubuntu-latest-not-flaky (push) Has been cancelled
python / test-windows-latest-flaky (push) Has been cancelled
python / test-windows-latest-not-flaky (push) Has been cancelled
122 lines
3.4 KiB
TypeScript
122 lines
3.4 KiB
TypeScript
/**
|
|
* Tests for Download.svelte's language → file-extension mapping.
|
|
*
|
|
* Download.svelte is not a Gradio component so the tootils render() utility
|
|
* cannot mount it with props correctly (non-shared props are wrapped under a
|
|
* `props` key rather than spread at the top level). We therefore test the
|
|
* extension mapping through the full Code component, which is the realistic
|
|
* usage path anyway.
|
|
*/
|
|
import { test, describe, afterEach, expect } from "vitest";
|
|
import { cleanup, render } from "@self/tootils/render";
|
|
|
|
import Code from "./Index.svelte";
|
|
|
|
const base_props = {
|
|
value: "// code",
|
|
lines: 5,
|
|
interactive: false,
|
|
show_label: false,
|
|
label: "Code",
|
|
buttons: ["download"] as const
|
|
};
|
|
|
|
function get_download_link(container: HTMLElement): HTMLAnchorElement {
|
|
// The Download component renders an <a download="file.ext"> anchor.
|
|
// No accessible name or role distinguishes it better than the download
|
|
// attribute itself, so querySelector is used as the last-resort query.
|
|
const link = container.querySelector<HTMLAnchorElement>("a[download]");
|
|
if (!link) throw new Error("No download link found in rendered output");
|
|
return link;
|
|
}
|
|
|
|
describe("Download: language → file extension mapping", () => {
|
|
afterEach(() => cleanup());
|
|
|
|
const cases: Array<[string, string]> = [
|
|
["python", "py"],
|
|
["py", "py"],
|
|
["javascript", "js"],
|
|
["js", "js"],
|
|
["typescript", "ts"],
|
|
["ts", "ts"],
|
|
["shell", "sh"],
|
|
["sh", "sh"],
|
|
["markdown", "md"],
|
|
["md", "md"],
|
|
["json", "json"],
|
|
["html", "html"],
|
|
["css", "css"],
|
|
["yaml", "yaml"],
|
|
["yml", "yml"],
|
|
["dockerfile", "dockerfile"],
|
|
["latex", "tex"],
|
|
["r", "r"],
|
|
["c", "c"],
|
|
["cpp", "cpp"]
|
|
];
|
|
|
|
for (const [language, expected_ext] of cases) {
|
|
test(`language='${language}' produces download filename 'file.${expected_ext}'`, async () => {
|
|
const { container } = await render(Code, {
|
|
...base_props,
|
|
language
|
|
});
|
|
const link = get_download_link(container);
|
|
expect(link).toHaveAttribute("download", `file.${expected_ext}`);
|
|
});
|
|
}
|
|
|
|
test("unknown language falls back to 'file.txt'", async () => {
|
|
const { container } = await render(Code, {
|
|
...base_props,
|
|
language: "brainfuck"
|
|
});
|
|
const link = get_download_link(container);
|
|
expect(link).toHaveAttribute("download", "file.txt");
|
|
});
|
|
|
|
test("null language falls back to 'file.txt'", async () => {
|
|
const { container } = await render(Code, {
|
|
...base_props,
|
|
language: null
|
|
});
|
|
const link = get_download_link(container);
|
|
expect(link).toHaveAttribute("download", "file.txt");
|
|
});
|
|
});
|
|
|
|
describe("Download: link structure", () => {
|
|
afterEach(() => cleanup());
|
|
|
|
test("download link href is a blob URL", async () => {
|
|
const { container } = await render(Code, {
|
|
...base_props,
|
|
language: "python"
|
|
});
|
|
const link = get_download_link(container);
|
|
expect(link.getAttribute("href")).toMatch(/^blob:/);
|
|
});
|
|
|
|
test("download link is visible", async () => {
|
|
const { container } = await render(Code, {
|
|
...base_props,
|
|
language: "python"
|
|
});
|
|
const link = get_download_link(container);
|
|
expect(link).toBeVisible();
|
|
});
|
|
|
|
test("download link contains a button with label 'Download'", async () => {
|
|
const { getByLabelText } = await render(Code, {
|
|
...base_props,
|
|
language: "python"
|
|
});
|
|
expect(getByLabelText("Download")).toBeTruthy();
|
|
});
|
|
|
|
test.todo(
|
|
"VISUAL: clicking the download link changes the icon from Download to Check for ~2 seconds — needs Playwright screenshot comparison"
|
|
);
|
|
});
|