From 2b5d01fa5ed971fd53ecbdfa30c75d672bb6142a Mon Sep 17 00:00:00 2001 From: diattamo Date: Thu, 7 May 2026 16:52:23 -0400 Subject: [PATCH 01/12] feat(tests): Add tests for duplicating contour segments --- tests/ContourSegmentDuplicate.spec.ts | 104 ++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 tests/ContourSegmentDuplicate.spec.ts diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts new file mode 100644 index 00000000000..ba78729ed84 --- /dev/null +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -0,0 +1,104 @@ +import { + expect, + test, + visitStudy, + getSvgPath, + waitForViewportsRendered, +} from './utils'; + +const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; +const defaultSegment0Name = 'Threshold'; +const defaultSegment1Name = 'Big Sphere'; + +test.beforeEach(async ({ + page, + leftPanelPageObject, + DOMOverlayPageObject, +}) => { + const mode = 'segmentation'; + await visitStudy(page, studyInstanceUID, mode, 2000); + + await leftPanelPageObject.loadSeriesByModality('RTSTRUCT'); + await waitForViewportsRendered(page); + await expect(DOMOverlayPageObject.viewport.segmentationHydration.locator).toBeVisible(); + + await DOMOverlayPageObject.viewport.segmentationHydration.yes.click(); + await expect(page.getByTestId('data-row')).toHaveCount(4); +}); + +test('should duplicate a contour segment and add a new row to the panel', async ({ + page, + rightPanelPageObject, +}) => { + const panel = rightPanelPageObject.contourSegmentationPanel.panel; + + const initialCount = await panel.getSegmentCount(); + expect(initialCount, 'Expected to load with 4 segments').toBe(4); + + const segment0 = panel.nthSegment(0); + await expect(segment0.title).toHaveText(defaultSegment0Name); + + await segment0.actions.duplicate(); + + const countAfterDuplicate = await panel.getSegmentCount(); + expect(countAfterDuplicate, 'Expected one additional segment row after duplicating').toBe(5); + + //New segment's default name is formatted as "Segment {segmentCount}" + const newSegmentTitle = await panel.nthSegment(initialCount).title.textContent(); + expect(newSegmentTitle, 'Expected correct title for duplicated segment').toBe(`Segment 5`); + + // Original segment titles should be unchanged + await expect(panel.nthSegment(0).title).toHaveText(defaultSegment0Name); + await expect(panel.nthSegment(1).title).toHaveText(defaultSegment1Name); +}); + +test('should duplicate the same segment multiple times', async ({ + page, + rightPanelPageObject, +}) => { + const panel = rightPanelPageObject.contourSegmentationPanel.panel; + + const segment0 = panel.nthSegment(0); + + await segment0.actions.duplicate(); + await expect(page.getByTestId('data-row')).toHaveCount(5); + + const firstDuplicateTitle = await panel.nthSegment(4).title.textContent(); + expect(firstDuplicateTitle, 'Expected correct title for first duplicated segment').toBe(`Segment 5`); + + await segment0.actions.duplicate(); + expect(await panel.getSegmentCount(), 'Expected another segment row after duplicating the same segment again').toBe(6); + + const secondDuplicateTitle = await panel.nthSegment(5).title.textContent(); + expect(secondDuplicateTitle, 'Expected correct title for second duplicated segment').toBe(`Segment 6`); +}); + +test('should render the duplicated contour on the viewport', async ({ + rightPanelPageObject, + viewportPageObject, +}) => { + const panel = rightPanelPageObject.contourSegmentationPanel.panel; + + // Hide everything, to be able to grab only the SVG path of the segment to duplicate + await rightPanelPageObject.contourSegmentationPanel.segmentsVisibilityToggle.click(); + const segment0 = panel.nthSegment(0); + await segment0.toggleVisibility(); + await segment0.click(); + + const sourceSvgPath = await getSvgPath(viewportPageObject); + + // New segment is at index 4 + await segment0.actions.duplicate(); + const duplicatedSegment = panel.nthSegment(4); + + // Hide again to show duplicate only + await segment0.toggleVisibility(); + await duplicatedSegment.click(); + + const duplicatedSvgPath = await getSvgPath(viewportPageObject); + + expect( + duplicatedSvgPath, + 'Expected the duplicated segment to have the same SVG path as the source' + ).toBe(sourceSvgPath); +}); From f8cc5a99d6bf78b5ce75a88e646a9e802b336262 Mon Sep 17 00:00:00 2001 From: diattamo Date: Thu, 7 May 2026 18:02:30 -0400 Subject: [PATCH 02/12] Address review comments --- tests/ContourSegmentDuplicate.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index ba78729ed84..bea504a37b8 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -86,6 +86,7 @@ test('should render the duplicated contour on the viewport', async ({ await segment0.click(); const sourceSvgPath = await getSvgPath(viewportPageObject); + expect(sourceSvgPath, 'Expected a visible SVG path for the source segment').not.toBeNull(); // New segment is at index 4 await segment0.actions.duplicate(); @@ -96,6 +97,7 @@ test('should render the duplicated contour on the viewport', async ({ await duplicatedSegment.click(); const duplicatedSvgPath = await getSvgPath(viewportPageObject); + expect(duplicatedSvgPath, 'Expected a visible SVG path for the duplicated segment').not.toBeNull(); expect( duplicatedSvgPath, From 33dbc16c763cdda1c8cbdb481406ae2fe3f8560c Mon Sep 17 00:00:00 2001 From: diattamo Date: Wed, 13 May 2026 14:45:20 -0400 Subject: [PATCH 03/12] Address review comments --- tests/ContourSegmentDuplicate.spec.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index bea504a37b8..f3ba51da519 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -23,7 +23,6 @@ test.beforeEach(async ({ await expect(DOMOverlayPageObject.viewport.segmentationHydration.locator).toBeVisible(); await DOMOverlayPageObject.viewport.segmentationHydration.yes.click(); - await expect(page.getByTestId('data-row')).toHaveCount(4); }); test('should duplicate a contour segment and add a new row to the panel', async ({ @@ -44,8 +43,8 @@ test('should duplicate a contour segment and add a new row to the panel', async expect(countAfterDuplicate, 'Expected one additional segment row after duplicating').toBe(5); //New segment's default name is formatted as "Segment {segmentCount}" - const newSegmentTitle = await panel.nthSegment(initialCount).title.textContent(); - expect(newSegmentTitle, 'Expected correct title for duplicated segment').toBe(`Segment 5`); + const newSegmentLocator = panel.nthSegment(initialCount).title; + expect(newSegmentLocator, 'Expected correct title for duplicated segment').toHaveText(`Segment 5`); // Original segment titles should be unchanged await expect(panel.nthSegment(0).title).toHaveText(defaultSegment0Name); @@ -61,16 +60,16 @@ test('should duplicate the same segment multiple times', async ({ const segment0 = panel.nthSegment(0); await segment0.actions.duplicate(); - await expect(page.getByTestId('data-row')).toHaveCount(5); + expect(await panel.getSegmentCount(), 'Expected one additional segment row after duplicating').toBe(5); - const firstDuplicateTitle = await panel.nthSegment(4).title.textContent(); - expect(firstDuplicateTitle, 'Expected correct title for first duplicated segment').toBe(`Segment 5`); + const firstDuplicateTitleLocator = panel.nthSegment(4).title; + expect(firstDuplicateTitleLocator, 'Expected correct title for first duplicated segment').toHaveText(`Segment 5`); await segment0.actions.duplicate(); expect(await panel.getSegmentCount(), 'Expected another segment row after duplicating the same segment again').toBe(6); - const secondDuplicateTitle = await panel.nthSegment(5).title.textContent(); - expect(secondDuplicateTitle, 'Expected correct title for second duplicated segment').toBe(`Segment 6`); + const secondDuplicateTitleLocator = panel.nthSegment(5).title; + expect(secondDuplicateTitleLocator, 'Expected correct title for second duplicated segment').toHaveText(`Segment 6`); }); test('should render the duplicated contour on the viewport', async ({ From 7e657382d26d18f016d11a0ed91a32dfe855ce91 Mon Sep 17 00:00:00 2001 From: diattamo Date: Wed, 13 May 2026 16:14:46 -0400 Subject: [PATCH 04/12] Address minor comment --- tests/ContourSegmentDuplicate.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index f3ba51da519..fae9e86e745 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -44,7 +44,7 @@ test('should duplicate a contour segment and add a new row to the panel', async //New segment's default name is formatted as "Segment {segmentCount}" const newSegmentLocator = panel.nthSegment(initialCount).title; - expect(newSegmentLocator, 'Expected correct title for duplicated segment').toHaveText(`Segment 5`); + await expect(newSegmentLocator, 'Expected correct title for duplicated segment').toHaveText(`Segment 5`); // Original segment titles should be unchanged await expect(panel.nthSegment(0).title).toHaveText(defaultSegment0Name); @@ -63,13 +63,13 @@ test('should duplicate the same segment multiple times', async ({ expect(await panel.getSegmentCount(), 'Expected one additional segment row after duplicating').toBe(5); const firstDuplicateTitleLocator = panel.nthSegment(4).title; - expect(firstDuplicateTitleLocator, 'Expected correct title for first duplicated segment').toHaveText(`Segment 5`); + await expect(firstDuplicateTitleLocator, 'Expected correct title for first duplicated segment').toHaveText(`Segment 5`); await segment0.actions.duplicate(); expect(await panel.getSegmentCount(), 'Expected another segment row after duplicating the same segment again').toBe(6); const secondDuplicateTitleLocator = panel.nthSegment(5).title; - expect(secondDuplicateTitleLocator, 'Expected correct title for second duplicated segment').toHaveText(`Segment 6`); + await expect(secondDuplicateTitleLocator, 'Expected correct title for second duplicated segment').toHaveText(`Segment 6`); }); test('should render the duplicated contour on the viewport', async ({ From 058898796a8affc2f0d3a0d47c0f9d67c3fb99b9 Mon Sep 17 00:00:00 2001 From: diattamo Date: Fri, 15 May 2026 16:40:52 -0400 Subject: [PATCH 05/12] remove 'd' from the SVG Inner elements --- tests/pages/ViewportPageObject.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pages/ViewportPageObject.ts b/tests/pages/ViewportPageObject.ts index 4e6e67e2394..d9a10e169b8 100644 --- a/tests/pages/ViewportPageObject.ts +++ b/tests/pages/ViewportPageObject.ts @@ -10,7 +10,7 @@ import { DataOverlayPageObject } from './DataOverlayPageObject'; import { DOMOverlayPageObject } from './DOMOverlayPageObject'; import { MagnifyGlassPageObject } from './MagnifyGlassPageObject'; -type SvgInnerElement = 'circle' | 'path' | 'd' | 'line'; +type SvgInnerElement = 'circle' | 'path' | 'line'; type NormalizedDragParams = { start: { x: number; y: number }; From 49d43c19e11cf8b5e6fdd7b85d1378ac4113870b Mon Sep 17 00:00:00 2001 From: diattamo Date: Sat, 16 May 2026 12:45:03 -0400 Subject: [PATCH 06/12] Refactor the getSVGPath to getSVGPAthAttribute - Update other tests to reflect change --- tests/ContourSegNavigation.spec.ts | 36 ++++++++++---------- tests/ContourSegmentDuplicate.spec.ts | 8 +++-- tests/ContourSegmentToggleVisibility.spec.ts | 6 ++-- tests/pages/ViewportPageObject.ts | 2 +- tests/utils/getSvgAttribute.ts | 17 +++++++++ tests/utils/getSvgPath.ts | 7 ---- tests/utils/index.ts | 4 +-- 7 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 tests/utils/getSvgAttribute.ts delete mode 100644 tests/utils/getSvgPath.ts diff --git a/tests/ContourSegNavigation.spec.ts b/tests/ContourSegNavigation.spec.ts index 3eef690a4b7..10b9263c05f 100644 --- a/tests/ContourSegNavigation.spec.ts +++ b/tests/ContourSegNavigation.spec.ts @@ -1,4 +1,4 @@ -import { expect, test, visitStudy, getSvgPath, navigateWithViewportArrow } from './utils'; +import { expect, test, visitStudy, getSvgAttribute, navigateWithViewportArrow } from './utils'; import { expectRowSelected } from './utils/assertions'; const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; @@ -26,42 +26,42 @@ test('should navigate the contours when clicking each segments in the right pane const getSegment = (index: number) => rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(index); - const seg0 = await getSvgPath(viewportPageObject); + const seg0 = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect(seg0, 'Segment at index 0: expected a non-null SVG path').not.toBeNull(); await getSegment(3).click(); - const seg3 = await getSvgPath(viewportPageObject); + const seg3 = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const seg2 = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const seg1 = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const seg2Again = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const seg1Again = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const seg0Again = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const seg3Again = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect(seg3Again, 'Segment 3 again: expected to match the original segment 3 path').toBe(seg3); await expectRowSelected(getSegment(3)); }); @@ -73,29 +73,29 @@ test('should navigate the segmentations using the Viewport arrow buttons', async const getSegment = (index: number) => rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(index); - const initialSvgPath = await getSvgPath(viewportPageObject); + const initialSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const secondSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const thirdSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const fourthSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const svgPathWraparoundWithNext = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect( svgPathWraparoundWithNext, 'Expected svg path to match the initial svg path after wrapping around with next navigation' @@ -104,7 +104,7 @@ test('should navigate the segmentations using the Viewport arrow buttons', async // Wraparound test — prev from first should return to last segment await navigateWithViewportArrow(viewportPageObject, 'prev'); - const svgPathWraparoundWithPrev = await getSvgPath(viewportPageObject); + const svgPathWraparoundWithPrev = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect( svgPathWraparoundWithPrev, 'Expected svg path to match the fourth svg path after wrapping around with prev navigation' @@ -112,17 +112,17 @@ test('should navigate the segmentations using the Viewport arrow buttons', async await expectRowSelected(getSegment(3)); await navigateWithViewportArrow(viewportPageObject, 'prev'); - const backToThirdSvgPath = await getSvgPath(viewportPageObject); + const backToThirdSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const backToSecondSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); 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); + const backToFirstSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect(backToFirstSvgPath, 'Expected path to match first segment after going prev from second').toBe(initialSvgPath); await expectRowSelected(getSegment(0)); }); diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index fae9e86e745..52dca1ee9e8 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -2,9 +2,9 @@ import { expect, test, visitStudy, - getSvgPath, waitForViewportsRendered, } from './utils'; +import { getSvgAttribute } from './utils/getSvgAttribute'; const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; const defaultSegment0Name = 'Threshold'; @@ -84,7 +84,7 @@ test('should render the duplicated contour on the viewport', async ({ await segment0.toggleVisibility(); await segment0.click(); - const sourceSvgPath = await getSvgPath(viewportPageObject); + const sourceSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect(sourceSvgPath, 'Expected a visible SVG path for the source segment').not.toBeNull(); // New segment is at index 4 @@ -95,8 +95,10 @@ test('should render the duplicated contour on the viewport', async ({ await segment0.toggleVisibility(); await duplicatedSegment.click(); - const duplicatedSvgPath = await getSvgPath(viewportPageObject); + const duplicatedSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect(duplicatedSvgPath, 'Expected a visible SVG path for the duplicated segment').not.toBeNull(); + const duplicatedSvgPathsCount = await (await viewportPageObject.getById('default')).svg('path').count(); + expect(duplicatedSvgPathsCount, 'Expected only one SVG path element for the duplicated segment').toBe(1); expect( duplicatedSvgPath, diff --git a/tests/ContourSegmentToggleVisibility.spec.ts b/tests/ContourSegmentToggleVisibility.spec.ts index a4c6a65d9b4..92429a06b17 100644 --- a/tests/ContourSegmentToggleVisibility.spec.ts +++ b/tests/ContourSegmentToggleVisibility.spec.ts @@ -1,4 +1,4 @@ -import { expect, test, visitStudy, getSvgPath, navigateWithViewportArrow } from './utils'; +import { expect, test, visitStudy, getSvgAttribute, navigateWithViewportArrow } from './utils'; const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; @@ -78,7 +78,7 @@ test('should restore svg paths when segment visibility is toggled on/off', async const segment0 = rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(0); await segment0.toggleVisibility(); - const svgPathBefore = await getSvgPath(viewportPageObject); + const svgPathBefore = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect(svgPathBefore, 'Expected a visible SVG path for segment 0').not.toBeNull(); await segment0.toggleVisibility(); @@ -88,7 +88,7 @@ test('should restore svg paths when segment visibility is toggled on/off', async ).toHaveCount(0); await segment0.toggleVisibility(); - const svgPathAfter = await getSvgPath(viewportPageObject); + const svgPathAfter = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect(svgPathAfter, 'Expected SVG path to be restored after toggling visibility back on').toBe( svgPathBefore ); diff --git a/tests/pages/ViewportPageObject.ts b/tests/pages/ViewportPageObject.ts index d9a10e169b8..019a1308c3c 100644 --- a/tests/pages/ViewportPageObject.ts +++ b/tests/pages/ViewportPageObject.ts @@ -10,7 +10,7 @@ import { DataOverlayPageObject } from './DataOverlayPageObject'; import { DOMOverlayPageObject } from './DOMOverlayPageObject'; import { MagnifyGlassPageObject } from './MagnifyGlassPageObject'; -type SvgInnerElement = 'circle' | 'path' | 'line'; +export type SvgInnerElement = 'circle' | 'path' | 'line'; type NormalizedDragParams = { start: { x: number; y: number }; diff --git a/tests/utils/getSvgAttribute.ts b/tests/utils/getSvgAttribute.ts new file mode 100644 index 00000000000..99901dbe046 --- /dev/null +++ b/tests/utils/getSvgAttribute.ts @@ -0,0 +1,17 @@ +import { SvgInnerElement, ViewportPageObject } from '../pages/ViewportPageObject'; + +const getSvgAttribute = async ( + viewportPageObject: ViewportPageObject, + svgInnerElement: SvgInnerElement, + attributeName: string, + viewportId = 'default', + nth: number = 0 +) => { + return (await viewportPageObject.getById(viewportId)) + .svg(svgInnerElement) + .nth(nth) + .getAttribute(attributeName); +}; + + +export { getSvgAttribute }; diff --git a/tests/utils/getSvgPath.ts b/tests/utils/getSvgPath.ts deleted file mode 100644 index 1fb6359e35f..00000000000 --- a/tests/utils/getSvgPath.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ViewportPageObject } from '../pages/ViewportPageObject'; - -const getSvgPath = async (viewportPageObject: ViewportPageObject, viewportId = 'default') => { - return (await viewportPageObject.getById(viewportId)).svg('path').first().getAttribute('d'); -}; - -export { getSvgPath }; diff --git a/tests/utils/index.ts b/tests/utils/index.ts index fe37bcb3243..75bf7d344ef 100644 --- a/tests/utils/index.ts +++ b/tests/utils/index.ts @@ -20,7 +20,7 @@ import { clearAllAnnotations } from './clearAllAnnotations'; import { scrollVolumeViewport } from './scrollVolumeViewport'; import { attemptAction } from './attemptAction'; import { addLengthMeasurement } from './addLengthMeasurement'; -import { getSvgPath } from './getSvgPath'; +import { getSvgAttribute } from './getSvgAttribute'; import { navigateWithViewportArrow } from './navigateWithViewportArrow'; import { test, expect } from './fixture'; import { subscribeToMeasurementAdded } from './subscribeToMeasurement'; @@ -51,7 +51,7 @@ export { attemptAction, addLengthMeasurement, subscribeToMeasurementAdded, - getSvgPath, + getSvgAttribute, navigateWithViewportArrow, waitForAnyViewportNeedsRender, waitForViewportsRendered, From 197b32cadacf6704149a3940eb8e6a2525f5d571 Mon Sep 17 00:00:00 2001 From: diattamo Date: Sat, 16 May 2026 13:07:14 -0400 Subject: [PATCH 07/12] Add validation for SVG path count for the contour segment before duplication --- tests/ContourSegmentDuplicate.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index 52dca1ee9e8..98812fc52c0 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -86,6 +86,8 @@ test('should render the duplicated contour on the viewport', async ({ const sourceSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); expect(sourceSvgPath, 'Expected a visible SVG path for the source segment').not.toBeNull(); + const sourceSvgPathsCount = await (await viewportPageObject.getById('default')).svg('path').count(); + expect(sourceSvgPathsCount, 'Expected only one SVG path element for the original segment').toBe(1); // New segment is at index 4 await segment0.actions.duplicate(); From 710a50aa658f7b6478e43c6a532937df58155e96 Mon Sep 17 00:00:00 2001 From: diattamo Date: Wed, 20 May 2026 11:56:27 -0400 Subject: [PATCH 08/12] Address code review comments - refactor to update getSVGAtrribute calls --- tests/ContourSegNavigation.spec.ts | 102 +++++++++++++++---- tests/ContourSegmentDuplicate.spec.ts | 14 +-- tests/ContourSegmentToggleVisibility.spec.ts | 12 ++- tests/utils/getSvgAttribute.ts | 18 ++-- 4 files changed, 114 insertions(+), 32 deletions(-) diff --git a/tests/ContourSegNavigation.spec.ts b/tests/ContourSegNavigation.spec.ts index 10b9263c05f..18242e4aa16 100644 --- a/tests/ContourSegNavigation.spec.ts +++ b/tests/ContourSegNavigation.spec.ts @@ -26,42 +26,74 @@ test('should navigate the contours when clicking each segments in the right pane const getSegment = (index: number) => rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(index); - const seg0 = await getSvgAttribute(viewportPageObject, 'path', 'd'); + const seg0 = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); expect(seg0, 'Segment at index 0: expected a non-null SVG path').not.toBeNull(); await getSegment(3).click(); - const seg3 = await getSvgAttribute(viewportPageObject, 'path', 'd'); + const seg3 = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const seg2 = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const seg1 = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const seg2Again = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const seg1Again = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const seg0Again = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const seg3Again = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); expect(seg3Again, 'Segment 3 again: expected to match the original segment 3 path').toBe(seg3); await expectRowSelected(getSegment(3)); }); @@ -73,29 +105,49 @@ test('should navigate the segmentations using the Viewport arrow buttons', async const getSegment = (index: number) => rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(index); - const initialSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); + const initialSvgPath = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const secondSvgPath = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const thirdSvgPath = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const fourthSvgPath = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const svgPathWraparoundWithNext = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); expect( svgPathWraparoundWithNext, 'Expected svg path to match the initial svg path after wrapping around with next navigation' @@ -104,7 +156,11 @@ test('should navigate the segmentations using the Viewport arrow buttons', async // Wraparound test — prev from first should return to last segment await navigateWithViewportArrow(viewportPageObject, 'prev'); - const svgPathWraparoundWithPrev = await getSvgAttribute(viewportPageObject, 'path', 'd'); + const svgPathWraparoundWithPrev = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); expect( svgPathWraparoundWithPrev, 'Expected svg path to match the fourth svg path after wrapping around with prev navigation' @@ -112,17 +168,29 @@ test('should navigate the segmentations using the Viewport arrow buttons', async await expectRowSelected(getSegment(3)); await navigateWithViewportArrow(viewportPageObject, 'prev'); - const backToThirdSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); + const backToThirdSvgPath = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const backToSecondSvgPath = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); 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 getSvgAttribute(viewportPageObject, 'path', 'd'); + const backToFirstSvgPath = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); expect(backToFirstSvgPath, 'Expected path to match first segment after going prev from second').toBe(initialSvgPath); await expectRowSelected(getSegment(0)); }); diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index 98812fc52c0..efd34861ab5 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -40,7 +40,7 @@ test('should duplicate a contour segment and add a new row to the panel', async await segment0.actions.duplicate(); const countAfterDuplicate = await panel.getSegmentCount(); - expect(countAfterDuplicate, 'Expected one additional segment row after duplicating').toBe(5); + expect(countAfterDuplicate, 'Expected one additional segment row after duplicating').(5); //New segment's default name is formatted as "Segment {segmentCount}" const newSegmentLocator = panel.nthSegment(initialCount).title; @@ -84,10 +84,10 @@ test('should render the duplicated contour on the viewport', async ({ await segment0.toggleVisibility(); await segment0.click(); - const sourceSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); + const sourceSvgPath = await getSvgAttribute({viewportPageObject, svgInnerElement: 'path', attributeName: 'd'}); expect(sourceSvgPath, 'Expected a visible SVG path for the source segment').not.toBeNull(); - const sourceSvgPathsCount = await (await viewportPageObject.getById('default')).svg('path').count(); - expect(sourceSvgPathsCount, 'Expected only one SVG path element for the original segment').toBe(1); + const sourceSvgPaths = (await viewportPageObject.getById('default')).svg('path'); + expect(sourceSvgPaths, 'Expected only one SVG path element for the original segment').toHaveCount(1); // New segment is at index 4 await segment0.actions.duplicate(); @@ -97,10 +97,10 @@ test('should render the duplicated contour on the viewport', async ({ await segment0.toggleVisibility(); await duplicatedSegment.click(); - const duplicatedSvgPath = await getSvgAttribute(viewportPageObject, 'path', 'd'); + const duplicatedSvgPath = await getSvgAttribute({viewportPageObject, svgInnerElement: 'path', attributeName: 'd'}); expect(duplicatedSvgPath, 'Expected a visible SVG path for the duplicated segment').not.toBeNull(); - const duplicatedSvgPathsCount = await (await viewportPageObject.getById('default')).svg('path').count(); - expect(duplicatedSvgPathsCount, 'Expected only one SVG path element for the duplicated segment').toBe(1); + const duplicatedSvgPaths = (await viewportPageObject.getById('default')).svg('path'); + expect(duplicatedSvgPaths, 'Expected only one SVG path element for the duplicated segment').toHaveCount(1); expect( duplicatedSvgPath, diff --git a/tests/ContourSegmentToggleVisibility.spec.ts b/tests/ContourSegmentToggleVisibility.spec.ts index 92429a06b17..722faf13b97 100644 --- a/tests/ContourSegmentToggleVisibility.spec.ts +++ b/tests/ContourSegmentToggleVisibility.spec.ts @@ -78,7 +78,11 @@ test('should restore svg paths when segment visibility is toggled on/off', async const segment0 = rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(0); await segment0.toggleVisibility(); - const svgPathBefore = await getSvgAttribute(viewportPageObject, 'path', 'd'); + const svgPathBefore = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); expect(svgPathBefore, 'Expected a visible SVG path for segment 0').not.toBeNull(); await segment0.toggleVisibility(); @@ -88,7 +92,11 @@ test('should restore svg paths when segment visibility is toggled on/off', async ).toHaveCount(0); await segment0.toggleVisibility(); - const svgPathAfter = await getSvgAttribute(viewportPageObject, 'path', 'd'); + const svgPathAfter = await getSvgAttribute({ + viewportPageObject, + svgInnerElement: 'path', + attributeName: 'd', + }); expect(svgPathAfter, 'Expected SVG path to be restored after toggling visibility back on').toBe( svgPathBefore ); diff --git a/tests/utils/getSvgAttribute.ts b/tests/utils/getSvgAttribute.ts index 99901dbe046..66a24bc536f 100644 --- a/tests/utils/getSvgAttribute.ts +++ b/tests/utils/getSvgAttribute.ts @@ -1,12 +1,18 @@ import { SvgInnerElement, ViewportPageObject } from '../pages/ViewportPageObject'; -const getSvgAttribute = async ( - viewportPageObject: ViewportPageObject, - svgInnerElement: SvgInnerElement, - attributeName: string, +const getSvgAttribute = async ({ + viewportPageObject, + svgInnerElement, + attributeName, viewportId = 'default', - nth: number = 0 -) => { + nth = 0, +}: { + viewportPageObject: ViewportPageObject; + svgInnerElement: SvgInnerElement; + attributeName: string; + viewportId?: string; + nth?: number; +}) => { return (await viewportPageObject.getById(viewportId)) .svg(svgInnerElement) .nth(nth) From 0511bf84754e6e302def56b47dd379b20876d133 Mon Sep 17 00:00:00 2001 From: diattamo Date: Wed, 20 May 2026 12:14:35 -0400 Subject: [PATCH 09/12] fix accidental deletion --- tests/ContourSegmentDuplicate.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index efd34861ab5..27bd80e84fe 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -40,7 +40,7 @@ test('should duplicate a contour segment and add a new row to the panel', async await segment0.actions.duplicate(); const countAfterDuplicate = await panel.getSegmentCount(); - expect(countAfterDuplicate, 'Expected one additional segment row after duplicating').(5); + expect(countAfterDuplicate, 'Expected one additional segment row after duplicating').toBe(5); //New segment's default name is formatted as "Segment {segmentCount}" const newSegmentLocator = panel.nthSegment(initialCount).title; From 97e2b8e97163deefdec07e93d760658bc02cd3e6 Mon Sep 17 00:00:00 2001 From: diattamo Date: Wed, 20 May 2026 13:31:43 -0400 Subject: [PATCH 10/12] test: add navigation verification for duplicated contour segments --- tests/ContourSegmentDuplicate.spec.ts | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index 27bd80e84fe..dd330d3f056 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -107,3 +107,54 @@ test('should render the duplicated contour on the viewport', async ({ 'Expected the duplicated segment to have the same SVG path as the source' ).toBe(sourceSvgPath); }); + + +test.skip('should navigate to the correct instance number when a duplicated contour segment is selected', async ({ + rightPanelPageObject, + viewportPageObject, +}) => { + const panel = rightPanelPageObject.contourSegmentationPanel.panel; + + // get instance overlay of the contour segment at index 0 + const originalSegment = panel.nthSegment(0); + await originalSegment.click(); + const originalSegmentInstanceInfo = (await viewportPageObject.getById('default')).overlayText.bottomRight.instanceNumber; + expect(originalSegmentInstanceInfo, 'Expected instance information to be displayed in the viewport overlay').not.toBeNull(); + await expect(originalSegmentInstanceInfo, 'Expected instance information to be 46 for the Threshhold segment').toHaveText('I:46 (46/47)'); + + // Duplicate segment so new segment is at index 4 + await originalSegment.actions.duplicate(); + + //click another segment to ensure instance number changes accordingly + await panel.nthSegment(2).click(); + const anotherSegmentInstanceInfo = (await viewportPageObject.getById('default')).overlayText.bottomRight.instanceNumber; + expect(anotherSegmentInstanceInfo, 'Expected instance information to be displayed in the viewport overlay').not.toBeNull(); + await expect(anotherSegmentInstanceInfo, 'Expected instance information to be different from original contour').not.toHaveText('I:46 (46/47)'); + + //click duplicated segment to ensure instance number is consistent with original segment + const duplicatedSegment = panel.nthSegment(4); + await duplicatedSegment.click(); + const duplicatedSegmentInstanceInfoAfter = (await viewportPageObject.getById('default')).overlayText.bottomRight.instanceNumber; + expect(duplicatedSegmentInstanceInfoAfter, 'Expected instance information to be displayed in the viewport overlay').not.toBeNull(); + await expect(duplicatedSegmentInstanceInfoAfter, 'Expected instance information to be same as original contour after clicking duplicated segment').toHaveText('I:46 (46/47)'); + + //verify the svg paths are the same for the original and duplicated segments + await rightPanelPageObject.contourSegmentationPanel.segmentsVisibilityToggle.click(); + await originalSegment.toggleVisibility(); + await originalSegment.click(); + const originalSegmentSvgPath = await getSvgAttribute({viewportPageObject, svgInnerElement: 'path', attributeName: 'd'}); + expect(originalSegmentSvgPath, 'Expected a visible SVG path for the original segment').not.toBeNull(); + + // hide original segment to show duplicate only + await originalSegment.toggleVisibility(); + + await duplicatedSegment.toggleVisibility(); + await duplicatedSegment.click(); + const duplicatedSegmentSvgPath = await getSvgAttribute({viewportPageObject, svgInnerElement: 'path', attributeName: 'd'}); + expect(duplicatedSegmentSvgPath, 'Expected a visible SVG path for the duplicated segment').not.toBeNull(); + + expect( + duplicatedSegmentSvgPath, + 'Expected the duplicated segment to have the same SVG path as the original segment' + ).toBe(originalSegmentSvgPath); +} ); From f3fb3181176ef68a9c5b9c07d1c79edad59a9b02 Mon Sep 17 00:00:00 2001 From: diattamo Date: Thu, 21 May 2026 14:17:51 -0400 Subject: [PATCH 11/12] Correct spelling of 'Threshold' --- tests/ContourSegmentDuplicate.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index fd880cdace4..17f916d79d3 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -119,7 +119,7 @@ test.skip('should navigate to the correct instance number when a duplicated cont await originalSegment.click(); const originalSegmentInstanceInfo = (await viewportPageObject.getById('default')).overlayText.bottomRight.instanceNumber; expect(originalSegmentInstanceInfo, 'Expected instance information to be displayed in the viewport overlay').not.toBeNull(); - await expect(originalSegmentInstanceInfo, 'Expected instance information to be slice 46 for the Threshhold segment').toHaveText('I:46 (46/47)'); + await expect(originalSegmentInstanceInfo, 'Expected instance information to be slice 46 for the Threshold segment').toHaveText('I:46 (46/47)'); // Duplicate segment so new segment is at index 4 await originalSegment.actions.duplicate(); From 4bee07f807fcc89b44135083cb9d721284437aaf Mon Sep 17 00:00:00 2001 From: diattamo Date: Thu, 21 May 2026 14:25:22 -0400 Subject: [PATCH 12/12] code review updates --- tests/ContourSegmentDuplicate.spec.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/ContourSegmentDuplicate.spec.ts b/tests/ContourSegmentDuplicate.spec.ts index 17f916d79d3..184a9f7f429 100644 --- a/tests/ContourSegmentDuplicate.spec.ts +++ b/tests/ContourSegmentDuplicate.spec.ts @@ -26,7 +26,6 @@ test.beforeEach(async ({ }); test('should duplicate a contour segment and add a new row to the panel', async ({ - page, rightPanelPageObject, }) => { const panel = rightPanelPageObject.contourSegmentationPanel.panel; @@ -52,7 +51,6 @@ test('should duplicate a contour segment and add a new row to the panel', async }); test('should duplicate the same segment multiple times', async ({ - page, rightPanelPageObject, }) => { const panel = rightPanelPageObject.contourSegmentationPanel.panel; @@ -118,7 +116,7 @@ test.skip('should navigate to the correct instance number when a duplicated cont const originalSegment = panel.nthSegment(0); await originalSegment.click(); const originalSegmentInstanceInfo = (await viewportPageObject.getById('default')).overlayText.bottomRight.instanceNumber; - expect(originalSegmentInstanceInfo, 'Expected instance information to be displayed in the viewport overlay').not.toBeNull(); + expect(originalSegmentInstanceInfo, 'Expected instance information to be displayed in the viewport overlay').toBeVisible(); await expect(originalSegmentInstanceInfo, 'Expected instance information to be slice 46 for the Threshold segment').toHaveText('I:46 (46/47)'); // Duplicate segment so new segment is at index 4 @@ -127,14 +125,14 @@ test.skip('should navigate to the correct instance number when a duplicated cont //click another segment to ensure instance number changes accordingly await panel.nthSegment(2).click(); const anotherSegmentInstanceInfo = (await viewportPageObject.getById('default')).overlayText.bottomRight.instanceNumber; - expect(anotherSegmentInstanceInfo, 'Expected instance information to be displayed in the viewport overlay').not.toBeNull(); + expect(anotherSegmentInstanceInfo, 'Expected instance information to be displayed in the viewport overlay').toBeVisible(); await expect(anotherSegmentInstanceInfo, 'Expected instance information to be different from original contour').not.toHaveText('I:46 (46/47)'); //click duplicated segment to ensure instance number is consistent with original segment const duplicatedSegment = panel.nthSegment(4); await duplicatedSegment.click(); const duplicatedSegmentInstanceInfoAfter = (await viewportPageObject.getById('default')).overlayText.bottomRight.instanceNumber; - expect(duplicatedSegmentInstanceInfoAfter, 'Expected instance information to be displayed in the viewport overlay').not.toBeNull(); + expect(duplicatedSegmentInstanceInfoAfter, 'Expected instance information to be displayed in the viewport overlay').toBeVisible(); await expect(duplicatedSegmentInstanceInfoAfter, 'Expected instance information to be same as original contour after clicking duplicated segment').toHaveText('I:46 (46/47)'); //verify the svg paths are the same for the original and duplicated segments