Skip to content
Open
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
3 changes: 2 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"Bash(node:*)",
"Bash(tail:*)",
"Bash(git add src/components/CompareResults/SubtestsResults/SubtestsRevisionRow.tsx && git rebase --continue 2>&1)",
"Bash(grep:*)"
"Bash(grep:*)",
"Bash(npx jest *)"
]
}
}
14 changes: 8 additions & 6 deletions src/__tests__/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event';

import App, { router } from '../components/App';
import getTestData from './utils/fixtures';
import { act, render, screen } from './utils/test-utils';
import { act, render, screen, within } from './utils/test-utils';

describe('App', () => {
beforeEach(() => {
Expand Down Expand Up @@ -396,11 +396,13 @@ describe('App', () => {
// Wait for the page to load
await screen.findByText('a11yr');

// Verify that Mann-Whitney-U specific columns are rendered
// (this indicates the testVersion defaulted to mann-whitney-u)
expect(screen.getByText('CD')).toBeInTheDocument();
expect(screen.getByText('Sig')).toBeInTheDocument();
expect(screen.getByText('CLES (%)')).toBeInTheDocument();
// Verify a Mann-Whitney-U specific column is rendered — "Δ Median %" is
// unique to the Mann-Whitney strategy (Student-T uses "Delta"), so its
// presence in the table header indicates the testVersion defaulted to
// mann-whitney-u. Scope to the header since the "How to read the results"
// panel also names it.
const tableHeader = screen.getByTestId('table-header');
expect(within(tableHeader).getByText('Δ Median %')).toBeInTheDocument();

// Verify the Stats Test Version dropdown shows Mann-Whitney-U as selected
const testVersionDropdown = screen.getByRole('combobox', {
Expand Down
441 changes: 248 additions & 193 deletions src/__tests__/CompareResults/ResultsTable.test.tsx

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions src/__tests__/CompareResults/ResultsView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -566,4 +566,24 @@ describe('Results View', () => {
expect(screen.queryAllByTestId(/ExpandLessIcon/)).toHaveLength(0);
});
});

it('shows the "How to read the results" panel by default and lets the user dismiss it', async () => {
renderWithRoute(<ResultsView title={Strings.metaData.pageTitle.results} />);
await screen.findByText('a11yr');

// Shown by default.
const panel = screen.getByTestId('how-to-read-results');
expect(panel).toBeInTheDocument();

// Dismiss via the panel's close button.
const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
await user.click(screen.getByRole('button', { name: /close/i }));
expect(screen.queryByTestId('how-to-read-results')).not.toBeInTheDocument();

// The "How to read the results" checkbox brings it back.
await user.click(
screen.getByRole('checkbox', { name: /How to read the results/i }),
);
expect(screen.getByTestId('how-to-read-results')).toBeInTheDocument();
});
});
18 changes: 13 additions & 5 deletions src/__tests__/CompareResults/RevisionRow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import { useSubtestRegressionCount } from '../../hooks/useSubtestRegressionCount
import { CompareResultsItem, MannWhitneyResultsItem } from '../../types/state';
import { Platform } from '../../types/types';
import getTestData from '../utils/fixtures';
import { screen, renderWithRouter } from '../utils/test-utils';
import {
screen,
renderWithRouter,
enableAdvancedColumns,
} from '../utils/test-utils';

jest.mock('../../hooks/useSubtestRegressionCount');
const mockUseSubtestRegressionCount = useSubtestRegressionCount as jest.Mock;
Expand Down Expand Up @@ -427,6 +431,7 @@ describe('Expanded row', () => {
});

it('should display mean for base or new in row headers for mann-whitney-u testVersion', async () => {
enableAdvancedColumns();
const { testCompareMannWhitneyData: rowData } = getTestData();
renderWithRoute(
<RevisionRow
Expand Down Expand Up @@ -541,7 +546,7 @@ describe('Expanded row', () => {
};
}

it('shows dash when neither distribution is normal', async () => {
it('shows value with warning icon when neither distribution is normal', async () => {
const result = makeResult(tooFewRuns, tooFewRuns);
expect(isDistributionNormal(result)).toBe(false);
renderWithRoute(
Expand All @@ -555,7 +560,10 @@ describe('Expanded row', () => {
/>,
);
const roles = await screen.findAllByRole('cell');
expect(roles[4]).toHaveTextContent('-');
// The median difference is rank-based, so it's shown even for non-normal
// data; only a warning icon flags the shape.
expect(roles[4]).toHaveTextContent('%');
expect(roles[4].querySelector('svg[role="img"]')).toBeTruthy();
});

it('shows value with warning icon when only one distribution is normal', async () => {
Expand All @@ -572,7 +580,7 @@ describe('Expanded row', () => {
/>,
);
const roles = await screen.findAllByRole('cell');
expect(roles[4]).not.toHaveTextContent('-');
expect(roles[4]).toHaveTextContent('%');
expect(roles[4].querySelector('svg[role="img"]')).toBeTruthy();
});

Expand All @@ -590,7 +598,7 @@ describe('Expanded row', () => {
/>,
);
const roles = await screen.findAllByRole('cell');
expect(roles[4]).not.toHaveTextContent('-');
expect(roles[4]).toHaveTextContent('%');
expect(roles[4].querySelector('svg[role="img"]')).toBeFalsy();
});
});
Expand Down
148 changes: 83 additions & 65 deletions src/__tests__/CompareResults/SubtestsResultsView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import type { CombinedResultsItemType } from '../../types/state';
import { TestVersion } from '../../types/types';
import { getLocationOrigin } from '../../utils/location';
import getTestData from '../utils/fixtures';
import { renderWithRouter, screen } from '../utils/test-utils';
import {
renderWithRouter,
screen,
enableAdvancedColumns,
} from '../utils/test-utils';

jest.mock('../../utils/location');
const mockedGetLocationOrigin = getLocationOrigin as jest.Mock;
Expand Down Expand Up @@ -48,7 +52,7 @@ const setup = ({
// This handy function parses the results page and returns an array of visible
// rows. It makes it easy to assert visible rows when filtering them in a
// user-friendly way without using snapshots.
function summarizeVisibleRows(testVersion?: TestVersion) {
function summarizeVisibleRows(testVersion?: TestVersion, advanced = false) {
const rows = screen.getAllByRole('row');
const result = [];
for (const row of rows) {
Expand All @@ -59,10 +63,19 @@ function summarizeVisibleRows(testVersion?: TestVersion) {
}
const rowClasses =
testVersion === 'mann-whitney-u'
? ['.median-diff', '.delta', '.significance', '.effects']
? advanced
? ['.median-diff', '.delta', '.significance', '.effects']
: ['.median-diff', '.status-hint', '.significance']
: ['.delta', '.confidence'];
const rowString = rowClasses
.map((selector) => row.querySelector(selector)?.textContent.trim())
.map((selector) => {
const cell = row.querySelector(selector);
if (!cell) return undefined;
// Strip icon <title> text (e.g. the median-diff normality warning).
const clone = cell.cloneNode(true) as HTMLElement;
clone.querySelectorAll('svg').forEach((svg) => svg.remove());
return clone.textContent?.trim();
})
.join(', ');
result.push(`${subtest}: ${rowString}`);
}
Expand Down Expand Up @@ -499,6 +512,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', (
});

describe('table sorting', () => {
// These sort by CD and Significance, which are advanced-only columns.
beforeEach(() => {
enableAdvancedColumns();
});

async function setupForSorting({
extraParameters,
}: Partial<{
Expand Down Expand Up @@ -526,12 +544,12 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', (
it('can sort the table and persist the information to the URL of mann-whitney-u values', async () => {
await setupForSorting();
// Initial view (alphabetical ordered, even if "sort by subtests" isn't specified
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'browser.html: 0.963 %, -0.04, -, 15.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'improvement.html: 0.963 %, -0.05, , 50.00%',
'regression.html: 1.135 %, 0.12, , 25.00%',
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'browser.html: +1.14%, -0.04, Noise, 15.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'improvement.html: +1.14%, -0.05, Real, 50.00%',
'regression.html: +1.14%, 0.12, Real, 25.00%',
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
]);

// Sort by Delta
Expand All @@ -541,12 +559,12 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', (
expect(window.location.search).not.toContain('sort=');
// Sort descending
await user.click(deltaButton);
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'regression.html: 1.135 %, 0.12, , 25.00%',
'improvement.html: 0.963 %, -0.05, , 50.00%',
'browser.html: 0.963 %, -0.04, -, 15.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'regression.html: +1.14%, 0.12, Real, 25.00%',
'improvement.html: +1.14%, -0.05, Real, 50.00%',
'browser.html: +1.14%, -0.04, Noise, 15.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
]);

// It should have the "descending" SVG.
Expand All @@ -556,12 +574,12 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', (

// Sort ascending
await user.click(deltaButton);
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'browser.html: 0.963 %, -0.04, -, 15.00%',
'improvement.html: 0.963 %, -0.05, , 50.00%',
'regression.html: 1.135 %, 0.12, , 25.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'browser.html: +1.14%, -0.04, Noise, 15.00%',
'improvement.html: +1.14%, -0.05, Real, 50.00%',
'regression.html: +1.14%, 0.12, Real, 25.00%',
]);
// It should have the "ascending" SVG.
expect(deltaButton).toMatchSnapshot();
Expand All @@ -573,12 +591,12 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', (
name: /Sig.*sort/,
});
await user.click(significanceButton);
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'browser.html: 0.963 %, -0.04, -, 15.00%',
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'regression.html: 1.135 %, 0.12, , 25.00%',
'improvement.html: 0.963 %, -0.05, , 50.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'browser.html: +1.14%, -0.04, Noise, 15.00%',
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'regression.html: +1.14%, 0.12, Real, 25.00%',
'improvement.html: +1.14%, -0.05, Real, 50.00%',
]);
// It should have the "no sort" SVG.
expect(deltaButton).toMatchSnapshot();
Expand All @@ -589,26 +607,26 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', (

// Sort by Significance ascending
await user.click(significanceButton);
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'improvement.html: 0.963 %, -0.05, , 50.00%',
'regression.html: 1.135 %, 0.12, , 25.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
'browser.html: 0.963 %, -0.04, -, 15.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'improvement.html: +1.14%, -0.05, Real, 50.00%',
'regression.html: +1.14%, 0.12, Real, 25.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
'browser.html: +1.14%, -0.04, Noise, 15.00%',
]);
expectParameterToHaveValue('sort', 'significance|asc');

// Sort by Effect Size descending
const effectButton = screen.getByRole('button', {
name: /CLES \(%\).*sort/,
name: /CLES %.*sort/,
});
await user.click(effectButton);
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'browser.html: 0.963 %, -0.04, -, 15.00%',
'regression.html: 1.135 %, 0.12, , 25.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
'improvement.html: 0.963 %, -0.05, , 50.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'browser.html: +1.14%, -0.04, Noise, 15.00%',
'regression.html: +1.14%, 0.12, Real, 25.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
'improvement.html: +1.14%, -0.05, Real, 50.00%',
]);

// It should have the "descending" SVG.
Expand All @@ -618,25 +636,25 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', (

// Sort by Effect Size ascending
await user.click(effectButton);
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'improvement.html: 0.963 %, -0.05, , 50.00%',
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'regression.html: 1.135 %, 0.12, , 25.00%',
'browser.html: 0.963 %, -0.04, -, 15.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'improvement.html: +1.14%, -0.05, Real, 50.00%',
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'regression.html: +1.14%, 0.12, Real, 25.00%',
'browser.html: +1.14%, -0.04, Noise, 15.00%',
]);
expectParameterToHaveValue('sort', 'effects|asc');
});

