diff --git a/.claude/settings.local.json b/.claude/settings.local.json index f3cdb7021..668c033d2 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -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 *)" ] } } diff --git a/src/__tests__/App.test.tsx b/src/__tests__/App.test.tsx index a418178d9..c9c04bad8 100644 --- a/src/__tests__/App.test.tsx +++ b/src/__tests__/App.test.tsx @@ -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(() => { @@ -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', { diff --git a/src/__tests__/CompareResults/ResultsTable.test.tsx b/src/__tests__/CompareResults/ResultsTable.test.tsx index c663ada1d..fa7dd9f7b 100644 --- a/src/__tests__/CompareResults/ResultsTable.test.tsx +++ b/src/__tests__/CompareResults/ResultsTable.test.tsx @@ -14,7 +14,13 @@ import getTestData, { augmentCompareMannWhitneyDataWithSeveralRevisions, augmentCompareMannWhitneyDataWithSeveralTests, } from '../utils/fixtures'; -import { renderWithRouter, screen, waitFor, within } from '../utils/test-utils'; +import { + renderWithRouter, + screen, + waitFor, + within, + enableAdvancedColumns, +} from '../utils/test-utils'; function renderWithRoute(component: ReactElement, extraParameters?: string) { return renderWithRouter(component, { @@ -48,7 +54,7 @@ function setupAndRender( // 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 rowGroups = screen.getAllByRole('rowgroup'); const result = []; @@ -83,17 +89,33 @@ function summarizeVisibleRows(testVersion?: TestVersion) { for (const row of rows) { const rowClasses = testVersion === 'mann-whitney-u' - ? [ - '.platform span', - '.median-diff', - '.status', - '.delta', - '.significance', - '.effects', - ] + ? advanced + ? [ + '.platform span', + '.median-diff', + '.status-hint', + '.delta', + '.significance', + '.effects', + ] + : [ + '.platform span', + '.median-diff', + '.status-hint', + '.significance', + ] : ['.platform span', '.status', '.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 text (e.g. the median-diff normality warning) + // so the data-focused expectations stay stable; icon presence is + // asserted separately. + const clone = cell.cloneNode(true) as HTMLElement; + clone.querySelectorAll('svg').forEach((svg) => svg.remove()); + return clone.textContent?.trim(); + }) .join(', '); result.push(' - ' + rowString); @@ -690,6 +712,13 @@ describe('Results Table', () => { }); describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion', () => { + // These tests exercise the full (advanced) table — CD, CLES, Sig columns and + // their sort/filter behavior. The simplified default view (which hides those + // and shows Difference Size) is covered separately below. + beforeEach(() => { + enableAdvancedColumns(); + }); + it('Should match snapshot', async () => { const { testCompareMannWhitneyData } = getTestData(); @@ -719,12 +748,12 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio setupAndRender(simplerTestCompareData, 'test_version=mann-whitney-u'); await screen.findByText('a11yr'); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', ' rev: devilrabbit', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', ]); expect(screen.getByRole('rowgroup')).toMatchSnapshot(); }); @@ -746,25 +775,25 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio setupAndRender(testCompareMannWhitneyData, 'test_version=mann-whitney-u'); await screen.findByText('a11yr'); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - inexistant, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Android, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - inexistant, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); await clickMenuItem(user, 'Platform', /Windows/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - Android, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'linux', 'android', 'ios'], @@ -773,78 +802,78 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio // Clicking Windows again should remove the search param and make the // "inexitant" platform visible again. await clickMenuItem(user, 'Platform', /Windows/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - inexistant, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Android, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - inexistant, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); await clickMenuItem(user, 'Platform', /Windows/); await clickMenuItem(user, 'Platform', /Linux/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - Android, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'android', 'ios'], }); await clickMenuItem(user, 'Platform', /Linux/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - Android, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'android', 'ios', 'linux'], }); await clickMenuItem(user, 'Platform', 'Select all values'); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - inexistant, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Android, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - inexistant, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); await clickMenuItem(user, 'Platform', /macOS/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Android, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['windows', 'linux', 'android', 'ios'], }); await clickMenuItem(user, 'Platform', /Android/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['windows', 'linux', 'ios'], }); await clickMenuItem(user, 'Platform', /Select only.*Android/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - Android, +1.08%, Improvement, 0.1, Noise, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['android'], @@ -858,16 +887,16 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); - // Filter only "Significant" + // Filter only "Real" (significant) const signifianceMenu = await screen.findByRole('button', { name: /Sig.*filter/, }); await user.click(signifianceMenu); expect(signifianceMenu).toMatchSnapshot(); - // significant item 0 and Not significant item 1 + // "Real" is item 0, "Noise" (not significant) is item 1 const significantOptions = await screen.findAllByRole('menuitemcheckbox', { - name: /Significant/, + name: /Real|Noise/, }); await user.click(significantOptions[1]); await user.keyboard('[Escape]'); @@ -881,30 +910,30 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio setupAndRender(testCompareMannWhitneyData, 'test_version=mann-whitney-u'); await screen.findByText('a11yr'); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); await clickMenuItem(user, 'Status', /No changes/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['improvement', 'regression'], }); await clickMenuItem(user, 'Status', /Improvement/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['regression'], @@ -912,39 +941,39 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Select all values/); await clickMenuItem(user, 'Status', /Regression/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['none', 'improvement'], }); await clickMenuItem(user, 'Status', /Regression/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); await clickMenuItem(user, 'Status', /Select only.*Regression/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['regression'], }); await clickMenuItem(user, 'Status', /Select only.*Improvement/); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['improvement'], @@ -959,14 +988,14 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio ); await screen.findByText('dhtml.html'); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', ]); const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); expect(await summarizeTableFiltersFromCheckboxes(user)).toEqual({ 'Platform(2)': ['macOS', 'Android'], - 'Sig(2)': ['Significant', 'Not Significant-'], + 'Sig(2)': ['Real', 'Noise'], 'Status(3)': ['No changes', 'Improvement', 'Regression'], }); @@ -994,29 +1023,29 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(deltaButton).toMatchSnapshot(); // // Sort descending - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Linux 18.04, 1.849 %, Regression, 1.2, -, 44.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 1.3, -, 24.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', - ' - Windows 10, -2.401 %, , 1.2, , 49.00 %', + ' - Linux 18.04, +1.85%, Regression, 1.2, Noise, 44.00 %', + ' - macOS 10.15, +1.08%, Improvement, 1.3, Noise, 24.00 %', + ' - Windows 10, -, , 1.2, Real, 99.00 %', + ' - Windows 10, -2.40%, , 1.2, Real, 49.00 %', ' rev: tictactoe', - ' - Linux 18.04, 1.849 %, Regression, 2, -, 43.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 2.1, -, 23.00 %', - ' - Windows 10, -, , 2, , 98.00 %', - ' - Windows 10, -2.401 %, , 2, , 48.00 %', + ' - Linux 18.04, +1.85%, Regression, 2, Noise, 43.00 %', + ' - macOS 10.15, +1.08%, Improvement, 2.1, Noise, 23.00 %', + ' - Windows 10, -, , 2, Real, 98.00 %', + ' - Windows 10, -2.40%, , 2, Real, 48.00 %', 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ' rev: tictactoe', - ' - Linux 18.04, 1.849 %, Regression, 0.8, -, 44.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.9, -, 24.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', - ' - Windows 10, -2.401 %, , 0.8, , 49.00 %', + ' - Linux 18.04, +1.85%, Regression, 0.8, Noise, 44.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.9, Noise, 24.00 %', + ' - Windows 10, -, , 0.8, Real, 99.00 %', + ' - Windows 10, -2.40%, , 0.8, Real, 49.00 %', ]); // It should have the "descending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -1025,29 +1054,29 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio // sort ascending await user.click(deltaButton); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr aria.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, 1.078 %, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, 1.849 %, Regression, 2, -, 43.00 %', - ' - Windows 10, -2.401 %, , 2, , 48.00 %', - ' - Windows 10, -, , 2, , 98.00 %', + ' - macOS 10.15, +1.08%, Improvement, 2.1, Noise, 23.00 %', + ' - Linux 18.04, +1.85%, Regression, 2, Noise, 43.00 %', + ' - Windows 10, -2.40%, , 2, Real, 48.00 %', + ' - Windows 10, -, , 2, Real, 98.00 %', ' rev: spam', - ' - macOS 10.15, 1.078 %, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, 1.849 %, Regression, 1.2, -, 44.00 %', - ' - Windows 10, -2.401 %, , 1.2, , 49.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', + ' - macOS 10.15, +1.08%, Improvement, 1.3, Noise, 24.00 %', + ' - Linux 18.04, +1.85%, Regression, 1.2, Noise, 44.00 %', + ' - Windows 10, -2.40%, , 1.2, Real, 49.00 %', + ' - Windows 10, -, , 1.2, Real, 99.00 %', 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, 1.078 %, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, 1.849 %, Regression, 0.8, -, 44.00 %', - ' - Windows 10, -2.401 %, , 0.8, , 49.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.9, Noise, 24.00 %', + ' - Linux 18.04, +1.85%, Regression, 0.8, Noise, 44.00 %', + ' - Windows 10, -2.40%, , 0.8, Real, 49.00 %', + ' - Windows 10, -, , 0.8, Real, 99.00 %', ' rev: spam', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', - ' - Windows 10, -, , -, , 100.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', ]); // It should have the "ascending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -1059,29 +1088,29 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio name: /Sig.*sort/, }); await user.click(significanceButton); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr aria.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, 1.078 %, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, 1.849 %, Regression, 2, -, 43.00 %', - ' - Windows 10, -, , 2, , 98.00 %', - ' - Windows 10, -2.401 %, , 2, , 48.00 %', + ' - macOS 10.15, +1.08%, Improvement, 2.1, Noise, 23.00 %', + ' - Linux 18.04, +1.85%, Regression, 2, Noise, 43.00 %', + ' - Windows 10, -, , 2, Real, 98.00 %', + ' - Windows 10, -2.40%, , 2, Real, 48.00 %', ' rev: spam', - ' - macOS 10.15, 1.078 %, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, 1.849 %, Regression, 1.2, -, 44.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', - ' - Windows 10, -2.401 %, , 1.2, , 49.00 %', + ' - macOS 10.15, +1.08%, Improvement, 1.3, Noise, 24.00 %', + ' - Linux 18.04, +1.85%, Regression, 1.2, Noise, 44.00 %', + ' - Windows 10, -, , 1.2, Real, 99.00 %', + ' - Windows 10, -2.40%, , 1.2, Real, 49.00 %', 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, 1.078 %, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, 1.849 %, Regression, 0.8, -, 44.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', - ' - Windows 10, -2.401 %, , 0.8, , 49.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.9, Noise, 24.00 %', + ' - Linux 18.04, +1.85%, Regression, 0.8, Noise, 44.00 %', + ' - Windows 10, -, , 0.8, Real, 99.00 %', + ' - Windows 10, -2.40%, , 0.8, Real, 49.00 %', ' rev: spam', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ]); // It should have the "descending" SVG. expect(significanceButton).toMatchSnapshot(); @@ -1090,29 +1119,29 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio // Sort by Significance ascending await user.click(significanceButton); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -2.401 %, , -, , 50.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', ' rev: tictactoe', - ' - Windows 10, -2.401 %, , 0.8, , 49.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, 1.849 %, Regression, 0.8, -, 44.00 %', + ' - Windows 10, -2.40%, , 0.8, Real, 49.00 %', + ' - Windows 10, -, , 0.8, Real, 99.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.9, Noise, 24.00 %', + ' - Linux 18.04, +1.85%, Regression, 0.8, Noise, 44.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -2.401 %, , 1.2, , 49.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, 1.849 %, Regression, 1.2, -, 44.00 %', + ' - Windows 10, -2.40%, , 1.2, Real, 49.00 %', + ' - Windows 10, -, , 1.2, Real, 99.00 %', + ' - macOS 10.15, +1.08%, Improvement, 1.3, Noise, 24.00 %', + ' - Linux 18.04, +1.85%, Regression, 1.2, Noise, 44.00 %', ' rev: tictactoe', - ' - Windows 10, -2.401 %, , 2, , 48.00 %', - ' - Windows 10, -, , 2, , 98.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, 1.849 %, Regression, 2, -, 43.00 %', + ' - Windows 10, -2.40%, , 2, Real, 48.00 %', + ' - Windows 10, -, , 2, Real, 98.00 %', + ' - macOS 10.15, +1.08%, Improvement, 2.1, Noise, 23.00 %', + ' - Linux 18.04, +1.85%, Regression, 2, Noise, 43.00 %', ]); // It should have the "descending" SVG. expect(significanceButton).toMatchSnapshot(); @@ -1121,32 +1150,32 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio // Sort by Effect Size (%) descending const effectSizeButton = screen.getByRole('button', { - name: /CLES \(%\).*sort/, + name: /CLES %.*sort/, }); await user.click(effectSizeButton); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -, , -, , 100.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', ' rev: tictactoe', - ' - Windows 10, -, , 0.8, , 99.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, 1.849 %, Regression, 0.8, -, 44.00 %', - ' - Windows 10, -2.401 %, , 0.8, , 49.00 %', + ' - Windows 10, -, , 0.8, Real, 99.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.9, Noise, 24.00 %', + ' - Linux 18.04, +1.85%, Regression, 0.8, Noise, 44.00 %', + ' - Windows 10, -2.40%, , 0.8, Real, 49.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -, , 1.2, , 99.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, 1.849 %, Regression, 1.2, -, 44.00 %', - ' - Windows 10, -2.401 %, , 1.2, , 49.00 %', + ' - Windows 10, -, , 1.2, Real, 99.00 %', + ' - macOS 10.15, +1.08%, Improvement, 1.3, Noise, 24.00 %', + ' - Linux 18.04, +1.85%, Regression, 1.2, Noise, 44.00 %', + ' - Windows 10, -2.40%, , 1.2, Real, 49.00 %', ' rev: tictactoe', - ' - Windows 10, -, , 2, , 98.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, 1.849 %, Regression, 2, -, 43.00 %', - ' - Windows 10, -2.401 %, , 2, , 48.00 %', + ' - Windows 10, -, , 2, Real, 98.00 %', + ' - macOS 10.15, +1.08%, Improvement, 2.1, Noise, 23.00 %', + ' - Linux 18.04, +1.85%, Regression, 2, Noise, 43.00 %', + ' - Windows 10, -2.40%, , 2, Real, 48.00 %', ]); expect(effectSizeButton).toMatchSnapshot(); @@ -1155,46 +1184,46 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio // Sort by Effect Size (%) ascending await user.click(effectSizeButton); - expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ + expect(summarizeVisibleRows('mann-whitney-u', true)).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -2.401 %, , -, , 50.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', + ' - Windows 10, -2.40%, , -, Real, 50.00 %', + ' - Linux 18.04, +1.85%, Regression, -, Noise, 45.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.1, Noise, 25.00 %', + ' - Windows 10, -, , -, Real, 100.00 %', ' rev: tictactoe', - ' - Windows 10, -2.401 %, , 0.8, , 49.00 %', - ' - Linux 18.04, 1.849 %, Regression, 0.8, -, 44.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.9, -, 24.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', + ' - Windows 10, -2.40%, , 0.8, Real, 49.00 %', + ' - Linux 18.04, +1.85%, Regression, 0.8, Noise, 44.00 %', + ' - macOS 10.15, +1.08%, Improvement, 0.9, Noise, 24.00 %', + ' - Windows 10, -, , 0.8, Real, 99.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -2.401 %, , 1.2, , 49.00 %', - ' - Linux 18.04, 1.849 %, Regression, 1.2, -, 44.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 1.3, -, 24.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', + ' - Windows 10, -2.40%, , 1.2, Real, 49.00 %', + ' - Linux 18.04, +1.85%, Regression, 1.2, Noise, 44.00 %', + ' - macOS 10.15, +1.08%, Improvement, 1.3, Noise, 24.00 %', + ' - Windows 10, -, , 1.2, Real, 99.00 %', ' rev: tictactoe', - ' - Windows 10, -2.401 %, , 2, , 48.00 %', - ' - Linux 18.04, 1.849 %, Regression, 2, -, 43.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 2.1, -, 23.00 %', - ' - Windows 10, -, , 2, , 98.00 %', + ' - Windows 10, -2.40%, , 2, Real, 48.00 %', + ' - Linux 18.04, +1.85%, Regression, 2, Noise, 43.00 %', + ' - macOS 10.15, +1.08%, Improvement, 2.1, Noise, 23.00 %', + ' - Windows 10, -, , 2, Real, 98.00 %', ]); expect(effectSizeButton).toMatchSnapshot(); // It should be persisted in the URL expectParameterToHaveValue('sort', 'effects|asc'); - // Sort by MD(%) descending + // Sort by Δ Median % descending const medianDiffButton = screen.getByRole('button', { - name: /MD \(%\).*sort/, + name: /Δ Median %.*sort/, }); await user.click(medianDiffButton); - expect(summarizeVisibleRows('mann-whitney-u')).toMatchSnapshot(); + expect(summarizeVisibleRows('mann-whitney-u', true)).toMatchSnapshot(); expect(medianDiffButton).toMatchSnapshot(); expectParameterToHaveValue('sort', 'median-diff|desc'); // Sort by MD(%) ascending await user.click(medianDiffButton); - expect(summarizeVisibleRows('mann-whitney-u')).toMatchSnapshot(); + expect(summarizeVisibleRows('mann-whitney-u', true)).toMatchSnapshot(); expect(medianDiffButton).toMatchSnapshot(); expectParameterToHaveValue('sort', 'median-diff|asc'); }); @@ -1248,3 +1277,29 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio }); }); }); + +describe('Advanced-columns toggle for mann-whitney-u testVersion', () => { + it('shows Sig but hides CD/CLES in the simplified (default) view', async () => { + const { testCompareMannWhitneyData } = getTestData(); + setupAndRender(testCompareMannWhitneyData, 'test_version=mann-whitney-u'); + await screen.findByText('a11yr'); + + const header = screen.getByTestId('table-header'); + // Sig is shown in both views; CD/CLES are advanced-only. + expect(header.querySelector('.significance-header')).toBeTruthy(); + expect(header.querySelector('.delta-header')).toBeFalsy(); + expect(header.querySelector('.effects-header')).toBeFalsy(); + }); + + it('reveals CD/CLES when advanced columns are enabled (Sig stays)', async () => { + enableAdvancedColumns(); + const { testCompareMannWhitneyData } = getTestData(); + setupAndRender(testCompareMannWhitneyData, 'test_version=mann-whitney-u'); + await screen.findByText('a11yr'); + + const header = screen.getByTestId('table-header'); + expect(header.querySelector('.delta-header')).toBeTruthy(); + expect(header.querySelector('.effects-header')).toBeTruthy(); + expect(header.querySelector('.significance-header')).toBeTruthy(); + }); +}); diff --git a/src/__tests__/CompareResults/ResultsView.test.tsx b/src/__tests__/CompareResults/ResultsView.test.tsx index 9d6bb7f31..dd494e8cf 100644 --- a/src/__tests__/CompareResults/ResultsView.test.tsx +++ b/src/__tests__/CompareResults/ResultsView.test.tsx @@ -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(); + }); }); diff --git a/src/__tests__/CompareResults/RevisionRow.test.tsx b/src/__tests__/CompareResults/RevisionRow.test.tsx index ae86e4950..6f542eab5 100644 --- a/src/__tests__/CompareResults/RevisionRow.test.tsx +++ b/src/__tests__/CompareResults/RevisionRow.test.tsx @@ -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; @@ -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 @@ -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( @@ -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 () => { @@ -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(); }); @@ -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(); }); }); diff --git a/src/__tests__/CompareResults/SubtestsResultsView.test.tsx b/src/__tests__/CompareResults/SubtestsResultsView.test.tsx index 87e1b9081..d5737351a 100644 --- a/src/__tests__/CompareResults/SubtestsResultsView.test.tsx +++ b/src/__tests__/CompareResults/SubtestsResultsView.test.tsx @@ -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; @@ -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) { @@ -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}`); } @@ -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<{ @@ -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 @@ -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. @@ -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(); @@ -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(); @@ -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. @@ -618,12 +636,12 @@ 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'); }); @@ -631,12 +649,12 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( 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(); @@ -645,12 +663,12 @@ 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(); @@ -658,12 +676,12 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( 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(); diff --git a/src/__tests__/CompareResults/SubtestsRevisionRow.test.tsx b/src/__tests__/CompareResults/SubtestsRevisionRow.test.tsx index d8941e030..1b328e56a 100644 --- a/src/__tests__/CompareResults/SubtestsRevisionRow.test.tsx +++ b/src/__tests__/CompareResults/SubtestsRevisionRow.test.tsx @@ -7,7 +7,11 @@ import { loader } from '../../components/CompareResults/loader'; import SubtestsRevisionRow from '../../components/CompareResults/SubtestsResults/SubtestsRevisionRow'; import { MannWhitneyResultsItem } from '../../types/state'; import getTestData from '../utils/fixtures'; -import { screen, renderWithRouter } from '../utils/test-utils'; +import { + screen, + renderWithRouter, + enableAdvancedColumns, +} from '../utils/test-utils'; function renderWithRoute(component: ReactElement) { fetchMock @@ -178,6 +182,7 @@ describe('SubtestsRevisionRow Component', () => { }); it('should display cliffs delta, significance, and effects size in subtests for mann-whitney-u testVersion', async () => { + enableAdvancedColumns(); const { subtestsMannWhitneyResult } = getTestData(); const mockGridTemplateColumns = '1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr'; renderWithRoute( @@ -194,7 +199,7 @@ describe('SubtestsRevisionRow Component', () => { expect(effects).toHaveTextContent('60.00%'); const significanceCell = roles[8]; - expect(significanceCell?.querySelector('svg')).not.toBeNull(); + expect(significanceCell).toHaveTextContent('Real'); const cliffs_delta = roles[6]?.childNodes[1]; expect(cliffs_delta).toHaveTextContent('0.02'); @@ -213,7 +218,7 @@ describe('SubtestsRevisionRow Component', () => { ); const roles = await screen.findAllByRole('cell'); - const status = roles[5]?.childNodes[0]; + const status = roles[5]?.querySelector('.status-hint'); expect(status).toHaveTextContent('Regression'); expect(status).toHaveClass('status-hint-regression'); }); @@ -231,7 +236,7 @@ describe('SubtestsRevisionRow Component', () => { ); const roles1 = await screen.findAllByRole('cell'); - const status1 = roles1[5]?.childNodes[0]; + const status1 = roles1[5]?.querySelector('.status-hint'); expect(status1).toHaveTextContent('Improvement'); expect(status1).toHaveClass('status-hint-improvement'); }); @@ -253,7 +258,7 @@ describe('SubtestsRevisionRow Component', () => { }; } - it('shows dash when neither distribution is normal', async () => { + it('shows value with warning icon when neither distribution is normal', async () => { renderWithRoute( <SubtestsRevisionRow result={makeResult(tooFewRuns, tooFewRuns)} @@ -263,7 +268,10 @@ describe('SubtestsRevisionRow Component', () => { />, ); 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 () => { @@ -276,7 +284,7 @@ describe('SubtestsRevisionRow Component', () => { />, ); const roles = await screen.findAllByRole('cell'); - expect(roles[4]).not.toHaveTextContent('-'); + expect(roles[4]).toHaveTextContent('%'); expect(roles[4].querySelector('svg[role="img"]')).toBeTruthy(); }); @@ -290,7 +298,7 @@ describe('SubtestsRevisionRow Component', () => { />, ); const roles = await screen.findAllByRole('cell'); - expect(roles[4]).not.toHaveTextContent('-'); + expect(roles[4]).toHaveTextContent('%'); expect(roles[4].querySelector('svg[role="img"]')).toBeFalsy(); }); }); diff --git a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap index dbd059e14..128181692 100644 --- a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap @@ -52,7 +52,7 @@ exports[`Results View The table should match snapshot and other elements should aria-invalid="false" aria-label="Search by title, platform, revision or options" class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputSizeSmall MuiInputBase-inputAdornedStart MuiInputBase-inputAdornedEnd css-3v3un6-MuiInputBase-input-MuiOutlinedInput-input" - id="_r_a_" + id="_r_b_" placeholder="Filter results" type="search" value="" @@ -217,7 +217,7 @@ exports[`Results View The table should match snapshot and other elements should </div> </div> <div - class="MuiGrid-root MuiGrid-direction-xs-row MuiGrid-grid-xs-grow css-t3of1j-MuiGrid-root" + class="MuiGrid-root MuiGrid-direction-xs-row MuiGrid-grid-xs-grow css-vvfr7q-MuiGrid-root" > <div class="MuiBox-root css-0" @@ -295,7 +295,7 @@ exports[`Results View The table should match snapshot and other elements should </div> </div> <div - class="MuiGrid-root MuiGrid-direction-xs-row MuiGrid-grid-xs-grow css-t3of1j-MuiGrid-root" + class="MuiGrid-root MuiGrid-direction-xs-row MuiGrid-grid-xs-grow css-wautn6-MuiGrid-root" > <div class="f6hg2jo" @@ -312,41 +312,108 @@ exports[`Results View The table should match snapshot and other elements should <div class="MuiGrid-root MuiGrid-direction-xs-row MuiGrid-grid-xs-auto css-zh2j38-MuiGrid-root" > - <label - aria-label="Expand all rows" - class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-1bsjtco-MuiFormControlLabel-root" - data-mui-internal-clone-element="true" + <div + class="MuiBox-root css-p2w42" > - <span - class="MuiButtonBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall PrivateSwitchBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall css-1nff2up-MuiButtonBase-root-MuiSwitchBase-root-MuiCheckbox-root" + <label + aria-label="Show the advanced statistics columns (Cliff’s Delta, CLES, Significance)" + class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-1bsjtco-MuiFormControlLabel-root" + data-mui-internal-clone-element="true" > - <input - class="PrivateSwitchBase-input css-12xagqm-MuiSwitchBase-root" - data-indeterminate="false" - type="checkbox" - /> - <svg - aria-hidden="true" - class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall css-54rgmy-MuiSvgIcon-root" - data-testid="CheckBoxOutlineBlankIcon" - focusable="false" - viewBox="0 0 24 24" + <span + class="MuiButtonBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall PrivateSwitchBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall css-1nff2up-MuiButtonBase-root-MuiSwitchBase-root-MuiCheckbox-root" > - <path - d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z" + <input + class="PrivateSwitchBase-input css-12xagqm-MuiSwitchBase-root" + data-indeterminate="false" + type="checkbox" /> - </svg> - </span> - <span - class="MuiTypography-root MuiTypography-body1 MuiFormControlLabel-label css-n290n7-MuiTypography-root" + <svg + aria-hidden="true" + class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall css-54rgmy-MuiSvgIcon-root" + data-testid="CheckBoxOutlineBlankIcon" + focusable="false" + viewBox="0 0 24 24" + > + <path + d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z" + /> + </svg> + </span> + <span + class="MuiTypography-root MuiTypography-body1 MuiFormControlLabel-label css-n290n7-MuiTypography-root" + > + Advanced columns + </span> + </label> + <label + aria-label="Show the "How to read the results" guide above the table" + class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-1bsjtco-MuiFormControlLabel-root" + data-mui-internal-clone-element="true" > - Expand all - </span> - </label> + <span + class="MuiButtonBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall PrivateSwitchBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall Mui-checked MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall css-1nff2up-MuiButtonBase-root-MuiSwitchBase-root-MuiCheckbox-root" + > + <input + checked="" + class="PrivateSwitchBase-input css-12xagqm-MuiSwitchBase-root" + data-indeterminate="false" + type="checkbox" + /> + <svg + aria-hidden="true" + class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall css-54rgmy-MuiSvgIcon-root" + data-testid="CheckBoxIcon" + focusable="false" + viewBox="0 0 24 24" + > + <path + d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" + /> + </svg> + </span> + <span + class="MuiTypography-root MuiTypography-body1 MuiFormControlLabel-label css-n290n7-MuiTypography-root" + > + How to read the results + </span> + </label> + <label + aria-label="Expand all rows" + class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-1bsjtco-MuiFormControlLabel-root" + data-mui-internal-clone-element="true" + > + <span + class="MuiButtonBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall PrivateSwitchBase-root MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall MuiCheckbox-root MuiCheckbox-colorPrimary MuiCheckbox-sizeSmall css-1nff2up-MuiButtonBase-root-MuiSwitchBase-root-MuiCheckbox-root" + > + <input + class="PrivateSwitchBase-input css-12xagqm-MuiSwitchBase-root" + data-indeterminate="false" + type="checkbox" + /> + <svg + aria-hidden="true" + class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall css-54rgmy-MuiSvgIcon-root" + data-testid="CheckBoxOutlineBlankIcon" + focusable="false" + viewBox="0 0 24 24" + > + <path + d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z" + /> + </svg> + </span> + <span + class="MuiTypography-root MuiTypography-body1 MuiFormControlLabel-label css-n290n7-MuiTypography-root" + > + Expand all + </span> + </label> + </div> </div> </div> <div - class="fdtnfac f1l733lh" + class="fm2goje f1l733lh" data-testid="table-header" role="row" > @@ -417,12 +484,12 @@ exports[`Results View The table should match snapshot and other elements should role="columnheader" > <span - aria-label="Median Diff %: The percentage change in median from Base to New: ((New − Base) / Base) × 100." + aria-label="Shows how much the middle result changed from Base to New. We line up all the runs from smallest to biggest and pick the middle one for each side, then show the change as a percent. A postive sign means New is higher; a negative sign means New is lower." class="MuiBox-root css-1tkq7a4" data-mui-internal-clone-element="true" > <button - aria-label="MD (%) (Click to sort by this column)" + aria-label="Δ Median % (Click to sort by this column)" class="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedTableHeaderButton MuiButton-sizeSmall MuiButton-containedSizeSmall MuiButton-colorTableHeaderButton MuiButton-disableElevation css-7upxw3-MuiButtonBase-root-MuiButton-root" tabindex="0" type="button" @@ -438,10 +505,10 @@ exports[`Results View The table should match snapshot and other elements should d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99zM9 3 5 6.99h3V14h2V6.99h3z" /> <title> - Not sorted by MD (%) + Not sorted by Δ Median % - MD (%) + Δ Median % @@ -479,70 +546,6 @@ exports[`Results View The table should match snapshot and other elements should -
- - - -
-
- - - -
- 0 % + +1.08%
-
-
- - -
-
- - + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + -2.40%
-
-
- - -
-
- - + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + -2.40%
-
-
- - -
-
- - + class="MuiBox-root css-j0pheo" + > +
+
+
- + + + + + + + + Expand all + + +
@@ -1390,12 +1587,12 @@ exports[`Results Table Should match snapshot 1`] = ` role="columnheader" >
@@ -1452,70 +1649,6 @@ exports[`Results Table Should match snapshot 1`] = `
-
- - - -
-
- - - -
- 0 % + +1.08%
-
-
- - -
-
- - + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + -2.40%
-
-
- - -
-
- - + class="MuiBox-root css-j0pheo" + > +
+
+
- + + + + + + + + Expand all + + +
@@ -4273,12 +4572,12 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion role="columnheader" >
@@ -4376,7 +4675,7 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion data-mui-internal-clone-element="true" >
@@ -4598,7 +4897,7 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion class="revision-block fw0pvlu" >
- 1.849 % + +1.85%
- - Regression + + Regression +
+ + Negligible +
- - + Noise
- 1.078 % + +1.08%
- - Improvement + + Improvement +
- - + Noise
- -2.401 % + -2.40%
+ class="MuiBox-root css-j0pheo" + > +
+
- + Real
- 1.078 % + +1.08%
- - Improvement + + Improvement +
- - + Noise
- 1.078 % + +1.08%
- - Improvement + + Improvement +
- - + Noise
@@ -1634,70 +1699,6 @@ exports[`Results View The table should match snapshot and other elements should
-
- - - -
-
- - - -
- 0 % + +1.08%
-
-
- - -
-
- - + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + -2.40%
-
-
- - -
-
- - + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + -2.40%
-
-
- - -
-
- - + class="MuiBox-root css-j0pheo" + > +
+
+
+ +
@@ -904,12 +939,12 @@ exports[`SubtestsResultsView Component Tests should render the subtests results role="columnheader" >
@@ -966,70 +1001,6 @@ exports[`SubtestsResultsView Component Tests should render the subtests results
-
- - - -
-
- - - -
- 0 % + +1.14%
-
-
- - - -
-
- 0.00% + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + +1.14%
-
-
- - - -
-
- 0.00% + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + +1.14%
-
-
- - - -
-
- 0.00% + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + +0.98%
-
-
- - - -
-
- 0.00% + class="MuiBox-root css-j0pheo" + > +
+
+
+ +
@@ -2815,12 +2776,12 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi role="columnheader" >
@@ -2877,70 +2838,6 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi
-
- - - -
-
- - - -
- 1.135 % + +1.14%
- - Regression + + Regression +
+ + Negligible +
-
- - 0.02 -
-
- 60.00% -
- + Real
- 0.963 % + +1.14%
-
-
- - -0.05 -
-
- 50.00% + class="MuiBox-root css-j0pheo" + > +
+ + Negligible + +
- + Real
- 1.135 % + +1.14%
-
-
- - 0.12 -
-
- 25.00% + class="MuiBox-root css-j0pheo" + > +
+ + Small + +
- + Real
- 0.98 % + +0.98%
- - Improvement + + Improvement +
+ + Negligible +
-
- - 0.01 -
-
- 45.00% -
+
+ +
@@ -4417,12 +4290,12 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi role="columnheader" >
@@ -4479,70 +4352,6 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi
-
- - - -
-
- - - -
- 1.135 % + +1.14%
- - Regression + + Regression +
+ + Negligible +
-
- - 0.02 -
-
- 60.00% -
- + Real
- 0.963 % + +1.14%
-
-
- - -0.05 -
-
- 50.00% + class="MuiBox-root css-j0pheo" + > +
+ + Negligible + +
- + Real
- 1.135 % + +1.14%
-
-
- - 0.12 -
-
- 25.00% + class="MuiBox-root css-j0pheo" + > +
+ + Small + +
- + Real
- 0.98 % + +0.98%
- - Improvement + + Improvement +
+ + Negligible +
-
- - 0.01 -
-
- 45.00% -
+
+ +
@@ -6019,12 +5804,12 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when role="columnheader" >
@@ -6081,70 +5866,6 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when
-
- - - -
-
- - - -
- 1.135 % + +1.14%
- - Regression + + Regression +
+ + Negligible +
-
- - 0.02 -
-
- 60.00% -
- + Real
- 0.963 % + +1.14%
-
-
- - -0.05 -
-
- 50.00% + class="MuiBox-root css-j0pheo" + > +
+ + Negligible + +
- + Real
- 1.135 % + +1.14%
-
-
- - 0.12 -
-
- 25.00% + class="MuiBox-root css-j0pheo" + > +
+ + Small + +
- + Real
- 0.98 % + +0.98%
- - Improvement + + Improvement +
+ + Negligible +
-
- - 0.01 -
-
- 45.00% -
+
+ +
@@ -7621,12 +7318,12 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests role="columnheader" >
@@ -7683,70 +7380,6 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests
-
- - - -
-
- - - -
- 0 % + +1.14%
-
-
- - - -
-
- 0.00% + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + +1.14%
-
-
- - - -
-
- 0.00% + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + +1.14%
-
-
- - - -
-
- 0.00% + class="MuiBox-root css-j0pheo" + > +
+
- 0 % + +0.98%
-
-
- - - -
-
- 0.00% + class="MuiBox-root css-j0pheo" + > +
+
-
- {(() => { - const mwResult = result as MannWhitneyResultsItem; - const normality = checkDistributionNormality(mwResult); - if (normality === 'neither') return '-'; - const baseMedian = mwResult.base_standard_stats?.median ?? 0; - const newMedian = mwResult.new_standard_stats?.median ?? 0; - const pct = - baseMedian !== 0 - ? ((newMedian - baseMedian) / baseMedian) * 100 - : 0; - return ( - - {`${formatNumber(pct)} %`} - {normality === 'one' && ( - - )} - - ); - })()} -
-
- - {direction_of_change === 'improvement' ? ( - - ) : null} - {direction_of_change === 'regression' ? ( - - ) : null} - {capitalize(direction_of_change ?? '')} - -
-
- {' '} - {cliffs_delta || '-'} -
+ {renderMedianDiffCell(result as MannWhitneyResultsItem)} + {renderStatusCell(direction_of_change, cliffs_interpretation)} + {showAdvancedColumns && ( + <> +
+ {' '} + {cliffs_delta || '-'} +
-
- {clesVal ? `${clesVal}% ` : '-'} -
+
+ {clesVal ? `${clesVal}% ` : '-'} +
+ + )}
- {mann_whitney_test?.interpretation === 'significant' ? ( - - ) : ( - '-' - )} + {mann_whitney_test?.interpretation === 'significant' + ? 'Real' + : mann_whitney_test?.interpretation === 'not significant' + ? 'Noise' + : '-'}
); @@ -415,21 +523,13 @@ export const mannWhitneyStrategy = { ? adaptUnit([ci.medianDiff, ci.ciLow, ci.ciHigh], rawUnit) : adaptUnit([], rawUnit); const ciCrossesZero = ci && ci.ciLow < 0 && ci.ciHigh > 0; - const baseMedian = (() => { - if (!baseRuns.length) return null; - const s = [...baseRuns].sort((a, b) => a - b); - const m = Math.floor(s.length / 2); - return s.length % 2 === 0 ? (s[m - 1] + s[m]) / 2 : s[m]; - })(); - const pctDiff = - baseMedian && ci ? ((ci.medianDiff / baseMedian) * 100).toFixed(1) : null; + // Same run-based Δ median % the column shows, formatted identically. + const pctDiff = medianDiffPct(mwResult); const summary = ci ? ( Δ median = {fmt(ci.medianDiff)} {displayUnit} - {pctDiff !== null - ? ` (${Number(pctDiff) >= 0 ? '+' : ''}${pctDiff}%)` - : ''}{' '} - 95% CI [{fmt(ci.ciLow)}, {fmt(ci.ciHigh)}] + {pctDiff !== null ? ` (${formatMedianDiffPct(pctDiff)})` : ''} 95% CI [ + {fmt(ci.ciLow)}, {fmt(ci.ciHigh)}] {ciCrossesZero ? ' ⚠ interval includes zero — effect direction uncertain' : ''} @@ -474,83 +574,37 @@ export const mannWhitneyStrategy = { ); }, - renderColumns(result: CombinedResultsItemType) { + renderColumns(result: CombinedResultsItemType, showAdvancedColumns: boolean) { + const mwResult = result as MannWhitneyResultsItem; const { cliffs_delta, + cliffs_interpretation, direction_of_change, mann_whitney_test, cles, - base_standard_stats, - new_standard_stats, - } = result as MannWhitneyResultsItem; + } = mwResult; const clesValue = cles?.cles ? `${(cles.cles * 100).toFixed(2)} %` : '-'; - const baseMedian = base_standard_stats?.median ?? 0; - const newMedian = new_standard_stats?.median ?? 0; - const medianDiffPct = - baseMedian !== 0 ? ((newMedian - baseMedian) / baseMedian) * 100 : 0; - const normality = checkDistributionNormality( - result as MannWhitneyResultsItem, - ); return ( <> -
- {normality === 'neither' ? ( - '-' - ) : ( - - {`${formatNumber(medianDiffPct)} %`} - {normality === 'one' && ( - - )} - - )} -
-
- - {direction_of_change === 'improvement' ? ( - - ) : null} - {direction_of_change === 'regression' ? ( - - ) : null} - {capitalize(direction_of_change ?? '')} - -
-
- {cliffs_delta || '-'} -
-
- {clesValue} -
+ {renderMedianDiffCell(mwResult)} + {renderStatusCell(direction_of_change, cliffs_interpretation)} + {showAdvancedColumns && ( + <> +
+ {cliffs_delta || '-'} +
+
+ {clesValue} +
+ + )}
- {mann_whitney_test?.interpretation === 'significant' ? ( - - ) : ( - '-' - )} + {mann_whitney_test?.interpretation === 'significant' + ? 'Real' + : mann_whitney_test?.interpretation === 'not significant' + ? 'Noise' + : '-'}
); diff --git a/src/common/testVersions/studentT.tsx b/src/common/testVersions/studentT.tsx index 89c138cc9..266280ee5 100644 --- a/src/common/testVersions/studentT.tsx +++ b/src/common/testVersions/studentT.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import DragHandleIcon from '@mui/icons-material/DragHandle'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; @@ -41,7 +42,10 @@ const confidenceIcons: Record<'Low' | 'Medium' | 'High', React.ReactNode> = { }; export const studentTStrategy = { - getColumns(isSubtestTable: boolean): TableConfig { + getColumns( + isSubtestTable: boolean, + _showAdvancedColumns: boolean, + ): TableConfig { const platformConfig = isSubtestTable ? { name: 'Subtests', @@ -159,7 +163,11 @@ export const studentTStrategy = { }; }, - renderSubtestColumns(result: CombinedResultsItemType, expanded: boolean) { + renderSubtestColumns( + result: CombinedResultsItemType, + expanded: boolean, + _showAdvancedColumns: boolean, + ) { const { test, delta_percentage: deltaPercent, @@ -308,7 +316,10 @@ export const studentTStrategy = { return null; }, - renderColumns(result: CombinedResultsItemType) { + renderColumns( + result: CombinedResultsItemType, + _showAdvancedColumns: boolean, + ) { const { is_improvement: improvement, is_regression: regression, diff --git a/src/components/CompareResults/AdvancedColumnsToggle.tsx b/src/components/CompareResults/AdvancedColumnsToggle.tsx new file mode 100644 index 000000000..72728b856 --- /dev/null +++ b/src/components/CompareResults/AdvancedColumnsToggle.tsx @@ -0,0 +1,38 @@ +import Checkbox from '@mui/material/Checkbox'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Tooltip from '@mui/material/Tooltip'; + +import { useAppDispatch, useAppSelector } from '../../hooks/app'; +import { updateShowAdvancedColumns } from '../../reducers/ColumnPrefsSlice'; + +// Checkbox that toggles the advanced statistics columns (Cliff's Delta, CLES, +// Significance) in the results tables. Self-contained: reads/writes the +// columnPrefs Redux slice and mirrors the choice to localStorage so it +// persists across reloads. Shared by the main results controls and the +// subtests controls so the two stay in sync. +function AdvancedColumnsToggle() { + const dispatch = useAppDispatch(); + const showAdvancedColumns = useAppSelector( + (state) => state.columnPrefs.showAdvancedColumns, + ); + const onChange = (checked: boolean) => { + dispatch(updateShowAdvancedColumns(checked)); + localStorage.setItem('showAdvancedColumns', String(checked)); + }; + return ( + + onChange(e.target.checked)} + size='small' + /> + } + label='Advanced columns' + /> + + ); +} + +export default AdvancedColumnsToggle; diff --git a/src/components/CompareResults/HowToReadResults.tsx b/src/components/CompareResults/HowToReadResults.tsx new file mode 100644 index 000000000..7a79914b7 --- /dev/null +++ b/src/components/CompareResults/HowToReadResults.tsx @@ -0,0 +1,67 @@ +import Alert from '@mui/material/Alert'; +import AlertTitle from '@mui/material/AlertTitle'; +import Box from '@mui/material/Box'; + +import { useAppDispatch, useAppSelector } from '../../hooks/app'; +import { updateShowHowToRead } from '../../reducers/ColumnPrefsSlice'; + +// Beginner-friendly guide shown above the results table, explaining what each +// column means in plain language. +function HowToReadResults() { + const dispatch = useAppDispatch(); + const showHowToRead = useAppSelector( + (state) => state.columnPrefs.showHowToRead, + ); + + if (!showHowToRead) { + return null; + } + + const onClose = () => { + dispatch(updateShowHowToRead(false)); + localStorage.setItem('showHowToRead', 'false'); + }; + + return ( + + How to read the results + +
  • + Each row is one platform. Base is + the old build; New is your change. +
  • +
  • + Base and New show the average result + for each build, in the test's unit. +
  • +
  • + Δ Median % shows how much the middle result moved + from Base to New. A plus sign means New is higher; a minus sign means + New is lower. +
  • +
  • + Status says whether the change is an{' '} + Improvement, a Regression, or{' '} + No change — with the size of the difference + (negligible, small, medium, or large) shown beneath it. +
  • +
  • + Significance tells you whether the difference is + likely a Real change or just Noise + (random run-to-run variation). +
  • +
  • + Tick Advanced columns to add the expert stats + (Cliff's Delta and CLES). +
  • +
    +
    + ); +} + +export default HowToReadResults; diff --git a/src/components/CompareResults/ResultsControls.tsx b/src/components/CompareResults/ResultsControls.tsx index 103ec22cf..727366580 100644 --- a/src/components/CompareResults/ResultsControls.tsx +++ b/src/components/CompareResults/ResultsControls.tsx @@ -1,3 +1,4 @@ +import Box from '@mui/material/Box'; import Checkbox from '@mui/material/Checkbox'; import FormControl from '@mui/material/FormControl'; import FormControlLabel from '@mui/material/FormControlLabel'; @@ -5,10 +6,12 @@ import Grid from '@mui/material/Grid'; import Tooltip from '@mui/material/Tooltip'; import { style } from 'typestyle'; +import AdvancedColumnsToggle from './AdvancedColumnsToggle'; import { DownloadButton } from './DownloadButton'; import RevisionSelect from './RevisionSelect'; import SearchInput from './SearchInput'; -import { useAppSelector } from '../../hooks/app'; +import { useAppDispatch, useAppSelector } from '../../hooks/app'; +import { updateShowHowToRead } from '../../reducers/ColumnPrefsSlice'; import { Strings } from '../../resources/Strings'; import type { CombinedResultsItemType } from '../../types/state'; import type { Framework, TestVersion } from '../../types/types'; @@ -44,6 +47,14 @@ export default function ResultsControls({ onExpandAllChange, }: Props) { const mode = useAppSelector((state) => state.theme.mode); + const dispatch = useAppDispatch(); + const showHowToRead = useAppSelector( + (state) => state.columnPrefs.showHowToRead, + ); + const onShowHowToReadChange = (checked: boolean) => { + dispatch(updateShowHowToRead(checked)); + localStorage.setItem('showHowToRead', String(checked)); + }; return ( - + - + - - onExpandAllChange(e.target.checked)} - size='small' - /> - } - label='Expand all' - /> - + + + + onShowHowToReadChange(e.target.checked)} + size='small' + /> + } + label='How to read the results' + /> + + + onExpandAllChange(e.target.checked)} + size='small' + /> + } + label='Expand all' + /> + + ); diff --git a/src/components/CompareResults/ResultsMain.tsx b/src/components/CompareResults/ResultsMain.tsx index 85fbfb933..126f92e6d 100644 --- a/src/components/CompareResults/ResultsMain.tsx +++ b/src/components/CompareResults/ResultsMain.tsx @@ -7,6 +7,7 @@ import { Container } from '@mui/system'; import { useLoaderData } from 'react-router'; import { style } from 'typestyle'; +import HowToReadResults from './HowToReadResults'; import type { LoaderReturnValue } from './loader'; import type { LoaderReturnValue as OverTimeLoaderReturnValue } from './overTimeLoader'; import ResultsTable from './ResultsTable'; @@ -192,6 +193,7 @@ function ResultsMain() { {testWarnings[testVersion] ?? testWarnings[MANN_WHITNEY_U]} + ); diff --git a/src/components/CompareResults/ResultsTable.tsx b/src/components/CompareResults/ResultsTable.tsx index 3205fb5fe..8ca6a81e8 100644 --- a/src/components/CompareResults/ResultsTable.tsx +++ b/src/components/CompareResults/ResultsTable.tsx @@ -1,4 +1,4 @@ -import { Suspense, useState } from 'react'; +import { Suspense, useMemo, useState } from 'react'; import Box from '@mui/material/Box'; import CircularProgress from '@mui/material/CircularProgress'; @@ -10,6 +10,7 @@ import ResultsControls from './ResultsControls'; import TableContent from './TableContent'; import TableHeader from './TableHeader'; import { MANN_WHITNEY_U } from '../../common/constants'; +import { useAppSelector } from '../../hooks/app'; import useRawSearchParams from '../../hooks/useRawSearchParams'; import useTableFilters from '../../hooks/useTableFilters'; import useTableSort from '../../hooks/useTableSort'; @@ -35,9 +36,18 @@ export default function ResultsTable() { // This is our custom hook that updates the search params without a rerender. const [rawSearchParams, updateRawSearchParams] = useRawSearchParams(); - const columnsConfig = getColumnsConfiguration( - false, - testVersion ?? MANN_WHITNEY_U, + const showAdvancedColumns = useAppSelector( + (state) => state.columnPrefs.showAdvancedColumns, + ); + + const columnsConfig = useMemo( + () => + getColumnsConfiguration( + false, + testVersion ?? MANN_WHITNEY_U, + showAdvancedColumns, + ), + [testVersion, showAdvancedColumns], ); // This is our custom hook that manages table filters diff --git a/src/components/CompareResults/RevisionRow.tsx b/src/components/CompareResults/RevisionRow.tsx index 5a4a18f22..569107c59 100644 --- a/src/components/CompareResults/RevisionRow.tsx +++ b/src/components/CompareResults/RevisionRow.tsx @@ -12,6 +12,7 @@ import { RetriggerButton } from './Retrigger/RetriggerButton'; import RevisionRowExpandable from './RevisionRowExpandable'; import { compareView, compareOverTimeView } from '../../common/constants'; import { getStrategy } from '../../common/testVersions'; +import { useAppSelector } from '../../hooks/app'; import { useSubtestRegressionCount } from '../../hooks/useSubtestRegressionCount'; import { Strings } from '../../resources/Strings'; import { FontSize, Spacing } from '../../styles'; @@ -246,6 +247,9 @@ function RevisionRow(props: RevisionRowProps) { : baseRuns.length; const newRunsCount = replicates ? newRunsReplicates.length : newRuns.length; const strategy = getStrategy(testVersion); + const showAdvancedColumns = useAppSelector( + (state) => state.columnPrefs.showAdvancedColumns, + ); const { baseAvg: baseAvgValue, newAvg: newAvgValue } = strategy.getAvgValues(result); const [expanded, setExpanded] = useState(false); @@ -312,7 +316,7 @@ function RevisionRow(props: RevisionRowProps) { ({newApp}) )}
    - {strategy.renderColumns(result)} + {strategy.renderColumns(result, showAdvancedColumns)}
    + + + ); diff --git a/src/components/CompareResults/SubtestsResults/SubtestsResultsTable.tsx b/src/components/CompareResults/SubtestsResults/SubtestsResultsTable.tsx index 138c795d6..230b7a615 100644 --- a/src/components/CompareResults/SubtestsResults/SubtestsResultsTable.tsx +++ b/src/components/CompareResults/SubtestsResults/SubtestsResultsTable.tsx @@ -8,6 +8,7 @@ import SubtestsTableContent from './SubtestsTableContent'; import NoResultsFound from '.././NoResultsFound'; import TableHeader from '.././TableHeader'; import { STUDENT_T } from '../../../common/constants'; +import { useAppSelector } from '../../../hooks/app'; import useTableFilters, { filterResults } from '../../../hooks/useTableFilters'; import useTableSort, { sortResults } from '../../../hooks/useTableSort'; import type { CombinedResultsItemType } from '../../../types/state'; @@ -79,9 +80,17 @@ function SubtestsResultsTable({ replicates, testVersion, }: ResultsTableProps) { - const columnsConfiguration = getColumnsConfiguration( - true, - testVersion ?? STUDENT_T, + const showAdvancedColumns = useAppSelector( + (state) => state.columnPrefs.showAdvancedColumns, + ); + const columnsConfiguration = useMemo( + () => + getColumnsConfiguration( + true, + testVersion ?? STUDENT_T, + showAdvancedColumns, + ), + [testVersion, showAdvancedColumns], ); // This is our custom hook that manages table filters // and provides methods for clearing and toggling them. diff --git a/src/components/CompareResults/SubtestsResults/SubtestsRevisionRow.tsx b/src/components/CompareResults/SubtestsResults/SubtestsRevisionRow.tsx index 0529f5495..668ee17b6 100644 --- a/src/components/CompareResults/SubtestsResults/SubtestsRevisionRow.tsx +++ b/src/components/CompareResults/SubtestsResults/SubtestsRevisionRow.tsx @@ -9,6 +9,7 @@ import { style } from 'typestyle'; import RevisionRowExpandable from '.././RevisionRowExpandable'; import { MANN_WHITNEY_U } from '../../../common/constants'; import { getStrategy } from '../../../common/testVersions'; +import { useAppSelector } from '../../../hooks/app'; import { Strings } from '../../../resources/Strings'; import { Spacing } from '../../../styles'; import type { CombinedResultsItemType } from '../../../types/state'; @@ -119,6 +120,9 @@ function SubtestsRevisionRow(props: RevisionRowProps) { }; const strategy = getStrategy(testVersion ?? MANN_WHITNEY_U); + const showAdvancedColumns = useAppSelector( + (state) => state.columnPrefs.showAdvancedColumns, + ); return ( <> @@ -127,7 +131,7 @@ function SubtestsRevisionRow(props: RevisionRowProps) { sx={{ gridTemplateColumns, backgroundColor: 'revisionRow.background' }} role='row' > - {strategy.renderSubtestColumns(result, expanded)} + {strategy.renderSubtestColumns(result, expanded, showAdvancedColumns)}
    ) { + state.showAdvancedColumns = action.payload; + }, + updateShowHowToRead(state, action: PayloadAction) { + state.showHowToRead = action.payload; + }, + }, +}); + +export const { updateShowAdvancedColumns, updateShowHowToRead } = + columnPrefs.actions; +export default columnPrefs.reducer; diff --git a/src/utils/rowTemplateColumns.ts b/src/utils/rowTemplateColumns.ts index 1caa4d4a1..cc29f3140 100644 --- a/src/utils/rowTemplateColumns.ts +++ b/src/utils/rowTemplateColumns.ts @@ -11,6 +11,8 @@ export { export const getColumnsConfiguration = ( isSubtestTable: boolean, testVersion: TestVersion, -): TableConfig => getColumnsForVersion(testVersion, isSubtestTable); + showAdvancedColumns: boolean, +): TableConfig => + getColumnsForVersion(testVersion, isSubtestTable, showAdvancedColumns); export { toGridTemplateColumns } from './gridTemplateColumns';