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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 124 additions & 1 deletion src/__tests__/CompareResults/CommonGraph.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ describe('CommonGraph', () => {
newValues={[3, 4]}
unit='ms'
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

Expand Down Expand Up @@ -132,6 +134,8 @@ describe('CommonGraph', () => {
newValues={[3, 4]}
unit='ms'
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

Expand Down Expand Up @@ -164,6 +168,8 @@ describe('CommonGraph', () => {
newValues={[3, 4]}
unit='ms'
isSubtest={true}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

Expand Down Expand Up @@ -194,12 +200,18 @@ describe('CommonGraph', () => {
newValues={[]}
unit='ms'
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

const option = getLatestEChartsOption();
const allSeries = option.series as LineSeriesOption[];
const series = allSeries.filter((s) => s.type === 'line');
// Exclude the mode-overlay markLine series (named "_mode-*") — only count
// the two underlying KDE curves.
const series = allSeries.filter(
(s) => s.type === 'line' && !String(s.name ?? '').startsWith('_mode-'),
);
expect(series).toHaveLength(2);
// Base side has a resampled density curve.
expect(series[0].data as unknown[]).toHaveLength(1024);
Expand Down Expand Up @@ -232,6 +244,8 @@ describe('CommonGraph', () => {
newValues={[3, 4]}
unit='ms'
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

Expand All @@ -254,6 +268,8 @@ describe('CommonGraph', () => {
newValues={[3, 4]}
unit='ms'
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

Expand Down Expand Up @@ -296,6 +312,8 @@ describe('CommonGraph', () => {
newValues={[3, 4]}
unit='ms'
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

Expand Down Expand Up @@ -336,6 +354,8 @@ describe('CommonGraph', () => {
newValues={[3, 4]}
unit={null}
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

Expand All @@ -353,4 +373,107 @@ describe('CommonGraph', () => {
// No "(unit)" suffix after the value when unit is null.
expect(rendered).toBe('Value: 5.00<br>Base: 0.1000');
});

it('emits a mode-overlay markLine series for each detected peak', () => {
// Strictly increasing fake KDE — fitModesFromKde returns a single peak at
// the global max (last x). That yields exactly one "_mode-*" overlay per
// series, with a label tagged by series and letter A.
(fftkde as jest.Mock).mockImplementation(() => ({
x: [10, 20, 30],
y: [0.1, 0.2, 0.3],
bandwidth: 1,
}));

render(
<CommonGraph
baseValues={[1, 2]}
newValues={[3, 4]}
unit='ms'
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

const option = getLatestEChartsOption();
const series = option.series as Array<{
name?: string;
markLine?: {
data?: Array<{ xAxis?: number }>;
label?: { formatter?: string };
lineStyle?: { color?: string };
};
}>;
const overlays = series.filter((s) =>
String(s.name ?? '').startsWith('_mode-'),
);
// One overlay per series (Base + New), both peaking at the same x.
expect(overlays).toHaveLength(2);
expect(overlays[0].markLine?.data?.[0]?.xAxis).toBe(30);
expect(overlays[1].markLine?.data?.[0]?.xAxis).toBe(30);
expect(overlays[0].markLine?.label?.formatter).toMatch(/^Base A: 30/);
expect(overlays[1].markLine?.label?.formatter).toMatch(/^New A: 30/);
});

it('shows raw run values in the scatter tooltip with the unit suffix', () => {
(fftkde as jest.Mock).mockImplementation(() => ({
x: [10, 20, 30],
y: [0.1, 0.2, 0.3],
bandwidth: 1,
}));

render(
<CommonGraph
baseValues={[1, 2]}
newValues={[3, 4]}
unit='ms'
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

const formatter = getTooltipFormatter(getLatestEChartsOption());
// The formatter inspects items[0].seriesType to pick between scatter and
// KDE rendering — pass a scatter-shaped item to exercise the scatter path.
const rendered = formatter([
{
seriesType: 'scatter',
seriesName: 'Base',
value: [12.5, 0],
marker: '[m]',
},
] as unknown as Parameters<typeof formatter>[0]);
expect(rendered).toBe('[m]Base: 12.50 (ms)');
});

it("labels the scatter y-axis as 'Base' for 0 and 'New' for 1", () => {
(fftkde as jest.Mock).mockImplementation(() => ({
x: [10, 20, 30],
y: [0.1, 0.2, 0.3],
bandwidth: 1,
}));

render(
<CommonGraph
baseValues={[1, 2]}
newValues={[3, 4]}
unit='ms'
isSubtest={false}
vt={0.5}
onVtChange={jest.fn()}
/>,
);

const option = getLatestEChartsOption();
const yAxes = option.yAxis as Array<{
axisLabel?: { formatter?: (v: number) => string };
}>;
const scatterYAxisFormatter = yAxes[1]?.axisLabel?.formatter;
expect(scatterYAxisFormatter).toBeDefined();
expect(scatterYAxisFormatter!(0)).toBe('Base');
expect(scatterYAxisFormatter!(1)).toBe('New');
// Anything else returns empty so intermediate jitter values stay unlabelled.
expect(scatterYAxisFormatter!(0.5)).toBe('');
});
});
126 changes: 123 additions & 3 deletions src/__tests__/CompareResults/__snapshots__/ResultsView.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exports[`Results View Should display Base, New and Common graphs with replicates
<section
aria-label="Revision Row Details"
class="MuiBox-root css-13s8wtg"
id="_r_c3_"
id="_r_c4_"
>
<div
class="MuiStack-root css-1714cpj-MuiStack-root"
Expand All @@ -30,11 +30,71 @@ exports[`Results View Should display Base, New and Common graphs with replicates
>
Runs Density Distribution
</h3>
<div
class="MuiBox-root css-1ntc4s6"
>
<span
class="MuiTypography-root MuiTypography-body2 css-ftpr4e-MuiTypography-root"
>
Valley depth threshold
<svg
aria-hidden="true"
aria-label="A valley between two peaks must be shallower than this fraction of the shorter peak to count as a mode boundary. Higher = more splits detected."
class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall css-86dkbz-MuiSvgIcon-root"
data-mui-internal-clone-element="true"
data-testid="InfoOutlinedIcon"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8"
/>
</svg>
:
</span>
<span
class="MuiSlider-root MuiSlider-colorPrimary MuiSlider-sizeSmall css-hrrccv-MuiSlider-root"
>
<span
class="MuiSlider-rail css-r64h58-MuiSlider-rail"
/>
<span
class="MuiSlider-track css-1iqz70e-MuiSlider-track"
style="left: 0%; width: 44.9438202247191%;"
/>
<span
class="MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary css-1rsdqdo-MuiSlider-thumb"
data-index="0"
style="left: 44.9438202247191%;"
>
<input
aria-label="Valley depth threshold"
aria-orientation="horizontal"
aria-valuemax="0.99"
aria-valuemin="0.1"
aria-valuenow="0.5"
data-index="0"
max="0.99"
min="0.1"
step="0.01"
style="border: 0px; height: 100%; margin: -1px; overflow: hidden; padding: 0px; position: absolute; white-space: nowrap; width: 100%; direction: ltr;"
type="range"
value="0.5"
/>
</span>
</span>
<span
class="MuiTypography-root MuiTypography-body2 css-19x59xu-MuiTypography-root"
>
50
%
</span>
</div>
<div
class="MuiBox-root css-72fd9l"
>
<div
style="width: 100%; height: 325px;"
style="width: 100%; height: 340px;"
/>
</div>
</div>
Expand Down Expand Up @@ -482,11 +542,71 @@ exports[`Results View Should display Base, New and Common graphs with tooltips 1
>
Runs Density Distribution
</h3>
<div
class="MuiBox-root css-1ntc4s6"
>
<span
class="MuiTypography-root MuiTypography-body2 css-ftpr4e-MuiTypography-root"
>
Valley depth threshold
<svg
aria-hidden="true"
aria-label="A valley between two peaks must be shallower than this fraction of the shorter peak to count as a mode boundary. Higher = more splits detected."
class="MuiSvgIcon-root MuiSvgIcon-fontSizeSmall css-86dkbz-MuiSvgIcon-root"
data-mui-internal-clone-element="true"
data-testid="InfoOutlinedIcon"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8"
/>
</svg>
:
</span>
<span
class="MuiSlider-root MuiSlider-colorPrimary MuiSlider-sizeSmall css-hrrccv-MuiSlider-root"
>
<span
class="MuiSlider-rail css-r64h58-MuiSlider-rail"
/>
<span
class="MuiSlider-track css-1iqz70e-MuiSlider-track"
style="left: 0%; width: 44.9438202247191%;"
/>
<span
class="MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary css-1rsdqdo-MuiSlider-thumb"
data-index="0"
style="left: 44.9438202247191%;"
>
<input
aria-label="Valley depth threshold"
aria-orientation="horizontal"
aria-valuemax="0.99"
aria-valuemin="0.1"
aria-valuenow="0.5"
data-index="0"
max="0.99"
min="0.1"
step="0.01"
style="border: 0px; height: 100%; margin: -1px; overflow: hidden; padding: 0px; position: absolute; white-space: nowrap; width: 100%; direction: ltr;"
type="range"
value="0.5"
/>
</span>
</span>
<span
class="MuiTypography-root MuiTypography-body2 css-19x59xu-MuiTypography-root"
>
50
%
</span>
</div>
<div
class="MuiBox-root css-72fd9l"
>
<div
style="width: 100%; height: 325px;"
style="width: 100%; height: 340px;"
/>
</div>
</div>
Expand Down
Loading