test: add E2E test for contour combine intersect and subtract operations (#6131)
This commit is contained in:
parent
f0e2f64397
commit
01939e2236
@ -70,7 +70,10 @@ function SegmentSelector({
|
|||||||
onValueChange={onValueChange}
|
onValueChange={onValueChange}
|
||||||
value={value}
|
value={value}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="overflow-hidden">
|
<SelectTrigger
|
||||||
|
className="overflow-hidden"
|
||||||
|
data-cy={`logical-contour-segment-${label.toLowerCase()}-trigger`}
|
||||||
|
>
|
||||||
<SelectValue placeholder={t(placeholder)} />
|
<SelectValue placeholder={t(placeholder)} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -180,6 +183,7 @@ function LogicalContourOperationOptions() {
|
|||||||
value={value}
|
value={value}
|
||||||
key={`logical-contour-operation-${value}`}
|
key={`logical-contour-operation-${value}`}
|
||||||
onClick={() => setOperation(option)}
|
onClick={() => setOperation(option)}
|
||||||
|
data-cy={`logical-contour-operation-${value}`}
|
||||||
>
|
>
|
||||||
<Icons.ByName name={icon}></Icons.ByName>
|
<Icons.ByName name={icon}></Icons.ByName>
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
@ -207,6 +211,7 @@ function LogicalContourOperationOptions() {
|
|||||||
/>
|
/>
|
||||||
<div className="flex justify-end pl-[34px]">
|
<div className="flex justify-end pl-[34px]">
|
||||||
<Button
|
<Button
|
||||||
|
data-cy="apply-logical-contour-operation"
|
||||||
className="border-primary/60 grow border"
|
className="border-primary/60 grow border"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -221,6 +226,7 @@ function LogicalContourOperationOptions() {
|
|||||||
<div className="flex items-center justify-start gap-2">
|
<div className="flex items-center justify-start gap-2">
|
||||||
<Switch
|
<Switch
|
||||||
id="logical-contour-operations-create-new-segment-switch"
|
id="logical-contour-operations-create-new-segment-switch"
|
||||||
|
data-cy="logical-contour-create-new-segment-switch"
|
||||||
onCheckedChange={setCreateNewSegment}
|
onCheckedChange={setCreateNewSegment}
|
||||||
></Switch>
|
></Switch>
|
||||||
<Label htmlFor="logical-contour-operations-create-new-segment-switch">
|
<Label htmlFor="logical-contour-operations-create-new-segment-switch">
|
||||||
|
|||||||
@ -72,13 +72,22 @@ export const SegmentationTableConfig: React.FC<{ children?: React.ReactNode }> =
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TabsList>
|
<TabsList>
|
||||||
<TabsTrigger value="fill-and-outline">
|
<TabsTrigger
|
||||||
|
value="fill-and-outline"
|
||||||
|
data-cy={`segmentation-config-display-fill-and-outline${dataCyTypeSuffix}`}
|
||||||
|
>
|
||||||
<Icons.FillAndOutline className="text-primary" />
|
<Icons.FillAndOutline className="text-primary" />
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="outline">
|
<TabsTrigger
|
||||||
|
value="outline"
|
||||||
|
data-cy={`segmentation-config-display-outline${dataCyTypeSuffix}`}
|
||||||
|
>
|
||||||
<Icons.OutlineOnly className="text-primary" />
|
<Icons.OutlineOnly className="text-primary" />
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger value="fill">
|
<TabsTrigger
|
||||||
|
value="fill"
|
||||||
|
data-cy={`segmentation-config-display-fill${dataCyTypeSuffix}`}
|
||||||
|
>
|
||||||
<Icons.FillOnly className="text-primary" />
|
<Icons.FillOnly className="text-primary" />
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
|
|||||||
118
tests/ContourCombineOperations.spec.ts
Normal file
118
tests/ContourCombineOperations.spec.ts
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import {
|
||||||
|
test,
|
||||||
|
expect,
|
||||||
|
waitForViewportRenderCycle,
|
||||||
|
checkForScreenshot,
|
||||||
|
screenShotPaths,
|
||||||
|
visitStudyAndHydrate,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
|
const segments = {
|
||||||
|
bigSphere: 'Big Sphere',
|
||||||
|
smallSphere: 'Small Sphere',
|
||||||
|
result: 'Segment 5',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
test.beforeEach(
|
||||||
|
async ({ page, leftPanelPageObject, DOMOverlayPageObject, rightPanelPageObject }) => {
|
||||||
|
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
||||||
|
|
||||||
|
await visitStudyAndHydrate({
|
||||||
|
page,
|
||||||
|
leftPanelPageObject,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
studyInstanceUID,
|
||||||
|
modality: 'RTSTRUCT',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
test.describe('Intersect operation', () => {
|
||||||
|
test('intersect Big Sphere with Small Sphere (nested, no edge crossing) produces Small Sphere', async ({
|
||||||
|
page,
|
||||||
|
rightPanelPageObject,
|
||||||
|
viewportPageObject,
|
||||||
|
}) => {
|
||||||
|
const contourSegmentationPanel = rightPanelPageObject.contourSegmentationPanel;
|
||||||
|
|
||||||
|
const activeViewport = await viewportPageObject.active;
|
||||||
|
await activeViewport.pane.dblclick();
|
||||||
|
|
||||||
|
await contourSegmentationPanel.config.toggle.click();
|
||||||
|
|
||||||
|
await contourSegmentationPanel.config.display.fillAndOutline();
|
||||||
|
|
||||||
|
await contourSegmentationPanel.panel.segmentByText(segments.bigSphere).click();
|
||||||
|
|
||||||
|
const combineContours = rightPanelPageObject.contourSegmentationPanel.combineContours;
|
||||||
|
|
||||||
|
await combineContours.open();
|
||||||
|
await combineContours.selectOperation('intersect');
|
||||||
|
await combineContours.selectSegmentA(segments.bigSphere);
|
||||||
|
await combineContours.selectSegmentB(segments.smallSphere);
|
||||||
|
await combineContours.enableCreateNewSegment();
|
||||||
|
let viewportRenderCycle = waitForViewportRenderCycle(page);
|
||||||
|
await combineContours.apply();
|
||||||
|
await viewportRenderCycle;
|
||||||
|
|
||||||
|
await expect(contourSegmentationPanel.panel.rows).toHaveCount(5);
|
||||||
|
await expect(contourSegmentationPanel.panel.nthSegment(4).title).toHaveText(segments.result);
|
||||||
|
|
||||||
|
await contourSegmentationPanel.segmentsVisibilityToggle.click();
|
||||||
|
|
||||||
|
viewportRenderCycle = waitForViewportRenderCycle(page);
|
||||||
|
await contourSegmentationPanel.panel.segmentByText(segments.result).toggleVisibility();
|
||||||
|
await viewportRenderCycle;
|
||||||
|
|
||||||
|
await checkForScreenshot(
|
||||||
|
page,
|
||||||
|
viewportPageObject.grid,
|
||||||
|
screenShotPaths.contourCombineOperations.intersectBigSphereSmallSphereResult
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Subtract operation', () => {
|
||||||
|
test('subtract Big Sphere minus Small Sphere (nested, no edge crossing) produces Big Sphere with a hole', async ({
|
||||||
|
page,
|
||||||
|
rightPanelPageObject,
|
||||||
|
viewportPageObject,
|
||||||
|
}) => {
|
||||||
|
const contourSegmentationPanel = rightPanelPageObject.contourSegmentationPanel;
|
||||||
|
|
||||||
|
const activeViewport = await viewportPageObject.active;
|
||||||
|
await activeViewport.pane.dblclick();
|
||||||
|
|
||||||
|
await contourSegmentationPanel.config.toggle.click();
|
||||||
|
|
||||||
|
await contourSegmentationPanel.config.display.fillAndOutline();
|
||||||
|
|
||||||
|
await contourSegmentationPanel.panel.segmentByText(segments.bigSphere).click();
|
||||||
|
|
||||||
|
const combineContours = rightPanelPageObject.contourSegmentationPanel.combineContours;
|
||||||
|
|
||||||
|
await combineContours.open();
|
||||||
|
await combineContours.selectOperation('subtract');
|
||||||
|
await combineContours.selectSegmentA(segments.bigSphere);
|
||||||
|
await combineContours.selectSegmentB(segments.smallSphere);
|
||||||
|
await combineContours.enableCreateNewSegment();
|
||||||
|
let viewportRenderCycle = waitForViewportRenderCycle(page);
|
||||||
|
await combineContours.apply();
|
||||||
|
await viewportRenderCycle;
|
||||||
|
|
||||||
|
await expect(contourSegmentationPanel.panel.rows).toHaveCount(5);
|
||||||
|
await expect(contourSegmentationPanel.panel.nthSegment(4).title).toHaveText(segments.result);
|
||||||
|
|
||||||
|
await contourSegmentationPanel.segmentsVisibilityToggle.click();
|
||||||
|
|
||||||
|
viewportRenderCycle = waitForViewportRenderCycle(page);
|
||||||
|
await contourSegmentationPanel.panel.segmentByText(segments.result).toggleVisibility();
|
||||||
|
await viewportRenderCycle;
|
||||||
|
|
||||||
|
await checkForScreenshot(
|
||||||
|
page,
|
||||||
|
viewportPageObject.grid,
|
||||||
|
screenShotPaths.contourCombineOperations.subtractBigSphereMinusSmallSphereResult
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -395,6 +395,54 @@ export class RightPanelPageObject {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
get config() {
|
||||||
|
const configToggle = page.getByTestId('segmentation-config-toggle-Contour');
|
||||||
|
return {
|
||||||
|
toggle: {
|
||||||
|
locator: configToggle,
|
||||||
|
click: async () => {
|
||||||
|
await configToggle.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
display: {
|
||||||
|
fillAndOutline: async () => {
|
||||||
|
await page
|
||||||
|
.getByTestId(`segmentation-config-display-fill-and-outline-Contour`)
|
||||||
|
.click();
|
||||||
|
},
|
||||||
|
outline: async () => {
|
||||||
|
await page.getByTestId(`segmentation-config-display-outline-Contour`).click();
|
||||||
|
},
|
||||||
|
fill: async () => {
|
||||||
|
await page.getByTestId(`segmentation-config-display-fill-Contour`).click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
get combineContours() {
|
||||||
|
return {
|
||||||
|
open: async () => {
|
||||||
|
await page.getByTestId('LogicalContourOperations').click();
|
||||||
|
},
|
||||||
|
selectOperation: async (operation: 'merge' | 'intersect' | 'subtract') => {
|
||||||
|
await page.getByTestId(`logical-contour-operation-${operation}`).click();
|
||||||
|
},
|
||||||
|
selectSegmentA: async (label: string) => {
|
||||||
|
await page.getByTestId('logical-contour-segment-a-trigger').click();
|
||||||
|
await page.getByRole('option', { name: label }).click();
|
||||||
|
},
|
||||||
|
selectSegmentB: async (label: string) => {
|
||||||
|
await page.getByTestId('logical-contour-segment-b-trigger').click();
|
||||||
|
await page.getByRole('option', { name: label }).click();
|
||||||
|
},
|
||||||
|
apply: async () => {
|
||||||
|
await page.getByTestId('apply-logical-contour-operation').click();
|
||||||
|
},
|
||||||
|
enableCreateNewSegment: async () => {
|
||||||
|
await page.getByTestId('logical-contour-create-new-segment-switch').click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
get labelMapSegmentationPanel() {
|
get labelMapSegmentationPanel() {
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
@ -221,6 +221,10 @@ const screenShotPaths = {
|
|||||||
overlaysDisplayed: 'overlaysDisplayed.png',
|
overlaysDisplayed: 'overlaysDisplayed.png',
|
||||||
overlaySEGsAndRTDisplayed: 'overlaySEGsAndRTDisplayed.png',
|
overlaySEGsAndRTDisplayed: 'overlaySEGsAndRTDisplayed.png',
|
||||||
},
|
},
|
||||||
|
contourCombineOperations: {
|
||||||
|
subtractBigSphereMinusSmallSphereResult: 'subtractBigSphereMinusSmallSphereResult.png',
|
||||||
|
intersectBigSphereSmallSphereResult: 'intersectBigSphereSmallSphereResult.png',
|
||||||
|
},
|
||||||
workList: {
|
workList: {
|
||||||
scrollBarRenderedProperly: 'scrollBarRenderedProperly.png',
|
scrollBarRenderedProperly: 'scrollBarRenderedProperly.png',
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user