Skip to content

Commit 89f7a09

Browse files
authored
Layout tests (#13231)
1 parent 0dd1c79 commit 89f7a09

File tree

14 files changed

+822
-74
lines changed

14 files changed

+822
-74
lines changed

.changeset/eleven-paths-flash.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@gradio/column": patch
3+
"@gradio/dataset": patch
4+
"@gradio/form": patch
5+
"@gradio/group": patch
6+
"@gradio/row": patch
7+
"@gradio/sidebar": patch
8+
"gradio": patch
9+
---
10+
11+
feat:Layout tests

js/column/Column.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { test, describe, afterEach, expect } from "vitest";
2+
import { cleanup, render } from "@self/tootils/render";
3+
4+
import Column from "./Index.svelte";
5+
import ColumnWithChild from "./WithChild.svelte";
6+
7+
describe("Column", () => {
8+
afterEach(() => cleanup());
9+
10+
test("renders the column container", async () => {
11+
const { container } = await render(Column, {});
12+
// No role, label, or text available for a bare layout container —
13+
// querySelector(".column") is the appropriate query here.
14+
expect(container.querySelector(".column")).not.toBeNull();
15+
});
16+
17+
test("elem_id is applied to the root div", async () => {
18+
const { container } = await render(Column, { elem_id: "my-column" });
19+
expect(container.querySelector("#my-column")).not.toBeNull();
20+
});
21+
22+
test("elem_classes are applied to the root div", async () => {
23+
const { container } = await render(Column, {
24+
elem_classes: ["my-col-class"]
25+
});
26+
expect(container.querySelector(".my-col-class")).not.toBeNull();
27+
});
28+
29+
test("visible: true → container is visible", async () => {
30+
const { container } = await render(Column, {
31+
visible: true,
32+
elem_id: "col-visible"
33+
});
34+
expect(container.querySelector("#col-visible")).toBeVisible();
35+
});
36+
37+
test("visible: false → container is hidden in the DOM", async () => {
38+
const { container } = await render(Column, {
39+
visible: false,
40+
elem_id: "col-false"
41+
});
42+
const el = container.querySelector("#col-false");
43+
expect(el).not.toBeNull();
44+
expect(el).not.toBeVisible();
45+
});
46+
47+
test("visible: 'hidden' does NOT hide the container (Column uses !visible — 'hidden' is truthy)", async () => {
48+
// BaseColumn uses class:hide={!visible}. "hidden" is a non-empty string and
49+
// therefore truthy, so !("hidden") === false — .hide is not applied.
50+
// Same pattern as Row.
51+
const { container } = await render(Column, {
52+
visible: "hidden",
53+
elem_id: "col-str-hidden"
54+
});
55+
const el = container.querySelector("#col-str-hidden");
56+
expect(el).not.toBeNull();
57+
expect(el).toBeVisible();
58+
});
59+
});
60+
61+
describe("Children / slot", () => {
62+
afterEach(() => cleanup());
63+
64+
test("renders slot children inside the column container", async () => {
65+
const { getByTestId } = await render(ColumnWithChild, {});
66+
expect(getByTestId("slot-content")).not.toBeNull();
67+
});
68+
69+
test("slot children are visible when column is visible", async () => {
70+
const { getByTestId } = await render(ColumnWithChild, { visible: true });
71+
expect(getByTestId("slot-content")).toBeVisible();
72+
});
73+
74+
test("slot children are hidden when column is hidden (visible: false)", async () => {
75+
const { getByTestId } = await render(ColumnWithChild, { visible: false });
76+
// Column applies display:none via .hide class — children inherit the hidden state
77+
expect(getByTestId("slot-content")).not.toBeVisible();
78+
});
79+
});
80+
81+
test.todo(
82+
"VISUAL: variant='panel' applies panel border, background fill, and padding to the column container — needs Playwright visual regression screenshot comparison"
83+
);
84+
test.todo(
85+
"VISUAL: variant='compact' removes border-radius from direct child elements — needs Playwright visual regression screenshot comparison"
86+
);
87+
test.todo(
88+
"VISUAL: scale prop controls flex-grow, making the column proportionally wider when scale > 1 — needs Playwright visual regression screenshot comparison"
89+
);
90+
test.todo(
91+
"VISUAL: min_width prop enforces a minimum pixel width before the column wraps to a new row — needs Playwright visual regression screenshot comparison"
92+
);

js/column/WithChild.svelte

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script lang="ts">
2+
import Column from "./Index.svelte";
3+
let props = $props();
4+
</script>
5+
6+
<Column {...props}>
7+
<div data-testid="slot-content">test child</div>
8+
</Column>

js/dataframe/Dataframe.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { test, describe, afterEach, expect } from "vitest";
2-
import { cleanup, render, fireEvent } from "@self/tootils/render";
2+
import { cleanup, render, fireEvent, waitFor } from "@self/tootils/render";
33
import { tick } from "svelte";
44

55
import Dataframe from "./Index.svelte";
@@ -701,9 +701,11 @@ describe("Copy", () => {
701701

702702
const table_wrap = get_table_wrap(container)!;
703703
await fireEvent.keyDown(table_wrap, { key: "c", metaKey: true });
704-
await wait(100);
705704

706-
const clipboard = await navigator.clipboard.readText();
707-
expect(clipboard).toBe("Alice");
705+
// handle_copy() is async but called without await in the keydown handler,
706+
// so the clipboard write may not be complete immediately. Poll until it settles.
707+
await waitFor(async () => {
708+
expect(await navigator.clipboard.readText()).toBe("Alice");
709+
});
708710
});
709711
});

