test(ContourSegNavigation): Add e2e tests for contour segmentation navigation (#5834)
--------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
parent
b6d362f375
commit
f2ed4c9e6f
@ -12,11 +12,20 @@ const arrowClasses =
|
||||
*/
|
||||
function ViewportActionArrows({ onArrowsClick, className }) {
|
||||
return (
|
||||
<div className={classNames(className, 'flex')}>
|
||||
<div className={arrowClasses}>
|
||||
<div
|
||||
data-cy="viewport-action-arrows"
|
||||
className={classNames(className, 'flex')}
|
||||
>
|
||||
<div
|
||||
data-cy="viewport-action-arrows-left"
|
||||
className={arrowClasses}
|
||||
>
|
||||
<Icons.ArrowLeftBold onClick={() => onArrowsClick(-1)} />
|
||||
</div>
|
||||
<div className={arrowClasses}>
|
||||
<div
|
||||
data-cy="viewport-action-arrows-right"
|
||||
className={arrowClasses}
|
||||
>
|
||||
<Icons.ArrowRightBold onClick={() => onArrowsClick(1)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
128
tests/ContourSegNavigation.spec.ts
Normal file
128
tests/ContourSegNavigation.spec.ts
Normal file
@ -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));
|
||||
});
|
||||
@ -64,6 +64,17 @@ export interface IViewportPageObject {
|
||||
};
|
||||
pane: Locator;
|
||||
svg: (innerElement?: SvgInnerElement) => Locator;
|
||||
navigationArrows: {
|
||||
locator: Locator;
|
||||
prev: {
|
||||
button: Locator;
|
||||
click: () => Promise<void>;
|
||||
};
|
||||
next: {
|
||||
button: Locator;
|
||||
click: () => Promise<void>;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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');
|
||||
}
|
||||
|
||||
11
tests/utils/getSvgPath.ts
Normal file
11
tests/utils/getSvgPath.ts
Normal file
@ -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 };
|
||||
@ -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,
|
||||
};
|
||||
|
||||
13
tests/utils/navigateWithViewportArrow.ts
Normal file
13
tests/utils/navigateWithViewportArrow.ts
Normal file
@ -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 };
|
||||
|
||||
Loading…
Reference in New Issue
Block a user