From 9b9fa18992cbfa6547146834eeb5b4e0e2fb6ae3 Mon Sep 17 00:00:00 2001 From: Carla Severe Date: Tue, 23 Jun 2026 14:02:55 -0700 Subject: [PATCH 1/9] =?UTF-8?q?the=20median=20diff=20col=20has=20been=20re?= =?UTF-8?q?placed=20with=20a=20mode=20=CE=94=20col?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CompareResults/ResultsTable.test.tsx | 256 +++++++-------- .../CompareResults/RevisionRow.test.tsx | 71 ---- .../SubtestsResultsView.test.tsx | 102 +++--- .../SubtestsRevisionRow.test.tsx | 60 ---- .../OverTimeResultsView.test.tsx.snap | 52 +-- .../__snapshots__/ResultsTable.test.tsx.snap | 178 ++++------ .../__snapshots__/ResultsView.test.tsx.snap | 52 +-- .../SubtestsResultsView.test.tsx.snap | 310 ++++++------------ src/common/constants.ts | 4 +- src/common/testVersions/mannWhitney.tsx | 117 +++---- src/components/CompareResults/loader.ts | 23 ++ .../CompareResults/overTimeLoader.ts | 12 + .../CompareResults/subtestsLoader.ts | 13 +- .../CompareResults/subtestsOverTimeLoader.tsx | 11 +- src/types/state.ts | 6 + src/utils/kdeAnalysis.ts | 60 ++++ 16 files changed, 562 insertions(+), 765 deletions(-) diff --git a/src/__tests__/CompareResults/ResultsTable.test.tsx b/src/__tests__/CompareResults/ResultsTable.test.tsx index c663ada1d..57e9f4930 100644 --- a/src/__tests__/CompareResults/ResultsTable.test.tsx +++ b/src/__tests__/CompareResults/ResultsTable.test.tsx @@ -85,7 +85,7 @@ function summarizeVisibleRows(testVersion?: TestVersion) { testVersion === 'mann-whitney-u' ? [ '.platform span', - '.median-diff', + '.mode-delta', '.status', '.delta', '.significance', @@ -722,9 +722,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ' rev: devilrabbit', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ]); expect(screen.getByRole('rowgroup')).toMatchSnapshot(); }); @@ -748,12 +748,12 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await screen.findByText('a11yr'); expect(summarizeVisibleRows('mann-whitney-u')).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 %', + ' - Android, -, Improvement, 0.1, -, 25.00 %', + ' - inexistant, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); @@ -762,9 +762,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Windows/); expect(summarizeVisibleRows('mann-whitney-u')).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, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'linux', 'android', 'ios'], @@ -775,12 +775,12 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Windows/); expect(summarizeVisibleRows('mann-whitney-u')).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 %', + ' - Android, -, Improvement, 0.1, -, 25.00 %', + ' - inexistant, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); @@ -788,8 +788,8 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Linux/); expect(summarizeVisibleRows('mann-whitney-u')).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, -, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'android', 'ios'], @@ -798,9 +798,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Linux/); expect(summarizeVisibleRows('mann-whitney-u')).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, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'android', 'ios', 'linux'], @@ -809,22 +809,22 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', 'Select all values'); expect(summarizeVisibleRows('mann-whitney-u')).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 %', + ' - Android, -, Improvement, 0.1, -, 25.00 %', + ' - inexistant, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); await clickMenuItem(user, 'Platform', /macOS/); expect(summarizeVisibleRows('mann-whitney-u')).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 %', + ' - Android, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['windows', 'linux', 'android', 'ios'], @@ -833,9 +833,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Android/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['windows', 'linux', 'ios'], @@ -844,7 +844,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Select only.*Android/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - Android, -, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['android'], @@ -883,10 +883,10 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await screen.findByText('a11yr'); expect(summarizeVisibleRows('mann-whitney-u')).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, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); @@ -894,8 +894,8 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /No changes/); expect(summarizeVisibleRows('mann-whitney-u')).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, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['improvement', 'regression'], @@ -904,7 +904,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Improvement/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['regression'], @@ -914,9 +914,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Regression/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['none', 'improvement'], @@ -925,17 +925,17 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Regression/); expect(summarizeVisibleRows('mann-whitney-u')).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, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); await clickMenuItem(user, 'Status', /Select only.*Regression/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['regression'], @@ -944,7 +944,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Select only.*Improvement/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['improvement'], @@ -961,7 +961,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ]); const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); expect(await summarizeTableFiltersFromCheckboxes(user)).toEqual({ @@ -997,26 +997,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).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 %', + ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', + ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', ' - Windows 10, -, , 1.2, , 99.00 %', - ' - Windows 10, -2.401 %, , 1.2, , 49.00 %', + ' - Windows 10, -, , 1.2, , 49.00 %', ' rev: tictactoe', - ' - Linux 18.04, 1.849 %, Regression, 2, -, 43.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, -, Regression, 2, -, 43.00 %', + ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', ' - Windows 10, -, , 2, , 98.00 %', - ' - Windows 10, -2.401 %, , 2, , 48.00 %', + ' - Windows 10, -, , 2, , 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 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ' rev: tictactoe', - ' - Linux 18.04, 1.849 %, Regression, 0.8, -, 44.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', + ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', ' - Windows 10, -, , 0.8, , 99.00 %', - ' - Windows 10, -2.401 %, , 0.8, , 49.00 %', + ' - Windows 10, -, , 0.8, , 49.00 %', ]); // It should have the "descending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -1028,25 +1028,25 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).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 %', + ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, -, Regression, 2, -, 43.00 %', + ' - Windows 10, -, , 2, , 48.00 %', ' - Windows 10, -, , 2, , 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 %', + ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', + ' - Windows 10, -, , 1.2, , 49.00 %', ' - Windows 10, -, , 1.2, , 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 %', + ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', + ' - Windows 10, -, , 0.8, , 49.00 %', ' - Windows 10, -, , 0.8, , 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 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - Windows 10, -, , -, , 50.00 %', ' - Windows 10, -, , -, , 100.00 %', ]); // It should have the "ascending" SVG. @@ -1062,26 +1062,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).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 %', + ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, -, Regression, 2, -, 43.00 %', ' - Windows 10, -, , 2, , 98.00 %', - ' - Windows 10, -2.401 %, , 2, , 48.00 %', + ' - Windows 10, -, , 2, , 48.00 %', ' rev: spam', - ' - macOS 10.15, 1.078 %, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, 1.849 %, Regression, 1.2, -, 44.00 %', + ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', ' - Windows 10, -, , 1.2, , 99.00 %', - ' - Windows 10, -2.401 %, , 1.2, , 49.00 %', + ' - Windows 10, -, , 1.2, , 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 %', + ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', ' - Windows 10, -, , 0.8, , 99.00 %', - ' - Windows 10, -2.401 %, , 0.8, , 49.00 %', + ' - Windows 10, -, , 0.8, , 49.00 %', ' rev: spam', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ]); // It should have the "descending" SVG. expect(significanceButton).toMatchSnapshot(); @@ -1093,26 +1093,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -2.401 %, , -, , 50.00 %', + ' - Windows 10, -, , -, , 50.00 %', ' - Windows 10, -, , -, , 100.00 %', - ' - macOS 10.15, 1.078 %, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, 1.849 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', ' rev: tictactoe', - ' - Windows 10, -2.401 %, , 0.8, , 49.00 %', + ' - Windows 10, -, , 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 %', + ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -2.401 %, , 1.2, , 49.00 %', + ' - Windows 10, -, , 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 %', + ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', ' rev: tictactoe', - ' - Windows 10, -2.401 %, , 2, , 48.00 %', + ' - Windows 10, -, , 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 %', + ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, -, Regression, 2, -, 43.00 %', ]); // It should have the "descending" SVG. expect(significanceButton).toMatchSnapshot(); @@ -1128,25 +1128,25 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio '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 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - Windows 10, -, , -, , 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 %', + ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', + ' - Windows 10, -, , 0.8, , 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 %', + ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', + ' - Windows 10, -, , 1.2, , 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 %', + ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, -, Regression, 2, -, 43.00 %', + ' - Windows 10, -, , 2, , 48.00 %', ]); expect(effectSizeButton).toMatchSnapshot(); @@ -1158,45 +1158,45 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).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, -, , -, , 50.00 %', + ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', ' - Windows 10, -, , -, , 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, , 49.00 %', + ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', + ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', ' - Windows 10, -, , 0.8, , 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, , 49.00 %', + ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', + ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', ' - Windows 10, -, , 1.2, , 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, , 48.00 %', + ' - Linux 18.04, -, Regression, 2, -, 43.00 %', + ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', ' - Windows 10, -, , 2, , 98.00 %', ]); expect(effectSizeButton).toMatchSnapshot(); // It should be persisted in the URL expectParameterToHaveValue('sort', 'effects|asc'); - // Sort by MD(%) descending - const medianDiffButton = screen.getByRole('button', { - name: /MD \(%\).*sort/, + // Sort by Mode Δ (%) descending + const modeDeltaButton = screen.getByRole('button', { + name: /Mode .*sort/, }); - await user.click(medianDiffButton); + await user.click(modeDeltaButton); expect(summarizeVisibleRows('mann-whitney-u')).toMatchSnapshot(); - expect(medianDiffButton).toMatchSnapshot(); - expectParameterToHaveValue('sort', 'median-diff|desc'); + expect(modeDeltaButton).toMatchSnapshot(); + expectParameterToHaveValue('sort', 'mode-delta|desc'); - // Sort by MD(%) ascending - await user.click(medianDiffButton); + // Sort by Mode Δ (%) ascending + await user.click(modeDeltaButton); expect(summarizeVisibleRows('mann-whitney-u')).toMatchSnapshot(); - expect(medianDiffButton).toMatchSnapshot(); - expectParameterToHaveValue('sort', 'median-diff|asc'); + expect(modeDeltaButton).toMatchSnapshot(); + expectParameterToHaveValue('sort', 'mode-delta|asc'); }); it('should switch between Student-T and Mann-Whitney-U test versions', async () => { diff --git a/src/__tests__/CompareResults/RevisionRow.test.tsx b/src/__tests__/CompareResults/RevisionRow.test.tsx index ae86e4950..b33332cd3 100644 --- a/src/__tests__/CompareResults/RevisionRow.test.tsx +++ b/src/__tests__/CompareResults/RevisionRow.test.tsx @@ -4,7 +4,6 @@ import fetchMock from '@fetch-mock/jest'; import userEvent from '@testing-library/user-event'; import { compareView } from '../../common/constants'; -import { isDistributionNormal } from '../../common/testVersions/mannWhitney'; import { loader } from '../../components/CompareResults/loader'; import RevisionRow from '../../components/CompareResults/RevisionRow'; import { useSubtestRegressionCount } from '../../hooks/useSubtestRegressionCount'; @@ -524,76 +523,6 @@ describe('Expanded row', () => { expect(writeTextMock).toHaveBeenCalledWith(baseRuns); }); - - describe('median diff column normality gating', () => { - const normalRuns = [5.1, 5.2, 4.9, 5.0, 5.05]; - const tooFewRuns = [5.0]; - - function makeResult( - baseRuns: number[], - newRuns: number[], - ): MannWhitneyResultsItem { - const { testCompareMannWhitneyData } = getTestData(); - return { - ...testCompareMannWhitneyData[0], - base_runs: baseRuns, - new_runs: newRuns, - }; - } - - it('shows dash when neither distribution is normal', async () => { - const result = makeResult(tooFewRuns, tooFewRuns); - expect(isDistributionNormal(result)).toBe(false); - renderWithRoute( - , - ); - const roles = await screen.findAllByRole('cell'); - expect(roles[4]).toHaveTextContent('-'); - }); - - it('shows value with warning icon when only one distribution is normal', async () => { - const result = makeResult(normalRuns, tooFewRuns); - expect(isDistributionNormal(result)).toBe(true); - renderWithRoute( - , - ); - const roles = await screen.findAllByRole('cell'); - expect(roles[4]).not.toHaveTextContent('-'); - expect(roles[4].querySelector('svg[role="img"]')).toBeTruthy(); - }); - - it('shows value without warning icon when both distributions are normal', async () => { - const result = makeResult(normalRuns, normalRuns); - expect(isDistributionNormal(result)).toBe(true); - renderWithRoute( - , - ); - const roles = await screen.findAllByRole('cell'); - expect(roles[4]).not.toHaveTextContent('-'); - expect(roles[4].querySelector('svg[role="img"]')).toBeFalsy(); - }); - }); }); describe('expandAll prop', () => { diff --git a/src/__tests__/CompareResults/SubtestsResultsView.test.tsx b/src/__tests__/CompareResults/SubtestsResultsView.test.tsx index 87e1b9081..aaf94410d 100644 --- a/src/__tests__/CompareResults/SubtestsResultsView.test.tsx +++ b/src/__tests__/CompareResults/SubtestsResultsView.test.tsx @@ -59,7 +59,7 @@ function summarizeVisibleRows(testVersion?: TestVersion) { } const rowClasses = testVersion === 'mann-whitney-u' - ? ['.median-diff', '.delta', '.significance', '.effects'] + ? ['.mode-delta', '.delta', '.significance', '.effects'] : ['.delta', '.confidence']; const rowString = rowClasses .map((selector) => row.querySelector(selector)?.textContent.trim()) @@ -527,11 +527,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( 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%', + 'browser.html: -, -0.04, -, 15.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'improvement.html: -, -0.05, , 50.00%', + 'regression.html: -, 0.12, , 25.00%', + 'tablemutation.html: -, 0.01, -, 45.00%', ]); // Sort by Delta @@ -542,11 +542,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( // 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%', + 'regression.html: -, 0.12, , 25.00%', + 'improvement.html: -, -0.05, , 50.00%', + 'browser.html: -, -0.04, -, 15.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'tablemutation.html: -, 0.01, -, 45.00%', ]); // It should have the "descending" SVG. @@ -557,11 +557,11 @@ 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%', + 'tablemutation.html: -, 0.01, -, 45.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'browser.html: -, -0.04, -, 15.00%', + 'improvement.html: -, -0.05, , 50.00%', + 'regression.html: -, 0.12, , 25.00%', ]); // It should have the "ascending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -574,11 +574,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( }); 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%', + 'browser.html: -, -0.04, -, 15.00%', + 'tablemutation.html: -, 0.01, -, 45.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'regression.html: -, 0.12, , 25.00%', + 'improvement.html: -, -0.05, , 50.00%', ]); // It should have the "no sort" SVG. expect(deltaButton).toMatchSnapshot(); @@ -590,11 +590,11 @@ 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%', + 'improvement.html: -, -0.05, , 50.00%', + 'regression.html: -, 0.12, , 25.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'tablemutation.html: -, 0.01, -, 45.00%', + 'browser.html: -, -0.04, -, 15.00%', ]); expectParameterToHaveValue('sort', 'significance|asc'); @@ -604,11 +604,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( }); 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%', + 'browser.html: -, -0.04, -, 15.00%', + 'regression.html: -, 0.12, , 25.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'tablemutation.html: -, 0.01, -, 45.00%', + 'improvement.html: -, -0.05, , 50.00%', ]); // It should have the "descending" SVG. @@ -619,11 +619,11 @@ 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%', + 'improvement.html: -, -0.05, , 50.00%', + 'tablemutation.html: -, 0.01, -, 45.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'regression.html: -, 0.12, , 25.00%', + 'browser.html: -, -0.04, -, 15.00%', ]); expectParameterToHaveValue('sort', 'effects|asc'); }); @@ -632,11 +632,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( 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%', + 'tablemutation.html: -, 0.01, -, 45.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'browser.html: -, -0.04, -, 15.00%', + 'improvement.html: -, -0.05, , 50.00%', + 'regression.html: -, 0.12, , 25.00%', ]); // It should have the "ascending" SVG. expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot(); @@ -646,11 +646,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( 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%', + 'regression.html: -, 0.12, , 25.00%', + 'improvement.html: -, -0.05, , 50.00%', + 'browser.html: -, -0.04, -, 15.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'tablemutation.html: -, 0.01, -, 45.00%', ]); // It should have the "descending" SVG. expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot(); @@ -659,11 +659,11 @@ 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%', + 'regression.html: -, 0.12, , 25.00%', + 'improvement.html: -, -0.05, , 50.00%', + 'browser.html: -, -0.04, -, 15.00%', + 'dhtml.html: -, 0.02, , 60.00%', + 'tablemutation.html: -, 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..c6ca89d23 100644 --- a/src/__tests__/CompareResults/SubtestsRevisionRow.test.tsx +++ b/src/__tests__/CompareResults/SubtestsRevisionRow.test.tsx @@ -5,7 +5,6 @@ import userEvent from '@testing-library/user-event'; 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'; @@ -235,63 +234,4 @@ describe('SubtestsRevisionRow Component', () => { expect(status1).toHaveTextContent('Improvement'); expect(status1).toHaveClass('status-hint-improvement'); }); - - describe('median diff column normality gating', () => { - const normalRuns = [5.1, 5.2, 4.9, 5.0, 5.05]; - const tooFewRuns = [5.0]; - const mockGridTemplateColumns = '1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr'; - - function makeResult( - baseRuns: number[], - newRuns: number[], - ): MannWhitneyResultsItem { - const { subtestsMannWhitneyResult } = getTestData(); - return { - ...subtestsMannWhitneyResult[0], - base_runs: baseRuns, - new_runs: newRuns, - }; - } - - it('shows dash when neither distribution is normal', async () => { - renderWithRoute( - , - ); - const roles = await screen.findAllByRole('cell'); - expect(roles[4]).toHaveTextContent('-'); - }); - - it('shows value with warning icon when only one distribution is normal', async () => { - renderWithRoute( - , - ); - const roles = await screen.findAllByRole('cell'); - expect(roles[4]).not.toHaveTextContent('-'); - expect(roles[4].querySelector('svg[role="img"]')).toBeTruthy(); - }); - - it('shows value without warning icon when both distributions are normal', async () => { - renderWithRoute( - , - ); - const roles = await screen.findAllByRole('cell'); - expect(roles[4]).not.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..8d866e9f2 100644 --- a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap @@ -346,7 +346,7 @@ exports[`Results View The table should match snapshot and other elements should
@@ -413,16 +413,16 @@ exports[`Results View The table should match snapshot and other elements should
@@ -742,7 +742,7 @@ exports[`Results View The table should match snapshot and other elements should class="revision-block fw0pvlu" >
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
@@ -1386,16 +1386,16 @@ exports[`Results Table Should match snapshot 1`] = `
@@ -1715,7 +1715,7 @@ exports[`Results Table Should match snapshot 1`] = ` class="revision-block fw0pvlu" >
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
@@ -4269,16 +4253,16 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion
@@ -4598,7 +4582,7 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion class="revision-block fw0pvlu" >
- - 1.849 % - + -
- - 1.078 % - + -
- - -2.401 % - + -
- @@ -5835,32 +5807,32 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion [ "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 %", + " - macOS 10.15, -, Improvement, 0.1, -, 25.00 %", + " - Linux 18.04, -, Regression, -, -, 45.00 %", + " - Windows 10, -, , -, , 50.00 %", " - Windows 10, -, , -, , 100.00 %", - " - Windows 10, -2.401 %, , -, , 50.00 %", " rev: tictactoe", - " - Linux 18.04, 1.849 %, Regression, 0.8, -, 44.00 %", - " - macOS 10.15, 1.078 %, Improvement, 0.9, -, 24.00 %", + " - macOS 10.15, -, Improvement, 0.9, -, 24.00 %", + " - Linux 18.04, -, Regression, 0.8, -, 44.00 %", + " - Windows 10, -, , 0.8, , 49.00 %", " - Windows 10, -, , 0.8, , 99.00 %", - " - Windows 10, -2.401 %, , 0.8, , 49.00 %", "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 %", + " - macOS 10.15, -, Improvement, 1.3, -, 24.00 %", + " - Linux 18.04, -, Regression, 1.2, -, 44.00 %", + " - Windows 10, -, , 1.2, , 49.00 %", " - Windows 10, -, , 1.2, , 99.00 %", - " - Windows 10, -2.401 %, , 1.2, , 49.00 %", " rev: tictactoe", - " - Linux 18.04, 1.849 %, Regression, 2, -, 43.00 %", - " - macOS 10.15, 1.078 %, Improvement, 2.1, -, 23.00 %", + " - macOS 10.15, -, Improvement, 2.1, -, 23.00 %", + " - Linux 18.04, -, Regression, 2, -, 43.00 %", + " - Windows 10, -, , 2, , 48.00 %", " - Windows 10, -, , 2, , 98.00 %", - " - Windows 10, -2.401 %, , 2, , 48.00 %", ] `; exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion can sort params from the URL on mann-whitney-u test_version 9`] = `
- - 1.078 % - + -
- - 1.078 % - + -
@@ -1568,16 +1568,16 @@ exports[`Results View The table should match snapshot and other elements should
@@ -1897,7 +1897,7 @@ exports[`Results View The table should match snapshot and other elements should class="revision-block fw0pvlu" >
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
@@ -900,16 +900,16 @@ exports[`SubtestsResultsView Component Tests should render the subtests results
@@ -1112,7 +1112,7 @@ exports[`SubtestsResultsView Component Tests should render the subtests results />
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
@@ -2811,16 +2791,16 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi
@@ -3023,7 +3003,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi />
- - 0.963 % - + -
- - 1.135 % - + -
- - 0.963 % - + -
- - 1.135 % - + -
- - 0.98 % - + -
@@ -4413,16 +4373,16 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi
@@ -4625,7 +4585,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi />
- - 0.963 % - + -
- - 1.135 % - + -
- - 0.963 % - + -
- - 1.135 % - + -
- - 0.98 % - + -
@@ -6015,16 +5955,16 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when
@@ -6227,7 +6167,7 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when />
- - 0.963 % - + -
- - 1.135 % - + -
- - 0.963 % - + -
- - 1.135 % - + -
- - 0.98 % - + -
@@ -7617,16 +7537,16 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests
@@ -7829,7 +7749,7 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests />
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
- - 0 % - + -
{ - const base = r.base_standard_stats?.median ?? 0; - const newVal = r.new_standard_stats?.median ?? 0; - const rawPct = base !== 0 ? ((newVal - base) / base) * 100 : 0; - return r.lower_is_better ? -rawPct : rawPct; + // Normalize sign so positive = "improved" regardless of metric + // direction; rows without a computed shift sort as 0. + const normalized = (r: MannWhitneyResultsItem) => { + const pct = r.modeDeltaPct ?? 0; + return r.lower_is_better ? -pct : pct; }; - - return normalizedDiffPct(resultB) - normalizedDiffPct(resultA); + return normalized(resultB) - normalized(resultA); }, - tooltip: tooltipMedianDiff, + tooltip: tooltipModeDelta, }, { name: 'Status', @@ -295,34 +316,12 @@ export const mannWhitneyStrategy = { ({newApp}) )}
-
+
{(() => { - 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' && ( - - )} - - ); + const pct = (result as MannWhitneyResultsItem).modeDeltaPct; + return pct === null || pct === undefined + ? '-' + : `${pct.toFixed(2)} %`; })()}
@@ -480,40 +479,16 @@ export const mannWhitneyStrategy = { direction_of_change, mann_whitney_test, cles, - base_standard_stats, - new_standard_stats, + modeDeltaPct, } = result as MannWhitneyResultsItem; 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' && ( - - )} - - )} +
+ {modeDeltaPct === null || modeDeltaPct === undefined + ? '-' + : `${modeDeltaPct.toFixed(2)} %`}
{ + // Precompute the Mode Δ (largest matched-pair peak shift %) per row so + // the column can sort without re-running KDE + mode matching per + // sortFunction call. Top-level (non-subtest) table → isSubtest=false. + if (testVersion === MANN_WHITNEY_U) { + for (const oneRevsResults of results) { + precomputeLargestPeakShift( + oneRevsResults as unknown as MannWhitneyResultsItem[], + false, + ); + } + } + return results; }); // TODO what happens if there's no result? diff --git a/src/components/CompareResults/overTimeLoader.ts b/src/components/CompareResults/overTimeLoader.ts index 206d04d04..d6bd30c67 100644 --- a/src/components/CompareResults/overTimeLoader.ts +++ b/src/components/CompareResults/overTimeLoader.ts @@ -5,6 +5,7 @@ import { compareOverTimeView, MANN_WHITNEY_U, } from '../../common/constants'; +import { precomputeLargestPeakShift } from '../../common/testVersions/mannWhitney'; import { fetchCompareOverTimeResults, memoizedFetchRevisionForRepository, @@ -12,6 +13,7 @@ import { import { Changeset, CombinedResultsItemType, + MannWhitneyResultsItem, Repository, } from '../../types/state'; import { Framework, TestVersion, TimeRange } from '../../types/types'; @@ -228,6 +230,16 @@ export async function loader({ request }: { request: Request }) { replicates, testVersion, silvermanKDEEnabled, + }).then((results) => { + if (testVersion === MANN_WHITNEY_U) { + for (const oneRevsResults of results) { + precomputeLargestPeakShift( + oneRevsResults as unknown as MannWhitneyResultsItem[], + false, + ); + } + } + return results; }); const newRevsInfoPromises = newRevs.map((newRev, i) => diff --git a/src/components/CompareResults/subtestsLoader.ts b/src/components/CompareResults/subtestsLoader.ts index 2e381b7ea..a39384cc0 100644 --- a/src/components/CompareResults/subtestsLoader.ts +++ b/src/components/CompareResults/subtestsLoader.ts @@ -1,6 +1,7 @@ import { repoMap, frameworks, MANN_WHITNEY_U } from '../../common/constants'; +import { precomputeLargestPeakShift } from '../../common/testVersions/mannWhitney'; import { fetchSubtestsCompareResults } from '../../logic/treeherder'; -import { Repository } from '../../types/state'; +import { MannWhitneyResultsItem, Repository } from '../../types/state'; import { Framework, TestVersion } from '../../types/types'; // This function checks and sanitizes the input values, then returns values that @@ -186,6 +187,16 @@ export function loader({ request }: { request: Request }) { replicates, testVersion, silvermanKDEEnabled, + }).then((subtestResults) => { + // Subtests use ISJ bandwidth (narrower, data-driven) for Mode Δ since + // they typically have more samples than top-level aggregated rows. + if (testVersion === MANN_WHITNEY_U) { + precomputeLargestPeakShift( + subtestResults as unknown as MannWhitneyResultsItem[], + true, + ); + } + return subtestResults; }); return { diff --git a/src/components/CompareResults/subtestsOverTimeLoader.tsx b/src/components/CompareResults/subtestsOverTimeLoader.tsx index 906926b21..4da8373a7 100644 --- a/src/components/CompareResults/subtestsOverTimeLoader.tsx +++ b/src/components/CompareResults/subtestsOverTimeLoader.tsx @@ -4,8 +4,9 @@ import { timeRanges, MANN_WHITNEY_U, } from '../../common/constants'; +import { precomputeLargestPeakShift } from '../../common/testVersions/mannWhitney'; import { fetchSubtestsCompareOverTimeResults } from '../../logic/treeherder'; -import { Repository } from '../../types/state'; +import { MannWhitneyResultsItem, Repository } from '../../types/state'; import { Framework, TestVersion, TimeRange } from '../../types/types'; // This function checks and sanitizes the input values, then returns values that @@ -212,6 +213,14 @@ export function loader({ request }: { request: Request }) { replicates, testVersion, silvermanKDEEnabled, + }).then((subtestResults) => { + if (testVersion === MANN_WHITNEY_U) { + precomputeLargestPeakShift( + subtestResults as unknown as MannWhitneyResultsItem[], + true, + ); + } + return subtestResults; }); return { diff --git a/src/types/state.ts b/src/types/state.ts index 2091e09ef..13a3ff395 100644 --- a/src/types/state.ts +++ b/src/types/state.ts @@ -242,6 +242,12 @@ export type MannWhitneyResultsItem = { is_meaningful: boolean | null; more_runs_are_needed: boolean | null; warning_c_delta?: string | null; + // Largest matched-pair peak shift (signed, as % of base peak location) + // from KDE mode detection on base_runs/new_runs. Precomputed by the + // Mann-Whitney loader so the Mode Δ column can sort without re-running + // KDE + mode matching per row per render. `null` when the pipeline + // can't yield a value — see computeLargestPeakShiftPct. + modeDeltaPct?: number | null; /* Each test has a signature and each signature may or may not have a parent_signature. If a signature has a parent_signature then we are looking at a subtest. For regular tests this field will be null. diff --git a/src/utils/kdeAnalysis.ts b/src/utils/kdeAnalysis.ts index 2a3ff0795..0950d1954 100644 --- a/src/utils/kdeAnalysis.ts +++ b/src/utils/kdeAnalysis.ts @@ -9,6 +9,7 @@ import { fftkde, fitModesFromKde, improvedSheatherJones, + matchModes, silvermansRule, } from './kde.js'; @@ -137,3 +138,62 @@ export function computeModeInfo( letters: assignLetters(peakLocs), }; } + +/** + * Compute the largest matched-pair peak shift between base and new + * distributions, expressed as a percentage of the base peak location. + * + * Pipeline: same as `KdeModesPanel` — shared bandwidth (max of per-side + * `bandwidthFor`), `safeKde` both sides, `computeModeInfo` to get peaks + + * area fractions, `matchModes` to align base/new peaks. Then for every + * matched pair, computes `(newLoc - baseLoc) / baseLoc * 100` and returns + * the one with the largest absolute value (signed — positive means the + * new peak shifted higher). + * + * Returns `null` when: + * - either side has < 2 samples + * - either KDE fails (e.g. degenerate inputs) + * - mode detection finds no peaks on either side + * - no matched pairs (e.g. only unmatched modes — disappeared/appeared paths) + * - the only matched base peaks are at exactly zero (can't divide) + * + * @param valleyThreshold Passed to `fitModesFromKde`. Defaults to 0.5 to + * match `RevisionRowExpandable`'s slider default; the precompute path + * has no slider to read from. + */ +export function computeLargestPeakShiftPct( + baseValues: number[], + newValues: number[], + isSubtest: boolean, + valleyThreshold: number = 0.5, +): number | null { + if (baseValues.length < 2 || newValues.length < 2) return null; + const baseBw = bandwidthFor(baseValues, isSubtest) ?? 0; + const newBw = bandwidthFor(newValues, isSubtest) ?? 0; + const rawSharedBw = Math.max(baseBw, newBw); + const sharedBw = rawSharedBw > 0 ? rawSharedBw : undefined; + const bKde = safeKde(baseValues, sharedBw); + const nKde = safeKde(newValues, sharedBw); + if (!bKde || !nKde) return null; + const bModes = computeModeInfo(bKde.x, bKde.y, valleyThreshold); + const nModes = computeModeInfo(nKde.x, nKde.y, valleyThreshold); + if (!bModes.peakLocs.length || !nModes.peakLocs.length) return null; + const { pairs } = matchModes( + bModes.peakLocs, + bModes.fracs, + nModes.peakLocs, + nModes.fracs, + ); + if (!pairs.length) return null; + let bestPct: number | null = null; + for (const [bi, ni] of pairs) { + const baseLoc = bModes.peakLocs[bi]; + const newLoc = nModes.peakLocs[ni]; + if (baseLoc === 0) continue; + const pct = ((newLoc - baseLoc) / baseLoc) * 100; + if (bestPct === null || Math.abs(pct) > Math.abs(bestPct)) { + bestPct = pct; + } + } + return bestPct; +} From d052f2968db7dd8c99e15317476cead1e4846dee Mon Sep 17 00:00:00 2001 From: Carla Severe Date: Wed, 24 Jun 2026 15:27:34 -0700 Subject: [PATCH 2/9] TableHeader: show info icon next to columns with explanatory tooltips Mode change: dash to NM instead - No modes --- .../CompareResults/ResultsTable.test.tsx | 298 +++++------ .../SubtestsResultsView.test.tsx | 100 ++-- .../OverTimeResultsView.test.tsx.snap | 75 ++- .../__snapshots__/ResultsTable.test.tsx.snap | 310 +++++++++-- .../__snapshots__/ResultsView.test.tsx.snap | 75 ++- .../SubtestsResultsView.test.tsx.snap | 483 +++++++++++++++--- src/common/constants.ts | 2 +- src/common/testVersions/mannWhitney.tsx | 19 +- src/components/CompareResults/TableHeader.tsx | 21 + src/types/types.ts | 3 + 10 files changed, 1043 insertions(+), 343 deletions(-) diff --git a/src/__tests__/CompareResults/ResultsTable.test.tsx b/src/__tests__/CompareResults/ResultsTable.test.tsx index 57e9f4930..e0808db90 100644 --- a/src/__tests__/CompareResults/ResultsTable.test.tsx +++ b/src/__tests__/CompareResults/ResultsTable.test.tsx @@ -722,9 +722,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', ' rev: devilrabbit', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', ]); expect(screen.getByRole('rowgroup')).toMatchSnapshot(); }); @@ -748,12 +748,12 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await screen.findByText('a11yr'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, -, Improvement, 0.1, -, 25.00 %', - ' - inexistant, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - Android, NM, Improvement, 0.1, -, 25.00 %', + ' - inexistant, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); @@ -762,9 +762,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Windows/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - Android, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'linux', 'android', 'ios'], @@ -775,12 +775,12 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Windows/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, -, Improvement, 0.1, -, 25.00 %', - ' - inexistant, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - Android, NM, Improvement, 0.1, -, 25.00 %', + ' - inexistant, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); @@ -788,8 +788,8 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Linux/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, -, Improvement, 0.1, -, 25.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - Android, NM, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'android', 'ios'], @@ -798,9 +798,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Linux/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - Android, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'android', 'ios', 'linux'], @@ -809,22 +809,22 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', 'Select all values'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, -, Improvement, 0.1, -, 25.00 %', - ' - inexistant, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - Android, NM, Improvement, 0.1, -, 25.00 %', + ' - inexistant, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); await clickMenuItem(user, 'Platform', /macOS/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - Android, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['windows', 'linux', 'android', 'ios'], @@ -833,9 +833,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Android/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['windows', 'linux', 'ios'], @@ -844,7 +844,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Select only.*Android/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, -, Improvement, 0.1, -, 25.00 %', + ' - Android, NM, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['android'], @@ -883,10 +883,10 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await screen.findByText('a11yr'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); @@ -894,8 +894,8 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /No changes/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['improvement', 'regression'], @@ -904,7 +904,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Improvement/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['regression'], @@ -914,9 +914,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Regression/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['none', 'improvement'], @@ -925,17 +925,17 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Regression/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); await clickMenuItem(user, 'Status', /Select only.*Regression/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['regression'], @@ -944,7 +944,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Select only.*Improvement/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['improvement'], @@ -961,7 +961,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', ]); const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); expect(await summarizeTableFiltersFromCheckboxes(user)).toEqual({ @@ -997,26 +997,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', - ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', - ' - Windows 10, -, , 1.2, , 49.00 %', + ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', + ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', + ' - Windows 10, NM, , 1.2, , 99.00 %', + ' - Windows 10, NM, , 1.2, , 49.00 %', ' rev: tictactoe', - ' - Linux 18.04, -, Regression, 2, -, 43.00 %', - ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', - ' - Windows 10, -, , 2, , 98.00 %', - ' - Windows 10, -, , 2, , 48.00 %', + ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', + ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', + ' - Windows 10, NM, , 2, , 98.00 %', + ' - Windows 10, NM, , 2, , 48.00 %', 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ' rev: tictactoe', - ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', - ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', - ' - Windows 10, -, , 0.8, , 49.00 %', + ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', + ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', + ' - Windows 10, NM, , 0.8, , 99.00 %', + ' - Windows 10, NM, , 0.8, , 49.00 %', ]); // It should have the "descending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -1028,26 +1028,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr aria.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, -, Regression, 2, -, 43.00 %', - ' - Windows 10, -, , 2, , 48.00 %', - ' - Windows 10, -, , 2, , 98.00 %', + ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', + ' - Windows 10, NM, , 2, , 48.00 %', + ' - Windows 10, NM, , 2, , 98.00 %', ' rev: spam', - ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', - ' - Windows 10, -, , 1.2, , 49.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', + ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', + ' - Windows 10, NM, , 1.2, , 49.00 %', + ' - Windows 10, NM, , 1.2, , 99.00 %', 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', - ' - Windows 10, -, , 0.8, , 49.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', + ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', + ' - Windows 10, NM, , 0.8, , 49.00 %', + ' - Windows 10, NM, , 0.8, , 99.00 %', ' rev: spam', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - Windows 10, -, , -, , 50.00 %', - ' - Windows 10, -, , -, , 100.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - Windows 10, NM, , -, , 50.00 %', + ' - Windows 10, NM, , -, , 100.00 %', ]); // It should have the "ascending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -1062,26 +1062,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr aria.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, -, Regression, 2, -, 43.00 %', - ' - Windows 10, -, , 2, , 98.00 %', - ' - Windows 10, -, , 2, , 48.00 %', + ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', + ' - Windows 10, NM, , 2, , 98.00 %', + ' - Windows 10, NM, , 2, , 48.00 %', ' rev: spam', - ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', - ' - Windows 10, -, , 1.2, , 49.00 %', + ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', + ' - Windows 10, NM, , 1.2, , 99.00 %', + ' - Windows 10, NM, , 1.2, , 49.00 %', 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', - ' - Windows 10, -, , 0.8, , 49.00 %', + ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', + ' - Windows 10, NM, , 0.8, , 99.00 %', + ' - Windows 10, NM, , 0.8, , 49.00 %', ' rev: spam', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ]); // It should have the "descending" SVG. expect(significanceButton).toMatchSnapshot(); @@ -1093,26 +1093,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -, , -, , 50.00 %', - ' - Windows 10, -, , -, , 100.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', + ' - Windows 10, NM, , -, , 50.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', ' rev: tictactoe', - ' - Windows 10, -, , 0.8, , 49.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', - ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', + ' - Windows 10, NM, , 0.8, , 49.00 %', + ' - Windows 10, NM, , 0.8, , 99.00 %', + ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -, , 1.2, , 49.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', - ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', + ' - Windows 10, NM, , 1.2, , 49.00 %', + ' - Windows 10, NM, , 1.2, , 99.00 %', + ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', ' rev: tictactoe', - ' - Windows 10, -, , 2, , 48.00 %', - ' - Windows 10, -, , 2, , 98.00 %', - ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, -, Regression, 2, -, 43.00 %', + ' - Windows 10, NM, , 2, , 48.00 %', + ' - Windows 10, NM, , 2, , 98.00 %', + ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', ]); // It should have the "descending" SVG. expect(significanceButton).toMatchSnapshot(); @@ -1127,26 +1127,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -, , -, , 100.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - Windows 10, -, , -, , 50.00 %', + ' - Windows 10, NM, , -, , 100.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - Windows 10, NM, , -, , 50.00 %', ' rev: tictactoe', - ' - Windows 10, -, , 0.8, , 99.00 %', - ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', - ' - Windows 10, -, , 0.8, , 49.00 %', + ' - Windows 10, NM, , 0.8, , 99.00 %', + ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', + ' - Windows 10, NM, , 0.8, , 49.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -, , 1.2, , 99.00 %', - ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', - ' - Windows 10, -, , 1.2, , 49.00 %', + ' - Windows 10, NM, , 1.2, , 99.00 %', + ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', + ' - Windows 10, NM, , 1.2, , 49.00 %', ' rev: tictactoe', - ' - Windows 10, -, , 2, , 98.00 %', - ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, -, Regression, 2, -, 43.00 %', - ' - Windows 10, -, , 2, , 48.00 %', + ' - Windows 10, NM, , 2, , 98.00 %', + ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', + ' - Windows 10, NM, , 2, , 48.00 %', ]); expect(effectSizeButton).toMatchSnapshot(); @@ -1158,26 +1158,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -, , -, , 50.00 %', - ' - Linux 18.04, -, Regression, -, -, 45.00 %', - ' - macOS 10.15, -, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, -, , -, , 100.00 %', + ' - Windows 10, NM, , -, , 50.00 %', + ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, NM, , -, , 100.00 %', ' rev: tictactoe', - ' - Windows 10, -, , 0.8, , 49.00 %', - ' - Linux 18.04, -, Regression, 0.8, -, 44.00 %', - ' - macOS 10.15, -, Improvement, 0.9, -, 24.00 %', - ' - Windows 10, -, , 0.8, , 99.00 %', + ' - Windows 10, NM, , 0.8, , 49.00 %', + ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', + ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', + ' - Windows 10, NM, , 0.8, , 99.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, -, , 1.2, , 49.00 %', - ' - Linux 18.04, -, Regression, 1.2, -, 44.00 %', - ' - macOS 10.15, -, Improvement, 1.3, -, 24.00 %', - ' - Windows 10, -, , 1.2, , 99.00 %', + ' - Windows 10, NM, , 1.2, , 49.00 %', + ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', + ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', + ' - Windows 10, NM, , 1.2, , 99.00 %', ' rev: tictactoe', - ' - Windows 10, -, , 2, , 48.00 %', - ' - Linux 18.04, -, Regression, 2, -, 43.00 %', - ' - macOS 10.15, -, Improvement, 2.1, -, 23.00 %', - ' - Windows 10, -, , 2, , 98.00 %', + ' - Windows 10, NM, , 2, , 48.00 %', + ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', + ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', + ' - Windows 10, NM, , 2, , 98.00 %', ]); expect(effectSizeButton).toMatchSnapshot(); // It should be persisted in the URL diff --git a/src/__tests__/CompareResults/SubtestsResultsView.test.tsx b/src/__tests__/CompareResults/SubtestsResultsView.test.tsx index aaf94410d..06ab1010f 100644 --- a/src/__tests__/CompareResults/SubtestsResultsView.test.tsx +++ b/src/__tests__/CompareResults/SubtestsResultsView.test.tsx @@ -527,11 +527,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( await setupForSorting(); // Initial view (alphabetical ordered, even if "sort by subtests" isn't specified expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'browser.html: -, -0.04, -, 15.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'improvement.html: -, -0.05, , 50.00%', - 'regression.html: -, 0.12, , 25.00%', - 'tablemutation.html: -, 0.01, -, 45.00%', + 'browser.html: NM, -0.04, -, 15.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'improvement.html: NM, -0.05, , 50.00%', + 'regression.html: NM, 0.12, , 25.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', ]); // Sort by Delta @@ -542,11 +542,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( // Sort descending await user.click(deltaButton); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'regression.html: -, 0.12, , 25.00%', - 'improvement.html: -, -0.05, , 50.00%', - 'browser.html: -, -0.04, -, 15.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'tablemutation.html: -, 0.01, -, 45.00%', + 'regression.html: NM, 0.12, , 25.00%', + 'improvement.html: NM, -0.05, , 50.00%', + 'browser.html: NM, -0.04, -, 15.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', ]); // It should have the "descending" SVG. @@ -557,11 +557,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( // Sort ascending await user.click(deltaButton); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'tablemutation.html: -, 0.01, -, 45.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'browser.html: -, -0.04, -, 15.00%', - 'improvement.html: -, -0.05, , 50.00%', - 'regression.html: -, 0.12, , 25.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'browser.html: NM, -0.04, -, 15.00%', + 'improvement.html: NM, -0.05, , 50.00%', + 'regression.html: NM, 0.12, , 25.00%', ]); // It should have the "ascending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -574,11 +574,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( }); await user.click(significanceButton); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'browser.html: -, -0.04, -, 15.00%', - 'tablemutation.html: -, 0.01, -, 45.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'regression.html: -, 0.12, , 25.00%', - 'improvement.html: -, -0.05, , 50.00%', + 'browser.html: NM, -0.04, -, 15.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'regression.html: NM, 0.12, , 25.00%', + 'improvement.html: NM, -0.05, , 50.00%', ]); // It should have the "no sort" SVG. expect(deltaButton).toMatchSnapshot(); @@ -590,11 +590,11 @@ 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.05, , 50.00%', - 'regression.html: -, 0.12, , 25.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'tablemutation.html: -, 0.01, -, 45.00%', - 'browser.html: -, -0.04, -, 15.00%', + 'improvement.html: NM, -0.05, , 50.00%', + 'regression.html: NM, 0.12, , 25.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', + 'browser.html: NM, -0.04, -, 15.00%', ]); expectParameterToHaveValue('sort', 'significance|asc'); @@ -604,11 +604,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( }); await user.click(effectButton); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'browser.html: -, -0.04, -, 15.00%', - 'regression.html: -, 0.12, , 25.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'tablemutation.html: -, 0.01, -, 45.00%', - 'improvement.html: -, -0.05, , 50.00%', + 'browser.html: NM, -0.04, -, 15.00%', + 'regression.html: NM, 0.12, , 25.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', + 'improvement.html: NM, -0.05, , 50.00%', ]); // It should have the "descending" SVG. @@ -619,11 +619,11 @@ 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.05, , 50.00%', - 'tablemutation.html: -, 0.01, -, 45.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'regression.html: -, 0.12, , 25.00%', - 'browser.html: -, -0.04, -, 15.00%', + 'improvement.html: NM, -0.05, , 50.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'regression.html: NM, 0.12, , 25.00%', + 'browser.html: NM, -0.04, -, 15.00%', ]); expectParameterToHaveValue('sort', 'effects|asc'); }); @@ -632,11 +632,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( await setupForSorting({ extraParameters: 'sort=delta|asc' }); await screen.findByText('dhtml.html'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'tablemutation.html: -, 0.01, -, 45.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'browser.html: -, -0.04, -, 15.00%', - 'improvement.html: -, -0.05, , 50.00%', - 'regression.html: -, 0.12, , 25.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'browser.html: NM, -0.04, -, 15.00%', + 'improvement.html: NM, -0.05, , 50.00%', + 'regression.html: NM, 0.12, , 25.00%', ]); // It should have the "ascending" SVG. expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot(); @@ -646,11 +646,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( await setupForSorting({ extraParameters: 'sort=delta' }); await screen.findByText('dhtml.html'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'regression.html: -, 0.12, , 25.00%', - 'improvement.html: -, -0.05, , 50.00%', - 'browser.html: -, -0.04, -, 15.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'tablemutation.html: -, 0.01, -, 45.00%', + 'regression.html: NM, 0.12, , 25.00%', + 'improvement.html: NM, -0.05, , 50.00%', + 'browser.html: NM, -0.04, -, 15.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', ]); // It should have the "descending" SVG. expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot(); @@ -659,11 +659,11 @@ 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: -, 0.12, , 25.00%', - 'improvement.html: -, -0.05, , 50.00%', - 'browser.html: -, -0.04, -, 15.00%', - 'dhtml.html: -, 0.02, , 60.00%', - 'tablemutation.html: -, 0.01, -, 45.00%', + 'regression.html: NM, 0.12, , 25.00%', + 'improvement.html: NM, -0.05, , 50.00%', + 'browser.html: NM, -0.04, -, 15.00%', + 'dhtml.html: NM, 0.02, , 60.00%', + 'tablemutation.html: NM, 0.01, -, 45.00%', ]); // It should have the "descending" SVG. expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot(); diff --git a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap index 8d866e9f2..e06bf3c70 100644 --- a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap @@ -346,7 +346,7 @@ exports[`Results View The table should match snapshot and other elements should
@@ -417,7 +417,7 @@ exports[`Results View The table should match snapshot and other elements should role="columnheader" > @@ -442,6 +442,17 @@ exports[`Results View The table should match snapshot and other elements should Mode Δ (%) +
@@ -458,6 +469,17 @@ exports[`Results View The table should match snapshot and other elements should type="button" > Status +
CD +
@@ -540,6 +573,17 @@ exports[`Results View The table should match snapshot and other elements should CLES (%) +
@@ -581,6 +625,17 @@ exports[`Results View The table should match snapshot and other elements should type="button" > Sig +
- - + NM
- - + NM
- - + NM
- - + NM
@@ -1390,7 +1390,7 @@ exports[`Results Table Should match snapshot 1`] = ` role="columnheader" > @@ -1415,6 +1415,17 @@ exports[`Results Table Should match snapshot 1`] = ` Mode Δ (%) +
@@ -1431,6 +1442,17 @@ exports[`Results Table Should match snapshot 1`] = ` type="button" > Status +
CD +
@@ -1513,6 +1546,17 @@ exports[`Results Table Should match snapshot 1`] = ` CLES (%) +
@@ -1554,6 +1598,17 @@ exports[`Results Table Should match snapshot 1`] = ` type="button" > Sig +
- - + NM
- - + NM
- - + NM
- - + NM
@@ -4257,7 +4312,7 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion role="columnheader" > @@ -4282,6 +4337,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion Mode Δ (%) +
@@ -4298,6 +4364,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion type="button" > Status +
CD +
@@ -4380,6 +4468,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion CLES (%) +
@@ -4421,6 +4520,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion type="button" > Sig +
- - + NM
- - + NM
- - + NM
- - + NM
CD + `; @@ -5561,6 +5682,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion CD + `; @@ -5586,6 +5718,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion CD + @@ -5727,6 +5870,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion CLES (%) + @@ -5772,6 +5926,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion CLES (%) + @@ -5807,26 +5972,26 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion [ "a11yr dhtml.html opt e10s fission stylo webrender", " rev: spam", - " - macOS 10.15, -, Improvement, 0.1, -, 25.00 %", - " - Linux 18.04, -, Regression, -, -, 45.00 %", - " - Windows 10, -, , -, , 50.00 %", - " - Windows 10, -, , -, , 100.00 %", + " - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %", + " - Linux 18.04, NM, Regression, -, -, 45.00 %", + " - Windows 10, NM, , -, , 50.00 %", + " - Windows 10, NM, , -, , 100.00 %", " rev: tictactoe", - " - macOS 10.15, -, Improvement, 0.9, -, 24.00 %", - " - Linux 18.04, -, Regression, 0.8, -, 44.00 %", - " - Windows 10, -, , 0.8, , 49.00 %", - " - Windows 10, -, , 0.8, , 99.00 %", + " - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %", + " - Linux 18.04, NM, Regression, 0.8, -, 44.00 %", + " - Windows 10, NM, , 0.8, , 49.00 %", + " - Windows 10, NM, , 0.8, , 99.00 %", "a11yr aria.html opt e10s fission stylo webrender", " rev: spam", - " - macOS 10.15, -, Improvement, 1.3, -, 24.00 %", - " - Linux 18.04, -, Regression, 1.2, -, 44.00 %", - " - Windows 10, -, , 1.2, , 49.00 %", - " - Windows 10, -, , 1.2, , 99.00 %", + " - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %", + " - Linux 18.04, NM, Regression, 1.2, -, 44.00 %", + " - Windows 10, NM, , 1.2, , 49.00 %", + " - Windows 10, NM, , 1.2, , 99.00 %", " rev: tictactoe", - " - macOS 10.15, -, Improvement, 2.1, -, 23.00 %", - " - Linux 18.04, -, Regression, 2, -, 43.00 %", - " - Windows 10, -, , 2, , 48.00 %", - " - Windows 10, -, , 2, , 98.00 %", + " - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %", + " - Linux 18.04, NM, Regression, 2, -, 43.00 %", + " - Windows 10, NM, , 2, , 48.00 %", + " - Windows 10, NM, , 2, , 98.00 %", ] `; @@ -5852,6 +6017,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion Mode Δ (%) + @@ -5879,26 +6055,26 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion [ "a11yr dhtml.html opt e10s fission stylo webrender", " rev: spam", - " - macOS 10.15, -, Improvement, 0.1, -, 25.00 %", - " - Linux 18.04, -, Regression, -, -, 45.00 %", - " - Windows 10, -, , -, , 50.00 %", - " - Windows 10, -, , -, , 100.00 %", + " - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %", + " - Linux 18.04, NM, Regression, -, -, 45.00 %", + " - Windows 10, NM, , -, , 50.00 %", + " - Windows 10, NM, , -, , 100.00 %", " rev: tictactoe", - " - macOS 10.15, -, Improvement, 0.9, -, 24.00 %", - " - Linux 18.04, -, Regression, 0.8, -, 44.00 %", - " - Windows 10, -, , 0.8, , 49.00 %", - " - Windows 10, -, , 0.8, , 99.00 %", + " - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %", + " - Linux 18.04, NM, Regression, 0.8, -, 44.00 %", + " - Windows 10, NM, , 0.8, , 49.00 %", + " - Windows 10, NM, , 0.8, , 99.00 %", "a11yr aria.html opt e10s fission stylo webrender", " rev: spam", - " - macOS 10.15, -, Improvement, 1.3, -, 24.00 %", - " - Linux 18.04, -, Regression, 1.2, -, 44.00 %", - " - Windows 10, -, , 1.2, , 49.00 %", - " - Windows 10, -, , 1.2, , 99.00 %", + " - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %", + " - Linux 18.04, NM, Regression, 1.2, -, 44.00 %", + " - Windows 10, NM, , 1.2, , 49.00 %", + " - Windows 10, NM, , 1.2, , 99.00 %", " rev: tictactoe", - " - macOS 10.15, -, Improvement, 2.1, -, 23.00 %", - " - Linux 18.04, -, Regression, 2, -, 43.00 %", - " - Windows 10, -, , 2, , 48.00 %", - " - Windows 10, -, , 2, , 98.00 %", + " - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %", + " - Linux 18.04, NM, Regression, 2, -, 43.00 %", + " - Windows 10, NM, , 2, , 48.00 %", + " - Windows 10, NM, , 2, , 98.00 %", ] `; @@ -5924,6 +6100,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion Mode Δ (%) + @@ -5966,6 +6153,17 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion type="button" > Sig +
- - + NM
- - + NM
@@ -1572,7 +1572,7 @@ exports[`Results View The table should match snapshot and other elements should role="columnheader" > @@ -1597,6 +1597,17 @@ exports[`Results View The table should match snapshot and other elements should Mode Δ (%) +
@@ -1613,6 +1624,17 @@ exports[`Results View The table should match snapshot and other elements should type="button" > Status +
CD +
@@ -1695,6 +1728,17 @@ exports[`Results View The table should match snapshot and other elements should CLES (%) +
@@ -1736,6 +1780,17 @@ exports[`Results View The table should match snapshot and other elements should type="button" > Sig +
- - + NM
- - + NM
- - + NM
- - + NM
CD + `; @@ -47,6 +58,17 @@ exports[`SubtestsResultsView Component Tests for mann-whitney-u testVersion tabl CD + @@ -92,6 +114,17 @@ exports[`SubtestsResultsView Component Tests for mann-whitney-u testVersion tabl CD + @@ -145,6 +178,17 @@ exports[`SubtestsResultsView Component Tests for mann-whitney-u testVersion tabl CD + @@ -242,6 +286,17 @@ exports[`SubtestsResultsView Component Tests for mann-whitney-u testVersion tabl CLES (%) + @@ -287,6 +342,17 @@ exports[`SubtestsResultsView Component Tests for mann-whitney-u testVersion tabl CD + `; @@ -312,6 +378,17 @@ exports[`SubtestsResultsView Component Tests for mann-whitney-u testVersion tabl CD + `; @@ -337,6 +414,17 @@ exports[`SubtestsResultsView Component Tests for mann-whitney-u testVersion tabl CD + `; @@ -840,7 +928,7 @@ exports[`SubtestsResultsView Component Tests should render the subtests results role="table" >
@@ -904,7 +992,7 @@ exports[`SubtestsResultsView Component Tests should render the subtests results role="columnheader" > @@ -929,6 +1017,17 @@ exports[`SubtestsResultsView Component Tests should render the subtests results Mode Δ (%) +
@@ -945,6 +1044,17 @@ exports[`SubtestsResultsView Component Tests should render the subtests results type="button" > Status +
CD +
@@ -1027,6 +1148,17 @@ exports[`SubtestsResultsView Component Tests should render the subtests results CLES (%) +
@@ -1068,6 +1200,17 @@ exports[`SubtestsResultsView Component Tests should render the subtests results type="button" > Sig +
- - + NM
- - + NM
- - + NM
- - + NM
- - + NM
@@ -2795,7 +2938,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi role="columnheader" > @@ -2820,6 +2963,17 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi Mode Δ (%) +
@@ -2836,6 +2990,17 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi type="button" > Status +
CD +
@@ -2918,6 +3094,17 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi CLES (%) +
@@ -2959,6 +3146,17 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi type="button" > Sig +
- - + NM
- - + NM
- - + NM
- - + NM
- - + NM
@@ -4377,7 +4575,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi role="columnheader" > @@ -4402,6 +4600,17 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi Mode Δ (%) +
@@ -4418,6 +4627,17 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi type="button" > Status +
CD +
@@ -4500,6 +4731,17 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi CLES (%) +
@@ -4541,6 +4783,17 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi type="button" > Sig +
- - + NM
- - + NM
- - + NM
- - + NM
- - + NM
@@ -5959,7 +6212,7 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when role="columnheader" > @@ -5984,6 +6237,17 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when Mode Δ (%) +
@@ -6000,6 +6264,17 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when type="button" > Status +
CD +
@@ -6082,6 +6368,17 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when CLES (%) +
@@ -6123,6 +6420,17 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when type="button" > Sig +
- - + NM
- - + NM
- - + NM
- - + NM
- - + NM
@@ -7541,7 +7849,7 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests role="columnheader" > @@ -7566,6 +7874,17 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests Mode Δ (%) +
@@ -7582,6 +7901,17 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests type="button" > Status +
CD +
@@ -7664,6 +8005,17 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests CLES (%) +
@@ -7705,6 +8057,17 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests type="button" > Sig +
- - + NM
- - + NM
- - + NM
- - + NM
- - + NM
{ const pct = (result as MannWhitneyResultsItem).modeDeltaPct; return pct === null || pct === undefined - ? '-' + ? 'NM' : `${pct.toFixed(2)} %`; })()}
@@ -487,7 +492,7 @@ export const mannWhitneyStrategy = { <>
{modeDeltaPct === null || modeDeltaPct === undefined - ? '-' + ? 'NM' : `${modeDeltaPct.toFixed(2)} %`}
diff --git a/src/components/CompareResults/TableHeader.tsx b/src/components/CompareResults/TableHeader.tsx index 6e6c55490..6a81ba233 100644 --- a/src/components/CompareResults/TableHeader.tsx +++ b/src/components/CompareResults/TableHeader.tsx @@ -1,5 +1,6 @@ import { ReactNode } from 'react'; +import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import StraightIcon from '@mui/icons-material/Straight'; import SwapVert from '@mui/icons-material/SwapVert'; @@ -68,6 +69,17 @@ function SortDirectionIcon({ } } +// Render a small "info" icon. Used in column headers when a hover-tooltip +// is attached, so the tooltip is discoverable instead of hidden until hover. +function InfoIconHint() { + return ( + + ); +} + type FilterableColumnHeaderProps = { name: string; columnId: string; @@ -78,6 +90,7 @@ type FilterableColumnHeaderProps = { onToggleFilter: (checkedValues: Set) => unknown; onClearFilter: () => unknown; tooltip?: ReactNode; + showInfoIcon?: boolean; }; function FilterableColumnHeader({ @@ -87,6 +100,7 @@ function FilterableColumnHeader({ checkedValues, onToggleFilter, onClearFilter, + showInfoIcon, tooltip, }: FilterableColumnHeaderProps) { const popupState = usePopupState({ variant: 'popover', popupId: columnId }); @@ -127,6 +141,7 @@ function FilterableColumnHeader({ sx={{ paddingInline: 1.5, fontSize: '16px' }} > {name} + {showInfoIcon && } void; + showInfoIcon?: boolean; }; function SortableColumnHeader({ @@ -218,6 +234,7 @@ function SortableColumnHeader({ displayLabel, sortDirection, onToggle, + showInfoIcon, }: SortableColumnHeaderProps) { const buttonAriaLabel = sortDirection ? `${name} (Currently sorted by this column. Click to change)` @@ -263,6 +280,7 @@ function SortableColumnHeader({ sx={inlineIconStyle} /> {displayLabel ? name : null} + {displayLabel && showInfoIcon ? : null} ); } @@ -365,6 +383,7 @@ function TableHeader({ onToggleFilter(header.key, checkedValues) } tooltip={header.tooltip} + showInfoIcon={header.tooltipIcon} /> ); @@ -377,6 +396,7 @@ function TableHeader({ onToggle={(newSortDirection) => onToggleSort(header.key, newSortDirection) } + showInfoIcon={header.tooltipIcon} /> ); } else if ('filter' in header) { @@ -391,6 +411,7 @@ function TableHeader({ onToggleFilter(header.key, checkedValues) } tooltip={header.tooltip} + showInfoIcon={header.tooltipIcon} /> ); } diff --git a/src/types/types.ts b/src/types/types.ts index 962134a0e..a43556aba 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -17,6 +17,9 @@ export interface BasicColumn { // Used in the grid CSS property to configure the width of the column. gridWidth: string; tooltip?: React.ReactNode; + // When true, render a small info icon next to the column title so users + // know a hover-tooltip is available. Opt-in per column. + tooltipIcon?: boolean; } // This interface is used for a column that can be filtered. From 1f8491d3dda2f107c6020a1184c5d953de47b10d Mon Sep 17 00:00:00 2001 From: Carla Severe Date: Wed, 24 Jun 2026 15:55:24 -0700 Subject: [PATCH 3/9] mannWhitney: unify modality analysis as single source of truth --- .../__snapshots__/ResultsView.test.tsx.snap | 20 +++-- src/common/testVersions/mannWhitney.tsx | 21 ++++-- .../MannWhitneyCompareMetrics.tsx | 8 +- src/components/CompareResults/loader.ts | 6 +- .../CompareResults/overTimeLoader.ts | 4 +- .../CompareResults/subtestsLoader.ts | 4 +- .../CompareResults/subtestsOverTimeLoader.tsx | 4 +- src/types/state.ts | 13 ++-- src/utils/kdeAnalysis.ts | 73 +++++++++++++------ 9 files changed, 99 insertions(+), 54 deletions(-) diff --git a/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap index 8a3779e3f..398e1446e 100644 --- a/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap @@ -355,7 +355,7 @@ exports[`Results View Should display Base, New and Common graphs with replicates style="display: flex;" >
Estimated Modes - + @@ -900,7 +904,7 @@ exports[`Results View Should display Base, New and Common graphs with tooltips 1 style="display: flex;" >
- + + 0 + + 0 + No modes or data for Base and New, possible oversmoothing, KDE evaluation failed
Estimated Modes - + diff --git a/src/common/testVersions/mannWhitney.tsx b/src/common/testVersions/mannWhitney.tsx index a66e1b1be..a2fe44295 100644 --- a/src/common/testVersions/mannWhitney.tsx +++ b/src/common/testVersions/mannWhitney.tsx @@ -16,7 +16,7 @@ import { TableConfig } from '../../types/types'; import { bootstrapMedianDiffCI } from '../../utils/bootstrap-ci'; import { adaptUnit, formatNumber } from '../../utils/format'; import { capitalize } from '../../utils/helpers'; -import { computeLargestPeakShiftPct } from '../../utils/kdeAnalysis'; +import { computeModalityAnalysis } from '../../utils/kdeAnalysis'; import { getBrowserDisplay, getPlatformShortName } from '../../utils/platform'; import { determineSign, @@ -98,26 +98,31 @@ export function isDistributionNormal(result: MannWhitneyResultsItem): boolean { } /** - * Precompute the largest matched-pair peak shift % for every Mann-Whitney - * row and attach it to `result.modeDeltaPct`. Called from the data loaders - * so the Mode Δ column can sort without re-running KDE + mode matching - * per row per render (the whole pipeline — KDE, mode detection, modality - * matcher — is non-trivial and we don't want it in the sort hot path). + * Precompute the client-side modality analysis for every Mann-Whitney row + * and attach the relevant fields (`modeDeltaPct`, `baseModeCount`, + * `newModeCount`) to the result. Called from the data loaders so every UI + * that talks about modes — the Mode Δ column sort/cell, the Distribution + * Interpretation row in MannWhitneyCompareMetrics, KdeModesPanel — reads + * from the same numbers instead of mixing client-side ISJ output with the + * backend's wider Silverman counts (which used to disagree). * * `isSubtest` controls the bandwidth strategy used by KDE: subtest tables * use ISJ, top-level tables use the wider SJ approximation. See * `bandwidthFor` in kdeAnalysis.ts. */ -export function precomputeLargestPeakShift( +export function precomputeModalityAnalysis( results: MannWhitneyResultsItem[], isSubtest: boolean, ): void { for (const result of results) { - result.modeDeltaPct = computeLargestPeakShiftPct( + const analysis = computeModalityAnalysis( result.base_runs ?? [], result.new_runs ?? [], isSubtest, ); + result.modeDeltaPct = analysis.largestPeakShiftPct; + result.baseModeCount = analysis.baseModes.peakLocs.length; + result.newModeCount = analysis.newModes.peakLocs.length; } } diff --git a/src/components/CompareResults/MannWhitneyCompareMetrics.tsx b/src/components/CompareResults/MannWhitneyCompareMetrics.tsx index 1cead497e..b30d91a8e 100644 --- a/src/components/CompareResults/MannWhitneyCompareMetrics.tsx +++ b/src/components/CompareResults/MannWhitneyCompareMetrics.tsx @@ -52,11 +52,15 @@ export const MannWhitneyCompareMetrics = ({ result.shapiro_wilk_test_base?.interpretation ?? 'N/A'; const newShapiroWilkInterpretation = result.shapiro_wilk_test_new?.interpretation ?? 'N/A'; - const baseMode = result?.silverman_kde?.base_mode_count ?? null; - const newMode = result?.silverman_kde?.new_mode_count ?? null; + // Mode counts come from the precomputed client-side modality pipeline + // (see precomputeModalityAnalysis), not from the backend's wider-bandwidth + // Silverman KDE — otherwise this row could contradict the Mode Δ column. + const baseMode = result?.baseModeCount ?? null; + const newMode = result?.newModeCount ?? null; return ( { if (testVersion === MANN_WHITNEY_U) { for (const oneRevsResults of results) { - precomputeLargestPeakShift( + precomputeModalityAnalysis( oneRevsResults as unknown as MannWhitneyResultsItem[], false, ); diff --git a/src/components/CompareResults/subtestsLoader.ts b/src/components/CompareResults/subtestsLoader.ts index a39384cc0..d94c7e785 100644 --- a/src/components/CompareResults/subtestsLoader.ts +++ b/src/components/CompareResults/subtestsLoader.ts @@ -1,5 +1,5 @@ import { repoMap, frameworks, MANN_WHITNEY_U } from '../../common/constants'; -import { precomputeLargestPeakShift } from '../../common/testVersions/mannWhitney'; +import { precomputeModalityAnalysis } from '../../common/testVersions/mannWhitney'; import { fetchSubtestsCompareResults } from '../../logic/treeherder'; import { MannWhitneyResultsItem, Repository } from '../../types/state'; import { Framework, TestVersion } from '../../types/types'; @@ -191,7 +191,7 @@ export function loader({ request }: { request: Request }) { // Subtests use ISJ bandwidth (narrower, data-driven) for Mode Δ since // they typically have more samples than top-level aggregated rows. if (testVersion === MANN_WHITNEY_U) { - precomputeLargestPeakShift( + precomputeModalityAnalysis( subtestResults as unknown as MannWhitneyResultsItem[], true, ); diff --git a/src/components/CompareResults/subtestsOverTimeLoader.tsx b/src/components/CompareResults/subtestsOverTimeLoader.tsx index 4da8373a7..e7d5bb577 100644 --- a/src/components/CompareResults/subtestsOverTimeLoader.tsx +++ b/src/components/CompareResults/subtestsOverTimeLoader.tsx @@ -4,7 +4,7 @@ import { timeRanges, MANN_WHITNEY_U, } from '../../common/constants'; -import { precomputeLargestPeakShift } from '../../common/testVersions/mannWhitney'; +import { precomputeModalityAnalysis } from '../../common/testVersions/mannWhitney'; import { fetchSubtestsCompareOverTimeResults } from '../../logic/treeherder'; import { MannWhitneyResultsItem, Repository } from '../../types/state'; import { Framework, TestVersion, TimeRange } from '../../types/types'; @@ -215,7 +215,7 @@ export function loader({ request }: { request: Request }) { silvermanKDEEnabled, }).then((subtestResults) => { if (testVersion === MANN_WHITNEY_U) { - precomputeLargestPeakShift( + precomputeModalityAnalysis( subtestResults as unknown as MannWhitneyResultsItem[], true, ); diff --git a/src/types/state.ts b/src/types/state.ts index 13a3ff395..da54f1226 100644 --- a/src/types/state.ts +++ b/src/types/state.ts @@ -242,12 +242,15 @@ export type MannWhitneyResultsItem = { is_meaningful: boolean | null; more_runs_are_needed: boolean | null; warning_c_delta?: string | null; - // Largest matched-pair peak shift (signed, as % of base peak location) - // from KDE mode detection on base_runs/new_runs. Precomputed by the - // Mann-Whitney loader so the Mode Δ column can sort without re-running - // KDE + mode matching per row per render. `null` when the pipeline - // can't yield a value — see computeLargestPeakShiftPct. + // Client-side modality analysis precomputed by the Mann-Whitney loader. + // Single source of truth for any UI that needs to talk about modes (the + // Mode Δ column, the Distribution Interpretation row, KdeModesPanel) so + // those views can't drift onto different mode-detection logic. `null` + // means we never ran the pipeline (legacy/stale data). See + // computeModalityAnalysis in kdeAnalysis.ts. modeDeltaPct?: number | null; + baseModeCount?: number | null; + newModeCount?: number | null; /* Each test has a signature and each signature may or may not have a parent_signature. If a signature has a parent_signature then we are looking at a subtest. For regular tests this field will be null. diff --git a/src/utils/kdeAnalysis.ts b/src/utils/kdeAnalysis.ts index 0950d1954..7ba2d4e2e 100644 --- a/src/utils/kdeAnalysis.ts +++ b/src/utils/kdeAnalysis.ts @@ -140,60 +140,85 @@ export function computeModeInfo( } /** - * Compute the largest matched-pair peak shift between base and new - * distributions, expressed as a percentage of the base peak location. + * Combined output of the client-side modality pipeline. Used as the single + * source of truth for any UI that needs to talk about modes (counts in the + * Distribution Interpretation row, the Mode Δ column, KdeModesPanel, etc.) + * so the page never contradicts itself. + */ +export type ModalityAnalysis = { + baseModes: ModeInfo; + newModes: ModeInfo; + // Largest matched-pair peak shift as % of base peak location; null when + // KDE/mode/matching produced nothing usable. See computeModalityAnalysis. + largestPeakShiftPct: number | null; +}; + +export const EMPTY_MODALITY_ANALYSIS: ModalityAnalysis = { + baseModes: EMPTY_MODE_INFO, + newModes: EMPTY_MODE_INFO, + largestPeakShiftPct: null, +}; + +/** + * Run the full client-side modality pipeline for a base/new pair. * - * Pipeline: same as `KdeModesPanel` — shared bandwidth (max of per-side + * Pipeline (same as `KdeModesPanel`): shared bandwidth (max of per-side * `bandwidthFor`), `safeKde` both sides, `computeModeInfo` to get peaks + - * area fractions, `matchModes` to align base/new peaks. Then for every - * matched pair, computes `(newLoc - baseLoc) / baseLoc * 100` and returns - * the one with the largest absolute value (signed — positive means the - * new peak shifted higher). + * area fractions, `matchModes` to align base/new peaks. Then derives the + * largest matched-pair peak shift, as a signed percentage of the base peak + * location (positive = new peak shifted higher). * - * Returns `null` when: + * `largestPeakShiftPct` is `null` when: * - either side has < 2 samples * - either KDE fails (e.g. degenerate inputs) * - mode detection finds no peaks on either side - * - no matched pairs (e.g. only unmatched modes — disappeared/appeared paths) + * - no matched pairs (e.g. only unmatched modes — paths appeared/disappeared) * - the only matched base peaks are at exactly zero (can't divide) * + * Mode counts (`baseModes.peakLocs.length` / `newModes.peakLocs.length`) + * are 0 in the same conditions that drive `largestPeakShiftPct` to null + * (except the divide-by-zero case, which still yields counts). + * * @param valleyThreshold Passed to `fitModesFromKde`. Defaults to 0.5 to * match `RevisionRowExpandable`'s slider default; the precompute path * has no slider to read from. */ -export function computeLargestPeakShiftPct( +export function computeModalityAnalysis( baseValues: number[], newValues: number[], isSubtest: boolean, valleyThreshold: number = 0.5, -): number | null { - if (baseValues.length < 2 || newValues.length < 2) return null; +): ModalityAnalysis { + if (baseValues.length < 2 || newValues.length < 2) { + return EMPTY_MODALITY_ANALYSIS; + } const baseBw = bandwidthFor(baseValues, isSubtest) ?? 0; const newBw = bandwidthFor(newValues, isSubtest) ?? 0; const rawSharedBw = Math.max(baseBw, newBw); const sharedBw = rawSharedBw > 0 ? rawSharedBw : undefined; const bKde = safeKde(baseValues, sharedBw); const nKde = safeKde(newValues, sharedBw); - if (!bKde || !nKde) return null; - const bModes = computeModeInfo(bKde.x, bKde.y, valleyThreshold); - const nModes = computeModeInfo(nKde.x, nKde.y, valleyThreshold); - if (!bModes.peakLocs.length || !nModes.peakLocs.length) return null; + if (!bKde || !nKde) return EMPTY_MODALITY_ANALYSIS; + const baseModes = computeModeInfo(bKde.x, bKde.y, valleyThreshold); + const newModes = computeModeInfo(nKde.x, nKde.y, valleyThreshold); + if (!baseModes.peakLocs.length || !newModes.peakLocs.length) { + return { baseModes, newModes, largestPeakShiftPct: null }; + } const { pairs } = matchModes( - bModes.peakLocs, - bModes.fracs, - nModes.peakLocs, - nModes.fracs, + baseModes.peakLocs, + baseModes.fracs, + newModes.peakLocs, + newModes.fracs, ); - if (!pairs.length) return null; let bestPct: number | null = null; for (const [bi, ni] of pairs) { - const baseLoc = bModes.peakLocs[bi]; - const newLoc = nModes.peakLocs[ni]; + const baseLoc = baseModes.peakLocs[bi]; + const newLoc = newModes.peakLocs[ni]; if (baseLoc === 0) continue; const pct = ((newLoc - baseLoc) / baseLoc) * 100; if (bestPct === null || Math.abs(pct) > Math.abs(bestPct)) { bestPct = pct; } } - return bestPct; + return { baseModes, newModes, largestPeakShiftPct: bestPct }; } From 4efb2e24d4c0a95153d40320fc3468ab7e8eb1be Mon Sep 17 00:00:00 2001 From: Carla Severe Date: Wed, 24 Jun 2026 16:15:08 -0700 Subject: [PATCH 4/9] mannWhitney: precompute modality on replicates when available --- src/common/testVersions/mannWhitney.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/common/testVersions/mannWhitney.tsx b/src/common/testVersions/mannWhitney.tsx index a2fe44295..7fe5164e0 100644 --- a/src/common/testVersions/mannWhitney.tsx +++ b/src/common/testVersions/mannWhitney.tsx @@ -115,11 +115,20 @@ export function precomputeModalityAnalysis( isSubtest: boolean, ): void { for (const result of results) { - const analysis = computeModalityAnalysis( - result.base_runs ?? [], - result.new_runs ?? [], - isSubtest, - ); + // Prefer replicates when present — same selection KdeModesPanel and the + // chart use in RevisionRowExpandable. Otherwise the precomputed counts + // (driving the Mode Δ column and the Distribution Interpretation row) + // would run KDE on fewer samples than the blurb, and the two views + // would disagree on rows that have rich replicates data. + const baseValues = + result.base_runs_replicates && result.base_runs_replicates.length + ? result.base_runs_replicates + : (result.base_runs ?? []); + const newValues = + result.new_runs_replicates && result.new_runs_replicates.length + ? result.new_runs_replicates + : (result.new_runs ?? []); + const analysis = computeModalityAnalysis(baseValues, newValues, isSubtest); result.modeDeltaPct = analysis.largestPeakShiftPct; result.baseModeCount = analysis.baseModes.peakLocs.length; result.newModeCount = analysis.newModes.peakLocs.length; From fabd084dd98f0c7c50fc02dde9f2ca248fe9823c Mon Sep 17 00:00:00 2001 From: Carla Severe Date: Wed, 24 Jun 2026 16:49:52 -0700 Subject: [PATCH 5/9] =?UTF-8?q?mannWhitney:=20fix=20Mode=20=CE=94=20sort?= =?UTF-8?q?=20direction=20=E2=80=94=20DESC=20now=20shows=20biggest=20impro?= =?UTF-8?q?vement=20first?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/testVersions/mannWhitney.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/common/testVersions/mannWhitney.tsx b/src/common/testVersions/mannWhitney.tsx index 7fe5164e0..4c26802b6 100644 --- a/src/common/testVersions/mannWhitney.tsx +++ b/src/common/testVersions/mannWhitney.tsx @@ -178,13 +178,16 @@ export const mannWhitneyStrategy = { resultA: MannWhitneyResultsItem, resultB: MannWhitneyResultsItem, ) { - // Normalize sign so positive = "improved" regardless of metric - // direction; rows without a computed shift sort as 0. + // ASC semantics — useTableSort swaps args for DESC. So in DESC + // mode this produces "biggest improvement first" (largest + // normalized first); in ASC mode the inverse. The normalization + // makes a positive value always mean "improved" regardless of + // metric direction; rows without a computed shift sort as 0. const normalized = (r: MannWhitneyResultsItem) => { const pct = r.modeDeltaPct ?? 0; return r.lower_is_better ? -pct : pct; }; - return normalized(resultB) - normalized(resultA); + return normalized(resultA) - normalized(resultB); }, tooltip: tooltipModeDelta, tooltipIcon: true, From 2aec513f90836666c1d9a56390fd40e097e1f7d9 Mon Sep 17 00:00:00 2001 From: Carla Severe Date: Wed, 24 Jun 2026 19:53:40 -0700 Subject: [PATCH 6/9] =?UTF-8?q?mannWhitney:=20lazy-precompute=20Mode=20?= =?UTF-8?q?=CE=94=20analysis=20to=20restore=20load=20speed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CompareResults/ResultsTable.test.tsx | 298 +++++++++--------- .../SubtestsResultsView.test.tsx | 100 +++--- .../OverTimeResultsView.test.tsx.snap | 10 +- .../__snapshots__/ResultsTable.test.tsx.snap | 24 +- .../__snapshots__/ResultsView.test.tsx.snap | 10 +- .../SubtestsResultsView.test.tsx.snap | 60 ++-- src/common/constants.ts | 2 +- src/common/testVersions/mannWhitney.tsx | 107 ++++--- .../MannWhitneyCompareMetrics.tsx | 11 +- src/components/CompareResults/loader.ts | 23 -- .../CompareResults/overTimeLoader.ts | 12 - .../CompareResults/subtestsLoader.ts | 13 +- .../CompareResults/subtestsOverTimeLoader.tsx | 11 +- 13 files changed, 330 insertions(+), 351 deletions(-) diff --git a/src/__tests__/CompareResults/ResultsTable.test.tsx b/src/__tests__/CompareResults/ResultsTable.test.tsx index e0808db90..5fb5c3adb 100644 --- a/src/__tests__/CompareResults/ResultsTable.test.tsx +++ b/src/__tests__/CompareResults/ResultsTable.test.tsx @@ -722,9 +722,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', ' rev: devilrabbit', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', ]); expect(screen.getByRole('rowgroup')).toMatchSnapshot(); }); @@ -748,12 +748,12 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await screen.findByText('a11yr'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, NM, Improvement, 0.1, -, 25.00 %', - ' - inexistant, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - Android, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - inexistant, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); @@ -762,9 +762,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Windows/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Android, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'linux', 'android', 'ios'], @@ -775,12 +775,12 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Windows/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, NM, Improvement, 0.1, -, 25.00 %', - ' - inexistant, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - Android, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - inexistant, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); @@ -788,8 +788,8 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Linux/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, NM, Improvement, 0.1, -, 25.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Android, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'android', 'ios'], @@ -798,9 +798,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Linux/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Android, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['osx', 'android', 'ios', 'linux'], @@ -809,22 +809,22 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', 'Select all values'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, NM, Improvement, 0.1, -, 25.00 %', - ' - inexistant, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - Android, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - inexistant, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); await clickMenuItem(user, 'Platform', /macOS/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - Android, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['windows', 'linux', 'android', 'ios'], @@ -833,9 +833,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Android/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['windows', 'linux', 'ios'], @@ -844,7 +844,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Platform', /Select only.*Android/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Android, NM, Improvement, 0.1, -, 25.00 %', + ' - Android, ~1.08 %, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ platform: ['android'], @@ -883,10 +883,10 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await screen.findByText('a11yr'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); @@ -894,8 +894,8 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /No changes/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['improvement', 'regression'], @@ -904,7 +904,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Improvement/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['regression'], @@ -914,9 +914,9 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Regression/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['none', 'improvement'], @@ -925,17 +925,17 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Regression/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({}); await clickMenuItem(user, 'Status', /Select only.*Regression/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['regression'], @@ -944,7 +944,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio await clickMenuItem(user, 'Status', /Select only.*Improvement/); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', ]); expect(summarizeTableFiltersFromUrl()).toEqual({ status: ['improvement'], @@ -961,7 +961,7 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html spam opt e10s fission stylo webrender', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', ]); const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); expect(await summarizeTableFiltersFromCheckboxes(user)).toEqual({ @@ -997,26 +997,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', - ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', - ' - Windows 10, NM, , 1.2, , 99.00 %', - ' - Windows 10, NM, , 1.2, , 49.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 1.2, -, 44.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 1.3, -, 24.00 %', + ' - Windows 10, ~0.00 %, , 1.2, , 99.00 %', + ' - Windows 10, ~-2.40 %, , 1.2, , 49.00 %', ' rev: tictactoe', - ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', - ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', - ' - Windows 10, NM, , 2, , 98.00 %', - ' - Windows 10, NM, , 2, , 48.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 2, -, 43.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 2.1, -, 23.00 %', + ' - Windows 10, ~0.00 %, , 2, , 98.00 %', + ' - Windows 10, ~-2.40 %, , 2, , 48.00 %', 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ' rev: tictactoe', - ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', - ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', - ' - Windows 10, NM, , 0.8, , 99.00 %', - ' - Windows 10, NM, , 0.8, , 49.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 0.8, -, 44.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.9, -, 24.00 %', + ' - Windows 10, ~0.00 %, , 0.8, , 99.00 %', + ' - Windows 10, ~-2.40 %, , 0.8, , 49.00 %', ]); // It should have the "descending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -1028,26 +1028,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr aria.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', - ' - Windows 10, NM, , 2, , 48.00 %', - ' - Windows 10, NM, , 2, , 98.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 2, -, 43.00 %', + ' - Windows 10, ~-2.40 %, , 2, , 48.00 %', + ' - Windows 10, ~0.00 %, , 2, , 98.00 %', ' rev: spam', - ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', - ' - Windows 10, NM, , 1.2, , 49.00 %', - ' - Windows 10, NM, , 1.2, , 99.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 1.2, -, 44.00 %', + ' - Windows 10, ~-2.40 %, , 1.2, , 49.00 %', + ' - Windows 10, ~0.00 %, , 1.2, , 99.00 %', 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', - ' - Windows 10, NM, , 0.8, , 49.00 %', - ' - Windows 10, NM, , 0.8, , 99.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 0.8, -, 44.00 %', + ' - Windows 10, ~-2.40 %, , 0.8, , 49.00 %', + ' - Windows 10, ~0.00 %, , 0.8, , 99.00 %', ' rev: spam', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - Windows 10, NM, , -, , 50.00 %', - ' - Windows 10, NM, , -, , 100.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', ]); // It should have the "ascending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -1062,26 +1062,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr aria.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', - ' - Windows 10, NM, , 2, , 98.00 %', - ' - Windows 10, NM, , 2, , 48.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 2, -, 43.00 %', + ' - Windows 10, ~0.00 %, , 2, , 98.00 %', + ' - Windows 10, ~-2.40 %, , 2, , 48.00 %', ' rev: spam', - ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', - ' - Windows 10, NM, , 1.2, , 99.00 %', - ' - Windows 10, NM, , 1.2, , 49.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 1.2, -, 44.00 %', + ' - Windows 10, ~0.00 %, , 1.2, , 99.00 %', + ' - Windows 10, ~-2.40 %, , 1.2, , 49.00 %', 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: tictactoe', - ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', - ' - Windows 10, NM, , 0.8, , 99.00 %', - ' - Windows 10, NM, , 0.8, , 49.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 0.8, -, 44.00 %', + ' - Windows 10, ~0.00 %, , 0.8, , 99.00 %', + ' - Windows 10, ~-2.40 %, , 0.8, , 49.00 %', ' rev: spam', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ]); // It should have the "descending" SVG. expect(significanceButton).toMatchSnapshot(); @@ -1093,26 +1093,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, NM, , -, , 50.00 %', - ' - Windows 10, NM, , -, , 100.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', ' rev: tictactoe', - ' - Windows 10, NM, , 0.8, , 49.00 %', - ' - Windows 10, NM, , 0.8, , 99.00 %', - ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', + ' - Windows 10, ~-2.40 %, , 0.8, , 49.00 %', + ' - Windows 10, ~0.00 %, , 0.8, , 99.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 0.8, -, 44.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, NM, , 1.2, , 49.00 %', - ' - Windows 10, NM, , 1.2, , 99.00 %', - ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', + ' - Windows 10, ~-2.40 %, , 1.2, , 49.00 %', + ' - Windows 10, ~0.00 %, , 1.2, , 99.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 1.2, -, 44.00 %', ' rev: tictactoe', - ' - Windows 10, NM, , 2, , 48.00 %', - ' - Windows 10, NM, , 2, , 98.00 %', - ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', + ' - Windows 10, ~-2.40 %, , 2, , 48.00 %', + ' - Windows 10, ~0.00 %, , 2, , 98.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 2, -, 43.00 %', ]); // It should have the "descending" SVG. expect(significanceButton).toMatchSnapshot(); @@ -1127,26 +1127,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, NM, , -, , 100.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - Windows 10, NM, , -, , 50.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', ' rev: tictactoe', - ' - Windows 10, NM, , 0.8, , 99.00 %', - ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', - ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', - ' - Windows 10, NM, , 0.8, , 49.00 %', + ' - Windows 10, ~0.00 %, , 0.8, , 99.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.9, -, 24.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 0.8, -, 44.00 %', + ' - Windows 10, ~-2.40 %, , 0.8, , 49.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, NM, , 1.2, , 99.00 %', - ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', - ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', - ' - Windows 10, NM, , 1.2, , 49.00 %', + ' - Windows 10, ~0.00 %, , 1.2, , 99.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 1.3, -, 24.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 1.2, -, 44.00 %', + ' - Windows 10, ~-2.40 %, , 1.2, , 49.00 %', ' rev: tictactoe', - ' - Windows 10, NM, , 2, , 98.00 %', - ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', - ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', - ' - Windows 10, NM, , 2, , 48.00 %', + ' - Windows 10, ~0.00 %, , 2, , 98.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 2.1, -, 23.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 2, -, 43.00 %', + ' - Windows 10, ~-2.40 %, , 2, , 48.00 %', ]); expect(effectSizeButton).toMatchSnapshot(); @@ -1158,26 +1158,26 @@ describe('Results Table for MannWhitneyResultsItem for mann-whitney-u testVersio expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ 'a11yr dhtml.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, NM, , -, , 50.00 %', - ' - Linux 18.04, NM, Regression, -, -, 45.00 %', - ' - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %', - ' - Windows 10, NM, , -, , 100.00 %', + ' - Windows 10, ~-2.40 %, , -, , 50.00 %', + ' - Linux 18.04, ~1.85 %, Regression, -, -, 45.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.1, -, 25.00 %', + ' - Windows 10, ~0.00 %, , -, , 100.00 %', ' rev: tictactoe', - ' - Windows 10, NM, , 0.8, , 49.00 %', - ' - Linux 18.04, NM, Regression, 0.8, -, 44.00 %', - ' - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %', - ' - Windows 10, NM, , 0.8, , 99.00 %', + ' - Windows 10, ~-2.40 %, , 0.8, , 49.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 0.8, -, 44.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 0.9, -, 24.00 %', + ' - Windows 10, ~0.00 %, , 0.8, , 99.00 %', 'a11yr aria.html opt e10s fission stylo webrender', ' rev: spam', - ' - Windows 10, NM, , 1.2, , 49.00 %', - ' - Linux 18.04, NM, Regression, 1.2, -, 44.00 %', - ' - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %', - ' - Windows 10, NM, , 1.2, , 99.00 %', + ' - Windows 10, ~-2.40 %, , 1.2, , 49.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 1.2, -, 44.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 1.3, -, 24.00 %', + ' - Windows 10, ~0.00 %, , 1.2, , 99.00 %', ' rev: tictactoe', - ' - Windows 10, NM, , 2, , 48.00 %', - ' - Linux 18.04, NM, Regression, 2, -, 43.00 %', - ' - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %', - ' - Windows 10, NM, , 2, , 98.00 %', + ' - Windows 10, ~-2.40 %, , 2, , 48.00 %', + ' - Linux 18.04, ~1.85 %, Regression, 2, -, 43.00 %', + ' - macOS 10.15, ~1.08 %, Improvement, 2.1, -, 23.00 %', + ' - Windows 10, ~0.00 %, , 2, , 98.00 %', ]); expect(effectSizeButton).toMatchSnapshot(); // It should be persisted in the URL diff --git a/src/__tests__/CompareResults/SubtestsResultsView.test.tsx b/src/__tests__/CompareResults/SubtestsResultsView.test.tsx index 06ab1010f..7e7c516eb 100644 --- a/src/__tests__/CompareResults/SubtestsResultsView.test.tsx +++ b/src/__tests__/CompareResults/SubtestsResultsView.test.tsx @@ -527,11 +527,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( await setupForSorting(); // Initial view (alphabetical ordered, even if "sort by subtests" isn't specified expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'browser.html: NM, -0.04, -, 15.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'improvement.html: NM, -0.05, , 50.00%', - 'regression.html: NM, 0.12, , 25.00%', - 'tablemutation.html: NM, 0.01, -, 45.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', + 'dhtml.html: ~1.14 %, 0.02, , 60.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', + 'tablemutation.html: ~0.98 %, 0.01, -, 45.00%', ]); // Sort by Delta @@ -542,11 +542,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( // Sort descending await user.click(deltaButton); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'regression.html: NM, 0.12, , 25.00%', - 'improvement.html: NM, -0.05, , 50.00%', - 'browser.html: NM, -0.04, -, 15.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'tablemutation.html: NM, 0.01, -, 45.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', + 'dhtml.html: ~1.14 %, 0.02, , 60.00%', + 'tablemutation.html: ~0.98 %, 0.01, -, 45.00%', ]); // It should have the "descending" SVG. @@ -557,11 +557,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( // Sort ascending await user.click(deltaButton); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'tablemutation.html: NM, 0.01, -, 45.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'browser.html: NM, -0.04, -, 15.00%', - 'improvement.html: NM, -0.05, , 50.00%', - 'regression.html: NM, 0.12, , 25.00%', + 'tablemutation.html: ~0.98 %, 0.01, -, 45.00%', + 'dhtml.html: ~1.14 %, 0.02, , 60.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', ]); // It should have the "ascending" SVG. expect(deltaButton).toMatchSnapshot(); @@ -574,11 +574,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( }); await user.click(significanceButton); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'browser.html: NM, -0.04, -, 15.00%', - 'tablemutation.html: NM, 0.01, -, 45.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'regression.html: NM, 0.12, , 25.00%', - 'improvement.html: NM, -0.05, , 50.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', + 'tablemutation.html: ~0.98 %, 0.01, -, 45.00%', + 'dhtml.html: ~1.14 %, 0.02, , 60.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', ]); // It should have the "no sort" SVG. expect(deltaButton).toMatchSnapshot(); @@ -590,11 +590,11 @@ 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: NM, -0.05, , 50.00%', - 'regression.html: NM, 0.12, , 25.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'tablemutation.html: NM, 0.01, -, 45.00%', - 'browser.html: NM, -0.04, -, 15.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', + 'dhtml.html: ~1.14 %, 0.02, , 60.00%', + 'tablemutation.html: ~0.98 %, 0.01, -, 45.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', ]); expectParameterToHaveValue('sort', 'significance|asc'); @@ -604,11 +604,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( }); await user.click(effectButton); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'browser.html: NM, -0.04, -, 15.00%', - 'regression.html: NM, 0.12, , 25.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'tablemutation.html: NM, 0.01, -, 45.00%', - 'improvement.html: NM, -0.05, , 50.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', + 'dhtml.html: ~1.14 %, 0.02, , 60.00%', + 'tablemutation.html: ~0.98 %, 0.01, -, 45.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', ]); // It should have the "descending" SVG. @@ -619,11 +619,11 @@ 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: NM, -0.05, , 50.00%', - 'tablemutation.html: NM, 0.01, -, 45.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'regression.html: NM, 0.12, , 25.00%', - 'browser.html: NM, -0.04, -, 15.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', + 'tablemutation.html: ~0.98 %, 0.01, -, 45.00%', + 'dhtml.html: ~1.14 %, 0.02, , 60.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', ]); expectParameterToHaveValue('sort', 'effects|asc'); }); @@ -632,11 +632,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( await setupForSorting({ extraParameters: 'sort=delta|asc' }); await screen.findByText('dhtml.html'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'tablemutation.html: NM, 0.01, -, 45.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'browser.html: NM, -0.04, -, 15.00%', - 'improvement.html: NM, -0.05, , 50.00%', - 'regression.html: NM, 0.12, , 25.00%', + 'tablemutation.html: ~0.98 %, 0.01, -, 45.00%', + 'dhtml.html: ~1.14 %, 0.02, , 60.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', ]); // It should have the "ascending" SVG. expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot(); @@ -646,11 +646,11 @@ describe('SubtestsResultsView Component Tests for mann-whitney-u testVersion', ( await setupForSorting({ extraParameters: 'sort=delta' }); await screen.findByText('dhtml.html'); expect(summarizeVisibleRows('mann-whitney-u')).toEqual([ - 'regression.html: NM, 0.12, , 25.00%', - 'improvement.html: NM, -0.05, , 50.00%', - 'browser.html: NM, -0.04, -, 15.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'tablemutation.html: NM, 0.01, -, 45.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', + 'dhtml.html: ~1.14 %, 0.02, , 60.00%', + 'tablemutation.html: ~0.98 %, 0.01, -, 45.00%', ]); // It should have the "descending" SVG. expect(screen.getByRole('button', { name: /CD/ })).toMatchSnapshot(); @@ -659,11 +659,11 @@ 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: NM, 0.12, , 25.00%', - 'improvement.html: NM, -0.05, , 50.00%', - 'browser.html: NM, -0.04, -, 15.00%', - 'dhtml.html: NM, 0.02, , 60.00%', - 'tablemutation.html: NM, 0.01, -, 45.00%', + 'regression.html: ~1.04 %, 0.12, , 25.00%', + 'improvement.html: ~-1.44 %, -0.05, , 50.00%', + 'browser.html: ~-1.43 %, -0.04, -, 15.00%', + 'dhtml.html: ~1.14 %, 0.02, , 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/__snapshots__/OverTimeResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap index e06bf3c70..42939ebe6 100644 --- a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap @@ -417,7 +417,7 @@ exports[`Results View The table should match snapshot and other elements should role="columnheader" > @@ -849,7 +849,7 @@ exports[`Results View The table should match snapshot and other elements should class="mode-delta cell" role="cell" > - NM + ~1.85 %
- NM + ~1.08 %
- NM + ~-24.00 %
- NM + ~-2.40 %
@@ -1822,7 +1822,7 @@ exports[`Results Table Should match snapshot 1`] = ` class="mode-delta cell" role="cell" > - NM + ~1.85 %
- NM + ~1.08 %
- NM + ~-2.40 %
- NM + ~-24.00 %
@@ -4744,7 +4744,7 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion class="mode-delta cell" role="cell" > - NM + ~1.85 %
- NM + ~1.08 %
- NM + ~-2.40 %
- NM + ~0.00 %
- NM + ~1.08 %
- NM + ~1.08 %
@@ -2012,7 +2012,7 @@ exports[`Results View The table should match snapshot and other elements should class="mode-delta cell" role="cell" > - NM + ~1.85 %
- NM + ~1.08 %
- NM + ~-24.00 %
- NM + ~-2.40 %
@@ -1303,7 +1303,7 @@ exports[`SubtestsResultsView Component Tests should render the subtests results class="mode-delta cell" role="cell" > - NM + ~-1.43 %
- NM + ~1.14 %
- NM + ~-1.44 %
- NM + ~1.04 %
- NM + ~0.98 %
@@ -3251,7 +3251,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi class="mode-delta cell" role="cell" > - NM + ~-1.43 %
- NM + ~1.14 %
- NM + ~-1.44 %
- NM + ~1.04 %
- NM + ~0.98 %
@@ -4888,7 +4888,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi class="mode-delta cell" role="cell" > - NM + ~-1.43 %
- NM + ~1.14 %
- NM + ~-1.44 %
- NM + ~1.04 %
- NM + ~0.98 %
@@ -6525,7 +6525,7 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when class="mode-delta cell" role="cell" > - NM + ~-1.43 %
- NM + ~1.14 %
- NM + ~-1.44 %
- NM + ~1.04 %
- NM + ~0.98 %
@@ -8160,7 +8160,7 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests class="mode-delta cell" role="cell" > - NM + ~-1.43 %
- NM + ~1.14 %
- NM + ~-1.44 %
- NM + ~1.04 %
- NM + ~0.98 %
{ const pct = r.modeDeltaPct ?? 0; return r.lower_is_better ? -pct : pct; @@ -339,12 +373,7 @@ export const mannWhitneyStrategy = { )}
- {(() => { - const pct = (result as MannWhitneyResultsItem).modeDeltaPct; - return pct === null || pct === undefined - ? 'NM' - : `${pct.toFixed(2)} %`; - })()} + {formatModeDelta(result as MannWhitneyResultsItem)}
- {modeDeltaPct === null || modeDeltaPct === undefined - ? 'NM' - : `${modeDeltaPct.toFixed(2)} %`} + {formatModeDelta(mwResult)}
{ - // Precompute the Mode Δ (largest matched-pair peak shift %) per row so - // the column can sort without re-running KDE + mode matching per - // sortFunction call. Top-level (non-subtest) table → isSubtest=false. - if (testVersion === MANN_WHITNEY_U) { - for (const oneRevsResults of results) { - precomputeModalityAnalysis( - oneRevsResults as unknown as MannWhitneyResultsItem[], - false, - ); - } - } - return results; }); // TODO what happens if there's no result? diff --git a/src/components/CompareResults/overTimeLoader.ts b/src/components/CompareResults/overTimeLoader.ts index 3f123913d..206d04d04 100644 --- a/src/components/CompareResults/overTimeLoader.ts +++ b/src/components/CompareResults/overTimeLoader.ts @@ -5,7 +5,6 @@ import { compareOverTimeView, MANN_WHITNEY_U, } from '../../common/constants'; -import { precomputeModalityAnalysis } from '../../common/testVersions/mannWhitney'; import { fetchCompareOverTimeResults, memoizedFetchRevisionForRepository, @@ -13,7 +12,6 @@ import { import { Changeset, CombinedResultsItemType, - MannWhitneyResultsItem, Repository, } from '../../types/state'; import { Framework, TestVersion, TimeRange } from '../../types/types'; @@ -230,16 +228,6 @@ export async function loader({ request }: { request: Request }) { replicates, testVersion, silvermanKDEEnabled, - }).then((results) => { - if (testVersion === MANN_WHITNEY_U) { - for (const oneRevsResults of results) { - precomputeModalityAnalysis( - oneRevsResults as unknown as MannWhitneyResultsItem[], - false, - ); - } - } - return results; }); const newRevsInfoPromises = newRevs.map((newRev, i) => diff --git a/src/components/CompareResults/subtestsLoader.ts b/src/components/CompareResults/subtestsLoader.ts index d94c7e785..2e381b7ea 100644 --- a/src/components/CompareResults/subtestsLoader.ts +++ b/src/components/CompareResults/subtestsLoader.ts @@ -1,7 +1,6 @@ import { repoMap, frameworks, MANN_WHITNEY_U } from '../../common/constants'; -import { precomputeModalityAnalysis } from '../../common/testVersions/mannWhitney'; import { fetchSubtestsCompareResults } from '../../logic/treeherder'; -import { MannWhitneyResultsItem, Repository } from '../../types/state'; +import { Repository } from '../../types/state'; import { Framework, TestVersion } from '../../types/types'; // This function checks and sanitizes the input values, then returns values that @@ -187,16 +186,6 @@ export function loader({ request }: { request: Request }) { replicates, testVersion, silvermanKDEEnabled, - }).then((subtestResults) => { - // Subtests use ISJ bandwidth (narrower, data-driven) for Mode Δ since - // they typically have more samples than top-level aggregated rows. - if (testVersion === MANN_WHITNEY_U) { - precomputeModalityAnalysis( - subtestResults as unknown as MannWhitneyResultsItem[], - true, - ); - } - return subtestResults; }); return { diff --git a/src/components/CompareResults/subtestsOverTimeLoader.tsx b/src/components/CompareResults/subtestsOverTimeLoader.tsx index e7d5bb577..906926b21 100644 --- a/src/components/CompareResults/subtestsOverTimeLoader.tsx +++ b/src/components/CompareResults/subtestsOverTimeLoader.tsx @@ -4,9 +4,8 @@ import { timeRanges, MANN_WHITNEY_U, } from '../../common/constants'; -import { precomputeModalityAnalysis } from '../../common/testVersions/mannWhitney'; import { fetchSubtestsCompareOverTimeResults } from '../../logic/treeherder'; -import { MannWhitneyResultsItem, Repository } from '../../types/state'; +import { Repository } from '../../types/state'; import { Framework, TestVersion, TimeRange } from '../../types/types'; // This function checks and sanitizes the input values, then returns values that @@ -213,14 +212,6 @@ export function loader({ request }: { request: Request }) { replicates, testVersion, silvermanKDEEnabled, - }).then((subtestResults) => { - if (testVersion === MANN_WHITNEY_U) { - precomputeModalityAnalysis( - subtestResults as unknown as MannWhitneyResultsItem[], - true, - ); - } - return subtestResults; }); return { From c6abeeb4651a21271d0d34cf47d669706570f346 Mon Sep 17 00:00:00 2001 From: Carla Severe Date: Wed, 24 Jun 2026 19:56:26 -0700 Subject: [PATCH 7/9] lint fix --- src/common/testVersions/mannWhitney.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/common/testVersions/mannWhitney.tsx b/src/common/testVersions/mannWhitney.tsx index 823a23316..401b4d689 100644 --- a/src/common/testVersions/mannWhitney.tsx +++ b/src/common/testVersions/mannWhitney.tsx @@ -526,12 +526,8 @@ export const mannWhitneyStrategy = { renderColumns(result: CombinedResultsItemType) { const mwResult = result as MannWhitneyResultsItem; - const { - cliffs_delta, - direction_of_change, - mann_whitney_test, - cles, - } = mwResult; + const { cliffs_delta, direction_of_change, mann_whitney_test, cles } = + mwResult; const clesValue = cles?.cles ? `${(cles.cles * 100).toFixed(2)} %` : '-'; return ( From 6354698f7cd3884d559462f6db050affebf8c3f4 Mon Sep 17 00:00:00 2001 From: Carla Severe Date: Tue, 21 Jul 2026 18:23:52 -0700 Subject: [PATCH 8/9] replace NM with "No modes" --- .../OverTimeResultsView.test.tsx.snap | 2 +- .../__snapshots__/ResultsTable.test.tsx.snap | 68 +++++++++---------- .../__snapshots__/ResultsView.test.tsx.snap | 2 +- .../SubtestsResultsView.test.tsx.snap | 10 +-- src/common/constants.ts | 2 +- src/common/testVersions/mannWhitney.tsx | 8 +-- 6 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap index 42939ebe6..63100b1ee 100644 --- a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap @@ -417,7 +417,7 @@ exports[`Results View The table should match snapshot and other elements should role="columnheader" > diff --git a/src/__tests__/CompareResults/__snapshots__/ResultsTable.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/ResultsTable.test.tsx.snap index c575e39e8..ceac71ad7 100644 --- a/src/__tests__/CompareResults/__snapshots__/ResultsTable.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/ResultsTable.test.tsx.snap @@ -1390,7 +1390,7 @@ exports[`Results Table Should match snapshot 1`] = ` role="columnheader" > @@ -4312,7 +4312,7 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion role="columnheader" > @@ -5972,26 +5972,26 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion [ "a11yr dhtml.html opt e10s fission stylo webrender", " rev: spam", - " - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %", - " - Linux 18.04, NM, Regression, -, -, 45.00 %", - " - Windows 10, NM, , -, , 50.00 %", - " - Windows 10, NM, , -, , 100.00 %", + " - macOS 10.15, No modes, Improvement, 0.1, -, 25.00 %", + " - Linux 18.04, No modes, Regression, -, -, 45.00 %", + " - Windows 10, No modes, , -, , 50.00 %", + " - Windows 10, No modes, , -, , 100.00 %", " rev: tictactoe", - " - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %", - " - Linux 18.04, NM, Regression, 0.8, -, 44.00 %", - " - Windows 10, NM, , 0.8, , 49.00 %", - " - Windows 10, NM, , 0.8, , 99.00 %", + " - macOS 10.15, No modes, Improvement, 0.9, -, 24.00 %", + " - Linux 18.04, No modes, Regression, 0.8, -, 44.00 %", + " - Windows 10, No modes, , 0.8, , 49.00 %", + " - Windows 10, No modes, , 0.8, , 99.00 %", "a11yr aria.html opt e10s fission stylo webrender", " rev: spam", - " - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %", - " - Linux 18.04, NM, Regression, 1.2, -, 44.00 %", - " - Windows 10, NM, , 1.2, , 49.00 %", - " - Windows 10, NM, , 1.2, , 99.00 %", + " - macOS 10.15, No modes, Improvement, 1.3, -, 24.00 %", + " - Linux 18.04, No modes, Regression, 1.2, -, 44.00 %", + " - Windows 10, No modes, , 1.2, , 49.00 %", + " - Windows 10, No modes, , 1.2, , 99.00 %", " rev: tictactoe", - " - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %", - " - Linux 18.04, NM, Regression, 2, -, 43.00 %", - " - Windows 10, NM, , 2, , 48.00 %", - " - Windows 10, NM, , 2, , 98.00 %", + " - macOS 10.15, No modes, Improvement, 2.1, -, 23.00 %", + " - Linux 18.04, No modes, Regression, 2, -, 43.00 %", + " - Windows 10, No modes, , 2, , 48.00 %", + " - Windows 10, No modes, , 2, , 98.00 %", ] `; @@ -6055,26 +6055,26 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion [ "a11yr dhtml.html opt e10s fission stylo webrender", " rev: spam", - " - macOS 10.15, NM, Improvement, 0.1, -, 25.00 %", - " - Linux 18.04, NM, Regression, -, -, 45.00 %", - " - Windows 10, NM, , -, , 50.00 %", - " - Windows 10, NM, , -, , 100.00 %", + " - macOS 10.15, No modes, Improvement, 0.1, -, 25.00 %", + " - Linux 18.04, No modes, Regression, -, -, 45.00 %", + " - Windows 10, No modes, , -, , 50.00 %", + " - Windows 10, No modes, , -, , 100.00 %", " rev: tictactoe", - " - macOS 10.15, NM, Improvement, 0.9, -, 24.00 %", - " - Linux 18.04, NM, Regression, 0.8, -, 44.00 %", - " - Windows 10, NM, , 0.8, , 49.00 %", - " - Windows 10, NM, , 0.8, , 99.00 %", + " - macOS 10.15, No modes, Improvement, 0.9, -, 24.00 %", + " - Linux 18.04, No modes, Regression, 0.8, -, 44.00 %", + " - Windows 10, No modes, , 0.8, , 49.00 %", + " - Windows 10, No modes, , 0.8, , 99.00 %", "a11yr aria.html opt e10s fission stylo webrender", " rev: spam", - " - macOS 10.15, NM, Improvement, 1.3, -, 24.00 %", - " - Linux 18.04, NM, Regression, 1.2, -, 44.00 %", - " - Windows 10, NM, , 1.2, , 49.00 %", - " - Windows 10, NM, , 1.2, , 99.00 %", + " - macOS 10.15, No modes, Improvement, 1.3, -, 24.00 %", + " - Linux 18.04, No modes, Regression, 1.2, -, 44.00 %", + " - Windows 10, No modes, , 1.2, , 49.00 %", + " - Windows 10, No modes, , 1.2, , 99.00 %", " rev: tictactoe", - " - macOS 10.15, NM, Improvement, 2.1, -, 23.00 %", - " - Linux 18.04, NM, Regression, 2, -, 43.00 %", - " - Windows 10, NM, , 2, , 48.00 %", - " - Windows 10, NM, , 2, , 98.00 %", + " - macOS 10.15, No modes, Improvement, 2.1, -, 23.00 %", + " - Linux 18.04, No modes, Regression, 2, -, 43.00 %", + " - Windows 10, No modes, , 2, , 48.00 %", + " - Windows 10, No modes, , 2, , 98.00 %", ] `; diff --git a/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap index 46e656977..b93ff129d 100644 --- a/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap @@ -1580,7 +1580,7 @@ exports[`Results View The table should match snapshot and other elements should role="columnheader" > diff --git a/src/__tests__/CompareResults/__snapshots__/SubtestsResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/SubtestsResultsView.test.tsx.snap index 2ac53d54c..2f2064ba5 100644 --- a/src/__tests__/CompareResults/__snapshots__/SubtestsResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/SubtestsResultsView.test.tsx.snap @@ -992,7 +992,7 @@ exports[`SubtestsResultsView Component Tests should render the subtests results role="columnheader" > @@ -2938,7 +2938,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi role="columnheader" > @@ -4575,7 +4575,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi role="columnheader" > @@ -6212,7 +6212,7 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when role="columnheader" > @@ -7849,7 +7849,7 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests role="columnheader" > diff --git a/src/common/constants.ts b/src/common/constants.ts index 21d9e2e27..dec5f35cf 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -338,4 +338,4 @@ export const tooltipConfidence = export const tooltipDelta = 'The percentage difference between the Base and New values'; export const tooltipModeDelta = - 'Largest peak shift between the Base and New distributions, expressed as a percentage of the base peak location. Peaks are detected by KDE mode analysis and paired with the modality matcher; the matched pair with the largest absolute shift is shown. Positive values mean the new peak shifted higher. Values prefixed with "~" are the backend\'s median diff percentage shown as an approximation — click the column header to compute the real Mode Δ across all rows. "NM" (No Modes) means the value could not be computed: too few runs (fewer than 2 per side), KDE could not find any peaks on one or both sides, or no base peak could be paired with a new peak (a path appeared or disappeared entirely).'; + 'Largest peak shift between the Base and New distributions, expressed as a percentage of the base peak location. Peaks are detected by KDE mode analysis and paired with the modality matcher; the matched pair with the largest absolute shift is shown. Positive values mean the new peak shifted higher. Values prefixed with "~" are the backend\'s median diff percentage shown as an approximation — click the column header to compute the real Mode Δ across all rows. "No modes" means the value could not be computed: too few runs (fewer than 2 per side), KDE could not find any peaks on one or both sides, or no base peak could be paired with a new peak (a path appeared or disappeared entirely).'; diff --git a/src/common/testVersions/mannWhitney.tsx b/src/common/testVersions/mannWhitney.tsx index 401b4d689..077591aef 100644 --- a/src/common/testVersions/mannWhitney.tsx +++ b/src/common/testVersions/mannWhitney.tsx @@ -139,11 +139,11 @@ export function ensureModalityAnalysis( /** * Format the Mode Δ cell text: * - cached number → "X.XX %" - * - cached `null` → "NM" (modality pipeline ran, no usable pair) + * - cached `null` → "No modes" (modality pipeline ran, no usable pair) * - uncached → "~X.XX %" using the backend's `delta_percentage`, * prefixed with `~` to signal "approximate, click * the column to compute the real Mode Δ" - * - no fallback → "NM" + * - no fallback → "No modes" * * Cell renders run for EVERY row on every render. Triggering the modality * pipeline here would re-introduce the per-row load cost the lazy @@ -153,13 +153,13 @@ export function ensureModalityAnalysis( function formatModeDelta(result: MannWhitneyResultsItem): string { const cached = result.modeDeltaPct; if (typeof cached === 'number') return `${cached.toFixed(2)} %`; - if (cached === null) return 'NM'; + if (cached === null) return 'No modes'; // Not yet computed — fall back to the backend's median diff percentage. const fallback = result.delta_percentage; if (typeof fallback === 'number' && Number.isFinite(fallback)) { return `~${fallback.toFixed(2)} %`; } - return 'NM'; + return 'No modes'; } export const mannWhitneyStrategy = { From d27d39a5b0bd997be3ee0b5b5ef7f04e9f31d6e9 Mon Sep 17 00:00:00 2001 From: Carla Severe Date: Tue, 21 Jul 2026 19:48:54 -0700 Subject: [PATCH 9/9] use peak magnitude vs shift and simplify tooltip text --- .../OverTimeResultsView.test.tsx.snap | 2 +- .../__snapshots__/ResultsTable.test.tsx.snap | 4 +- .../__snapshots__/ResultsView.test.tsx.snap | 2 +- .../SubtestsResultsView.test.tsx.snap | 10 ++-- src/common/constants.ts | 2 +- src/common/testVersions/mannWhitney.tsx | 2 +- src/utils/kdeAnalysis.ts | 53 ++++++++++++------- 7 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap index 63100b1ee..b35653ea9 100644 --- a/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/OverTimeResultsView.test.tsx.snap @@ -417,7 +417,7 @@ exports[`Results View The table should match snapshot and other elements should role="columnheader" > diff --git a/src/__tests__/CompareResults/__snapshots__/ResultsTable.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/ResultsTable.test.tsx.snap index ceac71ad7..dccda5540 100644 --- a/src/__tests__/CompareResults/__snapshots__/ResultsTable.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/ResultsTable.test.tsx.snap @@ -1390,7 +1390,7 @@ exports[`Results Table Should match snapshot 1`] = ` role="columnheader" > @@ -4312,7 +4312,7 @@ exports[`Results Table for MannWhitneyResultsItem for mann-whitney-u testVersion role="columnheader" > diff --git a/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap index b93ff129d..f99849d63 100644 --- a/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap @@ -1580,7 +1580,7 @@ exports[`Results View The table should match snapshot and other elements should role="columnheader" > diff --git a/src/__tests__/CompareResults/__snapshots__/SubtestsResultsView.test.tsx.snap b/src/__tests__/CompareResults/__snapshots__/SubtestsResultsView.test.tsx.snap index 2f2064ba5..f7801cfe1 100644 --- a/src/__tests__/CompareResults/__snapshots__/SubtestsResultsView.test.tsx.snap +++ b/src/__tests__/CompareResults/__snapshots__/SubtestsResultsView.test.tsx.snap @@ -992,7 +992,7 @@ exports[`SubtestsResultsView Component Tests should render the subtests results role="columnheader" > @@ -2938,7 +2938,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi role="columnheader" > @@ -4575,7 +4575,7 @@ exports[`SubtestsViewCompareOverTime Component Tests in mann-whitney-u testVersi role="columnheader" > @@ -6212,7 +6212,7 @@ exports[`SubtestsViewCompareOverTime Component Tests renders over-time view when role="columnheader" > @@ -7849,7 +7849,7 @@ exports[`SubtestsViewCompareOverTime Component Tests should render the subtests role="columnheader" > diff --git a/src/common/constants.ts b/src/common/constants.ts index dec5f35cf..c72c00933 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -338,4 +338,4 @@ export const tooltipConfidence = export const tooltipDelta = 'The percentage difference between the Base and New values'; export const tooltipModeDelta = - 'Largest peak shift between the Base and New distributions, expressed as a percentage of the base peak location. Peaks are detected by KDE mode analysis and paired with the modality matcher; the matched pair with the largest absolute shift is shown. Positive values mean the new peak shifted higher. Values prefixed with "~" are the backend\'s median diff percentage shown as an approximation — click the column header to compute the real Mode Δ across all rows. "No modes" means the value could not be computed: too few runs (fewer than 2 per side), KDE could not find any peaks on one or both sides, or no base peak could be paired with a new peak (a path appeared or disappeared entirely).'; + 'Shows how much the main group of results moved from Base to New, as a percent. Runs tend to fall into groups, and this compares the biggest group on each side — so one odd run won\'t throw off the result. A positive number means New is higher. A "~" means it\'s a quick estimate; click the column title to get the exact number. "No modes" means there wasn\'t enough clear data to measure a shift.'; diff --git a/src/common/testVersions/mannWhitney.tsx b/src/common/testVersions/mannWhitney.tsx index 077591aef..20a74a234 100644 --- a/src/common/testVersions/mannWhitney.tsx +++ b/src/common/testVersions/mannWhitney.tsx @@ -131,7 +131,7 @@ export function ensureModalityAnalysis( ? result.new_runs_replicates : (result.new_runs ?? []); const analysis = computeModalityAnalysis(baseValues, newValues, isSubtest); - result.modeDeltaPct = analysis.largestPeakShiftPct; + result.modeDeltaPct = analysis.dominantModeShiftPct; result.baseModeCount = analysis.baseModes.peakLocs.length; result.newModeCount = analysis.newModes.peakLocs.length; } diff --git a/src/utils/kdeAnalysis.ts b/src/utils/kdeAnalysis.ts index 7ba2d4e2e..3c20507bc 100644 --- a/src/utils/kdeAnalysis.ts +++ b/src/utils/kdeAnalysis.ts @@ -148,36 +148,48 @@ export function computeModeInfo( export type ModalityAnalysis = { baseModes: ModeInfo; newModes: ModeInfo; - // Largest matched-pair peak shift as % of base peak location; null when - // KDE/mode/matching produced nothing usable. See computeModalityAnalysis. - largestPeakShiftPct: number | null; + // How far the biggest group of runs moved from Base to New, as a % of the + // base peak's position. null when there's no trustworthy group to measure + // (see computeModalityAnalysis for the exact cases). + dominantModeShiftPct: number | null; }; export const EMPTY_MODALITY_ANALYSIS: ModalityAnalysis = { baseModes: EMPTY_MODE_INFO, newModes: EMPTY_MODE_INFO, - largestPeakShiftPct: null, + dominantModeShiftPct: null, }; +// Each peak in the KDE curve covers some share of the runs (its "area +// fraction"); all peaks on one side add up to ~1, i.e. 100% of the runs. +// A peak must cover at least this share — 10% — to count as a real group of +// runs. Smaller peaks are treated as noise (a few stray runs) and ignored, so +// a tiny bump that happens to move a lot can't hijack the reported shift. +const MODE_AREA_FLOOR = 0.1; + /** * Run the full client-side modality pipeline for a base/new pair. * * Pipeline (same as `KdeModesPanel`): shared bandwidth (max of per-side * `bandwidthFor`), `safeKde` both sides, `computeModeInfo` to get peaks + * area fractions, `matchModes` to align base/new peaks. Then derives the - * largest matched-pair peak shift, as a signed percentage of the base peak - * location (positive = new peak shifted higher). + * shift of the dominant matched mode — the pair holding the largest share + * of the runs — as a signed percentage of the base peak location (positive = + * new peak shifted higher). Picking the biggest group rather than the biggest + * mover keeps a small, noisy peak from driving the reported number when the + * main peak barely moved. * - * `largestPeakShiftPct` is `null` when: + * `dominantModeShiftPct` is `null` when: * - either side has < 2 samples * - either KDE fails (e.g. degenerate inputs) * - mode detection finds no peaks on either side * - no matched pairs (e.g. only unmatched modes — paths appeared/disappeared) - * - the only matched base peaks are at exactly zero (can't divide) + * - no matched pair clears MODE_AREA_FLOOR (only noise-level modes) + * - the dominant matched base peak is at exactly zero (can't divide) * * Mode counts (`baseModes.peakLocs.length` / `newModes.peakLocs.length`) - * are 0 in the same conditions that drive `largestPeakShiftPct` to null - * (except the divide-by-zero case, which still yields counts). + * are 0 in the same conditions that drive `dominantModeShiftPct` to null + * (except the divide-by-zero / below-floor cases, which still yield counts). * * @param valleyThreshold Passed to `fitModesFromKde`. Defaults to 0.5 to * match `RevisionRowExpandable`'s slider default; the precompute path @@ -202,7 +214,7 @@ export function computeModalityAnalysis( const baseModes = computeModeInfo(bKde.x, bKde.y, valleyThreshold); const newModes = computeModeInfo(nKde.x, nKde.y, valleyThreshold); if (!baseModes.peakLocs.length || !newModes.peakLocs.length) { - return { baseModes, newModes, largestPeakShiftPct: null }; + return { baseModes, newModes, dominantModeShiftPct: null }; } const { pairs } = matchModes( baseModes.peakLocs, @@ -210,15 +222,20 @@ export function computeModalityAnalysis( newModes.peakLocs, newModes.fracs, ); - let bestPct: number | null = null; + // Report how far the biggest group of runs moved — not whichever peak moved + // the most. Each matched pair's "size" is the average share of runs under + // its two peaks; pairs smaller than MODE_AREA_FLOOR are noise and skipped. + // Of the rest we keep the largest (the dominant group) and use its shift. + let dominantModeShiftPct: number | null = null; + let bestMag = -Infinity; for (const [bi, ni] of pairs) { const baseLoc = baseModes.peakLocs[bi]; const newLoc = newModes.peakLocs[ni]; - if (baseLoc === 0) continue; - const pct = ((newLoc - baseLoc) / baseLoc) * 100; - if (bestPct === null || Math.abs(pct) > Math.abs(bestPct)) { - bestPct = pct; - } + if (baseLoc === 0) continue; // can't express the shift as a percentage + const mag = (baseModes.fracs[bi] + newModes.fracs[ni]) / 2; + if (mag < MODE_AREA_FLOOR || mag <= bestMag) continue; + bestMag = mag; + dominantModeShiftPct = ((newLoc - baseLoc) / baseLoc) * 100; } - return { baseModes, newModes, largestPeakShiftPct: bestPct }; + return { baseModes, newModes, dominantModeShiftPct }; }
- + + 0 + + 0 + No modes or data for Base and New, possible oversmoothing, KDE evaluation failed