feat(tests): Add tests for duplicating contour segments (#6002)
This commit is contained in:
parent
d186749c5a
commit
2258c7957a
@ -1,4 +1,4 @@
|
||||
import { expect, test, visitStudy, getSvgPath, navigateWithViewportArrow } from './utils';
|
||||
import { expect, test, visitStudy, getSvgAttribute, navigateWithViewportArrow } from './utils';
|
||||
import { expectRowSelected } from './utils/assertions';
|
||||
|
||||
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
||||
@ -26,42 +26,74 @@ test('should navigate the contours when clicking each segments in the right pane
|
||||
const getSegment = (index: number) =>
|
||||
rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(index);
|
||||
|
||||
const seg0 = await getSvgPath(viewportPageObject);
|
||||
const seg0 = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(seg0, 'Segment at index 0: expected a non-null SVG path').not.toBeNull();
|
||||
|
||||
await getSegment(3).click();
|
||||
const seg3 = await getSvgPath(viewportPageObject);
|
||||
const seg3 = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(seg3, 'Segment at index 3: expected a non-null SVG path').not.toBeNull();
|
||||
await expectRowSelected(getSegment(3));
|
||||
|
||||
await getSegment(2).click();
|
||||
const seg2 = await getSvgPath(viewportPageObject);
|
||||
const seg2 = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(seg2, 'Segment at index 2: expected a non-null SVG path').not.toBeNull();
|
||||
await expectRowSelected(getSegment(2));
|
||||
|
||||
await getSegment(1).click();
|
||||
const seg1 = await getSvgPath(viewportPageObject);
|
||||
const seg1 = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(seg1, 'Segment at index 1: expected a non-null SVG path').not.toBeNull();
|
||||
await expectRowSelected(getSegment(1));
|
||||
|
||||
// Clicking segments again should return the original paths
|
||||
await getSegment(2).click();
|
||||
const seg2Again = await getSvgPath(viewportPageObject);
|
||||
const seg2Again = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(seg2Again, 'Segment 2 again: expected to match the original segment 2 path').toBe(seg2);
|
||||
await expectRowSelected(getSegment(2));
|
||||
|
||||
await getSegment(1).click();
|
||||
const seg1Again = await getSvgPath(viewportPageObject);
|
||||
const seg1Again = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(seg1Again, 'Segment 1 again: expected to match the original segment 1 path').toBe(seg1);
|
||||
await expectRowSelected(getSegment(1));
|
||||
|
||||
await getSegment(0).click();
|
||||
const seg0Again = await getSvgPath(viewportPageObject);
|
||||
const seg0Again = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(seg0Again, 'Segment 0 again: expected to match the original segment 0 path').toBe(seg0);
|
||||
await expectRowSelected(getSegment(0));
|
||||
|
||||
await getSegment(3).click();
|
||||
const seg3Again = await getSvgPath(viewportPageObject);
|
||||
const seg3Again = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(seg3Again, 'Segment 3 again: expected to match the original segment 3 path').toBe(seg3);
|
||||
await expectRowSelected(getSegment(3));
|
||||
});
|
||||
@ -73,29 +105,49 @@ test('should navigate the segmentations using the Viewport arrow buttons', async
|
||||
const getSegment = (index: number) =>
|
||||
rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(index);
|
||||
|
||||
const initialSvgPath = await getSvgPath(viewportPageObject);
|
||||
const initialSvgPath = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(initialSvgPath, 'Segment at index 0: expected a non-null SVG path').not.toBeNull();
|
||||
// Expect the correct segment to be selected in the right panel
|
||||
await expectRowSelected(getSegment(0));
|
||||
|
||||
await navigateWithViewportArrow(viewportPageObject, 'next');
|
||||
const secondSvgPath = await getSvgPath(viewportPageObject);
|
||||
const secondSvgPath = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(secondSvgPath, 'Segment at index 1: expected a different SVG path from segment 0').not.toBe(initialSvgPath);
|
||||
await expectRowSelected(getSegment(1));
|
||||
|
||||
await navigateWithViewportArrow(viewportPageObject, 'next');
|
||||
const thirdSvgPath = await getSvgPath(viewportPageObject);
|
||||
const thirdSvgPath = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(thirdSvgPath, 'Segment at index 2: expected a different SVG path from segment 1').not.toBe(secondSvgPath);
|
||||
await expectRowSelected(getSegment(2));
|
||||
|
||||
await navigateWithViewportArrow(viewportPageObject, 'next');
|
||||
const fourthSvgPath = await getSvgPath(viewportPageObject);
|
||||
const fourthSvgPath = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(fourthSvgPath, 'Segment at index 3: expected a different SVG path from segment 2').not.toBe(thirdSvgPath);
|
||||
await expectRowSelected(getSegment(3));
|
||||
|
||||
// Wraparound test — next from last should return to first segment
|
||||
await navigateWithViewportArrow(viewportPageObject, 'next');
|
||||
const svgPathWraparoundWithNext = await getSvgPath(viewportPageObject);
|
||||
const svgPathWraparoundWithNext = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(
|
||||
svgPathWraparoundWithNext,
|
||||
'Expected svg path to match the initial svg path after wrapping around with next navigation'
|
||||
@ -104,7 +156,11 @@ test('should navigate the segmentations using the Viewport arrow buttons', async
|
||||
|
||||
// Wraparound test — prev from first should return to last segment
|
||||
await navigateWithViewportArrow(viewportPageObject, 'prev');
|
||||
const svgPathWraparoundWithPrev = await getSvgPath(viewportPageObject);
|
||||
const svgPathWraparoundWithPrev = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(
|
||||
svgPathWraparoundWithPrev,
|
||||
'Expected svg path to match the fourth svg path after wrapping around with prev navigation'
|
||||
@ -112,17 +168,29 @@ test('should navigate the segmentations using the Viewport arrow buttons', async
|
||||
await expectRowSelected(getSegment(3));
|
||||
|
||||
await navigateWithViewportArrow(viewportPageObject, 'prev');
|
||||
const backToThirdSvgPath = await getSvgPath(viewportPageObject);
|
||||
const backToThirdSvgPath = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(backToThirdSvgPath, 'Expected path to match third segment after going prev from fourth').toBe(thirdSvgPath);
|
||||
await expectRowSelected(getSegment(2));
|
||||
|
||||
await navigateWithViewportArrow(viewportPageObject, 'prev');
|
||||
const backToSecondSvgPath = await getSvgPath(viewportPageObject);
|
||||
const backToSecondSvgPath = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(backToSecondSvgPath, 'Expected path to match second segment after going prev from third').toBe(secondSvgPath);
|
||||
await expectRowSelected(getSegment(1));
|
||||
|
||||
await navigateWithViewportArrow(viewportPageObject, 'prev');
|
||||
const backToFirstSvgPath = await getSvgPath(viewportPageObject);
|
||||
const backToFirstSvgPath = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(backToFirstSvgPath, 'Expected path to match first segment after going prev from second').toBe(initialSvgPath);
|
||||
await expectRowSelected(getSegment(0));
|
||||
});
|
||||
|
||||
109
tests/ContourSegmentDuplicate.spec.ts
Normal file
109
tests/ContourSegmentDuplicate.spec.ts
Normal file
@ -0,0 +1,109 @@
|
||||
import {
|
||||
expect,
|
||||
test,
|
||||
visitStudy,
|
||||
waitForViewportsRendered,
|
||||
} from './utils';
|
||||
import { getSvgAttribute } from './utils/getSvgAttribute';
|
||||
|
||||
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
||||
const defaultSegment0Name = 'Threshold';
|
||||
const defaultSegment1Name = 'Big Sphere';
|
||||
|
||||
test.beforeEach(async ({
|
||||
page,
|
||||
leftPanelPageObject,
|
||||
DOMOverlayPageObject,
|
||||
}) => {
|
||||
const mode = 'segmentation';
|
||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||
|
||||
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||
await waitForViewportsRendered(page);
|
||||
await expect(DOMOverlayPageObject.viewport.segmentationHydration.locator).toBeVisible();
|
||||
|
||||
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||
});
|
||||
|
||||
test('should duplicate a contour segment and add a new row to the panel', async ({
|
||||
page,
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const panel = rightPanelPageObject.contourSegmentationPanel.panel;
|
||||
|
||||
const initialCount = await panel.getSegmentCount();
|
||||
expect(initialCount, 'Expected to load with 4 segments').toBe(4);
|
||||
|
||||
const segment0 = panel.nthSegment(0);
|
||||
await expect(segment0.title).toHaveText(defaultSegment0Name);
|
||||
|
||||
await segment0.actions.duplicate();
|
||||
|
||||
const countAfterDuplicate = await panel.getSegmentCount();
|
||||
expect(countAfterDuplicate, 'Expected one additional segment row after duplicating').toBe(5);
|
||||
|
||||
//New segment's default name is formatted as "Segment {segmentCount}"
|
||||
const newSegmentLocator = panel.nthSegment(initialCount).title;
|
||||
await expect(newSegmentLocator, 'Expected correct title for duplicated segment').toHaveText(`Segment 5`);
|
||||
|
||||
// Original segment titles should be unchanged
|
||||
await expect(panel.nthSegment(0).title).toHaveText(defaultSegment0Name);
|
||||
await expect(panel.nthSegment(1).title).toHaveText(defaultSegment1Name);
|
||||
});
|
||||
|
||||
test('should duplicate the same segment multiple times', async ({
|
||||
page,
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const panel = rightPanelPageObject.contourSegmentationPanel.panel;
|
||||
|
||||
const segment0 = panel.nthSegment(0);
|
||||
|
||||
await segment0.actions.duplicate();
|
||||
expect(await panel.getSegmentCount(), 'Expected one additional segment row after duplicating').toBe(5);
|
||||
|
||||
const firstDuplicateTitleLocator = panel.nthSegment(4).title;
|
||||
await expect(firstDuplicateTitleLocator, 'Expected correct title for first duplicated segment').toHaveText(`Segment 5`);
|
||||
|
||||
await segment0.actions.duplicate();
|
||||
expect(await panel.getSegmentCount(), 'Expected another segment row after duplicating the same segment again').toBe(6);
|
||||
|
||||
const secondDuplicateTitleLocator = panel.nthSegment(5).title;
|
||||
await expect(secondDuplicateTitleLocator, 'Expected correct title for second duplicated segment').toHaveText(`Segment 6`);
|
||||
});
|
||||
|
||||
test('should render the duplicated contour on the viewport', async ({
|
||||
rightPanelPageObject,
|
||||
viewportPageObject,
|
||||
}) => {
|
||||
const panel = rightPanelPageObject.contourSegmentationPanel.panel;
|
||||
|
||||
// Hide everything, to be able to grab only the SVG path of the segment to duplicate
|
||||
await rightPanelPageObject.contourSegmentationPanel.segmentsVisibilityToggle.click();
|
||||
const segment0 = panel.nthSegment(0);
|
||||
await segment0.toggleVisibility();
|
||||
await segment0.click();
|
||||
|
||||
const sourceSvgPath = await getSvgAttribute({viewportPageObject, svgInnerElement: 'path', attributeName: 'd'});
|
||||
expect(sourceSvgPath, 'Expected a visible SVG path for the source segment').not.toBeNull();
|
||||
const sourceSvgPaths = (await viewportPageObject.getById('default')).svg('path');
|
||||
expect(sourceSvgPaths, 'Expected only one SVG path element for the original segment').toHaveCount(1);
|
||||
|
||||
// New segment is at index 4
|
||||
await segment0.actions.duplicate();
|
||||
const duplicatedSegment = panel.nthSegment(4);
|
||||
|
||||
// Hide again to show duplicate only
|
||||
await segment0.toggleVisibility();
|
||||
await duplicatedSegment.click();
|
||||
|
||||
const duplicatedSvgPath = await getSvgAttribute({viewportPageObject, svgInnerElement: 'path', attributeName: 'd'});
|
||||
expect(duplicatedSvgPath, 'Expected a visible SVG path for the duplicated segment').not.toBeNull();
|
||||
const duplicatedSvgPaths = (await viewportPageObject.getById('default')).svg('path');
|
||||
expect(duplicatedSvgPaths, 'Expected only one SVG path element for the duplicated segment').toHaveCount(1);
|
||||
|
||||
expect(
|
||||
duplicatedSvgPath,
|
||||
'Expected the duplicated segment to have the same SVG path as the source'
|
||||
).toBe(sourceSvgPath);
|
||||
});
|
||||
@ -1,4 +1,4 @@
|
||||
import { expect, test, visitStudy, getSvgPath, navigateWithViewportArrow } from './utils';
|
||||
import { expect, test, visitStudy, getSvgAttribute, navigateWithViewportArrow } from './utils';
|
||||
|
||||
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
||||
|
||||
@ -78,7 +78,11 @@ test('should restore svg paths when segment visibility is toggled on/off', async
|
||||
|
||||
const segment0 = rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(0);
|
||||
await segment0.toggleVisibility();
|
||||
const svgPathBefore = await getSvgPath(viewportPageObject);
|
||||
const svgPathBefore = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(svgPathBefore, 'Expected a visible SVG path for segment 0').not.toBeNull();
|
||||
|
||||
await segment0.toggleVisibility();
|
||||
@ -88,7 +92,11 @@ test('should restore svg paths when segment visibility is toggled on/off', async
|
||||
).toHaveCount(0);
|
||||
|
||||
await segment0.toggleVisibility();
|
||||
const svgPathAfter = await getSvgPath(viewportPageObject);
|
||||
const svgPathAfter = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'd',
|
||||
});
|
||||
expect(svgPathAfter, 'Expected SVG path to be restored after toggling visibility back on').toBe(
|
||||
svgPathBefore
|
||||
);
|
||||
|
||||
@ -11,7 +11,7 @@ import { DataOverlayPageObject } from './DataOverlayPageObject';
|
||||
import { DOMOverlayPageObject } from './DOMOverlayPageObject';
|
||||
import { MagnifyGlassPageObject } from './MagnifyGlassPageObject';
|
||||
|
||||
type SvgInnerElement = 'circle' | 'path' | 'd' | 'line' | 'g';
|
||||
export type SvgInnerElement = 'circle' | 'path' | 'line' | 'g';
|
||||
|
||||
type NormalizedDragParams = {
|
||||
start: { x: number; y: number };
|
||||
|
||||
23
tests/utils/getSvgAttribute.ts
Normal file
23
tests/utils/getSvgAttribute.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { SvgInnerElement, ViewportPageObject } from '../pages/ViewportPageObject';
|
||||
|
||||
const getSvgAttribute = async ({
|
||||
viewportPageObject,
|
||||
svgInnerElement,
|
||||
attributeName,
|
||||
viewportId = 'default',
|
||||
nth = 0,
|
||||
}: {
|
||||
viewportPageObject: ViewportPageObject;
|
||||
svgInnerElement: SvgInnerElement;
|
||||
attributeName: string;
|
||||
viewportId?: string;
|
||||
nth?: number;
|
||||
}) => {
|
||||
return (await viewportPageObject.getById(viewportId))
|
||||
.svg(svgInnerElement)
|
||||
.nth(nth)
|
||||
.getAttribute(attributeName);
|
||||
};
|
||||
|
||||
|
||||
export { getSvgAttribute };
|
||||
@ -1,7 +0,0 @@
|
||||
import { ViewportPageObject } from '../pages/ViewportPageObject';
|
||||
|
||||
const getSvgPath = async (viewportPageObject: ViewportPageObject, viewportId = 'default') => {
|
||||
return (await viewportPageObject.getById(viewportId)).svg('path').first().getAttribute('d');
|
||||
};
|
||||
|
||||
export { getSvgPath };
|
||||
@ -24,7 +24,7 @@ import { clearAllAnnotations } from './clearAllAnnotations';
|
||||
import { scrollVolumeViewport } from './scrollVolumeViewport';
|
||||
import { attemptAction } from './attemptAction';
|
||||
import { addLengthMeasurement } from './addLengthMeasurement';
|
||||
import { getSvgPath } from './getSvgPath';
|
||||
import { getSvgAttribute } from './getSvgAttribute';
|
||||
import { navigateWithViewportArrow } from './navigateWithViewportArrow';
|
||||
import { test, expect } from './fixture';
|
||||
import { subscribeToMeasurementAdded } from './subscribeToMeasurement';
|
||||
@ -57,7 +57,7 @@ export {
|
||||
attemptAction,
|
||||
addLengthMeasurement,
|
||||
subscribeToMeasurementAdded,
|
||||
getSvgPath,
|
||||
getSvgAttribute,
|
||||
navigateWithViewportArrow,
|
||||
waitForAnyViewportNeedsRender,
|
||||
waitForViewportsRendered,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user