it('initializes the sort from the URL at load time for an ascending sort', async () => {
await setupForSorting({ extraParameters: 'sort=delta|asc' });
await screen.findByText('dhtml.html');
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'browser.html: 0.963 %, -0.04, -, 15.00%',
'improvement.html: 0.963 %, -0.05, , 50.00%',
'regression.html: 1.135 %, 0.12, , 25.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'browser.html: +1.14%, -0.04, Noise, 15.00%',
'improvement.html: +1.14%, -0.05, Real, 50.00%',
'regression.html: +1.14%, 0.12, Real, 25.00%',
]);
// It should have the "ascending" SVG.
expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot();
Expand All @@ -645,25 +663,25 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', (
it('initializes the sort from the URL at load time for an implicit descending sort', async () => {
await setupForSorting({ extraParameters: 'sort=delta' });
await screen.findByText('dhtml.html');
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'regression.html: 1.135 %, 0.12, , 25.00%',
'improvement.html: 0.963 %, -0.05, , 50.00%',
'browser.html: 0.963 %, -0.04, -, 15.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'regression.html: +1.14%, 0.12, Real, 25.00%',
'improvement.html: +1.14%, -0.05, Real, 50.00%',
'browser.html: +1.14%, -0.04, Noise, 15.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
]);
// It should have the "descending" SVG.
expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot();
});

it('initializes the sort from the URL at load time for a descending sort', async () => {
await setupForSorting({ extraParameters: 'sort=delta|desc' });
expect(summarizeVisibleRows('mann-whitney-u')).toEqual([
'regression.html: 1.135 %, 0.12, , 25.00%',
'improvement.html: 0.963 %, -0.05, , 50.00%',
'browser.html: 0.963 %, -0.04, -, 15.00%',
'dhtml.html: 1.135 %, 0.02, , 60.00%',
'tablemutation.html: 0.98 %, 0.01, -, 45.00%',
expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([
'regression.html: +1.14%, 0.12, Real, 25.00%',
'improvement.html: +1.14%, -0.05, Real, 50.00%',
'browser.html: +1.14%, -0.04, Noise, 15.00%',
'dhtml.html: +1.14%, 0.02, Real, 60.00%',
'tablemutation.html: +0.98%, 0.01, -, 45.00%',
]);
// It should have the "descending" SVG.
expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot();
Expand Down
Loading