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}
|
||||
value={value}
|
||||
>
|
||||
<SelectTrigger className="overflow-hidden">
|
||||
<SelectTrigger
|
||||
className="overflow-hidden"
|
||||
data-cy={`logical-contour-segment-${label.toLowerCase()}-trigger`}
|
||||
>
|
||||
<SelectValue placeholder={t(placeholder)} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@ -180,6 +183,7 @@ function LogicalContourOperationOptions() {
|
||||
value={value}
|
||||
key={`logical-contour-operation-${value}`}
|
||||
onClick={() => setOperation(option)}
|
||||
data-cy={`logical-contour-operation-${value}`}
|
||||
>
|
||||
<Icons.ByName name={icon}></Icons.ByName>
|
||||
</TabsTrigger>
|
||||
@ -207,6 +211,7 @@ function LogicalContourOperationOptions() {
|
||||
/>
|
||||
<div className="flex justify-end pl-[34px]">
|
||||
<Button
|
||||
data-cy="apply-logical-contour-operation"
|
||||
className="border-primary/60 grow border"
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
@ -221,6 +226,7 @@ function LogicalContourOperationOptions() {
|
||||
<div className="flex items-center justify-start gap-2">
|
||||
<Switch
|
||||
id="logical-contour-operations-create-new-segment-switch"
|
||||
data-cy="logical-contour-create-new-segment-switch"
|
||||
onCheckedChange={setCreateNewSegment}
|
||||
></Switch>
|
||||
<Label htmlFor="logical-contour-operations-create-new-segment-switch">
|
||||
|
||||
@ -72,13 +72,22 @@ export const SegmentationTableConfig: React.FC<{ children?: React.ReactNode }> =
|
||||
}}
|
||||
>
|
||||
<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" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="outline">
|
||||
<TabsTrigger
|
||||
value="outline"
|
||||
data-cy={`segmentation-config-display-outline${dataCyTypeSuffix}`}
|
||||
>
|
||||
<Icons.OutlineOnly className="text-primary" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="fill">
|
||||
<TabsTrigger
|
||||
value="fill"
|
||||
data-cy={`segmentation-config-display-fill${dataCyTypeSuffix}`}
|
||||
>
|
||||
<Icons.FillOnly className="text-primary" />
|
||||
</TabsTrigger>
|
||||
</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() {
|
||||
|
||||
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',
|
||||
overlaySEGsAndRTDisplayed: 'overlaySEGsAndRTDisplayed.png',
|
||||
},
|
||||
contourCombineOperations: {
|
||||
subtractBigSphereMinusSmallSphereResult: 'subtractBigSphereMinusSmallSphereResult.png',
|
||||
intersectBigSphereSmallSphereResult: 'intersectBigSphereSmallSphereResult.png',
|
||||
},
|
||||
workList: {
|
||||
scrollBarRenderedProperly: 'scrollBarRenderedProperly.png',
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user