From bdad2264ed6ee56802f887ab707711ab8987051e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Alves=20de=20Faria=20Resende?= Date: Thu, 20 Nov 2025 11:29:14 -0300 Subject: [PATCH] tests(Playwright): Introduction of Page Object Models (POMs) to Playwright tests (#5557) --- platform/app/src/components/ViewportGrid.tsx | 1 + tests/3DFourUp.spec.ts | 19 +- tests/3DMain.spec.ts | 19 +- tests/3DOnly.spec.ts | 19 +- tests/3DPrimary.spec.ts | 19 +- tests/Angle.spec.ts | 35 +-- tests/ArrowAnnotate.spec.ts | 44 +-- tests/AxialPrimary.spec.ts | 12 +- tests/Bidirectional.spec.ts | 31 +- tests/Circle.spec.ts | 30 +- tests/CobbAngle.spec.ts | 40 +-- tests/ContextMenu.spec.ts | 41 +-- tests/ContourSegLocking.spec.ts | 23 +- tests/Crosshairs.spec.ts | 50 +-- tests/DataOverlayMenu.spec.ts | 20 +- tests/DicomTagBrowser.spec.ts | 16 +- tests/Ellipse.spec.ts | 30 +- tests/FlipHorizontal.spec.ts | 8 +- tests/Invert.spec.ts | 8 +- tests/JumpToMeasurementMPR.spec.ts | 34 +-- tests/LabelMapSegLocking.spec.ts | 25 +- tests/Length.spec.ts | 29 +- tests/Livewire.spec.ts | 50 +-- tests/MPR.spec.ts | 8 +- tests/MPRThenRTOverlayNoHydration.spec.ts | 15 +- tests/MPRThenSEGOverlayNoHydration.spec.ts | 15 +- tests/MeasurementPanel.spec.ts | 10 +- .../MultipleSegmentationDataOverlays.spec.ts | 22 +- tests/Probe.spec.ts | 23 +- ...rUnreferencedDisplaySetNoHydration.spec.ts | 8 +- tests/RTDataOverlayNoHydrationThenMPR.spec.ts | 12 +- tests/RTHydrationFromMPR.spec.ts | 11 +- tests/RTHydrationThenMPR.spec.ts | 8 +- tests/RTNoHydrationThenMPR.spec.ts | 8 +- tests/Rectangle.spec.ts | 30 +- tests/Reset.spec.ts | 14 +- tests/RotateRight.spec.ts | 8 +- ...rUnreferencedDisplaySetNoHydration.spec.ts | 8 +- .../SEGDataOverlayNoHydrationThenMPR.spec.ts | 12 +- tests/SEGDrawingToolsResizing.spec.ts | 39 +-- tests/SEGHydrationFrom3DFourUp.spec.ts | 18 +- tests/SEGHydrationFromMPR.spec.ts | 11 +- tests/SEGHydrationThenMPR.spec.ts | 8 +- tests/SEGNoHydrationThenMPR.spec.ts | 8 +- tests/Scoord3dProbe.spec.ts | 74 +++-- tests/ScoordRectangle.spec.ts | 74 +++-- tests/SegmentationPanel.spec.ts | 11 +- tests/Spline.spec.ts | 50 +-- tests/TMTVAlignment.spec.ts | 65 ++-- tests/TMTVCSVReport.spec.ts | 14 +- tests/TMTVModalityUnit.spec.ts | 33 +- tests/TMTVRecalculate.spec.ts | 30 +- tests/TMTVSUV.spec.ts | 12 +- tests/pages/MainToolbarPageObject.ts | 287 ++++++++++++++++++ tests/pages/ViewportPageObject.ts | 189 ++++++++++++ tests/pages/index.ts | 4 + tests/utils/fixture.ts | 18 ++ tests/utils/index.ts | 5 + tests/utils/locators.ts | 31 -- 59 files changed, 1040 insertions(+), 756 deletions(-) create mode 100644 tests/pages/MainToolbarPageObject.ts create mode 100644 tests/pages/ViewportPageObject.ts create mode 100644 tests/pages/index.ts create mode 100644 tests/utils/fixture.ts delete mode 100644 tests/utils/locators.ts diff --git a/platform/app/src/components/ViewportGrid.tsx b/platform/app/src/components/ViewportGrid.tsx index 1bf35281b..9c0d326a4 100644 --- a/platform/app/src/components/ViewportGrid.tsx +++ b/platform/app/src/components/ViewportGrid.tsx @@ -273,6 +273,7 @@ function ViewerViewportGrid(props: withAppTypes) { >
{ @@ -14,13 +14,8 @@ test.beforeEach(async ({ page }) => { }); test.describe('3D four up Test', async () => { - test('should render 3D four up correctly.', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page - .locator('div') - .filter({ hasText: /^3D four up$/ }) - .first() - .click(); + test('should render 3D four up correctly.', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.layoutSelection.threeDFourUp.click(); await attemptAction(() => reduce3DViewportSize(page), 10, 100); diff --git a/tests/3DMain.spec.ts b/tests/3DMain.spec.ts index dad949c02..b0832a6ef 100644 --- a/tests/3DMain.spec.ts +++ b/tests/3DMain.spec.ts @@ -1,10 +1,10 @@ -import { test } from 'playwright-test-coverage'; import { - visitStudy, - checkForScreenshot, - screenShotPaths, - reduce3DViewportSize, attemptAction, + checkForScreenshot, + reduce3DViewportSize, + screenShotPaths, + test, + visitStudy, } from './utils'; test.beforeEach(async ({ page }) => { @@ -14,13 +14,8 @@ test.beforeEach(async ({ page }) => { }); test.describe('3D main Test', async () => { - test('should render 3D main correctly.', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page - .locator('div') - .filter({ hasText: /^3D main$/ }) - .first() - .click(); + test('should render 3D main correctly.', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.layoutSelection.threeDMain.click(); await attemptAction(() => reduce3DViewportSize(page), 10, 100); await page.waitForTimeout(5000); await checkForScreenshot(page, page, screenShotPaths.threeDMain.threeDMainDisplayedCorrectly); diff --git a/tests/3DOnly.spec.ts b/tests/3DOnly.spec.ts index 472349383..feb3551fd 100644 --- a/tests/3DOnly.spec.ts +++ b/tests/3DOnly.spec.ts @@ -1,10 +1,10 @@ -import { test } from 'playwright-test-coverage'; import { - visitStudy, - checkForScreenshot, - screenShotPaths, - reduce3DViewportSize, attemptAction, + checkForScreenshot, + reduce3DViewportSize, + screenShotPaths, + test, + visitStudy, } from './utils'; test.beforeEach(async ({ page }) => { @@ -14,13 +14,8 @@ test.beforeEach(async ({ page }) => { }); test.describe('3D only Test', async () => { - test('should render 3D only correctly.', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page - .locator('div') - .filter({ hasText: /^3D only$/ }) - .first() - .click(); + test('should render 3D only correctly.', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.layoutSelection.threeDOnly.click(); await attemptAction(() => reduce3DViewportSize(page), 10, 100); await page.waitForTimeout(5000); // Use a 4 percent diff pixel ratio to account for slight color differences in the 3D viewport diff --git a/tests/3DPrimary.spec.ts b/tests/3DPrimary.spec.ts index 59c791b35..79ca0a150 100644 --- a/tests/3DPrimary.spec.ts +++ b/tests/3DPrimary.spec.ts @@ -1,10 +1,10 @@ -import { test } from 'playwright-test-coverage'; import { - visitStudy, - checkForScreenshot, - screenShotPaths, - reduce3DViewportSize, attemptAction, + checkForScreenshot, + reduce3DViewportSize, + screenShotPaths, + test, + visitStudy, } from './utils'; test.beforeEach(async ({ page }) => { @@ -14,13 +14,8 @@ test.beforeEach(async ({ page }) => { }); test.describe('3D primary Test', async () => { - test('should render 3D primary correctly.', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page - .locator('div') - .filter({ hasText: /^3D primary$/ }) - .first() - .click(); + test('should render 3D primary correctly.', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.layoutSelection.threeDPrimary.click(); await attemptAction(() => reduce3DViewportSize(page), 10, 100); await page.waitForTimeout(5000); diff --git a/tests/Angle.spec.ts b/tests/Angle.spec.ts index 1a964db38..d92f9e293 100644 --- a/tests/Angle.spec.ts +++ b/tests/Angle.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,27 +6,17 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the angle tool', async ({ page }) => { - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('Angle').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 550, - y: 200, - }, - { - x: 450, - y: 250, - }, - { - x: 550, - y: 300, - }, - ], - }); +test('should display the angle tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.moreTools.angle.click(); + await viewportPageObject.active.clickAt([ + { x: 550, y: 200 }, + { x: 450, y: 250 }, + { x: 550, y: 300 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.angle.angleDisplayedCorrectly); }); diff --git a/tests/ArrowAnnotate.spec.ts b/tests/ArrowAnnotate.spec.ts index a73c2f713..a7be02a55 100644 --- a/tests/ArrowAnnotate.spec.ts +++ b/tests/ArrowAnnotate.spec.ts @@ -1,11 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { - visitStudy, - checkForScreenshot, - screenShotPaths, - simulateClicksOnElement, - simulateDoubleClickOnElement, -} from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -13,26 +6,19 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the arrow tool and allow free-form text to be entered', async ({ page }) => { +test('should display the arrow tool and allow free-form text to be entered', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { await page.getByTestId('trackedMeasurements-btn').click(); - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('ArrowAnnotate').click(); + await mainToolbarPageObject.measurementTools.arrowAnnotate.click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 164, - y: 234, - }, - { - x: 344, - y: 232, - }, - ], - }); + await viewportPageObject.active.clickAt([ + { x: 164, y: 234 }, + { x: 344, y: 232 }, + ]); await page.getByTestId('dialog-input').fill('Ringo Starr was the drummer for The Beatles'); await page.getByTestId('input-dialog-save-button').click(); @@ -49,13 +35,7 @@ test('should display the arrow tool and allow free-form text to be entered', asy // Now edit the arrow text and the label should not change. - await simulateDoubleClickOnElement({ - locator, - point: { - x: 164, - y: 234, - }, - }); + await viewportPageObject.active.doubleClickAt({ x: 164, y: 234 }); await page.getByTestId('dialog-input').fill('Neil Peart was the drummer for Rush'); await page.getByTestId('input-dialog-save-button').click(); diff --git a/tests/AxialPrimary.spec.ts b/tests/AxialPrimary.spec.ts index a1dbc2cb0..31c1b4bf2 100644 --- a/tests/AxialPrimary.spec.ts +++ b/tests/AxialPrimary.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; @@ -8,13 +7,8 @@ test.beforeEach(async ({ page }) => { }); test.describe('Axial Primary Test', async () => { - test('should render Axial Primary correctly.', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page - .locator('div') - .filter({ hasText: /^Axial Primary$/ }) - .first() - .click(); + test('should render Axial Primary correctly.', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.layoutSelection.axialPrimary.click(); await checkForScreenshot( page, page, diff --git a/tests/Bidirectional.spec.ts b/tests/Bidirectional.spec.ts index 16dbb4018..293a8df13 100644 --- a/tests/Bidirectional.spec.ts +++ b/tests/Bidirectional.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,24 +6,16 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the bidirectional tool', async ({ page }) => { - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('Bidirectional').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - - await simulateClicksOnElement({ - locator, - points: [ - { - x: 405, - y: 277, - }, - { - x: 515, - y: 339, - }, - ], - }); +test('should display the bidirectional tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.measurementTools.bidirectional.click(); + await viewportPageObject.active.clickAt([ + { x: 405, y: 277 }, + { x: 515, y: 339 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot( page, diff --git a/tests/Circle.spec.ts b/tests/Circle.spec.ts index 43f31fe8d..d475d7af2 100644 --- a/tests/Circle.spec.ts +++ b/tests/Circle.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,23 +6,16 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the circle tool', async ({ page }) => { - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('CircleROI').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 480, - y: 205, - }, - { - x: 488, - y: 247, - }, - ], - }); +test('should display the circle tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.measurementTools.circleROI.click(); + await viewportPageObject.active.clickAt([ + { x: 480, y: 205 }, + { x: 488, y: 247 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.circle.circleDisplayedCorrectly); }); diff --git a/tests/CobbAngle.spec.ts b/tests/CobbAngle.spec.ts index a87a279a2..012fb4580 100644 --- a/tests/CobbAngle.spec.ts +++ b/tests/CobbAngle.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,31 +6,18 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the cobb angle tool', async ({ page }) => { - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('CobbAngle').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 515, - y: 212, - }, - { - x: 616, - y: 207, - }, - { - x: 527, - y: 293, - }, - { - x: 625, - y: 291, - }, - ], - }); +test('should display the cobb angle tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.moreTools.cobbAngle.click(); + await viewportPageObject.active.clickAt([ + { x: 515, y: 212 }, + { x: 616, y: 207 }, + { x: 527, y: 293 }, + { x: 625, y: 291 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.cobbangle.cobbangleDisplayedCorrectly); }); diff --git a/tests/ContextMenu.spec.ts b/tests/ContextMenu.spec.ts index 8a37f01d7..1327cec71 100644 --- a/tests/ContextMenu.spec.ts +++ b/tests/ContextMenu.spec.ts @@ -1,11 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { - visitStudy, - checkForScreenshot, - screenShotPaths, - simulateNormalizedClicksOnElement, - simulateNormalizedClickOnElement, -} from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -15,36 +8,20 @@ test.beforeEach(async ({ page }) => { test('should the context menu completely on screen and is not clipped for a point near the bottom edge of the screen', async ({ page, + mainToolbarPageObject, + viewportPageObject, }) => { - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.locator('css=div[data-cy="Length"]').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateNormalizedClicksOnElement({ - locator, - normalizedPoints: [ - { - x: 0.45, - y: 0.98, - }, - { - x: 0.55, - y: 0.98, - }, - ], - }); + await mainToolbarPageObject.measurementTools.length.click(); + await viewportPageObject.active.normalizedClickAt([ + { x: 0.45, y: 0.98 }, + { x: 0.55, y: 0.98 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.contextMenu.preContextMenuNearBottomEdge); - await simulateNormalizedClickOnElement({ - locator, - normalizedPoint: { - x: 0.55, - y: 0.98, - }, - button: 'right', - }); + await viewportPageObject.active.normalizedClickAt([{ x: 0.55, y: 0.98 }], 'right'); await checkForScreenshot({ page, diff --git a/tests/ContourSegLocking.spec.ts b/tests/ContourSegLocking.spec.ts index fbd72719c..7eacd1339 100644 --- a/tests/ContourSegLocking.spec.ts +++ b/tests/ContourSegLocking.spec.ts @@ -1,11 +1,12 @@ -import { test, expect } from 'playwright-test-coverage'; -import { visitStudy } from './utils'; -import { viewportSVGPathLocator } from './utils/locators'; +import { expect, test, visitStudy } from './utils'; import { simulateNormalizedDragOnElement } from './utils/simulateDragOnElement'; const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; -test('should not allow contours to be edited in basic viewer mode', async ({ page }) => { +test('should not allow contours to be edited in basic viewer mode', async ({ + page, + viewportPageObject, +}) => { const mode = 'viewer'; await visitStudy(page, studyInstanceUID, mode, 2000); @@ -19,7 +20,7 @@ test('should not allow contours to be edited in basic viewer mode', async ({ pag // Wait for the segmentation to hydrate. await page.waitForTimeout(5000); - const svgPathLocatorPreEdit = viewportSVGPathLocator({ page, viewportId: 'default' }); + const svgPathLocatorPreEdit = viewportPageObject.getById('default').svg(); expect( await svgPathLocatorPreEdit.count(), @@ -35,7 +36,7 @@ test('should not allow contours to be edited in basic viewer mode', async ({ pag end: { x: 0.1, y: -0.2 }, }); - const svgPathLocatorPostEdit = viewportSVGPathLocator({ page, viewportId: 'default' }); + const svgPathLocatorPostEdit = viewportPageObject.getById('default').svg(); expect( await svgPathLocatorPostEdit.getAttribute('d'), @@ -45,6 +46,7 @@ test('should not allow contours to be edited in basic viewer mode', async ({ pag test('should not allow contours to be edited when panelSegmentation.disableEditing is true', async ({ page, + viewportPageObject, }) => { const mode = 'segmentation'; await visitStudy(page, studyInstanceUID, mode, 2000); @@ -69,7 +71,7 @@ test('should not allow contours to be edited when panelSegmentation.disableEditi // Wait for the segmentation to hydrate. await page.waitForTimeout(5000); - const svgPathLocatorPreEdit = viewportSVGPathLocator({ page, viewportId: 'default' }); + const svgPathLocatorPreEdit = viewportPageObject.getById('default').svg(); expect( await svgPathLocatorPreEdit.count(), @@ -85,7 +87,7 @@ test('should not allow contours to be edited when panelSegmentation.disableEditi end: { x: 0.1, y: -0.2 }, }); - const svgPathLocatorPostEdit = viewportSVGPathLocator({ page, viewportId: 'default' }); + const svgPathLocatorPostEdit = viewportPageObject.getById('default').svg(); expect( await svgPathLocatorPostEdit.getAttribute('d'), @@ -95,6 +97,7 @@ test('should not allow contours to be edited when panelSegmentation.disableEditi test('should allow contours to be edited when panelSegmentation.disableEditing is false', async ({ page, + viewportPageObject, }) => { const mode = 'segmentation'; await visitStudy(page, studyInstanceUID, mode, 2000); @@ -119,7 +122,7 @@ test('should allow contours to be edited when panelSegmentation.disableEditing i // Wait for the segmentation to hydrate. await page.waitForTimeout(5000); - const svgPathLocatorPreEdit = viewportSVGPathLocator({ page, viewportId: 'default' }); + const svgPathLocatorPreEdit = viewportPageObject.getById('default').svg('path'); expect( await svgPathLocatorPreEdit.count(), @@ -135,7 +138,7 @@ test('should allow contours to be edited when panelSegmentation.disableEditing i end: { x: 0.1, y: -0.2 }, }); - const svgPathLocatorPostEdit = viewportSVGPathLocator({ page, viewportId: 'default' }); + const svgPathLocatorPostEdit = viewportPageObject.getById('default').svg('path'); expect( await svgPathLocatorPostEdit.getAttribute('d'), diff --git a/tests/Crosshairs.spec.ts b/tests/Crosshairs.spec.ts index 432ad3a25..003ec80d7 100644 --- a/tests/Crosshairs.spec.ts +++ b/tests/Crosshairs.spec.ts @@ -1,17 +1,18 @@ -import { Page, test } from 'playwright-test-coverage'; +import { Page } from '@playwright/test'; import { - visitStudy, checkForScreenshot, - screenShotPaths, - initializeMousePositionTracker, getMousePosition, + initializeMousePositionTracker, + screenShotPaths, + test, + visitStudy, } from './utils/index.js'; const rotateCrosshairs = async (page: Page, id: string, lineNumber: number) => { - const locator = await page.locator(id).locator('line').nth(lineNumber); + const locator = page.locator(id).locator('line').nth(lineNumber); await locator.click({ force: true }); await locator.hover({ force: true }); - const circleLocator = await page.locator(id).locator('circle').nth(1); + const circleLocator = page.locator(id).locator('circle').nth(1); await circleLocator.hover({ force: true }); await page.mouse.down(); const position = await getMousePosition(page); @@ -20,10 +21,10 @@ const rotateCrosshairs = async (page: Page, id: string, lineNumber: number) => { }; const increaseSlabThickness = async (page: Page, id: string, lineNumber: number, axis: string) => { - const locator = await page.locator(id).locator('line').nth(lineNumber); + const locator = page.locator(id).locator('line').nth(lineNumber); await locator.click({ force: true }); await locator.hover({ force: true }); - const circleLocator = await page.locator(id).locator('rect').first(); + const circleLocator = page.locator(id).locator('rect').first(); await circleLocator.hover({ force: true }); await page.mouse.down(); const position = await getMousePosition(page); @@ -46,17 +47,18 @@ test.beforeEach(async ({ page }) => { }); test.describe('Crosshairs Test', async () => { - test('should render the crosshairs correctly.', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + test('should render the crosshairs correctly.', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.getByTestId('Crosshairs').click(); await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRendered); }); - test('should allow the user to rotate the crosshairs', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + test('should allow the user to rotate the crosshairs', async ({ + page, + mainToolbarPageObject, + }) => { + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.getByTestId('Crosshairs').click(); await rotateCrosshairs(page, '#svg-layer-mpr-axial', 3); @@ -66,9 +68,11 @@ test.describe('Crosshairs Test', async () => { await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRotated); }); - test('should allow the user to adjust the slab thickness', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + test('should allow the user to adjust the slab thickness', async ({ + page, + mainToolbarPageObject, + }) => { + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.getByTestId('Crosshairs').click(); await increaseSlabThickness(page, '#svg-layer-mpr-axial', 0, 'x'); @@ -80,9 +84,9 @@ test.describe('Crosshairs Test', async () => { test('should reset the crosshairs to the initial position when reset is clicked', async ({ page, + mainToolbarPageObject, }) => { - await page.getByTestId('Layout').click(); - await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.getByTestId('Crosshairs').click(); await rotateCrosshairs(page, '#svg-layer-mpr-axial', 3); @@ -94,9 +98,11 @@ test.describe('Crosshairs Test', async () => { await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsResetToolbar); }); - test('should reset the crosshairs when a new displayset is loaded', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + test('should reset the crosshairs when a new displayset is loaded', async ({ + page, + mainToolbarPageObject, + }) => { + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.getByTestId('Crosshairs').click(); await rotateCrosshairs(page, '#svg-layer-mpr-axial', 0); diff --git a/tests/DataOverlayMenu.spec.ts b/tests/DataOverlayMenu.spec.ts index e3667fb9d..649d90811 100644 --- a/tests/DataOverlayMenu.spec.ts +++ b/tests/DataOverlayMenu.spec.ts @@ -1,14 +1,16 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; import { press } from './utils/keyboardUtils'; -test('should display added, selected and removed segmentation promptly', async ({ page }) => { +test('should display added, selected and removed segmentation promptly', async ({ + page, + viewportPageObject, +}) => { const studyInstanceUID = '1.3.6.1.4.1.32722.99.99.239341353911714368772597187099978969331'; const mode = 'segmentation'; await visitStudy(page, studyInstanceUID, mode, 2000); // Add a segmentation overlay and ensure the overlay menu reflects this change. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.getByTestId('AddSegmentationDataOverlay-default').click(); await page.getByText('SELECT A SEGMENTATION').click(); await page.getByTestId('2d-tta_nnU-Net_Segmentation').click(); @@ -22,7 +24,7 @@ test('should display added, selected and removed segmentation promptly', async ( }); // Hide the overlay menu. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // navigate to the 51st image and ensure the correct overlay is displayed await press({ page, key: 'ArrowDown', nTimes: 50 }); @@ -35,7 +37,7 @@ test('should display added, selected and removed segmentation promptly', async ( }); // Show the overlay menu. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // Change the segmentation overlay to a different one and ensure the overlay menu reflects this change. await page.getByTestId('overlay-ds-select-value-2D-TTA_NNU-NET_SEGMENTATION').click(); @@ -49,7 +51,7 @@ test('should display added, selected and removed segmentation promptly', async ( }); // Hide the overlay menu. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // navigate to the 51st image and ensure the correct overlay is displayed await press({ page, key: 'ArrowDown', nTimes: 50 }); @@ -62,7 +64,7 @@ test('should display added, selected and removed segmentation promptly', async ( }); // Show the overlay menu. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // Remove the segmentation overlay and ensure the overlay menu reflects this change. await page.getByTestId('overlay-ds-more-button-SEGMENTATION').click(); @@ -76,7 +78,7 @@ test('should display added, selected and removed segmentation promptly', async ( }); // Hide the overlay menu. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // navigate to the 51st image and ensure no overlay is displayed await press({ page, key: 'ArrowDown', nTimes: 50 }); diff --git a/tests/DicomTagBrowser.spec.ts b/tests/DicomTagBrowser.spec.ts index 299680d7e..89d2206ab 100644 --- a/tests/DicomTagBrowser.spec.ts +++ b/tests/DicomTagBrowser.spec.ts @@ -1,13 +1,11 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; -test('should display the dicom tag browser', async ({ page }) => { +test('should display the dicom tag browser', async ({ page, mainToolbarPageObject }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; const mode = 'viewer'; await visitStudy(page, studyInstanceUID, mode, 2000); - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('TagBrowser').click(); + await mainToolbarPageObject.moreTools.tagBrowser.click(); await checkForScreenshot( page, page, @@ -15,13 +13,15 @@ test('should display the dicom tag browser', async ({ page }) => { ); }); -test('should render the scroll bar with the correct look-and-feel', async ({ page }) => { +test('should render the scroll bar with the correct look-and-feel', async ({ + page, + mainToolbarPageObject, +}) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; const mode = 'viewer'; await visitStudy(page, studyInstanceUID, mode, 2000); - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('TagBrowser').click(); + await mainToolbarPageObject.moreTools.tagBrowser.click(); await checkForScreenshot({ page, normalizedClip: { x: 0.77, y: 0.25, width: 0.03, height: 0.75 }, diff --git a/tests/Ellipse.spec.ts b/tests/Ellipse.spec.ts index 6dc72569d..bec7ecc57 100644 --- a/tests/Ellipse.spec.ts +++ b/tests/Ellipse.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,23 +6,16 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the ellipse tool', async ({ page }) => { - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('EllipticalROI').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 446, - y: 245, - }, - { - x: 508, - y: 281, - }, - ], - }); +test('should display the ellipse tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.measurementTools.ellipticalROI.click(); + await viewportPageObject.active.clickAt([ + { x: 446, y: 245 }, + { x: 508, y: 281 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.ellipse.ellipseDisplayedCorrectly); }); diff --git a/tests/FlipHorizontal.spec.ts b/tests/FlipHorizontal.spec.ts index 1fb21709f..c81f49684 100644 --- a/tests/FlipHorizontal.spec.ts +++ b/tests/FlipHorizontal.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; @@ -7,9 +6,8 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should flip the image horizontally', async ({ page }) => { - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('flipHorizontal').click(); +test('should flip the image horizontally', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.moreTools.flipHorizontal.click(); await checkForScreenshot( page, page, diff --git a/tests/Invert.spec.ts b/tests/Invert.spec.ts index f9fed41d6..9a5d88c55 100644 --- a/tests/Invert.spec.ts +++ b/tests/Invert.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,8 +6,7 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should invert the image', async ({ page }) => { - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('invert').click(); +test('should invert the image', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.moreTools.invert.click(); await checkForScreenshot(page, page, screenShotPaths.invert.invertDisplayedCorrectly); }); diff --git a/tests/JumpToMeasurementMPR.spec.ts b/tests/JumpToMeasurementMPR.spec.ts index e5a3941b6..4935b78e2 100644 --- a/tests/JumpToMeasurementMPR.spec.ts +++ b/tests/JumpToMeasurementMPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,7 +6,11 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 5000); }); -test('should hydrate in MPR correctly', async ({ page }) => { +test('should hydrate in MPR correctly', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { await page.getByTestId('side-panel-header-right').click(); await page.getByTestId('trackedMeasurements-btn').click(); @@ -38,23 +41,11 @@ test('should hydrate in MPR correctly', async ({ page }) => { await page.waitForTimeout(5000); - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('Bidirectional').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - - await simulateClicksOnElement({ - locator, - points: [ - { - x: 405, - y: 277, - }, - { - x: 515, - y: 339, - }, - ], - }); + await mainToolbarPageObject.measurementTools.bidirectional.click(); + await viewportPageObject.active.clickAt([ + { x: 405, y: 277 }, + { x: 515, y: 339 }, + ]); // wait 2 seconds await page.waitForTimeout(2000); @@ -93,8 +84,7 @@ test('should hydrate in MPR correctly', async ({ page }) => { await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.jumpToMeasurementStack); - await page.getByTestId('Layout').click(); - await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); // wait 5 seconds await page.waitForTimeout(5000); diff --git a/tests/LabelMapSegLocking.spec.ts b/tests/LabelMapSegLocking.spec.ts index 773e37a4a..c2ddb603e 100644 --- a/tests/LabelMapSegLocking.spec.ts +++ b/tests/LabelMapSegLocking.spec.ts @@ -1,8 +1,5 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; import { press } from './utils/keyboardUtils'; -import { simulateNormalizedDragOnElement } from './utils/simulateDragOnElement'; -import { viewportLocator } from './utils/locators'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.256467663913010332776401703474716742458'; @@ -12,6 +9,7 @@ test.beforeEach(async ({ page }) => { test('should prevent editing of label map segmentations when panelSegmentation.disableEditing is true', async ({ page, + viewportPageObject, }) => { // disable editing of segmentations via the customization service await page.evaluate(() => { @@ -45,18 +43,15 @@ test('should prevent editing of label map segmentations when panelSegmentation.d await page.locator(`css=div[data-cy="eraser-radius"] input`).fill('1000'); // Attempt to erase the segmentations by dragging the eraser tool across the image several times. - await simulateNormalizedDragOnElement({ - locator: viewportLocator({ page, viewportId: 'default' }), + await viewportPageObject.getById('default').normalizedDragAt({ start: { x: 0.01, y: 0.25 }, end: { x: 1.0, y: 0.25 }, }); - await simulateNormalizedDragOnElement({ - locator: viewportLocator({ page, viewportId: 'default' }), + await viewportPageObject.getById('default').normalizedDragAt({ start: { x: 0.01, y: 0.5 }, end: { x: 1.0, y: 0.5 }, }); - await simulateNormalizedDragOnElement({ - locator: viewportLocator({ page, viewportId: 'default' }), + await viewportPageObject.getById('default').normalizedDragAt({ start: { x: 0.01, y: 0.75 }, end: { x: 1.0, y: 0.75 }, }); @@ -66,6 +61,7 @@ test('should prevent editing of label map segmentations when panelSegmentation.d test('should allow editing of label map segmentations when panelSegmentation.disableEditing is false', async ({ page, + viewportPageObject, }) => { // disable editing of segmentations via the customization service await page.evaluate(() => { @@ -99,18 +95,15 @@ test('should allow editing of label map segmentations when panelSegmentation.dis await page.locator(`css=div[data-cy="eraser-radius"] input`).fill('1000'); // Attempt to erase the segmentations by dragging the eraser tool across the image several times. - await simulateNormalizedDragOnElement({ - locator: viewportLocator({ page, viewportId: 'default' }), + await viewportPageObject.getById('default').normalizedDragAt({ start: { x: 0.01, y: 0.25 }, end: { x: 1.0, y: 0.25 }, }); - await simulateNormalizedDragOnElement({ - locator: viewportLocator({ page, viewportId: 'default' }), + await viewportPageObject.getById('default').normalizedDragAt({ start: { x: 0.01, y: 0.5 }, end: { x: 1.0, y: 0.5 }, }); - await simulateNormalizedDragOnElement({ - locator: viewportLocator({ page, viewportId: 'default' }), + await viewportPageObject.getById('default').normalizedDragAt({ start: { x: 0.01, y: 0.75 }, end: { x: 1.0, y: 0.75 }, }); diff --git a/tests/Length.spec.ts b/tests/Length.spec.ts index 3951d7841..3124c6e5a 100644 --- a/tests/Length.spec.ts +++ b/tests/Length.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,22 +6,16 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the length tool', async ({ page }) => { - await page.getByTestId('MeasurementTools-split-button-primary').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 364, - y: 234, - }, - { - x: 544, - y: 232, - }, - ], - }); +test('should display the length tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.measurementTools.length.click(); + await viewportPageObject.active.clickAt([ + { x: 364, y: 234 }, + { x: 544, y: 232 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.length.lengthDisplayedCorrectly); }); diff --git a/tests/Livewire.spec.ts b/tests/Livewire.spec.ts index 22128fd23..f4f96354c 100644 --- a/tests/Livewire.spec.ts +++ b/tests/Livewire.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,39 +6,20 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the livewire tool', async ({ page }) => { - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('LivewireContour').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 380, - y: 459, - }, - { - x: 420, - y: 396, - }, - { - x: 523, - y: 392, - }, - { - x: 581, - y: 447, - }, - { - x: 482, - y: 493, - }, - { - x: 383, - y: 461, - }, - ], - }); +test('should display the livewire tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.measurementTools.livewireContour.click(); + await viewportPageObject.active.clickAt([ + { x: 380, y: 459 }, + { x: 420, y: 396 }, + { x: 523, y: 392 }, + { x: 581, y: 447 }, + { x: 482, y: 493 }, + { x: 383, y: 461 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.livewire.livewireDisplayedCorrectly); }); diff --git a/tests/MPR.spec.ts b/tests/MPR.spec.ts index 8319a431d..53aae6433 100644 --- a/tests/MPR.spec.ts +++ b/tests/MPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils/index.js'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils/index.js'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; @@ -8,9 +7,8 @@ test.beforeEach(async ({ page }) => { }); test.describe('MPR Test', async () => { - test('should render MPR correctly.', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page.locator('div').filter({ hasText: /^MPR$/ }).first().click(); + test('should render MPR correctly.', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.layoutSelection.MPR.click(); await checkForScreenshot(page, page, screenShotPaths.mpr.mprDisplayedCorrectly); }); }); diff --git a/tests/MPRThenRTOverlayNoHydration.spec.ts b/tests/MPRThenRTOverlayNoHydration.spec.ts index fd88eed18..3a5764d73 100644 --- a/tests/MPRThenRTOverlayNoHydration.spec.ts +++ b/tests/MPRThenRTOverlayNoHydration.spec.ts @@ -1,7 +1,5 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; import { assertNumberOfModalityLoadBadges } from './utils/assertions'; -import { viewportLocator } from './utils/locators'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0'; @@ -11,9 +9,10 @@ test.beforeEach(async ({ page }) => { test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay menu', async ({ page, + mainToolbarPageObject, + viewportPageObject, }) => { - await page.getByTestId('Layout').click(); - await page.getByTestId('MPR').click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); // Wait 5 seconds for MPR to load. This is necessary in particular when screen shots are added or replaced. await page.waitForTimeout(10000); @@ -25,14 +24,14 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me ); // Hover over the middle/sagittal viewport so that the data overlay menu is available. - await viewportLocator({ viewportId: 'mpr-sagittal', page }).hover(); - await page.getByTestId('dataOverlayMenu-mpr-sagittal-btn').click(); + await viewportPageObject.getById('mpr-sagittal').pane.hover(); + await viewportPageObject.getById('mpr-sagittal').overlayMenu.dataOverlay.click(); await page.getByTestId('AddSegmentationDataOverlay-mpr-sagittal').click(); await page.getByText('SELECT A SEGMENTATION').click(); await page.getByTestId('ARIA RadOnc Structure Sets').click(); // Hide the overlay menu. - await page.getByTestId('dataOverlayMenu-mpr-sagittal-btn').click(); + await viewportPageObject.getById('mpr-sagittal').overlayMenu.dataOverlay.click(); // Adding an overlay should not show the LOAD button. assertNumberOfModalityLoadBadges({ page, expectedCount: 0 }); diff --git a/tests/MPRThenSEGOverlayNoHydration.spec.ts b/tests/MPRThenSEGOverlayNoHydration.spec.ts index e7e0e2420..9cb24a1e6 100644 --- a/tests/MPRThenSEGOverlayNoHydration.spec.ts +++ b/tests/MPRThenSEGOverlayNoHydration.spec.ts @@ -1,7 +1,5 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; import { assertNumberOfModalityLoadBadges } from './utils/assertions'; -import { viewportLocator } from './utils/locators'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046'; @@ -11,11 +9,12 @@ test.beforeEach(async ({ page }) => { test('should launch MPR with unhydrated SEG chosen from the data overlay menu', async ({ page, + mainToolbarPageObject, + viewportPageObject, }) => { await page.getByTestId('side-panel-header-right').click(); - await page.getByTestId('Layout').click(); - await page.getByTestId('MPR').click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.waitForTimeout(5000); @@ -26,14 +25,14 @@ test('should launch MPR with unhydrated SEG chosen from the data overlay menu', ); // Hover over the middle/sagittal viewport so that the data overlay menu is available. - await viewportLocator({ viewportId: 'mpr-sagittal', page }).hover(); - await page.getByTestId('dataOverlayMenu-mpr-sagittal-btn').click(); + await viewportPageObject.getById('mpr-sagittal').pane.hover(); + await viewportPageObject.getById('mpr-sagittal').overlayMenu.dataOverlay.click(); await page.getByTestId('AddSegmentationDataOverlay-mpr-sagittal').click(); await page.getByText('SELECT A SEGMENTATION').click(); await page.getByTestId('Segmentation').click(); // Hide the overlay menu. - await page.getByTestId('dataOverlayMenu-mpr-sagittal-btn').click(); + await viewportPageObject.getById('mpr-sagittal').overlayMenu.dataOverlay.click(); // Adding an overlay should not show the LOAD button. assertNumberOfModalityLoadBadges({ page, expectedCount: 0 }); diff --git a/tests/MeasurementPanel.spec.ts b/tests/MeasurementPanel.spec.ts index aad296a3a..326dd0905 100644 --- a/tests/MeasurementPanel.spec.ts +++ b/tests/MeasurementPanel.spec.ts @@ -1,5 +1,4 @@ -import { test, expect } from 'playwright-test-coverage'; -import { visitStudy, addLengthMeasurement, scrollVolumeViewport } from './utils'; +import { addLengthMeasurement, expect, scrollVolumeViewport, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { // Using same one as JumpToMeasurementMPR.spec.ts @@ -136,8 +135,11 @@ test('checks if measurement item can be relabeled through the context menu on th await expect(measurementRow).toContainText(relabelText); }); -test('checks if image would jump when clicked on a measurement item', async ({ page }) => { - const viewportInfoBottomRight = page.getByTestId('viewport-overlay-bottom-right'); +test('checks if image would jump when clicked on a measurement item', async ({ + page, + viewportPageObject, +}) => { + const viewportInfoBottomRight = viewportPageObject.active.overlayText.bottomRight; // Image loads on slice 1, confirm on slice 1 then add measurement await expect(viewportInfoBottomRight).toContainText('1/', { timeout: 10000 }); diff --git a/tests/MultipleSegmentationDataOverlays.spec.ts b/tests/MultipleSegmentationDataOverlays.spec.ts index bec837e4d..044d8b3dc 100644 --- a/tests/MultipleSegmentationDataOverlays.spec.ts +++ b/tests/MultipleSegmentationDataOverlays.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; import { press } from './utils/keyboardUtils'; import { assertNumberOfModalityLoadBadges } from './utils/assertions'; @@ -9,11 +8,14 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display multiple segmentation overlays (both SEG and RT)', async ({ page }) => { +test('should display multiple segmentation overlays (both SEG and RT)', async ({ + page, + viewportPageObject, +}) => { await page.getByTestId('side-panel-header-right').click(); // Add multiple segmentation overlays and ensure the overlay menu reflects this change. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.getByTestId('AddSegmentationDataOverlay-default').click(); await page.getByText('SELECT A SEGMENTATION').click(); @@ -51,15 +53,15 @@ test('should display multiple segmentation overlays (both SEG and RT)', async ({ }); // Hide the overlay menu and then show it again. The overlays from before should still be displayed. - await page.getByTestId('dataOverlayMenu-default-btn').click(); // hide - await page.getByTestId('dataOverlayMenu-default-btn').click(); // show + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // hide + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // show await checkForScreenshot({ page, screenshotPath: screenShotPaths.multipleSegmentationDataOverlays.threeSegOverlaysInOverlayMenu, }); - await page.getByTestId('dataOverlayMenu-default-btn').click(); // hide + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // hide // Navigate to image 56. await press({ page, key: 'ArrowDown', nTimes: 55 }); @@ -72,7 +74,7 @@ test('should display multiple segmentation overlays (both SEG and RT)', async ({ }); // Now add the RT overlay - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.getByTestId('AddSegmentationDataOverlay-default').click(); await page.getByText('SELECT A SEGMENTATION').click(); @@ -90,8 +92,8 @@ test('should display multiple segmentation overlays (both SEG and RT)', async ({ }); // Hide the overlay menu and then show it again. The overlays from before should still be displayed. - await page.getByTestId('dataOverlayMenu-default-btn').click(); // hide - await page.getByTestId('dataOverlayMenu-default-btn').click(); // show + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // hide + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // show await checkForScreenshot({ page, diff --git a/tests/Probe.spec.ts b/tests/Probe.spec.ts index d4570ae91..86eda1baf 100644 --- a/tests/Probe.spec.ts +++ b/tests/Probe.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,19 +6,13 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the probe tool', async ({ page }) => { - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('Probe').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 550, - y: 200, - }, - ], - }); +test('should display the probe tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.moreTools.probe.click(); + await viewportPageObject.active.clickAt([{ x: 550, y: 200 }]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.probe.probeDisplayedCorrectly); }); diff --git a/tests/RTDataOverlayForUnreferencedDisplaySetNoHydration.spec.ts b/tests/RTDataOverlayForUnreferencedDisplaySetNoHydration.spec.ts index 35c5a539d..ca29d3c3b 100644 --- a/tests/RTDataOverlayForUnreferencedDisplaySetNoHydration.spec.ts +++ b/tests/RTDataOverlayForUnreferencedDisplaySetNoHydration.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; import { press } from './utils/keyboardUtils'; import { assertNumberOfModalityLoadBadges } from './utils/assertions'; @@ -11,8 +10,9 @@ test.beforeEach(async ({ page }) => { test('should overlay an unhydrated RTSTRUCT over a display set that the RTSTRUCT does NOT reference', async ({ page, + viewportPageObject, }) => { - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.getByTestId('AddSegmentationDataOverlay-default').click(); await page.getByText('SELECT A SEGMENTATION').click(); await page.getByTestId('Contours on PET').click(); @@ -21,7 +21,7 @@ test('should overlay an unhydrated RTSTRUCT over a display set that the RTSTRUCT assertNumberOfModalityLoadBadges({ page, expectedCount: 0 }); // Hide the overlay menu. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.waitForTimeout(5000); diff --git a/tests/RTDataOverlayNoHydrationThenMPR.spec.ts b/tests/RTDataOverlayNoHydrationThenMPR.spec.ts index 1c2bb5ee1..e84e24648 100644 --- a/tests/RTDataOverlayNoHydrationThenMPR.spec.ts +++ b/tests/RTDataOverlayNoHydrationThenMPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; import { assertNumberOfModalityLoadBadges } from './utils/assertions'; test.beforeEach(async ({ page }) => { @@ -10,9 +9,11 @@ test.beforeEach(async ({ page }) => { test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay menu', async ({ page, + mainToolbarPageObject, + viewportPageObject, }) => { await page.getByTestId('side-panel-header-right').click(); - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.getByTestId('AddSegmentationDataOverlay-default').click(); await page.getByText('SELECT A SEGMENTATION').click(); await page.getByTestId('ARIA RadOnc Structure Sets').click(); @@ -21,7 +22,7 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me assertNumberOfModalityLoadBadges({ page, expectedCount: 0 }); // Hide the overlay menu. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.waitForTimeout(5000); @@ -31,8 +32,7 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me screenShotPaths.rtDataOverlayNoHydrationThenMPR.rtDataOverlayNoHydrationPreMPR ); - await page.getByTestId('Layout').click(); - await page.getByTestId('MPR').click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.waitForTimeout(5000); diff --git a/tests/RTHydrationFromMPR.spec.ts b/tests/RTHydrationFromMPR.spec.ts index ae38e898b..3d286a71b 100644 --- a/tests/RTHydrationFromMPR.spec.ts +++ b/tests/RTHydrationFromMPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0'; @@ -7,11 +6,10 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should hydrate an RTSTRUCT from MPR', async ({ page }) => { +test('should hydrate an RTSTRUCT from MPR', async ({ page, mainToolbarPageObject }) => { await page.getByTestId('side-panel-header-right').click(); - await page.getByTestId('Layout').click(); - await page.getByTestId('MPR').click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.waitForTimeout(10000); @@ -29,8 +27,7 @@ test('should hydrate an RTSTRUCT from MPR', async ({ page }) => { await checkForScreenshot(page, page, screenShotPaths.rtHydrationFromMPR.mprAfterRTHydrated); - await page.getByTestId('Layout').click(); - await page.getByTestId('Axial Primary').click(); + await mainToolbarPageObject.layoutSelection.axialPrimary.click(); await checkForScreenshot( page, diff --git a/tests/RTHydrationThenMPR.spec.ts b/tests/RTHydrationThenMPR.spec.ts index 7e2ceec81..f8d13277f 100644 --- a/tests/RTHydrationThenMPR.spec.ts +++ b/tests/RTHydrationThenMPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0'; @@ -7,7 +6,7 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should hydrate an RTSTRUCT and then launch MPR', async ({ page }) => { +test('should hydrate an RTSTRUCT and then launch MPR', async ({ page, mainToolbarPageObject }) => { await page.getByTestId('side-panel-header-right').click(); await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); @@ -17,8 +16,7 @@ test('should hydrate an RTSTRUCT and then launch MPR', async ({ page }) => { await checkForScreenshot(page, page, screenShotPaths.rtHydrationThenMPR.rtPostHydration); - await page.getByTestId('Layout').click(); - await page.getByTestId('Axial Primary').click(); + await mainToolbarPageObject.layoutSelection.axialPrimary.click(); await page.waitForTimeout(5000); diff --git a/tests/RTNoHydrationThenMPR.spec.ts b/tests/RTNoHydrationThenMPR.spec.ts index 84d364062..cf41f44a6 100644 --- a/tests/RTNoHydrationThenMPR.spec.ts +++ b/tests/RTNoHydrationThenMPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0'; @@ -7,7 +6,7 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should launch MPR with unhydrated RTSTRUCT', async ({ page }) => { +test('should launch MPR with unhydrated RTSTRUCT', async ({ page, mainToolbarPageObject }) => { await page.getByTestId('side-panel-header-right').click(); await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); @@ -15,8 +14,7 @@ test('should launch MPR with unhydrated RTSTRUCT', async ({ page }) => { await checkForScreenshot(page, page, screenShotPaths.rtNoHydrationThenMPR.rtNoHydrationPreMPR); - await page.getByTestId('Layout').click(); - await page.getByTestId('MPR').click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.waitForTimeout(5000); diff --git a/tests/Rectangle.spec.ts b/tests/Rectangle.spec.ts index f781ddf8d..c32a2dece 100644 --- a/tests/Rectangle.spec.ts +++ b/tests/Rectangle.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,23 +6,16 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the rectangle tool', async ({ page }) => { - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('RectangleROI').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 476, - y: 159, - }, - { - x: 591, - y: 217, - }, - ], - }); +test('should display the rectangle tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.measurementTools.rectangleROI.click(); + await viewportPageObject.active.clickAt([ + { x: 476, y: 159 }, + { x: 591, y: 217 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.rectangle.rectangleDisplayedCorrectly); }); diff --git a/tests/Reset.spec.ts b/tests/Reset.spec.ts index 0a6175710..e6adaf109 100644 --- a/tests/Reset.spec.ts +++ b/tests/Reset.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '2.16.840.1.114362.1.11972228.22789312658.616067305.306.2'; @@ -7,12 +6,9 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should reset the image to its original state', async ({ page }) => { - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('rotate-right').click(); - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('invert').click(); - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByText('Reset View').click(); +test('should reset the image to its original state', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.moreTools.rotateRight.click(); + await mainToolbarPageObject.moreTools.invert.click(); + await mainToolbarPageObject.moreTools.reset.click(); await checkForScreenshot(page, page, screenShotPaths.reset.resetDisplayedCorrectly); }); diff --git a/tests/RotateRight.spec.ts b/tests/RotateRight.spec.ts index a210fa7f1..6198b7619 100644 --- a/tests/RotateRight.spec.ts +++ b/tests/RotateRight.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,8 +6,7 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should rotate the image to the right', async ({ page }) => { - await page.getByTestId('MoreTools-split-button-secondary').click(); - await page.getByTestId('rotate-right').click(); +test('should rotate the image to the right', async ({ page, mainToolbarPageObject }) => { + await mainToolbarPageObject.moreTools.rotateRight.click(); await checkForScreenshot(page, page, screenShotPaths.rotateRight.rotateRightDisplayedCorrectly); }); diff --git a/tests/SEGDataOverlayForUnreferencedDisplaySetNoHydration.spec.ts b/tests/SEGDataOverlayForUnreferencedDisplaySetNoHydration.spec.ts index 6974a91a2..0b1b96139 100644 --- a/tests/SEGDataOverlayForUnreferencedDisplaySetNoHydration.spec.ts +++ b/tests/SEGDataOverlayForUnreferencedDisplaySetNoHydration.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; import { press } from './utils/keyboardUtils'; import { assertNumberOfModalityLoadBadges } from './utils/assertions'; @@ -11,10 +10,11 @@ test.beforeEach(async ({ page }) => { test('should overlay an unhydrated SEG over a display set that the SEG does NOT reference', async ({ page, + viewportPageObject, }) => { await page.getByTestId('study-browser-thumbnail').nth(2).dblclick(); - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.getByTestId('AddSegmentationDataOverlay-default').click(); await page.getByText('SELECT A SEGMENTATION').click(); await page.getByTestId('T2 Weighted Axial Segmentations').click(); @@ -23,7 +23,7 @@ test('should overlay an unhydrated SEG over a display set that the SEG does NOT assertNumberOfModalityLoadBadges({ page, expectedCount: 0 }); // Hide the overlay menu. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.waitForTimeout(5000); diff --git a/tests/SEGDataOverlayNoHydrationThenMPR.spec.ts b/tests/SEGDataOverlayNoHydrationThenMPR.spec.ts index 98ca53ef1..41c542474 100644 --- a/tests/SEGDataOverlayNoHydrationThenMPR.spec.ts +++ b/tests/SEGDataOverlayNoHydrationThenMPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; import { assertNumberOfModalityLoadBadges } from './utils/assertions'; test.beforeEach(async ({ page }) => { @@ -10,9 +9,11 @@ test.beforeEach(async ({ page }) => { test('should launch MPR with unhydrated SEG chosen from the data overlay menu', async ({ page, + mainToolbarPageObject, + viewportPageObject, }) => { await page.getByTestId('side-panel-header-right').click(); - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.getByTestId('AddSegmentationDataOverlay-default').click(); await page.getByText('SELECT A SEGMENTATION').click(); await page.getByTestId('Segmentation').click(); @@ -21,7 +22,7 @@ test('should launch MPR with unhydrated SEG chosen from the data overlay menu', assertNumberOfModalityLoadBadges({ page, expectedCount: 0 }); // Hide the overlay menu. - await page.getByTestId('dataOverlayMenu-default-btn').click(); + await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); await page.waitForTimeout(5000); @@ -31,8 +32,7 @@ test('should launch MPR with unhydrated SEG chosen from the data overlay menu', screenShotPaths.segDataOverlayNoHydrationThenMPR.segDataOverlayNoHydrationPreMPR ); - await page.getByTestId('Layout').click(); - await page.getByTestId('MPR').click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.waitForTimeout(5000); diff --git a/tests/SEGDrawingToolsResizing.spec.ts b/tests/SEGDrawingToolsResizing.spec.ts index 2ac1408b9..55deeaa7a 100644 --- a/tests/SEGDrawingToolsResizing.spec.ts +++ b/tests/SEGDrawingToolsResizing.spec.ts @@ -1,7 +1,7 @@ -import { test, expect } from 'playwright-test-coverage'; import { Page } from '@playwright/test'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { ViewportPageObject } from './pages'; +import { checkForScreenshot, expect, screenShotPaths, test, visitStudy } from './utils'; import { press } from './utils/keyboardUtils'; test.beforeEach(async ({ page }) => { @@ -15,13 +15,16 @@ test.beforeEach(async ({ page }) => { await page.waitForTimeout(500); }); -async function performDrawingToolInteraction(page: Page, toolName: string) { +async function performDrawingToolInteraction( + page: Page, + toolName: string, + viewportPageObject: ViewportPageObject +) { const brushRadiusInput = page.getByTestId(`${toolName}-radius`).locator('input'); - const viewportGrid = page.getByTestId('viewport-grid'); - const circle = viewportGrid.locator('svg.svg-layer circle').first(); + const circle = viewportPageObject.active.svg('circle').first(); await expect(brushRadiusInput).toHaveValue('25'); - await viewportGrid.click({ position: { x: 275, y: 300 } }); + await viewportPageObject.active.clickAt([{ x: 275, y: 300 }]); let radius = parseFloat(await circle.getAttribute('r')); expect(radius).toBeGreaterThanOrEqual(65); expect(radius).toBeLessThanOrEqual(68); @@ -29,7 +32,7 @@ async function performDrawingToolInteraction(page: Page, toolName: string) { await page.waitForTimeout(500); await press({ page, key: '[', nTimes: 2 }); await expect(brushRadiusInput).toHaveValue('19'); - await viewportGrid.click({ position: { x: 500, y: 300 } }); + await viewportPageObject.active.clickAt([{ x: 500, y: 300 }]); radius = parseFloat(await circle.getAttribute('r')); expect(radius).toBeGreaterThanOrEqual(49); expect(radius).toBeLessThanOrEqual(52); @@ -38,7 +41,7 @@ async function performDrawingToolInteraction(page: Page, toolName: string) { await press({ page, key: ']', nTimes: 5 }); await expect(brushRadiusInput).toHaveValue('34'); - await viewportGrid.click({ position: { x: 275, y: 500 } }); + await viewportPageObject.active.clickAt([{ x: 275, y: 500 }]); radius = parseFloat(await circle.getAttribute('r')); expect(radius).toBeGreaterThanOrEqual(87); expect(radius).toBeLessThanOrEqual(90); @@ -46,7 +49,7 @@ async function performDrawingToolInteraction(page: Page, toolName: string) { await page.waitForTimeout(500); await brushRadiusInput.fill('42'); - await viewportGrid.click({ position: { x: 500, y: 500 } }); + await viewportPageObject.active.clickAt([{ x: 500, y: 500 }]); radius = parseFloat(await circle.getAttribute('r')); expect(radius).toBeGreaterThanOrEqual(108); expect(radius).toBeLessThanOrEqual(111); @@ -54,23 +57,23 @@ async function performDrawingToolInteraction(page: Page, toolName: string) { await page.waitForTimeout(500); } -test('(shouldUpdateThis) should resize segmentation brush tool', async ({ page }) => { +test('should resize segmentation brush tool', async ({ page, viewportPageObject }) => { await page.getByTestId('Brush-btn').click(); - await performDrawingToolInteraction(page, 'brush'); + await performDrawingToolInteraction(page, 'brush', viewportPageObject); await checkForScreenshot( page, - page.getByTestId('viewport-grid'), + viewportPageObject.active.pane, screenShotPaths.segDrawingToolsResizing.brushTool ); }); -test('(shouldUpdateThis) should resize segmentation eraser tool', async ({ page }) => { +test('should resize segmentation eraser tool', async ({ page, viewportPageObject }) => { await page.getByTestId('Brush-btn').click(); await page.getByTestId('brush-radius').locator('input').fill('99.5'); - await page.getByTestId('viewport-grid').click({ position: { x: 400, y: 400 } }); + await viewportPageObject.active.clickAt([{ x: 400, y: 400 }]); await page.waitForTimeout(500); @@ -79,17 +82,17 @@ test('(shouldUpdateThis) should resize segmentation eraser tool', async ({ page await page.waitForTimeout(500); - await performDrawingToolInteraction(page, 'eraser'); + await performDrawingToolInteraction(page, 'eraser', viewportPageObject); await checkForScreenshot( page, - page.getByTestId('viewport-grid'), + viewportPageObject.active.pane, screenShotPaths.segDrawingToolsResizing.eraserTool ); }); -test('(shouldUpdateThis) should resize segmentation threshold tool', async ({ page }) => { +test('should resize segmentation threshold tool', async ({ page, viewportPageObject }) => { await page.getByTestId('Threshold-btn').click(); - await performDrawingToolInteraction(page, 'threshold'); + await performDrawingToolInteraction(page, 'threshold', viewportPageObject); }); diff --git a/tests/SEGHydrationFrom3DFourUp.spec.ts b/tests/SEGHydrationFrom3DFourUp.spec.ts index b604350f6..c2193408b 100644 --- a/tests/SEGHydrationFrom3DFourUp.spec.ts +++ b/tests/SEGHydrationFrom3DFourUp.spec.ts @@ -1,10 +1,10 @@ -import { test } from 'playwright-test-coverage'; import { - visitStudy, - checkForScreenshot, - screenShotPaths, - reduce3DViewportSize, attemptAction, + checkForScreenshot, + reduce3DViewportSize, + screenShotPaths, + test, + visitStudy, } from './utils'; test.beforeEach(async ({ page }) => { @@ -14,9 +14,11 @@ test.beforeEach(async ({ page }) => { }); test.describe('3D four up SEG hydration', async () => { - test('should properly hydrate SEG from 3D four up layout', async ({ page }) => { - await page.getByTestId('Layout').click(); - await page.getByTestId('3D four up').click(); + test('should properly hydrate SEG from 3D four up layout', async ({ + page, + mainToolbarPageObject, + }) => { + await mainToolbarPageObject.layoutSelection.threeDFourUp.click(); await attemptAction(() => reduce3DViewportSize(page), 10, 100); diff --git a/tests/SEGHydrationFromMPR.spec.ts b/tests/SEGHydrationFromMPR.spec.ts index 142385afc..4b3ccaa25 100644 --- a/tests/SEGHydrationFromMPR.spec.ts +++ b/tests/SEGHydrationFromMPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046'; @@ -7,11 +6,10 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should properly display MPR for MR', async ({ page }) => { +test('should properly display MPR for MR', async ({ page, mainToolbarPageObject }) => { await page.getByTestId('side-panel-header-right').click(); - await page.getByTestId('Layout').click(); - await page.getByTestId('MPR').click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.waitForTimeout(5000); await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprBeforeSEG); @@ -26,8 +24,7 @@ test('should properly display MPR for MR', async ({ page }) => { await page.waitForTimeout(5000); await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprAfterSegHydrated); - await page.getByTestId('Layout').click(); - await page.getByTestId('Axial Primary').click(); + await mainToolbarPageObject.layoutSelection.axialPrimary.click(); await page.waitForTimeout(5000); await checkForScreenshot( diff --git a/tests/SEGHydrationThenMPR.spec.ts b/tests/SEGHydrationThenMPR.spec.ts index 509c3981b..dd40fc6f3 100644 --- a/tests/SEGHydrationThenMPR.spec.ts +++ b/tests/SEGHydrationThenMPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046'; @@ -7,7 +6,7 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should properly display MPR for MR', async ({ page }) => { +test('should properly display MPR for MR', async ({ page, mainToolbarPageObject }) => { await page.getByTestId('side-panel-header-right').click(); await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); @@ -16,8 +15,7 @@ test('should properly display MPR for MR', async ({ page }) => { await page.waitForTimeout(5000); await checkForScreenshot(page, page, screenShotPaths.segHydrationThenMPR.segPostHydration); - await page.getByTestId('Layout').click(); - await page.getByTestId('Axial Primary').click(); + await mainToolbarPageObject.layoutSelection.axialPrimary.click(); await page.waitForTimeout(5000); await checkForScreenshot( diff --git a/tests/SEGNoHydrationThenMPR.spec.ts b/tests/SEGNoHydrationThenMPR.spec.ts index b5be3f586..0e3957026 100644 --- a/tests/SEGNoHydrationThenMPR.spec.ts +++ b/tests/SEGNoHydrationThenMPR.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046'; @@ -7,7 +6,7 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should launch MPR with unhydrated SEG', async ({ page }) => { +test('should launch MPR with unhydrated SEG', async ({ page, mainToolbarPageObject }) => { await page.getByTestId('side-panel-header-right').click(); await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); @@ -15,8 +14,7 @@ test('should launch MPR with unhydrated SEG', async ({ page }) => { await checkForScreenshot(page, page, screenShotPaths.segNoHydrationThenMPR.segNoHydrationPreMPR); - await page.getByTestId('Layout').click(); - await page.getByTestId('MPR').click(); + await mainToolbarPageObject.layoutSelection.MPR.click(); await page.waitForTimeout(5000); diff --git a/tests/Scoord3dProbe.spec.ts b/tests/Scoord3dProbe.spec.ts index 6b716ee77..524d47f78 100644 --- a/tests/Scoord3dProbe.spec.ts +++ b/tests/Scoord3dProbe.spec.ts @@ -1,17 +1,15 @@ -import { test, expect } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; -import { viewportLocator } from './utils/locators'; +import { checkForScreenshot, expect, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.7310.5101.860473186348887719777907797922'; const mode = 'viewer'; - + await visitStudy(page, studyInstanceUID, mode, 5000); - + // Log the actual URL that was loaded const currentUrl = page.url(); console.log(`✅ Actual page URL: ${currentUrl}\n`); - + // Remove any webpack dev server overlays that might be blocking interactions await page.evaluate(() => { const overlay = document.getElementById('webpack-dev-server-client-overlay'); @@ -21,23 +19,30 @@ test.beforeEach(async ({ page }) => { }); }); -test('should hydrate SCOORD3D probe measurements correctly', async ({ page }) => { +test('should hydrate SCOORD3D probe measurements correctly', async ({ + page, + viewportPageObject, +}) => { // Wait for the side panel to be visible and clickable await page.waitForTimeout(3000); - + // Navigate to the tracked measurements panel await page.getByTestId('side-panel-header-right').click({ timeout: 15000 }); await page.getByTestId('trackedMeasurements-btn').click(); - + // Double-click on the study browser thumbnail to load the SR await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); await page.waitForTimeout(2000); - + // Wait for the SR to load and stabilize before taking screenshot await page.waitForTimeout(1000); - + // Take screenshot before hydration - use viewport locator instead of full page - await checkForScreenshot(page, viewportLocator({ page, viewportId: 'default' }), screenShotPaths.scoord3dProbe.scoord3dProbePreHydration); + await checkForScreenshot( + page, + viewportPageObject.active.pane, + screenShotPaths.scoord3dProbe.scoord3dProbePreHydration + ); // Zoom in to better see the measurements await page.evaluate(() => { @@ -58,27 +63,31 @@ test('should hydrate SCOORD3D probe measurements correctly', async ({ page }) => viewport.render(); } }); - + // Wait for rendering to complete await page.waitForTimeout(1000); // Wait for the hydrate button to be visible and clickable await page.getByTestId('yes-hydrate-btn').waitFor({ state: 'visible', timeout: 15000 }); - + // Click the hydrate button to load the SCOORD3D probe measurements await page.getByTestId('yes-hydrate-btn').click(); - + // Wait for hydration to complete and rendering to stabilize await page.waitForTimeout(3000); - + // Take screenshot after hydration showing the probe measurements - use viewport locator - await checkForScreenshot(page, viewportLocator({ page, viewportId: 'default' }), screenShotPaths.scoord3dProbe.scoord3dProbePostHydration); - + await checkForScreenshot( + page, + viewportPageObject.active.pane, + screenShotPaths.scoord3dProbe.scoord3dProbePostHydration + ); + // Verify the measurements list has the correct probe measurements const measurementRows = page.getByTestId('data-row'); const rowCount = await measurementRows.count(); expect(rowCount).toBeGreaterThan(0); - + // Verify that the measurements are probe measurements (not other types) for (let i = 0; i < rowCount; i++) { const row = measurementRows.nth(i); @@ -111,19 +120,26 @@ test('should hydrate SCOORD3D probe measurements correctly', async ({ page }) => await page.getByTestId('data-row').first().click(); // Take screenshot showing the jump to measurement functionality - use viewport locator - await checkForScreenshot(page, viewportLocator({ page, viewportId: 'default' }), screenShotPaths.scoord3dProbe.scoord3dProbeJumpToMeasurement); + await checkForScreenshot( + page, + viewportPageObject.active.pane, + screenShotPaths.scoord3dProbe.scoord3dProbeJumpToMeasurement + ); }); -test('should display SCOORD3D probe measurements correctly', async ({ page }) => { +test('should display SCOORD3D probe measurements correctly', async ({ + page, + viewportPageObject, +}) => { // Wait for the side panel to be visible and clickable await page.waitForTimeout(3000); - + // First hydrate the SR to load the measurements await page.getByTestId('side-panel-header-right').click({ timeout: 15000 }); await page.getByTestId('trackedMeasurements-btn').click(); await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); await page.waitForTimeout(2000); - + // Wait for the hydrate button to be visible and clickable await page.getByTestId('yes-hydrate-btn').waitFor({ state: 'visible', timeout: 15000 }); await page.getByTestId('yes-hydrate-btn').click(); @@ -147,18 +163,22 @@ test('should display SCOORD3D probe measurements correctly', async ({ page }) => viewport.render(); } }); - + // Wait for rendering to complete before taking screenshot await page.waitForTimeout(2000); // Take screenshot showing the SCOORD3D probe measurements rendered correctly - use viewport locator - await checkForScreenshot(page, viewportLocator({ page, viewportId: 'default' }), screenShotPaths.scoord3dProbe.scoord3dProbeDisplayedCorrectly); - + await checkForScreenshot( + page, + viewportPageObject.active.pane, + screenShotPaths.scoord3dProbe.scoord3dProbeDisplayedCorrectly + ); + // Verify the measurements list has the correct probe measurements and not others const measurementRows = page.getByTestId('data-row'); const rowCount = await measurementRows.count(); expect(rowCount).toBeGreaterThan(0); - + // Verify that the measurements are probe measurements (not other types like rectangle) for (let i = 0; i < rowCount; i++) { const row = measurementRows.nth(i); diff --git a/tests/ScoordRectangle.spec.ts b/tests/ScoordRectangle.spec.ts index 38dab4ac7..59ecdc00d 100644 --- a/tests/ScoordRectangle.spec.ts +++ b/tests/ScoordRectangle.spec.ts @@ -1,17 +1,15 @@ -import { test, expect } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; -import { viewportLocator } from './utils/locators'; +import { checkForScreenshot, expect, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.2.840.113654.2.55.242841386983064378162007136685545369722'; const mode = 'viewer'; - + await visitStudy(page, studyInstanceUID, mode, 5000); - + // Log the actual URL that was loaded const currentUrl = page.url(); console.log(`✅ Actual page URL: ${currentUrl}\n`); - + // Remove any webpack dev server overlays that might be blocking interactions await page.evaluate(() => { const overlay = document.getElementById('webpack-dev-server-client-overlay'); @@ -22,23 +20,30 @@ test.beforeEach(async ({ page }) => { }); // -test('should hydrate SCOORD rectangle measurements correctly', async ({ page }) => { +test('should hydrate SCOORD rectangle measurements correctly', async ({ + page, + viewportPageObject, +}) => { // Wait for the side panel to be visible and clickable await page.waitForTimeout(3000); - + // Navigate to the tracked measurements panel await page.getByTestId('side-panel-header-right').click({ timeout: 15000 }); await page.getByTestId('trackedMeasurements-btn').click(); - + // Double-click on the study browser thumbnail to load the SR await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); await page.waitForTimeout(2000); - + // Wait for the SR to load and stabilize before taking screenshot await page.waitForTimeout(1000); - + // Take screenshot before hydration - use viewport locator instead of full page - await checkForScreenshot(page, viewportLocator({ page, viewportId: 'default' }), screenShotPaths.scoordRectangle.scoordRectanglePreHydration); + await checkForScreenshot( + page, + viewportPageObject.active.pane, + screenShotPaths.scoordRectangle.scoordRectanglePreHydration + ); // Zoom in to better see the measurements await page.evaluate(() => { @@ -59,27 +64,31 @@ test('should hydrate SCOORD rectangle measurements correctly', async ({ page }) viewport.render(); } }); - + // Wait for rendering to complete await page.waitForTimeout(1000); // Wait for the hydrate button to be visible and clickable await page.getByTestId('yes-hydrate-btn').waitFor({ state: 'visible', timeout: 15000 }); - + // Click the hydrate button to load the SCOORD rectangle measurements await page.getByTestId('yes-hydrate-btn').click(); - + // Wait for hydration to complete and rendering to stabilize await page.waitForTimeout(3000); - + // Take screenshot after hydration showing the rectangle measurements - use viewport locator - await checkForScreenshot(page, viewportLocator({ page, viewportId: 'default' }), screenShotPaths.scoordRectangle.scoordRectanglePostHydration); - + await checkForScreenshot( + page, + viewportPageObject.active.pane, + screenShotPaths.scoordRectangle.scoordRectanglePostHydration + ); + // Verify the measurements list has the correct rectangle measurements const measurementRows = page.getByTestId('data-row'); const rowCount = await measurementRows.count(); expect(rowCount).toBeGreaterThan(0); - + // Verify that the measurements are rectangle measurements (not other types) for (let i = 0; i < rowCount; i++) { const row = measurementRows.nth(i); @@ -112,19 +121,26 @@ test('should hydrate SCOORD rectangle measurements correctly', async ({ page }) await page.getByTestId('data-row').first().click(); // Take screenshot showing the jump to measurement functionality - use viewport locator - await checkForScreenshot(page, viewportLocator({ page, viewportId: 'default' }), screenShotPaths.scoordRectangle.scoordRectangleJumpToMeasurement); + await checkForScreenshot( + page, + viewportPageObject.active.pane, + screenShotPaths.scoordRectangle.scoordRectangleJumpToMeasurement + ); }); -test('should display SCOORD rectangle measurements correctly', async ({ page }) => { +test('should display SCOORD rectangle measurements correctly', async ({ + page, + viewportPageObject, +}) => { // Wait for the side panel to be visible and clickable await page.waitForTimeout(3000); - + // First hydrate the SR to load the measurements await page.getByTestId('side-panel-header-right').click({ timeout: 15000 }); await page.getByTestId('trackedMeasurements-btn').click(); await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); await page.waitForTimeout(2000); - + // Wait for the hydrate button to be visible and clickable await page.getByTestId('yes-hydrate-btn').waitFor({ state: 'visible', timeout: 15000 }); await page.getByTestId('yes-hydrate-btn').click(); @@ -148,18 +164,22 @@ test('should display SCOORD rectangle measurements correctly', async ({ page }) viewport.render(); } }); - + // Wait for rendering to complete before taking screenshot await page.waitForTimeout(2000); // Take screenshot showing the SCOORD rectangle measurements rendered correctly - use viewport locator - await checkForScreenshot(page, viewportLocator({ page, viewportId: 'default' }), screenShotPaths.scoordRectangle.scoordRectangleDisplayedCorrectly); - + await checkForScreenshot( + page, + viewportPageObject.active.pane, + screenShotPaths.scoordRectangle.scoordRectangleDisplayedCorrectly + ); + // Verify the measurements list has the correct rectangle measurements and not others const measurementRows = page.getByTestId('data-row'); const rowCount = await measurementRows.count(); expect(rowCount).toBeGreaterThan(0); - + // Verify that the measurements are rectangle measurements (not other types like probe) for (let i = 0; i < rowCount; i++) { const row = measurementRows.nth(i); diff --git a/tests/SegmentationPanel.spec.ts b/tests/SegmentationPanel.spec.ts index 4cc86b4a6..ea715e770 100644 --- a/tests/SegmentationPanel.spec.ts +++ b/tests/SegmentationPanel.spec.ts @@ -1,5 +1,4 @@ -import { test, expect } from 'playwright-test-coverage'; -import { visitStudy } from './utils'; +import { expect, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { // Using same one as JumpToMeasurementMPR.spec.ts @@ -55,9 +54,11 @@ test('checks basic add, rename, delete segments from panel', async ({ page }) => await expect(page.getByTestId('data-row')).toHaveCount(0); }); -test('checks saved segmentations loads and jumps to slices', async ({ page }) => { - const viewportInfoBottomRight = page.getByTestId('viewport-overlay-bottom-right'); - +test('checks saved segmentations loads and jumps to slices', async ({ + page, + viewportPageObject, +}) => { + const viewportInfoBottomRight = viewportPageObject.active.overlayText.bottomRight; // Image loads on slice 1, confirm on slice 1 await expect(viewportInfoBottomRight).toContainText('1/', { timeout: 10000 }); diff --git a/tests/Spline.spec.ts b/tests/Spline.spec.ts index f22d508e4..c87493bc3 100644 --- a/tests/Spline.spec.ts +++ b/tests/Spline.spec.ts @@ -1,5 +1,4 @@ -import { test } from 'playwright-test-coverage'; -import { visitStudy, checkForScreenshot, screenShotPaths, simulateClicksOnElement } from './utils'; +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; test.beforeEach(async ({ page }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; @@ -7,39 +6,20 @@ test.beforeEach(async ({ page }) => { await visitStudy(page, studyInstanceUID, mode, 2000); }); -test('should display the spline tool', async ({ page }) => { - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('SplineROI').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas'); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 380, - y: 459, - }, - { - x: 420, - y: 396, - }, - { - x: 523, - y: 392, - }, - { - x: 581, - y: 447, - }, - { - x: 482, - y: 493, - }, - { - x: 383, - y: 461, - }, - ], - }); +test('should display the spline tool', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.measurementTools.splineROI.click(); + await viewportPageObject.active.clickAt([ + { x: 380, y: 459 }, + { x: 420, y: 396 }, + { x: 523, y: 392 }, + { x: 581, y: 447 }, + { x: 482, y: 493 }, + { x: 383, y: 461 }, + ]); await page.getByTestId('prompt-begin-tracking-yes-btn').click(); await checkForScreenshot(page, page, screenShotPaths.spline.splineDisplayedCorrectly); }); diff --git a/tests/TMTVAlignment.spec.ts b/tests/TMTVAlignment.spec.ts index 73d891351..611cd8e9c 100644 --- a/tests/TMTVAlignment.spec.ts +++ b/tests/TMTVAlignment.spec.ts @@ -1,54 +1,55 @@ -import { test, expect } from 'playwright-test-coverage'; -import { visitStudy, scrollVolumeViewport } from './utils'; +import { expect, scrollVolumeViewport, test, visitStudy } from './utils'; -test.skip('PT should show slice closest to CT', async ({ page }) => { +test.skip('PT should show slice closest to CT', async ({ page, viewportPageObject }) => { const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; const mode = 'tmtv'; await visitStudy(page, studyInstanceUID, mode); - const vp = page.getByTestId('viewport-pane'); + const getNthViewportPane = (index: number) => viewportPageObject.getNth(index).pane; // Sagittal - await expect(vp.nth(1)).toContainText('257/512', { useInnerText: true }); // Should default i 257 - await expect.soft(vp.nth(4)).toContainText('97/192'); + await expect(getNthViewportPane(1)).toContainText('257/512', { + useInnerText: true, + }); // Should default i 257 + await expect.soft(getNthViewportPane(4)).toContainText('97/192'); await scrollVolumeViewport(page, 'ctSAGITTAL', -1); // CT i 256 - await expect(vp.nth(1)).toContainText('256/512'); - await expect.soft(vp.nth(4)).toContainText('96/192'); + await expect(getNthViewportPane(1)).toContainText('256/512'); + await expect.soft(getNthViewportPane(4)).toContainText('96/192'); await scrollVolumeViewport(page, 'ctSAGITTAL', -1); // CT i 255 - await expect(vp.nth(1)).toContainText('255/512'); - await expect.soft(vp.nth(4)).toContainText('95/192'); + await expect(getNthViewportPane(1)).toContainText('255/512'); + await expect.soft(getNthViewportPane(4)).toContainText('95/192'); await scrollVolumeViewport(page, 'ctSAGITTAL', -1); // CT i 254 - await expect(vp.nth(1)).toContainText('254/512'); - await expect.soft(vp.nth(4)).toContainText('95/192'); + await expect(getNthViewportPane(1)).toContainText('254/512'); + await expect.soft(getNthViewportPane(4)).toContainText('95/192'); await scrollVolumeViewport(page, 'ctSAGITTAL', -1); // CT i 253 - await expect(vp.nth(1)).toContainText('253/512'); - await expect.soft(vp.nth(4)).toContainText('94/192'); + await expect(getNthViewportPane(1)).toContainText('253/512'); + await expect.soft(getNthViewportPane(4)).toContainText('94/192'); await scrollVolumeViewport(page, 'ctSAGITTAL', -1); // CT i 252 - await expect(vp.nth(1)).toContainText('252/512'); - await expect.soft(vp.nth(4)).toContainText('94/192'); + await expect(getNthViewportPane(1)).toContainText('252/512'); + await expect.soft(getNthViewportPane(4)).toContainText('94/192'); await scrollVolumeViewport(page, 'ctSAGITTAL', -1); // CT i 251 - await expect(vp.nth(1)).toContainText('251/512'); - await expect.soft(vp.nth(4)).toContainText('93/192'); + await expect(getNthViewportPane(1)).toContainText('251/512'); + await expect.soft(getNthViewportPane(4)).toContainText('93/192'); // Coronal - await expect(vp.nth(2)).toContainText('256/512'); // Should default i 256 - await expect.soft(vp.nth(5)).toContainText('96/192'); + await expect(getNthViewportPane(2)).toContainText('256/512'); // Should default i 256 + await expect.soft(getNthViewportPane(5)).toContainText('96/192'); await scrollVolumeViewport(page, 'ctCORONAL', -1); // CT i 255 - await expect(vp.nth(2)).toContainText('255/512'); - await expect.soft(vp.nth(5)).toContainText('96/192'); + await expect(getNthViewportPane(2)).toContainText('255/512'); + await expect.soft(getNthViewportPane(5)).toContainText('96/192'); await scrollVolumeViewport(page, 'ctCORONAL', -1); // CT i 254 - await expect(vp.nth(2)).toContainText('254/512'); - await expect.soft(vp.nth(5)).toContainText('95/192'); + await expect(getNthViewportPane(2)).toContainText('254/512'); + await expect.soft(getNthViewportPane(5)).toContainText('95/192'); await scrollVolumeViewport(page, 'ctCORONAL', -1); // CT i 253 - await expect(vp.nth(2)).toContainText('253/512'); - await expect.soft(vp.nth(5)).toContainText('95/192'); + await expect(getNthViewportPane(2)).toContainText('253/512'); + await expect.soft(getNthViewportPane(5)).toContainText('95/192'); await scrollVolumeViewport(page, 'ctCORONAL', -1); // CT i 252 - await expect(vp.nth(2)).toContainText('252/512'); - await expect.soft(vp.nth(5)).toContainText('94/192'); + await expect(getNthViewportPane(2)).toContainText('252/512'); + await expect.soft(getNthViewportPane(5)).toContainText('94/192'); await scrollVolumeViewport(page, 'ctCORONAL', -1); // CT i 251 - await expect(vp.nth(2)).toContainText('251/512'); - await expect.soft(vp.nth(5)).toContainText('94/192'); + await expect(getNthViewportPane(2)).toContainText('251/512'); + await expect.soft(getNthViewportPane(5)).toContainText('94/192'); await scrollVolumeViewport(page, 'ctCORONAL', -1); // CT i 250 - await expect(vp.nth(2)).toContainText('250/512'); - await expect.soft(vp.nth(5)).toContainText('93/192'); + await expect(getNthViewportPane(2)).toContainText('250/512'); + await expect.soft(getNthViewportPane(5)).toContainText('93/192'); }); diff --git a/tests/TMTVCSVReport.spec.ts b/tests/TMTVCSVReport.spec.ts index fc472fe1a..ae26065b6 100644 --- a/tests/TMTVCSVReport.spec.ts +++ b/tests/TMTVCSVReport.spec.ts @@ -1,9 +1,10 @@ -import { test, expect } from 'playwright-test-coverage'; -import { visitStudy, simulateNormalizedClickOnElement } from './utils/index'; -import { viewportLocator } from './utils/locators'; +import { expect, test, visitStudy } from './utils'; import { downloadAsString } from './utils/download'; -test('should create and download the TMTV CSV report correctly', async ({ page }) => { +test('should create and download the TMTV CSV report correctly', async ({ + page, + viewportPageObject, +}) => { const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; const mode = 'tmtv'; await visitStudy(page, studyInstanceUID, mode, 10000); @@ -11,10 +12,7 @@ test('should create and download the TMTV CSV report correctly', async ({ page } await page.getByTestId('addSegmentation').click(); await page.getByTestId('Brush-btn').click(); - await simulateNormalizedClickOnElement({ - locator: viewportLocator({ viewportId: 'ctAXIAL', page }), - normalizedPoint: { x: 0.5, y: 0.5 }, - }); + await viewportPageObject.getById('ctAXIAL').normalizedClickAt([{ x: 0.5, y: 0.5 }]); await page.waitForTimeout(5000); diff --git a/tests/TMTVModalityUnit.spec.ts b/tests/TMTVModalityUnit.spec.ts index 2a7e2bc48..d80f5e5b7 100644 --- a/tests/TMTVModalityUnit.spec.ts +++ b/tests/TMTVModalityUnit.spec.ts @@ -1,13 +1,9 @@ -import { test, expect } from 'playwright-test-coverage'; -import { - visitStudy, - simulateClicksOnElement, - getTMTVModalityUnit, - clearAllAnnotations, -} from './utils/index'; +import { expect, clearAllAnnotations, getTMTVModalityUnit, test, visitStudy } from './utils'; test.skip('pets where SUV cannot be calculated should show same unit in TMTV as in Basic Viewer.', async ({ page, + mainToolbarPageObject, + viewportPageObject, }) => { const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; const mode = 'tmtv'; @@ -17,31 +13,20 @@ test.skip('pets where SUV cannot be calculated should show same unit in TMTV as await page.getByTestId('side-panel-header-left').click(); // Change to image where SUV cannot be calculated - await page.getByTestId('viewport-grid').locator('canvas').nth(3).click(); + await viewportPageObject.getNth(3).normalizedClickAt([{ x: 0.5, y: 0.5 }]); await page.getByRole('button', { name: 'NAC' }).nth(1).dblclick(); // Wait for the new series to load await page.waitForLoadState('networkidle'); // Add ROI annotation - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('EllipticalROI').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas').first(); + mainToolbarPageObject.measurementTools.ellipticalROI.click(); await clearAllAnnotations(page); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 100, - y: 100, - }, - { - x: 150, - y: 150, - }, - ], - }); + await viewportPageObject.active.clickAt([ + { x: 100, y: 100 }, + { x: 150, y: 150 }, + ]); const modalityUnit = await getTMTVModalityUnit(page); diff --git a/tests/TMTVRecalculate.spec.ts b/tests/TMTVRecalculate.spec.ts index 8110d6692..ea363e9c4 100644 --- a/tests/TMTVRecalculate.spec.ts +++ b/tests/TMTVRecalculate.spec.ts @@ -1,31 +1,23 @@ -import { expect, test } from 'playwright-test-coverage'; -import { visitStudy, simulateClicksOnElement, getSUV, clearAllAnnotations } from './utils/index'; +import { expect, clearAllAnnotations, getSUV, test, visitStudy } from './utils'; -test.skip('should update SUV values correctly.', async ({ page }) => { +test.skip('should update SUV values correctly.', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; const mode = 'tmtv'; await visitStudy(page, studyInstanceUID, mode, 10000); // Create ROI await page.getByTestId('petSUV-btn').click(); - await page.getByTestId('MeasurementTools-split-button-secondary').click(); - await page.getByTestId('EllipticalROI').click(); - const locator = page.getByTestId('viewport-pane').locator('canvas').first(); + await mainToolbarPageObject.measurementTools.ellipticalROI.click(); await clearAllAnnotations(page); - await simulateClicksOnElement({ - locator, - points: [ - { - x: 100, - y: 100, - }, - { - x: 150, - y: 150, - }, - ], - }); + await viewportPageObject.active.clickAt([ + { x: 100, y: 100 }, + { x: 150, y: 150 }, + ]); // Get current SUV text let oldSUV = await getSUV(page); diff --git a/tests/TMTVSUV.spec.ts b/tests/TMTVSUV.spec.ts index 552847398..518dddbba 100644 --- a/tests/TMTVSUV.spec.ts +++ b/tests/TMTVSUV.spec.ts @@ -1,14 +1,14 @@ -import { test, expect } from 'playwright-test-coverage'; -import { visitStudy, simulateNormalizedClickOnElement } from './utils/index'; -import { viewportLocator } from './utils/locators'; -import { downloadAsString } from './utils/download'; +import { expect, test, visitStudy } from './utils'; -test('should restrict the percentage of max SUV to be between 0 and 1', async ({ page }) => { +test('should restrict the percentage of max SUV to be between 0 and 1', async ({ + page, + viewportPageObject, +}) => { const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501'; const mode = 'tmtv'; await visitStudy(page, studyInstanceUID, mode, 10000); - await viewportLocator({ viewportId: 'ptAXIAL', page }).click(); + await viewportPageObject.getById('ptAXIAL').normalizedClickAt([{ x: 0.5, y: 0.5 }]); await page.getByTestId('addSegmentation').click(); await page.getByTestId('RectangleROIStartEndThreshold-btn').click(); diff --git a/tests/pages/MainToolbarPageObject.ts b/tests/pages/MainToolbarPageObject.ts new file mode 100644 index 000000000..8422fcc1d --- /dev/null +++ b/tests/pages/MainToolbarPageObject.ts @@ -0,0 +1,287 @@ +import { Page } from '@playwright/test'; + +export class MainToolbarPageObject { + readonly page: Page; + + constructor(page: Page) { + this.page = page; + } + + get layoutSelection() { + const page = this.page; + + const button = page.getByTestId('Layout'); + const layoutSelection = { + button, + async click() { + await button.click(); + }, + }; + + return { + ...layoutSelection, + get axialPrimary() { + const button = page.getByTestId('Axial Primary'); + return { + button, + async click() { + await layoutSelection.click(); + await button.click(); + }, + }; + }, + get MPR() { + const button = page.getByTestId('MPR'); + return { + button, + async click() { + await layoutSelection.click(); + await button.click(); + }, + }; + }, + get threeDFourUp() { + const button = page.getByTestId('3D four up'); + return { + button, + async click() { + await layoutSelection.click(); + await button.click(); + }, + }; + }, + get threeDMain() { + const button = page.getByTestId('3D main'); + return { + button, + async click() { + await layoutSelection.click(); + await button.click(); + }, + }; + }, + get threeDOnly() { + const button = page.getByTestId('3D only'); + return { + button, + async click() { + await layoutSelection.click(); + await button.click(); + }, + }; + }, + get threeDPrimary() { + const button = page.getByTestId('3D primary'); + return { + button, + async click() { + await layoutSelection.click(); + await button.click(); + }, + }; + }, + }; + } + + get measurementTools() { + const page = this.page; + + const button = page.getByTestId('MeasurementTools-split-button-secondary'); + const measurementTools = { + button, + async click() { + await button.click(); + }, + }; + + return { + ...measurementTools, + get arrowAnnotate() { + const button = page.getByTestId('ArrowAnnotate'); + return { + button, + async click() { + await measurementTools.click(); + await button.click(); + }, + }; + }, + get bidirectional() { + const button = page.getByTestId('Bidirectional'); + return { + button, + async click() { + await measurementTools.click(); + await button.click(); + }, + }; + }, + get circleROI() { + const button = page.getByTestId('CircleROI'); + return { + button, + async click() { + await measurementTools.click(); + await button.click(); + }, + }; + }, + get ellipticalROI() { + const button = page.getByTestId('EllipticalROI'); + return { + button, + async click() { + await measurementTools.click(); + await button.click(); + }, + }; + }, + get length() { + const button = page.locator('[data-cy="Length"][role="menuitem"]'); + return { + button, + async click() { + await measurementTools.click(); + await button.click(); + }, + }; + }, + get livewireContour() { + const button = page.getByTestId('LivewireContour'); + return { + button, + async click() { + await measurementTools.click(); + await button.click(); + }, + }; + }, + get rectangleROI() { + const button = page.getByTestId('RectangleROI'); + return { + button, + async click() { + await measurementTools.click(); + await button.click(); + }, + }; + }, + get splineROI() { + const button = page.getByTestId('SplineROI'); + return { + button, + async click() { + await measurementTools.click(); + await button.click(); + }, + }; + }, + }; + } + + get moreTools() { + const page = this.page; + + const button = page.getByTestId('MoreTools-split-button-secondary'); + const moreTools = { + button, + async click() { + await button.click(); + }, + }; + + return { + ...moreTools, + get angle() { + const button = page.getByTestId('Angle'); + return { + button, + async click() { + await moreTools.click(); + await button.click(); + }, + }; + }, + get cobbAngle() { + const button = page.getByTestId('CobbAngle'); + return { + button, + async click() { + await moreTools.click(); + await button.click(); + }, + }; + }, + get flipHorizontal() { + const button = page.getByTestId('flipHorizontal'); + return { + button, + async click() { + await moreTools.click(); + await button.click(); + }, + }; + }, + get invert() { + const button = page.getByTestId('invert'); + return { + button, + async click() { + await moreTools.click(); + await button.click(); + }, + }; + }, + get probe() { + const button = page.getByTestId('Probe'); + return { + button, + async click() { + await moreTools.click(); + await button.click(); + }, + }; + }, + get reset() { + const button = page.locator('[data-cy="Reset"][role="menuitem"]'); + return { + button, + async click() { + await moreTools.click(); + await button.click(); + }, + }; + }, + get rotateRight() { + const button = page.getByTestId('rotate-right'); + return { + button, + async click() { + await moreTools.click(); + await button.click(); + }, + }; + }, + get tagBrowser() { + const button = page.getByTestId('TagBrowser'); + return { + button, + async click() { + await moreTools.click(); + await button.click(); + }, + }; + }, + }; + } + + get panTool() { + const button = this.page.getByTestId('Pan'); + return { + button, + async click() { + await button.click(); + }, + }; + } +} diff --git a/tests/pages/ViewportPageObject.ts b/tests/pages/ViewportPageObject.ts new file mode 100644 index 000000000..cb022f826 --- /dev/null +++ b/tests/pages/ViewportPageObject.ts @@ -0,0 +1,189 @@ +import { Locator, Page } from '@playwright/test'; +import { + simulateClicksOnElement, + simulateDoubleClickOnElement, + simulateNormalizedClicksOnElement, + simulateNormalizedDragOnElement, +} from '../utils'; + +type SvgInnerElement = 'circle' | 'path' | 'd'; + +type NormalizedDragParams = { + start: { x: number; y: number }; + end: { x: number; y: number }; + config?: { button?: 'left' | 'right' | 'middle'; delay?: number; steps?: number }; +}; + +export interface IViewportPageObject { + doubleClickAt: (point: { x: number; y: number }) => Promise; + clickAt: ( + points: { x: number; y: number }[], + button?: 'left' | 'right' | 'middle' + ) => Promise; + normalizedClickAt: ( + normalizedPoints: { x: number; y: number }[], + button?: 'left' | 'right' | 'middle' + ) => Promise; + normalizedDragAt: (params: NormalizedDragParams) => Promise; + orientationMarkers: { + topMid: Locator; + leftMid: Locator; + rightMid: Locator; + bottomMid: Locator; + }; + overlayText: { + topLeft: Locator; + topRight: Locator; + bottomLeft: Locator; + bottomRight: Locator; + }; + overlayMenu: { + dataOverlay: { + button: Locator; + click: () => Promise; + }; + orientation: { + button: Locator; + click: () => Promise; + }; + windowLevel: { + button: Locator; + click: () => Promise; + }; + }; + pane: Locator; + svg: (innerElement?: SvgInnerElement) => Locator; +} + +export class ViewportPageObject { + readonly page: Page; + + constructor(page: Page) { + this.page = page; + } + + private getOrientationMarkers(viewport: Locator) { + return { + topMid: viewport.locator('.top-mid.orientation-marker'), + leftMid: viewport.locator('.left-mid.orientation-marker'), + rightMid: viewport.locator('.right-mid.orientation-marker'), + bottomMid: viewport.locator('.bottom-mid.orientation-marker'), + }; + } + + private getOverlayText(viewport: Locator) { + return { + topLeft: viewport.getByTestId('viewport-overlay-top-left'), + topRight: viewport.getByTestId('viewport-overlay-top-right'), + bottomLeft: viewport.getByTestId('viewport-overlay-bottom-left'), + bottomRight: viewport.getByTestId('viewport-overlay-bottom-right'), + }; + } + + private getOverlayMenu(viewport: Locator) { + return { + get dataOverlay() { + const button = viewport.locator('[data-cy^="dataOverlayMenu"]').first(); + return { + button, + async click() { + await button.click(); + }, + }; + }, + get orientation() { + const button = viewport.locator('[data-cy^="orientationMenu"]'); + return { + button, + async click() { + await button.click(); + }, + }; + }, + get windowLevel() { + const button = viewport.locator('[data-cy^="windowLevelMenu"]'); + return { + button, + async click() { + await button.click(); + }, + }; + }, + }; + } + + private getSvg(viewport: Locator, innerElement?: SvgInnerElement) { + return viewport.locator(`svg.svg-layer${innerElement ? ` ${innerElement}` : ''}`); + } + + private viewportPageObjectFactory(viewport: Locator): IViewportPageObject { + return { + doubleClickAt: async (point: { x: number; y: number }) => { + await simulateDoubleClickOnElement({ + locator: viewport, + point, + }); + }, + clickAt: async (points: { x: number; y: number }[], button?: 'left' | 'right' | 'middle') => { + await simulateClicksOnElement({ + locator: viewport, + points, + button, + }); + }, + normalizedClickAt: async ( + normalizedPoints: { x: number; y: number }[], + button?: 'left' | 'right' | 'middle' + ) => { + await simulateNormalizedClicksOnElement({ + locator: viewport, + normalizedPoints, + button, + }); + }, + normalizedDragAt: async (params: NormalizedDragParams) => { + await simulateNormalizedDragOnElement({ + locator: viewport, + start: params.start, + end: params.end, + button: params.config?.button, + delay: params.config?.delay, + steps: params.config?.steps, + }); + }, + orientationMarkers: this.getOrientationMarkers(viewport), + overlayText: this.getOverlayText(viewport), + overlayMenu: this.getOverlayMenu(viewport), + pane: viewport, + svg: (innerElement?: SvgInnerElement) => { + return this.getSvg(viewport, innerElement); + }, + }; + } + + get active(): IViewportPageObject { + const viewport = this.page.locator('[data-cy="viewport-pane"][data-is-active="true"]'); + return this.viewportPageObjectFactory(viewport); + } + + async getAll(): Promise { + const viewports = await this.page.getByTestId('viewport-pane').all(); + return viewports.map(viewport => this.viewportPageObjectFactory(viewport)); + } + + getNth(index: number): IViewportPageObject { + const viewport = this.page.getByTestId('viewport-pane').nth(index); + return this.viewportPageObjectFactory(viewport); + } + + getById(viewportId: string): IViewportPageObject { + const viewport = this.page.locator( + `[data-cy="viewport-pane"]:has(div[data-viewportid="${viewportId}"])` + ); + return this.viewportPageObjectFactory(viewport); + } + + get grid() { + return this.page.getByTestId('viewport-grid'); + } +} diff --git a/tests/pages/index.ts b/tests/pages/index.ts new file mode 100644 index 000000000..383eb03c0 --- /dev/null +++ b/tests/pages/index.ts @@ -0,0 +1,4 @@ +import { MainToolbarPageObject } from './MainToolbarPageObject'; +import { ViewportPageObject } from './ViewportPageObject'; + +export { MainToolbarPageObject, ViewportPageObject }; diff --git a/tests/utils/fixture.ts b/tests/utils/fixture.ts new file mode 100644 index 000000000..1fc467c13 --- /dev/null +++ b/tests/utils/fixture.ts @@ -0,0 +1,18 @@ +import { test as base } from 'playwright-test-coverage'; +import { MainToolbarPageObject, ViewportPageObject } from '../pages'; + +type PageObjects = { + mainToolbarPageObject: MainToolbarPageObject; + viewportPageObject: ViewportPageObject; +}; + +export const test = base.extend({ + mainToolbarPageObject: async ({ page }, use) => { + await use(new MainToolbarPageObject(page)); + }, + viewportPageObject: async ({ page }, use) => { + await use(new ViewportPageObject(page)); + }, +}); + +export { expect } from 'playwright-test-coverage'; diff --git a/tests/utils/index.ts b/tests/utils/index.ts index 8b8334325..7501286f9 100644 --- a/tests/utils/index.ts +++ b/tests/utils/index.ts @@ -7,6 +7,7 @@ import { simulateNormalizedClickOnElement, simulateNormalizedClicksOnElement, } from './simulateClicksOnElement'; +import { simulateNormalizedDragOnElement } from './simulateDragOnElement'; import { reduce3DViewportSize } from './reduce3DviewportSize'; import { getMousePosition, initializeMousePositionTracker } from './mouseUtils'; import { getSUV } from './getSUV'; @@ -15,6 +16,7 @@ import { clearAllAnnotations } from './clearAllAnnotations'; import { scrollVolumeViewport } from './scrollVolumeViewport'; import { attemptAction } from './attemptAction'; import { addLengthMeasurement } from './addLengthMeasurement'; +import { test, expect } from './fixture'; export { visitStudy, @@ -24,6 +26,7 @@ export { simulateDoubleClickOnElement, simulateNormalizedClickOnElement, simulateNormalizedClicksOnElement, + simulateNormalizedDragOnElement, reduce3DViewportSize, getMousePosition, initializeMousePositionTracker, @@ -33,4 +36,6 @@ export { scrollVolumeViewport, attemptAction, addLengthMeasurement, + test, + expect, }; diff --git a/tests/utils/locators.ts b/tests/utils/locators.ts deleted file mode 100644 index 00f2ca86b..000000000 --- a/tests/utils/locators.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Locator, Page } from '@playwright/test'; - -export const viewportLocator = ({ - page, - viewportId, -}: { - page: Page; - viewportId: string; -}): Locator => { - return page.locator(`css=div[data-viewportid="${viewportId}"]`); -}; - -export const viewportSVGLocator = ({ - page, - viewportId, -}: { - page: Page; - viewportId: string; -}): Locator => { - return page.locator(`css=div[data-viewportid="${viewportId}"] svg`); -}; - -export const viewportSVGPathLocator = ({ - page, - viewportId, -}: { - page: Page; - viewportId: string; -}): Locator => { - return page.locator(`css=div[data-viewportid="${viewportId}"] svg path`); -};