chore(testing): Playwright tests for contour segmentation create, update, delete interactions (#6091)
This commit is contained in:
1 parent
20632f97cf
commit
79cb2356e1
3 files changed
+320
-1
No files matched your search
@@ -0,0 +1,248 @@
|
||||
import { expect, test, visitStudy, visitStudyAndHydrate, waitForViewportsRendered } from './utils';
|
||||
import {
|
||||
expectRowSelected,
|
||||
expectRowNotSelected,
|
||||
expectSegmentationLabels,
|
||||
} from './utils/assertions';
|
||||
|
||||
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
||||
test.describe('Contour Segmentation from an empty panel', () => {
|
||||
test('should add a contour segmentation from the empty panel', async ({
|
||||
rightPanelPageObject,
|
||||
page,
|
||||
}) => {
|
||||
await visitStudy(page, studyInstanceUID, 'segmentation', 2000);
|
||||
await waitForViewportsRendered(page);
|
||||
// Segmentation mode opens on the labelmap tab; switch to the contour tab.
|
||||
await rightPanelPageObject.contourSegmentationPanel.select();
|
||||
|
||||
const { addSegmentationButton, panel, segmentationSelect } =
|
||||
rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
// No contour segmentation exists yet.
|
||||
await expect(panel.rows).toHaveCount(0);
|
||||
await expect(addSegmentationButton.button).toBeVisible();
|
||||
|
||||
await addSegmentationButton.click();
|
||||
|
||||
// The segmentation is added and becomes the active selection.
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 1');
|
||||
await expect(panel.rows).toHaveCount(1);
|
||||
const defaultSegment = panel.nthSegment(0);
|
||||
await expect(defaultSegment.title).toHaveText('Segment 1');
|
||||
await expectRowSelected(defaultSegment);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Contour Segmentation interactions on RTSTRUCT panel', () => {
|
||||
test.beforeEach(async ({ page, leftPanelPageObject, DOMOverlayPageObject }) => {
|
||||
await visitStudyAndHydrate({
|
||||
page,
|
||||
leftPanelPageObject,
|
||||
DOMOverlayPageObject,
|
||||
studyInstanceUID,
|
||||
modality: 'RTSTRUCT',
|
||||
});
|
||||
});
|
||||
|
||||
test('should create a new contour segmentation seeded with a default active segment', async ({
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const { panel, segmentationSelect } = rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
await expect(panel.rows).toHaveCount(4);
|
||||
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 2');
|
||||
await expect(panel.rows).toHaveCount(1);
|
||||
const defaultSegment = panel.nthSegment(0);
|
||||
await expect(defaultSegment.title).toHaveText('Segment 1');
|
||||
await expectRowSelected(defaultSegment);
|
||||
});
|
||||
|
||||
test('should add multiple segments to a newly created contour segmentation', async ({
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const { panel, addSegmentButton } = rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await expect(panel.rows).toHaveCount(1);
|
||||
|
||||
// Each added segment becomes the active one in place of the previous.
|
||||
await addSegmentButton.click();
|
||||
await expect(panel.rows).toHaveCount(2);
|
||||
await expectRowSelected(panel.nthSegment(1));
|
||||
await expectRowNotSelected(panel.nthSegment(0));
|
||||
|
||||
await addSegmentButton.click();
|
||||
await expect(panel.rows).toHaveCount(3);
|
||||
await expectRowSelected(panel.nthSegment(2));
|
||||
await expectRowNotSelected(panel.nthSegment(1));
|
||||
|
||||
await expect(panel.getSegmentLabels()).toHaveText(['Segment 1', 'Segment 2', 'Segment 3']);
|
||||
});
|
||||
|
||||
test('should list every created segmentation in the segmentation selector', async ({
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const { panel, segmentationSelect } = rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
// Only the hydrated RTSTRUCT segmentation exists at first.
|
||||
await expectSegmentationLabels(segmentationSelect, ['Contours on PET']);
|
||||
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
|
||||
// The two newly created segmentations are added to the selector.
|
||||
await expectSegmentationLabels(segmentationSelect, [
|
||||
'Contours on PET',
|
||||
'Segmentation 2',
|
||||
'Segmentation 3',
|
||||
]);
|
||||
});
|
||||
|
||||
test('should switch between segmentations and show the matching segments', async ({
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const { panel, segmentationSelect } = rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
// Create two more segmentations alongside the hydrated RTSTRUCT one, so the
|
||||
// selector lists: [0] Contours on PET, [1] Segmentation 2, [2] Segmentation 3.
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 3');
|
||||
|
||||
// Select out of listed order (active is 2 → 0 → 2 → 1) to prove the active
|
||||
// segmentation follows the selection, not the order the options are listed in.
|
||||
|
||||
// Index 0: the RTSTRUCT segmentation shows its four segments.
|
||||
await segmentationSelect.selectNthSegmentation(0);
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Contours on PET');
|
||||
await expect(panel.rows).toHaveCount(4);
|
||||
await expect(panel.getSegmentLabels()).toHaveText([
|
||||
'Threshold',
|
||||
'Big Sphere',
|
||||
'Small Sphere',
|
||||
'Large Box',
|
||||
]);
|
||||
|
||||
// Jump to the last-created segmentation (index 2), skipping over index 1.
|
||||
await segmentationSelect.selectNthSegmentation(2);
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 3');
|
||||
await expect(panel.rows).toHaveCount(1);
|
||||
await expect(panel.nthSegment(0).title).toHaveText('Segment 1');
|
||||
|
||||
// Back up to the middle segmentation (index 1).
|
||||
await segmentationSelect.selectNthSegmentation(1);
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 2');
|
||||
await expect(panel.rows).toHaveCount(1);
|
||||
await expect(panel.nthSegment(0).title).toHaveText('Segment 1');
|
||||
});
|
||||
|
||||
test('should rename a segmentation and reflect the new name in the selector', async ({
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const { panel, segmentationSelect } = rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 2');
|
||||
|
||||
await panel.moreMenu.rename('Renamed Segmentation');
|
||||
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Renamed Segmentation');
|
||||
await expectSegmentationLabels(segmentationSelect, ['Contours on PET', 'Renamed Segmentation']);
|
||||
});
|
||||
|
||||
test('should not rename a segmentation when the rename dialog is cancelled', async ({
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const { panel, segmentationSelect } = rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 2');
|
||||
|
||||
// Cancelling with an untouched dialog leaves the name unchanged.
|
||||
await panel.moreMenu.cancelRename();
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 2');
|
||||
|
||||
// Cancelling after typing a new name also discards it.
|
||||
await panel.moreMenu.cancelRename('Discarded Name');
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 2');
|
||||
});
|
||||
|
||||
test('should delete a segmentation and remove it from the selector', async ({
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const { panel, segmentationSelect } = rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 2');
|
||||
|
||||
await panel.moreMenu.delete();
|
||||
|
||||
// The remaining RTSTRUCT segmentation becomes active and is the only one left.
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Contours on PET');
|
||||
await expectSegmentationLabels(segmentationSelect, ['Contours on PET']);
|
||||
});
|
||||
|
||||
test('should delete every segmentation until none remain', async ({ rightPanelPageObject }) => {
|
||||
const { panel, addSegmentationButton, segmentationSelect } =
|
||||
rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
// Start with the hydrated RTSTRUCT plus two created segmentations.
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
|
||||
// Delete each of the three segmentations one by one.
|
||||
await panel.moreMenu.delete();
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Contours on PET');
|
||||
await panel.moreMenu.delete();
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 2');
|
||||
await panel.moreMenu.delete();
|
||||
|
||||
// No segmentation remains, so the panel has no segment rows and the
|
||||
// "Add segmentation" entry point is shown again.
|
||||
await expect(panel.rows).toHaveCount(0);
|
||||
await expect(addSegmentationButton.button).toBeVisible();
|
||||
});
|
||||
|
||||
test('should remove a segmentation from the viewport and drop it from the selector', async ({
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const { panel, segmentationSelect } = rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Segmentation 2');
|
||||
|
||||
await panel.moreMenu.removeFromViewport();
|
||||
|
||||
// Removing from the viewport drops it from the selector; the RTSTRUCT one stays active.
|
||||
await expect(segmentationSelect.selectedValue).toHaveText('Contours on PET');
|
||||
await expectSegmentationLabels(segmentationSelect, ['Contours on PET']);
|
||||
});
|
||||
|
||||
// KNOWN BUG: the last remaining segmentation cannot be removed from the viewport
|
||||
// ("Remove from Viewport" is a silent no-op once it is the only one left), so the
|
||||
// panel keeps its segment row instead of clearing. Skipped until the bug is fixed.
|
||||
// Tracked in https://github.com/OHIF/Viewers/issues/6090
|
||||
test.skip('should remove every segmentation from the viewport', async ({
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
const { panel, addSegmentationButton } = rightPanelPageObject.contourSegmentationPanel;
|
||||
|
||||
// Start with the hydrated RTSTRUCT plus two created segmentations.
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
await panel.moreMenu.createNewSegmentation();
|
||||
|
||||
// Remove each segmentation from the viewport one by one.
|
||||
await panel.moreMenu.removeFromViewport();
|
||||
await panel.moreMenu.removeFromViewport();
|
||||
await panel.moreMenu.removeFromViewport();
|
||||
|
||||
// The viewport should have no segmentations left: the selector is empty and the
|
||||
// "Add segmentation" entry point is shown again.
|
||||
await expect(panel.rows).toHaveCount(0);
|
||||
await expect(addSegmentationButton.button).toBeVisible();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user