+
onArrowsClick(-1)} />
-
diff --git a/tests/ContourSegNavigation.spec.ts b/tests/ContourSegNavigation.spec.ts
new file mode 100644
index 000000000..3eef690a4
--- /dev/null
+++ b/tests/ContourSegNavigation.spec.ts
@@ -0,0 +1,128 @@
+import { expect, test, visitStudy, getSvgPath, navigateWithViewportArrow } from './utils';
+import { expectRowSelected } from './utils/assertions';
+
+const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
+
+test.beforeEach(async ({
+ page,
+ leftPanelPageObject,
+ DOMOverlayPageObject,
+ rightPanelPageObject
+}) => {
+ const mode = 'segmentation';
+ await visitStudy(page, studyInstanceUID, mode, 2000);
+ await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
+ await page.waitForTimeout(5000);
+ await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
+ // Click segment 0 in the right panel to establish a known starting position
+ await rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(0).click();
+ await page.waitForTimeout(5000);
+});
+
+test('should navigate the contours when clicking each segments in the right panel', async ({
+ rightPanelPageObject,
+ viewportPageObject,
+}) => {
+ const getSegment = (index: number) =>
+ rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(index);
+
+ const seg0 = await getSvgPath(viewportPageObject);
+ expect(seg0, 'Segment at index 0: expected a non-null SVG path').not.toBeNull();
+
+ await getSegment(3).click();
+ const seg3 = await getSvgPath(viewportPageObject);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ expect(seg3Again, 'Segment 3 again: expected to match the original segment 3 path').toBe(seg3);
+ await expectRowSelected(getSegment(3));
+});
+
+test('should navigate the segmentations using the Viewport arrow buttons', async ({
+ rightPanelPageObject,
+ viewportPageObject,
+}) => {
+ const getSegment = (index: number) =>
+ rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(index);
+
+ const initialSvgPath = await getSvgPath(viewportPageObject);
+ 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);
+ 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);
+ 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);
+ 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);
+ expect(
+ svgPathWraparoundWithNext,
+ 'Expected svg path to match the initial svg path after wrapping around with next navigation'
+ ).toBe(initialSvgPath);
+ await expectRowSelected(getSegment(0));
+
+ // Wraparound test — prev from first should return to last segment
+ await navigateWithViewportArrow(viewportPageObject, 'prev');
+ const svgPathWraparoundWithPrev = await getSvgPath(viewportPageObject);
+ expect(
+ svgPathWraparoundWithPrev,
+ 'Expected svg path to match the fourth svg path after wrapping around with prev navigation'
+ ).toBe(fourthSvgPath);
+ await expectRowSelected(getSegment(3));
+
+ await navigateWithViewportArrow(viewportPageObject, 'prev');
+ const backToThirdSvgPath = await getSvgPath(viewportPageObject);
+ 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);
+ 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);
+ expect(backToFirstSvgPath, 'Expected path to match first segment after going prev from second').toBe(initialSvgPath);
+ await expectRowSelected(getSegment(0));
+});
diff --git a/tests/pages/ViewportPageObject.ts b/tests/pages/ViewportPageObject.ts
index 7a8fd0c40..138ac6cf8 100644
--- a/tests/pages/ViewportPageObject.ts
+++ b/tests/pages/ViewportPageObject.ts
@@ -64,6 +64,17 @@ export interface IViewportPageObject {
};
pane: Locator;
svg: (innerElement?: SvgInnerElement) => Locator;
+ navigationArrows: {
+ locator: Locator;
+ prev: {
+ button: Locator;
+ click: () => Promise
;
+ };
+ next: {
+ button: Locator;
+ click: () => Promise;
+ };
+ };
}
export class ViewportPageObject {
@@ -146,6 +157,27 @@ export class ViewportPageObject {
return viewport.locator(`svg.svg-layer${innerElement ? ` ${innerElement}` : ''}`);
}
+ private getNavigationArrows(viewport: Locator) {
+ const container = viewport.getByTestId('viewport-action-arrows');
+ const prevButton = viewport.getByTestId('viewport-action-arrows-left');
+ const nextButton = viewport.getByTestId('viewport-action-arrows-right');
+ return {
+ locator: container,
+ prev: {
+ button: prevButton,
+ click: async () => {
+ await prevButton.click();
+ },
+ },
+ next: {
+ button: nextButton,
+ click: async () => {
+ await nextButton.click();
+ },
+ },
+ };
+ }
+
private viewportPageObjectFactory(viewport: Locator): IViewportPageObject {
return {
nthAnnotation: (nth: number) => this.getAnnotation(viewport, nth),
@@ -189,6 +221,7 @@ export class ViewportPageObject {
svg: (innerElement?: SvgInnerElement) => {
return this.getSvg(viewport, innerElement);
},
+ navigationArrows: this.getNavigationArrows(viewport),
};
}
diff --git a/tests/utils/assertions.ts b/tests/utils/assertions.ts
index 17b2e7820..42ff6473f 100644
--- a/tests/utils/assertions.ts
+++ b/tests/utils/assertions.ts
@@ -61,3 +61,7 @@ export async function assertBoundingBoxIsContainedWithin({
`${innerBoxLabel} bottom edge should be within ${outerBoxLabel}`
).toBeLessThanOrEqual(outerBox.y + outerBox.height);
}
+
+export async function expectRowSelected(rowObject) {
+ await expect(rowObject.locator).toContainClass('bg-popover');
+}
diff --git a/tests/utils/getSvgPath.ts b/tests/utils/getSvgPath.ts
new file mode 100644
index 000000000..16461e823
--- /dev/null
+++ b/tests/utils/getSvgPath.ts
@@ -0,0 +1,11 @@
+import { ViewportPageObject } from '../pages/ViewportPageObject';
+
+const getSvgPath = async (viewportPageObject: ViewportPageObject, viewportId = 'default') => {
+ return viewportPageObject
+ .getById(viewportId)
+ .svg('path')
+ .first()
+ .getAttribute('d');
+};
+
+export { getSvgPath };
diff --git a/tests/utils/index.ts b/tests/utils/index.ts
index 6366b2a9c..50b6ba1c3 100644
--- a/tests/utils/index.ts
+++ b/tests/utils/index.ts
@@ -16,6 +16,8 @@ import { clearAllAnnotations } from './clearAllAnnotations';
import { scrollVolumeViewport } from './scrollVolumeViewport';
import { attemptAction } from './attemptAction';
import { addLengthMeasurement } from './addLengthMeasurement';
+import { getSvgPath } from './getSvgPath';
+import { navigateWithViewportArrow } from './navigateWithViewportArrow';
import { test, expect } from './fixture';
import { subscribeToMeasurementAdded } from './subscribeToMeasurement';
@@ -38,6 +40,8 @@ export {
attemptAction,
addLengthMeasurement,
subscribeToMeasurementAdded,
+ getSvgPath,
+ navigateWithViewportArrow,
test,
expect,
};
diff --git a/tests/utils/navigateWithViewportArrow.ts b/tests/utils/navigateWithViewportArrow.ts
new file mode 100644
index 000000000..bdd472ba5
--- /dev/null
+++ b/tests/utils/navigateWithViewportArrow.ts
@@ -0,0 +1,13 @@
+import { ViewportPageObject } from '../pages/ViewportPageObject';
+
+const navigateWithViewportArrow = async (
+ viewportPageObject: ViewportPageObject,
+ direction: 'next' | 'prev',
+ viewportId = 'default'
+) => {
+ const viewport = viewportPageObject.getById(viewportId);
+ await viewport.navigationArrows[direction].click();
+};
+
+export { navigateWithViewportArrow };
+