test(e2e): update Playwright screenshots and add better tests and assertions for area calculations (#6022)

* Add (better) assertions for area calculation fixes.
* Add SVG and measurement side panel area for freehand ROI test.
* Add Playwright viewport screenshot scope migration guide.
* Update cornerstonjs dependencies to 4.22.8. Ensure all versions of @babel/preset-env are 7.29.5.

---------

Co-authored-by: Ghadeer Albattarni <165973963+GhadeerAlbattarni@users.noreply.github.com>
This commit is contained in:
Joe BoccanfusoandGhadeer Albattarni authored and GitHub committed 2026-05-18 10:36:05 -04:00
1 parent cb0cbe702c
commit fe16e80cf3
174 files changed
+1071 -751

No files matched your search

+74 -1
View File
@@ -1,4 +1,10 @@
import { expect, test, visitStudy, subscribeToMeasurementAdded } from './utils';
import {
expect,
getAnnotationStats,
subscribeToMeasurementAdded,
test,
visitStudy,
} from './utils';
test.beforeEach(async ({ page }) => {
const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5';
@@ -32,3 +38,70 @@ test('should not fire MEASUREMENT_ADDED when clicking the annotation text', asyn
await measurementAdded.unsubscribe();
}
});
test('rectangle and freehand at identical coordinates should yield comparable area', async ({
page,
DOMOverlayPageObject,
mainToolbarPageObject,
rightPanelPageObject,
viewportPageObject,
}) => {
// Open measurements panel first — needed later for the delete action, and
// opening up-front means both shapes are drawn against the same viewport
// layout (so normalized coords don't shift between draws).
await rightPanelPageObject.toggle();
await rightPanelPageObject.measurementsPanel.select();
const activeViewport = await viewportPageObject.active;
// End on the left edge just shy of the start so cornerstone3D's proximity-
// close triggers via the standard mouseup path (which fires
// ANNOTATION_COMPLETED). Ending at the start point would enter interactive close-
// preview mode and suppress the completion event; ending further away
// would draw a diagonal that distorts the rectangular shape.
const corners = [
{ x: 0.3, y: 0.3 },
{ x: 0.55, y: 0.3 },
{ x: 0.55, y: 0.55 },
{ x: 0.3, y: 0.55 },
{ x: 0.3, y: 0.31 },
];
const [topLeft, , bottomRight] = corners;
await mainToolbarPageObject.measurementTools.rectangleROI.click();
await activeViewport.normalizedClickAt([topLeft, bottomRight]);
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
const rectangles = await getAnnotationStats(page, { toolName: 'RectangleROI' });
const rectArea = rectangles[0].firstTargetStats!.area as number;
const rectRow = rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0);
const rectSvgLines = activeViewport.getSvgAnnotationStatTextLines(rectangles[0].annotationUID);
await expect(rectSvgLines.nth(0)).toHaveText(`Area: ${Math.round(rectArea)} mm²`);
await expect(rectRow.stats.primary.lines.nth(0)).toHaveText(`${Math.round(rectArea)} mm²`);
// Remove the rectangle so the freehand can drag through the same coords
// without grabbing the rectangle's handles.
await rectRow.actions.delete();
await mainToolbarPageObject.measurementTools.freehandROI.click();
await activeViewport.normalizedPathDragAt({
path: corners,
config: { steps: 20, delay: 30 },
});
const freehands = await getAnnotationStats(page, { toolName: 'PlanarFreehandROI' });
const freehandArea = freehands[0].firstTargetStats!.area as number;
const freehandRow = rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0);
const freehandSvgLines = activeViewport.getSvgAnnotationStatTextLines(freehands[0].annotationUID);
await expect(freehandSvgLines.nth(0)).toHaveText(`Area: ${Math.round(freehandArea)} mm²`);
await expect(freehandRow.stats.primary.lines.nth(0)).toHaveText(`${Math.round(freehandArea)} mm²`);
const pctDiff = (Math.abs(rectArea - freehandArea) / rectArea) * 100;
console.log(
`Rectangle: ${rectArea.toFixed(2)} mm² | ` +
`Freehand: ${freehandArea.toFixed(2)} mm² | ` +
`diff: ${pctDiff.toFixed(2)}%`
);
expect(pctDiff).toBeLessThan(1);
});