Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions apps/bench/src/__tests__/mui-adapter.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { render, waitFor } from "@testing-library/react";
import { describe, expect, test } from "vitest";

import { MuiAdapter } from "../mui-adapter";
import type { BenchInteractionPlan } from "../interaction-plan";

const dataset = {
columns: [
Expand All @@ -14,6 +15,35 @@ const dataset = {
],
};

const statusDataset = {
columns: [
{ id: "id", header: "ID", wrap: false, widthPx: 80 },
{ id: "status", header: "Status", wrap: false, widthPx: 160 },
],
rows: [
{ id: "1", status: "running" },
{ id: "2", status: "stopped" },
{ id: "3", status: "running" },
{ id: "4", status: "idle" },
],
};

function filterPlan(
mode: "filter-metadata" | "filter-text",
filters: Record<string, string>,
): BenchInteractionPlan {
return {
focusedRowId: null,
filters,
mode,
probeColumnId: Object.keys(filters)[0] ?? "",
resultRowCount: 0,
rows: [],
selectedRowId: null,
sort: null,
};
}

describe("MuiAdapter", () => {
test("mounts and renders MUI DataGrid public selectors", async () => {
const { container } = render(
Expand All @@ -33,4 +63,34 @@ describe("MuiAdapter", () => {
expect(container.querySelector(".MuiDataGrid-root")).not.toBeNull();
});
});

test("publishes the post-filter row count, not the full dataset size", async () => {
const { container, rerender } = render(
<MuiAdapter
dataset={statusDataset as never}
runKey={0}
scriptName="filter-metadata"
interactionPlan={null}
/>,
);
await waitFor(() => {
expect(container.querySelector(".MuiDataGrid-root")).not.toBeNull();
});

rerender(
<MuiAdapter
dataset={statusDataset as never}
runKey={0}
scriptName="filter-metadata"
interactionPlan={filterPlan("filter-metadata", { status: "running" })}
/>,
);

// status === "running" matches 2 of 4 rows. The published count is sourced
// from the grid's filtered-row selector, not the full dataset size.
await waitFor(() => {
const section = container.querySelector('[data-benchmark-adapter="mui"]');
expect(section?.getAttribute("data-bench-result-row-count")).toBe("2");
});
});
});
64 changes: 64 additions & 0 deletions apps/bench/src/__tests__/tanstack-adapter.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { render, waitFor } from "@testing-library/react";
import { beforeAll, describe, expect, test } from "vitest";

import { TanstackAdapter } from "../tanstack-adapter";
import type { BenchInteractionPlan } from "../interaction-plan";

const dataset = {
columns: [
Expand All @@ -14,6 +15,35 @@ const dataset = {
],
};

const statusDataset = {
columns: [
{ id: "id", header: "ID", wrap: false, widthPx: 80 },
{ id: "status", header: "Status", wrap: false, widthPx: 160 },
],
rows: [
{ id: "1", status: "running" },
{ id: "2", status: "stopped" },
{ id: "3", status: "running" },
{ id: "4", status: "idle" },
],
};

function filterPlan(
mode: "filter-metadata" | "filter-text",
filters: Record<string, string>,
): BenchInteractionPlan {
return {
focusedRowId: null,
filters,
mode,
probeColumnId: Object.keys(filters)[0] ?? "",
resultRowCount: 0,
rows: [],
selectedRowId: null,
sort: null,
};
}

beforeAll(() => {
// jsdom doesn't ship ResizeObserver and reports zero offsetWidth /
// offsetHeight for every element. @tanstack/react-virtual reads
Expand Down Expand Up @@ -67,4 +97,38 @@ describe("TanstackAdapter", () => {
).toBeGreaterThan(0);
});
});

test("publishes the post-filter row count, not the full dataset size", async () => {
const { container, rerender } = render(
<TanstackAdapter
dataset={statusDataset as never}
runKey={0}
scriptName="filter-metadata"
interactionPlan={null}
/>,
);
await waitFor(() => {
expect(
container.querySelector("[data-pretable-bench-tanstack-viewport]"),
).not.toBeNull();
});

rerender(
<TanstackAdapter
dataset={statusDataset as never}
runKey={0}
scriptName="filter-metadata"
interactionPlan={filterPlan("filter-metadata", { status: "running" })}
/>,
);

// status === "running" matches 2 of 4 rows. The published count comes from
// table.getRowModel().rows (post-filter), not the full dataset size.
await waitFor(() => {
const section = container.querySelector(
'[data-benchmark-adapter="tanstack"]',
);
expect(section?.getAttribute("data-bench-result-row-count")).toBe("2");
});
});
});
26 changes: 24 additions & 2 deletions apps/bench/src/mui-adapter.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { DataGrid, useGridApiRef, type GridColDef } from "@mui/x-data-grid";
import {
DataGrid,
gridFilteredTopLevelRowCountSelector,
useGridApiRef,
type GridColDef,
} from "@mui/x-data-grid";

import type {
ScenarioColumn,
Expand Down Expand Up @@ -76,12 +81,29 @@ export function MuiAdapter({
onAutosizeReadyRef.current = onAutosizeReady;

const [rows, setRows] = useState<ScenarioRow[]>(() => dataset.rows.slice());
// Post-interaction visible-row count. `rows` above is always the full
// dataset (DataGrid filters internally), so the published count is sourced
// from the grid's filtered-row selector instead — keeping it in sync with
// what the grid actually shows after a filter.
const [resultRowCount, setResultRowCount] = useState(dataset.rows.length);

useEffect(() => {
// eslint-disable-next-line react-hooks/set-state-in-effect -- runKey reset
setRows(dataset.rows.slice());
}, [dataset.rows, runKey]);

useEffect(() => {
const api = apiRef.current;
if (!api) return;
// Seed immediately (covers a filter already applied before subscribe),
// then track every filter change. `filteredRowsSet` fires after the grid
// recomputes its filtered model.
const sync = () =>
setResultRowCount(gridFilteredTopLevelRowCountSelector(apiRef));
sync();
return api.subscribeEvent("filteredRowsSet", sync);
}, [apiRef, runKey, dataset.rows.length]);

const columns = useMemo(
() => dataset.columns.map((c) => toColDef(c, scriptName)),
[dataset.columns, scriptName],
Expand Down Expand Up @@ -146,7 +168,7 @@ export function MuiAdapter({
<section
aria-label="MUI X DataGrid adapter"
data-benchmark-adapter="mui"
data-bench-result-row-count={String(rows.length)}
data-bench-result-row-count={String(resultRowCount)}
style={{ display: "grid", gap: 12 }}
>
<header>
Expand Down
5 changes: 4 additions & 1 deletion apps/bench/src/tanstack-adapter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@ export function TanstackAdapter({
<section
aria-label="TanStack Table adapter"
data-benchmark-adapter="tanstack"
data-bench-result-row-count={String(data.length)}
// `rows` is the post-filter, post-sort row model (table.getRowModel()),
// so this reflects the count the grid actually displays after an
// interaction. `data` is the full unfiltered dataset (always 3000).
data-bench-result-row-count={String(rows.length)}
style={{ display: "grid", gap: 12 }}
>
<header>
Expand Down
Loading