js/dataset/Dataset.svelte

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
value: any;
111111
component: LoadingComponent;
112112
runtime: false | typeof import("svelte");
113-
}[][] = [];
113+
}[][] = $state([]);
114114
115115
async function get_component_meta(
116116
selected_samples_json: string
@@ -145,10 +145,39 @@
145145
let selected_samples_json = $derived(JSON.stringify(selected_samples || []));
146146
</script>
147147

148-
{#await get_component_meta(selected_samples_json) then _}
148+
{#await get_component_meta(selected_samples_json)}
149149
{#if gallery}
150150
<div class="gallery">
151-
{#each selected_samples as sample_row, i}
151+
{#each selected_samples as sample_row, i (i)}
152+
{#if sample_row[0] != null}
153+
<button
154+
class="gallery-item"
155+
onclick={() => {
156+
value = i + page * samples_per_page;
157+
onclick({ index: value, value: sample_row });
158+
onselect({ index: value, value: sample_row });
159+
}}
160+
onmouseenter={() => handle_mouseenter(i)}
161+
onmouseleave={() => handle_mouseleave()}
162+
>
163+
{#if sample_labels}
164+
<BaseExample
165+
value={sample_row[0]}
166+
selected={current_hover === i}
167+
type="gallery"
168+
/>
169+
{:else}
170+
{sample_row[0]}
171+
{/if}
172+
</button>
173+
{/if}
174+
{/each}
175+
</div>
176+
{/if}
177+
{:then _}
178+
{#if gallery}
179+
<div class="gallery">
180+
{#each selected_samples as sample_row, i (i)}
152181
{#if sample_row[0] != null}
153182
<button
154183
class="gallery-item"
@@ -192,15 +221,15 @@
192221
<table tabindex="0" role="grid">
193222
<thead>
194223
<tr class="tr-head">
195-
{#each headers as header}
224+
{#each headers as header (header)}
196225
<th>
197226
{header}
198227
</th>
199228
{/each}
200229
</tr>
201230
</thead>
202231
<tbody>
203-
{#each component_meta as sample_row, i}
232+
{#each component_meta as sample_row, i (i)}
204233
<tr
205234
class="tr-body"
206235
onclick={() => {
@@ -214,7 +243,7 @@
214243
onmouseenter={() => handle_mouseenter(i)}
215244
onmouseleave={() => handle_mouseleave()}
216245
>
217-
{#each sample_row as { value, component, runtime }, j}
246+
{#each sample_row as { value, component, runtime }, j (j)}
218247
{@const component_name = components[j]}
219248

220249
{#if component_name !== undefined}
@@ -249,7 +278,7 @@
249278
{#if paginate}
250279
<div class="paginate">
251280
Pages:
252-
{#each visible_pages as visible_page}
281+
{#each visible_pages as visible_page (visible_page)}
253282
{#if visible_page === -1}
254283
<div>...</div>
255284
{:else}

0 commit comments

Comments
 (0)