tests(Playwright): Full implementation of Page Object Models (POMs) to Playwright tests (#5608)
This commit is contained in:
parent
7b12dcf048
commit
d917e74e68
@ -12,8 +12,14 @@ export function UntrackSeriesModal({ hide, onConfirm, message }) {
|
|||||||
</div>
|
</div>
|
||||||
<FooterAction className="mt-4">
|
<FooterAction className="mt-4">
|
||||||
<FooterAction.Right>
|
<FooterAction.Right>
|
||||||
<FooterAction.Secondary onClick={hide}>Cancel</FooterAction.Secondary>
|
<FooterAction.Secondary
|
||||||
|
dataCY="untracked-series-modal-cancel-button"
|
||||||
|
onClick={hide}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</FooterAction.Secondary>
|
||||||
<FooterAction.Primary
|
<FooterAction.Primary
|
||||||
|
dataCY="untracked-series-modal-confirm-button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onConfirm();
|
onConfirm();
|
||||||
hide();
|
hide();
|
||||||
|
|||||||
@ -315,6 +315,7 @@ const DataRowComponent = React.forwardRef<HTMLDivElement, DataRowProps>(
|
|||||||
isSelected || !isVisible ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'
|
isSelected || !isVisible ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'
|
||||||
}`}
|
}`}
|
||||||
aria-label={isVisible ? t('Hide') : t('Show')}
|
aria-label={isVisible ? t('Hide') : t('Show')}
|
||||||
|
dataCY="data-row-visibility-toggle"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onToggleVisibility(e);
|
onToggleVisibility(e);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button } from '../Button/Button';
|
import { Button, ButtonProps } from '../Button/Button';
|
||||||
import { cn } from '../../lib/utils';
|
import { cn } from '../../lib/utils';
|
||||||
|
|
||||||
interface FooterActionProps {
|
interface FooterActionProps {
|
||||||
@ -7,7 +7,7 @@ interface FooterActionProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActionProps extends FooterActionProps {
|
interface ActionProps extends ButtonProps {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
@ -60,12 +60,18 @@ FooterAction.Right = ({ children }: FooterActionProps) => {
|
|||||||
FooterAction.Right.displayName = 'FooterAction.Right';
|
FooterAction.Right.displayName = 'FooterAction.Right';
|
||||||
|
|
||||||
// Primary action: Solid button (default)
|
// Primary action: Solid button (default)
|
||||||
FooterAction.Primary = ({ children, onClick, className = 'min-w-[80px]' }: ActionProps) => {
|
FooterAction.Primary = ({
|
||||||
|
children,
|
||||||
|
onClick,
|
||||||
|
className = 'min-w-[80px]',
|
||||||
|
...rest
|
||||||
|
}: ActionProps) => {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className={className}
|
className={className}
|
||||||
|
{...rest}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Button>
|
</Button>
|
||||||
@ -74,12 +80,18 @@ FooterAction.Primary = ({ children, onClick, className = 'min-w-[80px]' }: Actio
|
|||||||
FooterAction.Primary.displayName = 'FooterAction.Primary';
|
FooterAction.Primary.displayName = 'FooterAction.Primary';
|
||||||
|
|
||||||
// Secondary action: Ghost button
|
// Secondary action: Ghost button
|
||||||
FooterAction.Secondary = ({ children, onClick, className = 'min-w-[80px]' }: ActionProps) => {
|
FooterAction.Secondary = ({
|
||||||
|
children,
|
||||||
|
onClick,
|
||||||
|
className = 'min-w-[80px]',
|
||||||
|
...rest
|
||||||
|
}: ActionProps) => {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className={className}
|
className={className}
|
||||||
|
{...rest}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Button>
|
</Button>
|
||||||
@ -88,12 +100,13 @@ FooterAction.Secondary = ({ children, onClick, className = 'min-w-[80px]' }: Act
|
|||||||
FooterAction.Secondary.displayName = 'FooterAction.Secondary';
|
FooterAction.Secondary.displayName = 'FooterAction.Secondary';
|
||||||
|
|
||||||
// Tertiary action: Ghost button with different styling
|
// Tertiary action: Ghost button with different styling
|
||||||
FooterAction.Auxiliary = ({ children, onClick, className }: ActionProps) => {
|
FooterAction.Auxiliary = ({ children, onClick, className, ...rest }: ActionProps) => {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className={className}
|
className={className}
|
||||||
|
{...rest}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -88,7 +88,12 @@ const Thumbnail = ({
|
|||||||
loadingProgress && loadingProgress < 1 && 'bg-primary/25'
|
loadingProgress && loadingProgress < 1 && 'bg-primary/25'
|
||||||
)}
|
)}
|
||||||
></div>
|
></div>
|
||||||
<div className="text-[11px] font-semibold text-white">{modality}</div>
|
<div
|
||||||
|
className="text-[11px] font-semibold text-white"
|
||||||
|
data-cy="series-modality-label"
|
||||||
|
>
|
||||||
|
{modality}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* top right */}
|
{/* top right */}
|
||||||
@ -139,7 +144,10 @@ const Thumbnail = ({
|
|||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipContent>{description}</TooltipContent>
|
<TooltipContent>{description}</TooltipContent>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<div className="min-h-[18px] w-[128px] overflow-hidden text-ellipsis whitespace-nowrap pb-0.5 pl-1 text-left text-[12px] font-normal leading-4 text-white">
|
<div
|
||||||
|
className="min-h-[18px] w-[128px] overflow-hidden text-ellipsis whitespace-nowrap pb-0.5 pl-1 text-left text-[12px] font-normal leading-4 text-white"
|
||||||
|
data-cy="series-description-label"
|
||||||
|
>
|
||||||
{description}
|
{description}
|
||||||
</div>
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
@ -180,11 +188,19 @@ const Thumbnail = ({
|
|||||||
></div>
|
></div>
|
||||||
<div className="flex h-full w-[calc(100%-12px)] flex-col justify-start">
|
<div className="flex h-full w-[calc(100%-12px)] flex-col justify-start">
|
||||||
<div className="flex items-center gap-[7px]">
|
<div className="flex items-center gap-[7px]">
|
||||||
<div className="text-[13px] font-semibold text-white">{modality}</div>
|
<div
|
||||||
|
className="text-[13px] font-semibold text-white"
|
||||||
|
data-cy="series-modality-label"
|
||||||
|
>
|
||||||
|
{modality}
|
||||||
|
</div>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipContent>{description}</TooltipContent>
|
<TooltipContent>{description}</TooltipContent>
|
||||||
<TooltipTrigger className="w-full overflow-hidden">
|
<TooltipTrigger className="w-full overflow-hidden">
|
||||||
<div className="max-w-[160px] overflow-hidden overflow-ellipsis whitespace-nowrap text-left text-[13px] font-normal text-white">
|
<div
|
||||||
|
className="max-w-[160px] overflow-hidden overflow-ellipsis whitespace-nowrap text-left text-[13px] font-normal text-white"
|
||||||
|
data-cy="series-description-label"
|
||||||
|
>
|
||||||
{description}
|
{description}
|
||||||
</div>
|
</div>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|||||||
@ -8,6 +8,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the angle tool', async ({
|
test('should display the angle tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -17,6 +18,6 @@ test('should display the angle tool', async ({
|
|||||||
{ x: 450, y: 250 },
|
{ x: 450, y: 250 },
|
||||||
{ x: 550, y: 300 },
|
{ x: 550, y: 300 },
|
||||||
]);
|
]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.angle.angleDisplayedCorrectly);
|
await checkForScreenshot(page, page, screenShotPaths.angle.angleDisplayedCorrectly);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,10 +8,12 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the arrow tool and allow free-form text to be entered', async ({
|
test('should display the arrow tool and allow free-form text to be entered', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await page.getByTestId('trackedMeasurements-btn').click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
|
|
||||||
await mainToolbarPageObject.measurementTools.arrowAnnotate.click();
|
await mainToolbarPageObject.measurementTools.arrowAnnotate.click();
|
||||||
|
|
||||||
@ -20,10 +22,11 @@ test('should display the arrow tool and allow free-form text to be entered', asy
|
|||||||
{ x: 344, y: 232 },
|
{ x: 344, y: 232 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await page.getByTestId('dialog-input').fill('Ringo Starr was the drummer for The Beatles');
|
await DOMOverlayPageObject.dialog.input.fillAndSave(
|
||||||
await page.getByTestId('input-dialog-save-button').click();
|
'Ringo Starr was the drummer for The Beatles'
|
||||||
|
);
|
||||||
|
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
|
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
@ -37,8 +40,7 @@ test('should display the arrow tool and allow free-form text to be entered', asy
|
|||||||
|
|
||||||
await viewportPageObject.active.doubleClickAt({ 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 DOMOverlayPageObject.dialog.input.fillAndSave('Neil Peart was the drummer for Rush');
|
||||||
await page.getByTestId('input-dialog-save-button').click();
|
|
||||||
|
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
@ -50,11 +52,9 @@ test('should display the arrow tool and allow free-form text to be entered', asy
|
|||||||
|
|
||||||
// Now edit the label and the text should not change.
|
// Now edit the label and the text should not change.
|
||||||
|
|
||||||
await page.getByTestId('actionsMenuTrigger').click();
|
await rightPanelPageObject.measurementsPanel.panel
|
||||||
await page.getByTestId('Rename').click();
|
.nthMeasurement(0)
|
||||||
|
.actions.rename('Drummer annotation arrow');
|
||||||
await page.getByTestId('dialog-input').fill('Drummer annotation arrow');
|
|
||||||
await page.getByTestId('input-dialog-save-button').click();
|
|
||||||
|
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the bidirectional tool', async ({
|
test('should display the bidirectional tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -16,7 +17,7 @@ test('should display the bidirectional tool', async ({
|
|||||||
{ x: 405, y: 277 },
|
{ x: 405, y: 277 },
|
||||||
{ x: 515, y: 339 },
|
{ x: 515, y: 339 },
|
||||||
]);
|
]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(
|
await checkForScreenshot(
|
||||||
page,
|
page,
|
||||||
page,
|
page,
|
||||||
|
|||||||
@ -8,6 +8,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the circle tool', async ({
|
test('should display the circle tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -16,6 +17,6 @@ test('should display the circle tool', async ({
|
|||||||
{ x: 480, y: 205 },
|
{ x: 480, y: 205 },
|
||||||
{ x: 488, y: 247 },
|
{ x: 488, y: 247 },
|
||||||
]);
|
]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.circle.circleDisplayedCorrectly);
|
await checkForScreenshot(page, page, screenShotPaths.circle.circleDisplayedCorrectly);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,6 +8,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the cobb angle tool', async ({
|
test('should display the cobb angle tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -18,6 +19,6 @@ test('should display the cobb angle tool', async ({
|
|||||||
{ x: 527, y: 293 },
|
{ x: 527, y: 293 },
|
||||||
{ x: 625, y: 291 },
|
{ x: 625, y: 291 },
|
||||||
]);
|
]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.cobbangle.cobbangleDisplayedCorrectly);
|
await checkForScreenshot(page, page, screenShotPaths.cobbangle.cobbangleDisplayedCorrectly);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,6 +8,7 @@ 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 ({
|
test('should the context menu completely on screen and is not clipped for a point near the bottom edge of the screen', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -17,7 +18,7 @@ test('should the context menu completely on screen and is not clipped for a poin
|
|||||||
{ x: 0.55, y: 0.98 },
|
{ x: 0.55, y: 0.98 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.contextMenu.preContextMenuNearBottomEdge);
|
await checkForScreenshot(page, page, screenShotPaths.contextMenu.preContextMenuNearBottomEdge);
|
||||||
|
|
||||||
|
|||||||
@ -5,17 +5,20 @@ 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 ({
|
test('should not allow contours to be edited in basic viewer mode', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
const mode = 'viewer';
|
const mode = 'viewer';
|
||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
|
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
await rightPanelPageObject.toggle();
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||||
// Wait for the segmentation to be loaded.
|
// Wait for the segmentation to be loaded.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
// Wait for the segmentation to hydrate.
|
// Wait for the segmentation to hydrate.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
@ -46,13 +49,16 @@ test('should not allow contours to be edited in basic viewer mode', async ({
|
|||||||
|
|
||||||
test('should not allow contours to be edited when panelSegmentation.disableEditing is true', async ({
|
test('should not allow contours to be edited when panelSegmentation.disableEditing is true', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
const mode = 'segmentation';
|
const mode = 'segmentation';
|
||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
|
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
await rightPanelPageObject.toggle();
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||||
// Wait for the segmentation to be loaded.
|
// Wait for the segmentation to be loaded.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
@ -66,7 +72,7 @@ test('should not allow contours to be edited when panelSegmentation.disableEditi
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
// Wait for the segmentation to hydrate.
|
// Wait for the segmentation to hydrate.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
@ -97,13 +103,16 @@ test('should not allow contours to be edited when panelSegmentation.disableEditi
|
|||||||
|
|
||||||
test('should allow contours to be edited when panelSegmentation.disableEditing is false', async ({
|
test('should allow contours to be edited when panelSegmentation.disableEditing is false', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
const mode = 'segmentation';
|
const mode = 'segmentation';
|
||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
|
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
await rightPanelPageObject.toggle();
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||||
// Wait for the segmentation to be loaded.
|
// Wait for the segmentation to be loaded.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
@ -117,7 +126,7 @@ test('should allow contours to be edited when panelSegmentation.disableEditing i
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
// Wait for the segmentation to hydrate.
|
// Wait for the segmentation to hydrate.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|||||||
@ -1,44 +1,11 @@
|
|||||||
import { Page } from '@playwright/test';
|
|
||||||
import {
|
import {
|
||||||
checkForScreenshot,
|
checkForScreenshot,
|
||||||
getMousePosition,
|
|
||||||
initializeMousePositionTracker,
|
initializeMousePositionTracker,
|
||||||
screenShotPaths,
|
screenShotPaths,
|
||||||
test,
|
test,
|
||||||
visitStudy,
|
visitStudy,
|
||||||
} from './utils/index.js';
|
} from './utils/index.js';
|
||||||
|
|
||||||
const rotateCrosshairs = async (page: Page, id: string, lineNumber: number) => {
|
|
||||||
const locator = page.locator(id).locator('line').nth(lineNumber);
|
|
||||||
await locator.click({ force: true });
|
|
||||||
await locator.hover({ force: true });
|
|
||||||
const circleLocator = page.locator(id).locator('circle').nth(1);
|
|
||||||
await circleLocator.hover({ force: true });
|
|
||||||
await page.mouse.down();
|
|
||||||
const position = await getMousePosition(page);
|
|
||||||
await page.mouse.move(position.x, position.y + 100);
|
|
||||||
await page.mouse.up();
|
|
||||||
};
|
|
||||||
|
|
||||||
const increaseSlabThickness = async (page: Page, id: string, lineNumber: number, axis: string) => {
|
|
||||||
const locator = page.locator(id).locator('line').nth(lineNumber);
|
|
||||||
await locator.click({ force: true });
|
|
||||||
await locator.hover({ force: true });
|
|
||||||
const circleLocator = page.locator(id).locator('rect').first();
|
|
||||||
await circleLocator.hover({ force: true });
|
|
||||||
await page.mouse.down();
|
|
||||||
const position = await getMousePosition(page);
|
|
||||||
switch (axis) {
|
|
||||||
case 'x':
|
|
||||||
await page.mouse.move(position.x + 100, position.y);
|
|
||||||
break;
|
|
||||||
case 'y':
|
|
||||||
await page.mouse.move(position.x, position.y + 100);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
await page.mouse.up();
|
|
||||||
};
|
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785';
|
const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785';
|
||||||
const mode = 'viewer';
|
const mode = 'viewer';
|
||||||
@ -49,7 +16,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
test.describe('Crosshairs Test', async () => {
|
test.describe('Crosshairs Test', async () => {
|
||||||
test('should render the crosshairs correctly.', async ({ page, mainToolbarPageObject }) => {
|
test('should render the crosshairs correctly.', async ({ page, mainToolbarPageObject }) => {
|
||||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||||
await page.getByTestId('Crosshairs').click();
|
await mainToolbarPageObject.crosshairs.click();
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRendered);
|
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRendered);
|
||||||
});
|
});
|
||||||
@ -57,13 +24,14 @@ test.describe('Crosshairs Test', async () => {
|
|||||||
test('should allow the user to rotate the crosshairs', async ({
|
test('should allow the user to rotate the crosshairs', async ({
|
||||||
page,
|
page,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||||
await page.getByTestId('Crosshairs').click();
|
await mainToolbarPageObject.crosshairs.click();
|
||||||
|
|
||||||
await rotateCrosshairs(page, '#svg-layer-mpr-axial', 3);
|
await viewportPageObject.crosshairs.axial.rotate();
|
||||||
await rotateCrosshairs(page, '#svg-layer-mpr-sagittal', 0);
|
await viewportPageObject.crosshairs.sagittal.rotate();
|
||||||
await rotateCrosshairs(page, '#svg-layer-mpr-coronal', 0);
|
await viewportPageObject.crosshairs.coronal.rotate();
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRotated);
|
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRotated);
|
||||||
});
|
});
|
||||||
@ -71,13 +39,14 @@ test.describe('Crosshairs Test', async () => {
|
|||||||
test('should allow the user to adjust the slab thickness', async ({
|
test('should allow the user to adjust the slab thickness', async ({
|
||||||
page,
|
page,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||||
await page.getByTestId('Crosshairs').click();
|
await mainToolbarPageObject.crosshairs.click();
|
||||||
|
|
||||||
await increaseSlabThickness(page, '#svg-layer-mpr-axial', 0, 'x');
|
await viewportPageObject.crosshairs.axial.increase();
|
||||||
await increaseSlabThickness(page, '#svg-layer-mpr-sagittal', 2, 'x');
|
await viewportPageObject.crosshairs.sagittal.increase();
|
||||||
await increaseSlabThickness(page, '#svg-layer-mpr-coronal', 0, 'y');
|
await viewportPageObject.crosshairs.coronal.increase();
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsSlabThickness);
|
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsSlabThickness);
|
||||||
});
|
});
|
||||||
@ -85,15 +54,16 @@ test.describe('Crosshairs Test', async () => {
|
|||||||
test('should reset the crosshairs to the initial position when reset is clicked', async ({
|
test('should reset the crosshairs to the initial position when reset is clicked', async ({
|
||||||
page,
|
page,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||||
await page.getByTestId('Crosshairs').click();
|
await mainToolbarPageObject.crosshairs.click();
|
||||||
|
|
||||||
await rotateCrosshairs(page, '#svg-layer-mpr-axial', 3);
|
await viewportPageObject.crosshairs.axial.rotate();
|
||||||
await rotateCrosshairs(page, '#svg-layer-mpr-sagittal', 0);
|
await viewportPageObject.crosshairs.sagittal.rotate();
|
||||||
await rotateCrosshairs(page, '#svg-layer-mpr-coronal', 0);
|
await viewportPageObject.crosshairs.coronal.rotate();
|
||||||
|
|
||||||
await page.getByTestId('MoreTools-split-button-primary').click();
|
await mainToolbarPageObject.moreTools.reset.click();
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsResetToolbar);
|
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsResetToolbar);
|
||||||
});
|
});
|
||||||
@ -101,15 +71,17 @@ test.describe('Crosshairs Test', async () => {
|
|||||||
test('should reset the crosshairs when a new displayset is loaded', async ({
|
test('should reset the crosshairs when a new displayset is loaded', async ({
|
||||||
page,
|
page,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||||
await page.getByTestId('Crosshairs').click();
|
await mainToolbarPageObject.crosshairs.click();
|
||||||
|
|
||||||
await rotateCrosshairs(page, '#svg-layer-mpr-axial', 0);
|
await viewportPageObject.crosshairs.axial.rotate();
|
||||||
await rotateCrosshairs(page, '#svg-layer-mpr-sagittal', 0);
|
await viewportPageObject.crosshairs.sagittal.rotate();
|
||||||
await rotateCrosshairs(page, '#svg-layer-mpr-coronal', 3);
|
await viewportPageObject.crosshairs.coronal.rotate();
|
||||||
|
|
||||||
await page.getByTestId('study-browser-thumbnail').nth(1).dblclick();
|
await leftPanelPageObject.loadSeriesByDescription('Recon 3: LIVER 3 PHASE (AP)');
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsNewDisplayset);
|
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsNewDisplayset);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,10 +10,9 @@ test('should display added, selected and removed segmentation promptly', async (
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
|
|
||||||
// Add a segmentation overlay and ensure the overlay menu reflects this change.
|
// Add a segmentation overlay and ensure the overlay menu reflects this change.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
const dataOverlayPageObject = viewportPageObject.getById('default').overlayMenu.dataOverlay;
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-default').click();
|
await dataOverlayPageObject.toggle();
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
await dataOverlayPageObject.addSegmentation('2d-tta_nnU-Net_Segmentation');
|
||||||
await page.getByTestId('2d-tta_nnU-Net_Segmentation').click();
|
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
@ -24,7 +23,7 @@ test('should display added, selected and removed segmentation promptly', async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Hide the overlay menu.
|
// Hide the overlay menu.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle();
|
||||||
|
|
||||||
// navigate to the 51st image and ensure the correct overlay is displayed
|
// navigate to the 51st image and ensure the correct overlay is displayed
|
||||||
await press({ page, key: 'ArrowDown', nTimes: 50 });
|
await press({ page, key: 'ArrowDown', nTimes: 50 });
|
||||||
@ -37,11 +36,10 @@ test('should display added, selected and removed segmentation promptly', async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Show the overlay menu.
|
// Show the overlay menu.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle();
|
||||||
|
|
||||||
// Change the segmentation overlay to a different one and ensure the overlay menu reflects this change.
|
// 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();
|
await dataOverlayPageObject.changeSegmentation('2d-tta_nnU-Net_Segmentation', 'Segmentation');
|
||||||
await page.getByTestId('Segmentation-SEG').click();
|
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
@ -51,7 +49,7 @@ test('should display added, selected and removed segmentation promptly', async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Hide the overlay menu.
|
// Hide the overlay menu.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle();
|
||||||
|
|
||||||
// navigate to the 51st image and ensure the correct overlay is displayed
|
// navigate to the 51st image and ensure the correct overlay is displayed
|
||||||
await press({ page, key: 'ArrowDown', nTimes: 50 });
|
await press({ page, key: 'ArrowDown', nTimes: 50 });
|
||||||
@ -64,11 +62,10 @@ test('should display added, selected and removed segmentation promptly', async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Show the overlay menu.
|
// Show the overlay menu.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle();
|
||||||
|
|
||||||
// Remove the segmentation overlay and ensure the overlay menu reflects this change.
|
// Remove the segmentation overlay and ensure the overlay menu reflects this change.
|
||||||
await page.getByTestId('overlay-ds-more-button-SEGMENTATION').click();
|
await dataOverlayPageObject.remove('SEGMENTATION');
|
||||||
await page.getByTestId('overlay-ds-remove-button-SEGMENTATION').click();
|
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
@ -78,7 +75,7 @@ test('should display added, selected and removed segmentation promptly', async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Hide the overlay menu.
|
// Hide the overlay menu.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle();
|
||||||
|
|
||||||
// navigate to the 51st image and ensure no overlay is displayed
|
// navigate to the 51st image and ensure no overlay is displayed
|
||||||
await press({ page, key: 'ArrowDown', nTimes: 50 });
|
await press({ page, key: 'ArrowDown', nTimes: 50 });
|
||||||
|
|||||||
@ -8,6 +8,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the ellipse tool', async ({
|
test('should display the ellipse tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -16,6 +17,6 @@ test('should display the ellipse tool', async ({
|
|||||||
{ x: 446, y: 245 },
|
{ x: 446, y: 245 },
|
||||||
{ x: 508, y: 281 },
|
{ x: 508, y: 281 },
|
||||||
]);
|
]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.ellipse.ellipseDisplayedCorrectly);
|
await checkForScreenshot(page, page, screenShotPaths.ellipse.ellipseDisplayedCorrectly);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,15 +8,16 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should hydrate in MPR correctly', async ({
|
test('should hydrate in MPR correctly', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
await rightPanelPageObject.toggle();
|
||||||
await page.getByTestId('trackedMeasurements-btn').click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
|
|
||||||
// get the div that has Body 4.0 Lung I and double click it
|
await leftPanelPageObject.loadSeriesByDescription('Body 4.0 CE', 1);
|
||||||
|
|
||||||
await page.locator(':text("S:7")').first().dblclick();
|
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
@ -47,10 +48,9 @@ test('should hydrate in MPR correctly', async ({
|
|||||||
{ x: 515, y: 339 },
|
{ x: 515, y: 339 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// wait 2 seconds
|
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
|
|
||||||
// scroll away
|
// scroll away
|
||||||
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.initialDraw);
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.initialDraw);
|
||||||
@ -75,34 +75,32 @@ test('should hydrate in MPR correctly', async ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// wait 5 seconds
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.scrollAway);
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.scrollAway);
|
||||||
|
|
||||||
await page.getByTestId('data-row').first().click();
|
await rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).click();
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.jumpToMeasurementStack);
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.jumpToMeasurementStack);
|
||||||
|
|
||||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||||
|
|
||||||
// wait 5 seconds
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
// jump in viewport again
|
// jump in viewport again
|
||||||
await page.getByTestId('data-row').first().click();
|
await rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).click();
|
||||||
|
|
||||||
await page.waitForTimeout(3000);
|
await page.waitForTimeout(3000);
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.jumpInMPR);
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.jumpInMPR);
|
||||||
|
|
||||||
await page.locator(':text("S:3")').first().dblclick();
|
await leftPanelPageObject.loadSeriesByDescription('Lung 3.0 CE');
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.changeSeriesInMPR);
|
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.changeSeriesInMPR);
|
||||||
|
|
||||||
await page.getByTestId('data-row').first().click();
|
await rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).click();
|
||||||
|
|
||||||
await checkForScreenshot(
|
await checkForScreenshot(
|
||||||
page,
|
page,
|
||||||
|
|||||||
@ -9,6 +9,9 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should prevent editing of label map segmentations when panelSegmentation.disableEditing is true', async ({
|
test('should prevent editing of label map segmentations when panelSegmentation.disableEditing is true', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
// disable editing of segmentations via the customization service
|
// disable editing of segmentations via the customization service
|
||||||
@ -20,13 +23,13 @@ test('should prevent editing of label map segmentations when panelSegmentation.d
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
await page.getByTestId('panelSegmentationWithToolsLabelMap-btn').click();
|
await rightPanelPageObject.labelMapSegmentationPanel.select();
|
||||||
|
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('SEG');
|
||||||
// Wait for the segmentation to be loaded.
|
// Wait for the segmentation to be loaded.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
// Wait for the segmentation to hydrate.
|
// Wait for the segmentation to hydrate.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
@ -37,10 +40,10 @@ test('should prevent editing of label map segmentations when panelSegmentation.d
|
|||||||
await checkForScreenshot(page, page, screenShotPaths.labelMapSegLocking.globalLockedSegPreEdit);
|
await checkForScreenshot(page, page, screenShotPaths.labelMapSegLocking.globalLockedSegPreEdit);
|
||||||
|
|
||||||
// Attempt to erase the segmentations.
|
// Attempt to erase the segmentations.
|
||||||
await page.getByTestId('Eraser-btn').click();
|
await rightPanelPageObject.labelMapSegmentationPanel.tools.eraser.click();
|
||||||
|
|
||||||
// Use the largest eraser radius to help ensure the entire image is erased.
|
// Use the largest eraser radius to help ensure the entire image is erased.
|
||||||
await page.locator(`css=div[data-cy="eraser-radius"] input`).fill('1000');
|
await rightPanelPageObject.labelMapSegmentationPanel.tools.eraser.setRadius(1000);
|
||||||
|
|
||||||
// Attempt to erase the segmentations by dragging the eraser tool across the image several times.
|
// Attempt to erase the segmentations by dragging the eraser tool across the image several times.
|
||||||
await viewportPageObject.getById('default').normalizedDragAt({
|
await viewportPageObject.getById('default').normalizedDragAt({
|
||||||
@ -61,6 +64,9 @@ 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 ({
|
test('should allow editing of label map segmentations when panelSegmentation.disableEditing is false', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
// disable editing of segmentations via the customization service
|
// disable editing of segmentations via the customization service
|
||||||
@ -73,13 +79,13 @@ test('should allow editing of label map segmentations when panelSegmentation.dis
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
await page.getByTestId('panelSegmentationWithToolsLabelMap-btn').click();
|
await rightPanelPageObject.labelMapSegmentationPanel.select();
|
||||||
|
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('SEG');
|
||||||
// Wait for the segmentation to be loaded.
|
// Wait for the segmentation to be loaded.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
// Wait for the segmentation to hydrate.
|
// Wait for the segmentation to hydrate.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
@ -89,10 +95,10 @@ test('should allow editing of label map segmentations when panelSegmentation.dis
|
|||||||
await checkForScreenshot(page, page, screenShotPaths.labelMapSegLocking.globalUnlockedSegPreEdit);
|
await checkForScreenshot(page, page, screenShotPaths.labelMapSegLocking.globalUnlockedSegPreEdit);
|
||||||
|
|
||||||
// Attempt to erase the segmentations.
|
// Attempt to erase the segmentations.
|
||||||
await page.getByTestId('Eraser-btn').click();
|
await rightPanelPageObject.labelMapSegmentationPanel.tools.eraser.click();
|
||||||
|
|
||||||
// Use the largest eraser radius to help ensure the eraser passes over the entire image.
|
// Use the largest eraser radius to help ensure the eraser passes over the entire image.
|
||||||
await page.locator(`css=div[data-cy="eraser-radius"] input`).fill('1000');
|
await rightPanelPageObject.labelMapSegmentationPanel.tools.eraser.setRadius(1000);
|
||||||
|
|
||||||
// Attempt to erase the segmentations by dragging the eraser tool across the image several times.
|
// Attempt to erase the segmentations by dragging the eraser tool across the image several times.
|
||||||
await viewportPageObject.getById('default').normalizedDragAt({
|
await viewportPageObject.getById('default').normalizedDragAt({
|
||||||
|
|||||||
@ -8,6 +8,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the length tool', async ({
|
test('should display the length tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -16,6 +17,6 @@ test('should display the length tool', async ({
|
|||||||
{ x: 364, y: 234 },
|
{ x: 364, y: 234 },
|
||||||
{ x: 544, y: 232 },
|
{ x: 544, y: 232 },
|
||||||
]);
|
]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.length.lengthDisplayedCorrectly);
|
await checkForScreenshot(page, page, screenShotPaths.length.lengthDisplayedCorrectly);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,6 +8,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the livewire tool', async ({
|
test('should display the livewire tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -20,6 +21,6 @@ test('should display the livewire tool', async ({
|
|||||||
{ x: 482, y: 493 },
|
{ x: 482, y: 493 },
|
||||||
{ x: 383, y: 461 },
|
{ x: 383, y: 461 },
|
||||||
]);
|
]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.livewire.livewireDisplayedCorrectly);
|
await checkForScreenshot(page, page, screenShotPaths.livewire.livewireDisplayedCorrectly);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -25,16 +25,15 @@ 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.
|
// Hover over the middle/sagittal viewport so that the data overlay menu is available.
|
||||||
await viewportPageObject.getById('mpr-sagittal').pane.hover();
|
await viewportPageObject.getById('mpr-sagittal').pane.hover();
|
||||||
await viewportPageObject.getById('mpr-sagittal').overlayMenu.dataOverlay.click();
|
const dataOverlayPageObject = viewportPageObject.getById('mpr-sagittal').overlayMenu.dataOverlay;
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-mpr-sagittal').click();
|
await dataOverlayPageObject.toggle('mpr-sagittal');
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
await dataOverlayPageObject.addSegmentation('ARIA RadOnc Structure Sets', 'mpr-sagittal');
|
||||||
await page.getByTestId('ARIA RadOnc Structure Sets').click();
|
|
||||||
|
|
||||||
// Hide the overlay menu.
|
// Hide the overlay menu.
|
||||||
await viewportPageObject.getById('mpr-sagittal').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle('mpr-sagittal');
|
||||||
|
|
||||||
// Adding an overlay should not show the LOAD button.
|
// Adding an overlay should not show the LOAD button.
|
||||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
await assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||||
|
|
||||||
// Wait 5 seconds for RT to load. This is necessary in particular when screen shots are added or replaced.
|
// Wait 5 seconds for RT to load. This is necessary in particular when screen shots are added or replaced.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|||||||
@ -9,10 +9,11 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should launch MPR with unhydrated SEG chosen from the data overlay menu', async ({
|
test('should launch MPR with unhydrated SEG chosen from the data overlay menu', async ({
|
||||||
page,
|
page,
|
||||||
|
rightPanelPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
await rightPanelPageObject.toggle();
|
||||||
|
|
||||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||||
|
|
||||||
@ -25,17 +26,16 @@ 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.
|
// Hover over the middle/sagittal viewport so that the data overlay menu is available.
|
||||||
await viewportPageObject.getById('mpr-sagittal').pane.hover();
|
await viewportPageObject.getById('mpr-axial').pane.hover();
|
||||||
await viewportPageObject.getById('mpr-sagittal').overlayMenu.dataOverlay.click();
|
const dataOverlayPageObject = viewportPageObject.getById('mpr-axial').overlayMenu.dataOverlay;
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-mpr-sagittal').click();
|
await dataOverlayPageObject.toggle('mpr-axial');
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
await dataOverlayPageObject.addSegmentation('Segmentation', 'mpr-axial');
|
||||||
await page.getByTestId('Segmentation').click();
|
|
||||||
|
|
||||||
// Hide the overlay menu.
|
// Hide the overlay menu.
|
||||||
await viewportPageObject.getById('mpr-sagittal').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle('mpr-axial');
|
||||||
|
|
||||||
// Adding an overlay should not show the LOAD button.
|
// Adding an overlay should not show the LOAD button.
|
||||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
await assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
|||||||
@ -7,136 +7,114 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('checks if Measurements right panel can be hidden/displayed', async ({ page }) => {
|
test('checks if Measurements right panel can be hidden/displayed', async ({
|
||||||
const measurementsPanel = page.getByTestId('trackedMeasurements-panel').last();
|
rightPanelPageObject,
|
||||||
const rightCollapseBtn = page.getByTestId('side-panel-header-right');
|
}) => {
|
||||||
|
const measurementsPanel = rightPanelPageObject.measurementsPanel.panel.locator;
|
||||||
// No data-cy exists in this panel, using Segmentation header button
|
const segmentationPanel = rightPanelPageObject.labelMapSegmentationPanel.panel.locator;
|
||||||
const segmentationPanel = page.getByRole('button', { name: 'Segmentations' });
|
|
||||||
const measurementsBtn = page.getByTestId('trackedMeasurements-btn');
|
|
||||||
const segmentationsBtn = page.getByTestId('panelSegmentation-btn');
|
|
||||||
|
|
||||||
// Assert the measurements panel and segmentation panel is hidden initially
|
// Assert the measurements panel and segmentation panel is hidden initially
|
||||||
await expect(measurementsPanel).toBeHidden();
|
await expect(measurementsPanel).toBeHidden();
|
||||||
await expect(segmentationPanel).toBeHidden();
|
await expect(segmentationPanel).toBeHidden();
|
||||||
|
|
||||||
// Click the collapse button to show the panel container
|
// Click the collapse button to show the panel container
|
||||||
await rightCollapseBtn.click({ force: true });
|
await rightPanelPageObject.toggle();
|
||||||
|
|
||||||
// The segmentation panel should now be visible by default
|
// The segmentation panel should now be visible by default
|
||||||
await expect(segmentationPanel).toBeVisible();
|
await expect(segmentationPanel).toBeVisible();
|
||||||
|
|
||||||
// Switch to the measurements tab
|
// Switch to the measurements tab
|
||||||
await measurementsBtn.click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
|
|
||||||
// Assert the measurements panel is visible, and segmentation invisible
|
// Assert the measurements panel is visible, and segmentation invisible
|
||||||
await expect(measurementsPanel).toBeVisible();
|
await expect(measurementsPanel).toBeVisible();
|
||||||
await expect(segmentationPanel).toBeHidden();
|
await expect(segmentationPanel).toBeHidden();
|
||||||
|
|
||||||
// Switch back to segmentations panel
|
// Switch back to segmentations panel
|
||||||
await segmentationsBtn.click();
|
await rightPanelPageObject.noToolsSegmentationPanel.select();
|
||||||
|
|
||||||
// Assert the segmentations panel is now visible, measurements panel invisible
|
// Assert the segmentations panel is now visible, measurements panel invisible
|
||||||
await expect(segmentationPanel).toBeVisible();
|
await expect(segmentationPanel).toBeVisible();
|
||||||
await expect(measurementsPanel).toBeHidden();
|
await expect(measurementsPanel).toBeHidden();
|
||||||
|
|
||||||
// Click the collapse button to hide the panel
|
// Click the collapse button to hide the panel
|
||||||
await rightCollapseBtn.click();
|
await rightPanelPageObject.toggle();
|
||||||
|
|
||||||
// Assert the measurements and segmentation panel is now hidden
|
// Assert the measurements and segmentation panel is now hidden
|
||||||
await expect(measurementsPanel).toBeHidden();
|
await expect(measurementsPanel).toBeHidden();
|
||||||
await expect(segmentationPanel).toBeHidden();
|
await expect(segmentationPanel).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('checks if measurement item can be relabeled under Measurements panel', async ({ page }) => {
|
test('checks if measurement item can be relabeled under Measurements panel', async ({
|
||||||
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
const relabelText = 'Relabel 12345';
|
const relabelText = 'Relabel 12345';
|
||||||
const measurementsBtn = page.getByTestId('trackedMeasurements-btn');
|
|
||||||
|
|
||||||
// Add measurement
|
// Add measurement
|
||||||
await addLengthMeasurement(page);
|
await addLengthMeasurement(page);
|
||||||
|
|
||||||
const viewportNotification = page.getByTestId('viewport-notification');
|
const viewportNotification = DOMOverlayPageObject.viewport.measurementTracking.locator;
|
||||||
await expect(viewportNotification).toBeVisible();
|
await expect(viewportNotification).toBeVisible();
|
||||||
|
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
|
|
||||||
// Open measurement panel confirm default empty
|
// Open measurement panel confirm default empty
|
||||||
await measurementsBtn.click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
const measurementRow = page.getByTestId('data-row').first();
|
const measurementRow = rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).locator;
|
||||||
await expect(measurementRow).toContainText('(empty)');
|
await expect(measurementRow).toContainText('(empty)');
|
||||||
|
|
||||||
// Expand and click rename
|
// Expand and click rename
|
||||||
const actionsButton = measurementRow.getByRole('button', { name: 'Actions' });
|
await rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).actions.rename(relabelText);
|
||||||
await actionsButton.click();
|
|
||||||
|
|
||||||
const renameButton = page.getByRole('menuitem', { name: 'Rename' });
|
|
||||||
await renameButton.click();
|
|
||||||
|
|
||||||
// Interact with dialog
|
|
||||||
const renameDialog = page.getByRole('dialog', { name: 'Edit Measurement Label' });
|
|
||||||
const renameInput = renameDialog.getByPlaceholder('Enter new label');
|
|
||||||
const saveButton = renameDialog.getByRole('button', { name: 'Save' });
|
|
||||||
|
|
||||||
await expect(renameDialog).toBeVisible();
|
|
||||||
await expect(renameInput).toBeVisible();
|
|
||||||
await expect(saveButton).toBeEnabled();
|
|
||||||
|
|
||||||
await renameInput.fill(relabelText);
|
|
||||||
await saveButton.click();
|
|
||||||
|
|
||||||
// Check dialog closed and renamed
|
// Check dialog closed and renamed
|
||||||
await expect(renameDialog).toBeHidden();
|
await expect(DOMOverlayPageObject.dialog.input.locator).toBeHidden();
|
||||||
await expect(measurementRow).toContainText(relabelText);
|
await expect(measurementRow).toContainText(relabelText);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('checks if measurement item can be relabeled through the context menu on the viewport', async ({
|
test('checks if measurement item can be relabeled through the context menu on the viewport', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
const relabelText = 'Relabel 12345';
|
const relabelText = 'Relabel 12345';
|
||||||
const measurementsBtn = page.getByTestId('trackedMeasurements-btn');
|
|
||||||
|
|
||||||
// Add measurement
|
// Add measurement
|
||||||
await addLengthMeasurement(page);
|
await addLengthMeasurement(page);
|
||||||
|
|
||||||
const viewportNotification = page.getByTestId('viewport-notification');
|
const viewportNotification = DOMOverlayPageObject.viewport.measurementTracking.locator;
|
||||||
await expect(viewportNotification).toBeVisible();
|
await expect(viewportNotification).toBeVisible();
|
||||||
|
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
|
|
||||||
// Open measurement panel confirm default empty
|
// Open measurement panel confirm default empty
|
||||||
await measurementsBtn.click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
const measurementRow = page.getByTestId('data-row').first();
|
const measurementRow = rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).locator;
|
||||||
await expect(measurementRow).toContainText('(empty)');
|
await expect(measurementRow).toContainText('(empty)');
|
||||||
|
|
||||||
// Right click and click rename
|
// Right click and click rename
|
||||||
await page.waitForTimeout(200); // small delay for context menu
|
await page.waitForTimeout(200); // small delay for context menu
|
||||||
const measurementAnnotation = page.locator('g[data-annotation-uid]').first();
|
await viewportPageObject.active.nthAnnotation(0).contextMenu.open();
|
||||||
await measurementAnnotation.click({ button: 'right', force: true });
|
|
||||||
await page.waitForTimeout(200); // small delay for context menu
|
await page.waitForTimeout(200); // small delay for context menu
|
||||||
|
|
||||||
const addLabelButton = page.getByTestId('context-menu-item').filter({ hasText: 'Add Label' });
|
const addLabelButton = DOMOverlayPageObject.viewport.annotationContextMenu.addLabel;
|
||||||
await expect(addLabelButton).toBeVisible();
|
await expect(addLabelButton.locator).toBeVisible();
|
||||||
await addLabelButton.click();
|
await addLabelButton.click();
|
||||||
|
|
||||||
// Interact with dialog
|
// Interact with dialog
|
||||||
const renameDialog = page.getByRole('dialog', { name: 'Edit Measurement Label' });
|
await expect(DOMOverlayPageObject.dialog.title).toHaveText('Edit Measurement Label');
|
||||||
const renameInput = renameDialog.getByPlaceholder('Enter new label');
|
await DOMOverlayPageObject.dialog.input.fillAndSave(relabelText);
|
||||||
const saveButton = renameDialog.getByRole('button', { name: 'Save' });
|
|
||||||
|
|
||||||
await expect(renameDialog).toBeVisible();
|
|
||||||
await expect(renameInput).toBeVisible();
|
|
||||||
await expect(saveButton).toBeEnabled();
|
|
||||||
|
|
||||||
await renameInput.fill(relabelText);
|
|
||||||
await saveButton.click();
|
|
||||||
|
|
||||||
// Check dialog closed and renamed
|
// Check dialog closed and renamed
|
||||||
await expect(renameDialog).toBeHidden();
|
await expect(DOMOverlayPageObject.dialog.title).toBeHidden();
|
||||||
await expect(measurementRow).toContainText(relabelText);
|
await expect(measurementRow).toContainText(relabelText);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('checks if image would jump when clicked on a measurement item', async ({
|
test('checks if image would jump when clicked on a measurement item', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
const viewportInfoBottomRight = viewportPageObject.active.overlayText.bottomRight;
|
const viewportInfoBottomRight = viewportPageObject.active.overlayText.bottomRight;
|
||||||
@ -145,9 +123,8 @@ test('checks if image would jump when clicked on a measurement item', async ({
|
|||||||
await expect(viewportInfoBottomRight).toContainText('1/', { timeout: 10000 });
|
await expect(viewportInfoBottomRight).toContainText('1/', { timeout: 10000 });
|
||||||
await addLengthMeasurement(page);
|
await addLengthMeasurement(page);
|
||||||
|
|
||||||
const viewportNotification = page.getByTestId('viewport-notification');
|
await expect(DOMOverlayPageObject.viewport.measurementTracking.locator).toBeVisible();
|
||||||
await expect(viewportNotification).toBeVisible();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
|
||||||
|
|
||||||
// Change to slice 2
|
// Change to slice 2
|
||||||
await scrollVolumeViewport(page, 'default', 1);
|
await scrollVolumeViewport(page, 'default', 1);
|
||||||
@ -157,90 +134,79 @@ test('checks if image would jump when clicked on a measurement item', async ({
|
|||||||
await addLengthMeasurement(page);
|
await addLengthMeasurement(page);
|
||||||
|
|
||||||
// Open measurement panel and click first measurement
|
// Open measurement panel and click first measurement
|
||||||
const measurementsBtn = page.getByTestId('trackedMeasurements-btn');
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
await measurementsBtn.click();
|
await rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).click();
|
||||||
const measurementRow = page.getByTestId('data-row').first();
|
|
||||||
await measurementRow.click();
|
|
||||||
|
|
||||||
// Confirm jumped to slice 1
|
// Confirm jumped to slice 1
|
||||||
await expect(viewportInfoBottomRight).toContainText('1/', { timeout: 10000 });
|
await expect(viewportInfoBottomRight).toContainText('1/', { timeout: 10000 });
|
||||||
await expect(viewportInfoBottomRight).not.toContainText('2/');
|
await expect(viewportInfoBottomRight).not.toContainText('2/');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('checks if measurement item can be deleted under Measurements panel', async ({ page }) => {
|
test('checks if measurement item can be deleted under Measurements panel', async ({
|
||||||
const measurementsBtn = page.getByTestId('trackedMeasurements-btn');
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
// Add 3 measurements
|
// Add 3 measurements
|
||||||
await addLengthMeasurement(page);
|
await addLengthMeasurement(page);
|
||||||
|
|
||||||
const viewportNotification = page.getByTestId('viewport-notification');
|
await expect(DOMOverlayPageObject.viewport.measurementTracking.locator).toBeVisible();
|
||||||
await expect(viewportNotification).toBeVisible();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
|
||||||
|
|
||||||
await addLengthMeasurement(page, { firstClick: [170, 100], secondClick: [150, 170] });
|
await addLengthMeasurement(page, { firstClick: [170, 100], secondClick: [150, 170] });
|
||||||
await addLengthMeasurement(page, { firstClick: [190, 100], secondClick: [170, 170] });
|
await addLengthMeasurement(page, { firstClick: [190, 100], secondClick: [170, 170] });
|
||||||
|
|
||||||
// Open measurement panel, confirm 3 measurements
|
// Open measurement panel, confirm 3 measurements
|
||||||
await measurementsBtn.click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
await expect(page.getByTestId('data-row')).toHaveCount(3);
|
expect(await rightPanelPageObject.measurementsPanel.panel.getMeasurementCount()).toBe(3);
|
||||||
|
|
||||||
// Delete from measurement
|
// Delete from measurement
|
||||||
const measurementRow = page.getByTestId('data-row').first();
|
await rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).actions.delete();
|
||||||
const actionsButton = measurementRow.getByRole('button', { name: 'Actions' });
|
await page.waitForTimeout(200);
|
||||||
await actionsButton.click();
|
|
||||||
|
|
||||||
const menuDeleteButton = page.getByRole('menuitem', { name: 'Delete' });
|
|
||||||
await menuDeleteButton.click();
|
|
||||||
|
|
||||||
// Confirm one measurement is gone
|
// Confirm one measurement is gone
|
||||||
await expect(page.getByTestId('data-row')).toHaveCount(2);
|
expect(await rightPanelPageObject.measurementsPanel.panel.getMeasurementCount()).toBe(2);
|
||||||
|
|
||||||
// Delete all measurements via main Measurement Panel delete button and untrack
|
// Delete all measurements via main Measurement Panel delete button and untrack
|
||||||
const deleteButton = page.getByRole('button', { name: 'Delete' });
|
await rightPanelPageObject.measurementsPanel.panel.deleteAll();
|
||||||
deleteButton.click();
|
|
||||||
|
|
||||||
// Interact with dialog
|
// Interact with dialog
|
||||||
const untrackDialog = page.getByRole('dialog', { name: 'Untrack Study' });
|
await expect(DOMOverlayPageObject.dialog.title).toHaveText('Untrack Study');
|
||||||
const untrackButton = untrackDialog.getByRole('button', { name: 'Untrack' });
|
|
||||||
|
|
||||||
await expect(untrackDialog).toBeVisible();
|
await expect(DOMOverlayPageObject.dialog.confirmation.confirm.button).toBeEnabled();
|
||||||
await expect(untrackButton).toBeEnabled();
|
|
||||||
|
|
||||||
await untrackButton.click();
|
await DOMOverlayPageObject.dialog.confirmation.confirm.click();
|
||||||
|
|
||||||
// Check dialog closed and measurements gone
|
// Check dialog closed and measurements gone
|
||||||
await expect(untrackDialog).toBeHidden();
|
await expect(DOMOverlayPageObject.dialog.title).toBeHidden();
|
||||||
await expect(page.getByTestId('data-row')).toHaveCount(0);
|
expect(await rightPanelPageObject.measurementsPanel.panel.getMeasurementCount()).toBe(0);
|
||||||
|
|
||||||
const measurementsPanel = page.getByTestId('trackedMeasurements-panel').last();
|
const measurementsPanel = rightPanelPageObject.measurementsPanel.panel.locator;
|
||||||
await expect(measurementsPanel).toContainText('No tracked measurements');
|
await expect(measurementsPanel).toContainText('No tracked measurements');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('checks if measurement item can be deleted through the context menu on the viewport', async ({
|
test('checks if measurement item can be deleted through the context menu on the viewport', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
const measurementsBtn = page.getByTestId('trackedMeasurements-btn');
|
|
||||||
|
|
||||||
// Add measurement
|
// Add measurement
|
||||||
await addLengthMeasurement(page);
|
await addLengthMeasurement(page);
|
||||||
|
await expect(DOMOverlayPageObject.viewport.measurementTracking.locator).toBeVisible();
|
||||||
const viewportNotification = page.getByTestId('viewport-notification');
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await expect(viewportNotification).toBeVisible();
|
|
||||||
|
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
|
||||||
|
|
||||||
// Right click and click rename
|
// Right click and click rename
|
||||||
await page.waitForTimeout(200); // small delay for context menu
|
await page.waitForTimeout(200); // small delay for context menu
|
||||||
const measurementAnnotation = page.locator('g[data-annotation-uid]').first();
|
await viewportPageObject.active.nthAnnotation(0).contextMenu.open();
|
||||||
await measurementAnnotation.click({ button: 'right', force: true });
|
|
||||||
await page.waitForTimeout(200); // small delay for context menu
|
await page.waitForTimeout(200); // small delay for context menu
|
||||||
|
|
||||||
const deleteButton = page.getByTestId('context-menu-item').filter({ hasText: 'Delete' });
|
const deleteButton = DOMOverlayPageObject.viewport.annotationContextMenu.delete;
|
||||||
await expect(deleteButton).toBeVisible();
|
await expect(deleteButton.locator).toBeVisible();
|
||||||
await deleteButton.click();
|
await deleteButton.click();
|
||||||
|
|
||||||
// Open measurement panel and confirm measurement is gone
|
// Open measurement panel and confirm measurement is gone
|
||||||
await measurementsBtn.click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
await expect(measurementAnnotation).toBeHidden();
|
await expect(viewportPageObject.active.nthAnnotation(0).locator).toBeHidden();
|
||||||
await expect(page.getByTestId('data-row')).toHaveCount(0);
|
expect(await rightPanelPageObject.measurementsPanel.panel.getMeasurementCount()).toBe(0);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,16 +10,15 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display multiple segmentation overlays (both SEG and RT)', async ({
|
test('should display multiple segmentation overlays (both SEG and RT)', async ({
|
||||||
page,
|
page,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
await rightPanelPageObject.toggle();
|
||||||
|
|
||||||
// Add multiple segmentation overlays and ensure the overlay menu reflects this change.
|
// Add multiple segmentation overlays and ensure the overlay menu reflects this change.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
const dataOverlayPageObject = viewportPageObject.getById('default').overlayMenu.dataOverlay;
|
||||||
|
await dataOverlayPageObject.toggle();
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-default').click();
|
await dataOverlayPageObject.addSegmentation('2d-tta_nnU-Net_Segmentation');
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
|
||||||
await page.getByTestId('2d-tta_nnU-Net_Segmentation').click();
|
|
||||||
|
|
||||||
// A short wait after each overlay is selected to ensure it loads.
|
// A short wait after each overlay is selected to ensure it loads.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
@ -27,9 +26,7 @@ test('should display multiple segmentation overlays (both SEG and RT)', async ({
|
|||||||
// Adding an overlay should not show the LOAD button.
|
// Adding an overlay should not show the LOAD button.
|
||||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||||
|
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-default').click();
|
await dataOverlayPageObject.addSegmentation('Segmentation');
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
|
||||||
await page.getByTestId('Segmentation').click();
|
|
||||||
|
|
||||||
// A short wait after each overlay is selected to ensure it loads.
|
// A short wait after each overlay is selected to ensure it loads.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
@ -37,9 +34,7 @@ test('should display multiple segmentation overlays (both SEG and RT)', async ({
|
|||||||
// Adding an overlay should not show the LOAD button.
|
// Adding an overlay should not show the LOAD button.
|
||||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||||
|
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-default').click();
|
await dataOverlayPageObject.addSegmentation('3d_lowres-tta_nnU-Net_Segmentation');
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
|
||||||
await page.getByTestId('3d_lowres-tta_nnU-Net_Segmentation').click();
|
|
||||||
|
|
||||||
// A short wait after each overlay is selected to ensure it loads.
|
// A short wait after each overlay is selected to ensure it loads.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
@ -53,15 +48,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.
|
// Hide the overlay menu and then show it again. The overlays from before should still be displayed.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // hide
|
await dataOverlayPageObject.toggle(); // hide
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // show
|
await dataOverlayPageObject.toggle(); // show
|
||||||
|
|
||||||
await checkForScreenshot({
|
await checkForScreenshot({
|
||||||
page,
|
page,
|
||||||
screenshotPath: screenShotPaths.multipleSegmentationDataOverlays.threeSegOverlaysInOverlayMenu,
|
screenshotPath: screenShotPaths.multipleSegmentationDataOverlays.threeSegOverlaysInOverlayMenu,
|
||||||
});
|
});
|
||||||
|
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // hide
|
await dataOverlayPageObject.toggle(); // hide
|
||||||
|
|
||||||
// Navigate to image 56.
|
// Navigate to image 56.
|
||||||
await press({ page, key: 'ArrowDown', nTimes: 55 });
|
await press({ page, key: 'ArrowDown', nTimes: 55 });
|
||||||
@ -74,11 +69,9 @@ test('should display multiple segmentation overlays (both SEG and RT)', async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Now add the RT overlay
|
// Now add the RT overlay
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle();
|
||||||
|
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-default').click();
|
await dataOverlayPageObject.addSegmentation('Series 3 - RTSTRUCT');
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
|
||||||
await page.getByTestId('Series 3 - RTSTRUCT').click();
|
|
||||||
|
|
||||||
// A short wait after each overlay is selected to ensure it loads.
|
// A short wait after each overlay is selected to ensure it loads.
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
@ -92,8 +85,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.
|
// Hide the overlay menu and then show it again. The overlays from before should still be displayed.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // hide
|
await dataOverlayPageObject.toggle(); // hide
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click(); // show
|
await dataOverlayPageObject.toggle(); // show
|
||||||
|
|
||||||
await checkForScreenshot({
|
await checkForScreenshot({
|
||||||
page,
|
page,
|
||||||
|
|||||||
@ -8,11 +8,12 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the probe tool', async ({
|
test('should display the probe tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await mainToolbarPageObject.moreTools.probe.click();
|
await mainToolbarPageObject.moreTools.probe.click();
|
||||||
await viewportPageObject.active.clickAt([{ x: 550, y: 200 }]);
|
await viewportPageObject.active.clickAt([{ x: 550, y: 200 }]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.probe.probeDisplayedCorrectly);
|
await checkForScreenshot(page, page, screenShotPaths.probe.probeDisplayedCorrectly);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -12,16 +12,15 @@ test('should overlay an unhydrated RTSTRUCT over a display set that the RTSTRUCT
|
|||||||
page,
|
page,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
const dataOverlayPageObject = viewportPageObject.getById('default').overlayMenu.dataOverlay;
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-default').click();
|
await dataOverlayPageObject.toggle();
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
await dataOverlayPageObject.addSegmentation('Contours on PET');
|
||||||
await page.getByTestId('Contours on PET').click();
|
|
||||||
|
|
||||||
// Adding an overlay should not show the LOAD button.
|
// Adding an overlay should not show the LOAD button.
|
||||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||||
|
|
||||||
// Hide the overlay menu.
|
// Hide the overlay menu.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
|||||||
@ -10,19 +10,19 @@ test.beforeEach(async ({ page }) => {
|
|||||||
test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay menu', async ({
|
test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay menu', async ({
|
||||||
page,
|
page,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
await rightPanelPageObject.toggle();
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
const dataOverlayPageObject = viewportPageObject.getById('default').overlayMenu.dataOverlay;
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-default').click();
|
await dataOverlayPageObject.toggle();
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
await dataOverlayPageObject.addSegmentation('ARIA RadOnc Structure Sets');
|
||||||
await page.getByTestId('ARIA RadOnc Structure Sets').click();
|
|
||||||
|
|
||||||
// Adding an overlay should not show the LOAD button.
|
// Adding an overlay should not show the LOAD button.
|
||||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||||
|
|
||||||
// Hide the overlay menu.
|
// Hide the overlay menu.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await dataOverlayPageObject.toggle();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { test } from 'playwright-test-coverage';
|
import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils';
|
||||||
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils';
|
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
||||||
@ -7,17 +6,24 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should hydrate RT reports correctly', async ({ page }) => {
|
test('should hydrate RT reports correctly', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtPreHydration);
|
await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtPreHydration);
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtPostHydration);
|
await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtPostHydration);
|
||||||
|
|
||||||
await page.getByText('Small Sphere').click();
|
await rightPanelPageObject.labelMapSegmentationPanel.panel
|
||||||
|
.segmentationByText('Small Sphere')
|
||||||
|
.click();
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtJumpToStructure);
|
await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtJumpToStructure);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { test } from 'playwright-test-coverage';
|
import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils';
|
||||||
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils';
|
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
const studyInstanceUID = '1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0';
|
const studyInstanceUID = '1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0';
|
||||||
@ -7,9 +6,14 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should hydrate RT reports correctly', async ({ page }) => {
|
test('should hydrate RT reports correctly', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.rtHydration2.rtPreHydration);
|
await checkForScreenshot(page, page, screenShotPaths.rtHydration2.rtPreHydration);
|
||||||
// wait for 3 seconds
|
// wait for 3 seconds
|
||||||
@ -34,9 +38,7 @@ test('should hydrate RT reports correctly', async ({ page }) => {
|
|||||||
|
|
||||||
await page.waitForTimeout(3000);
|
await page.waitForTimeout(3000);
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
// should preserve zoom and pan and scroll position after hydration
|
// should preserve zoom and pan and scroll position after hydration
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtPostHydration);
|
await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtPostHydration);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -6,8 +6,14 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should hydrate an RTSTRUCT from MPR', async ({ page, mainToolbarPageObject }) => {
|
test('should hydrate an RTSTRUCT from MPR', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
|
||||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||||
|
|
||||||
@ -15,13 +21,13 @@ test('should hydrate an RTSTRUCT from MPR', async ({ page, mainToolbarPageObject
|
|||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.rtHydrationFromMPR.mprBeforeRT);
|
await checkForScreenshot(page, page, screenShotPaths.rtHydrationFromMPR.mprBeforeRT);
|
||||||
|
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.rtHydrationFromMPR.mprAfterRT);
|
await checkForScreenshot(page, page, screenShotPaths.rtHydrationFromMPR.mprAfterRT);
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
|||||||
@ -6,11 +6,17 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should hydrate an RTSTRUCT and then launch MPR', async ({ page, mainToolbarPageObject }) => {
|
test('should hydrate an RTSTRUCT and then launch MPR', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
|||||||
@ -6,9 +6,14 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should launch MPR with unhydrated RTSTRUCT', async ({ page, mainToolbarPageObject }) => {
|
test('should launch MPR with unhydrated RTSTRUCT', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
leftPanelPageObject,
|
||||||
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the rectangle tool', async ({
|
test('should display the rectangle tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -16,6 +17,6 @@ test('should display the rectangle tool', async ({
|
|||||||
{ x: 476, y: 159 },
|
{ x: 476, y: 159 },
|
||||||
{ x: 591, y: 217 },
|
{ x: 591, y: 217 },
|
||||||
]);
|
]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.rectangle.rectangleDisplayedCorrectly);
|
await checkForScreenshot(page, page, screenShotPaths.rectangle.rectangleDisplayedCorrectly);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,20 +10,21 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should overlay an unhydrated SEG over a display set that the SEG does NOT reference', async ({
|
test('should overlay an unhydrated SEG over a display set that the SEG does NOT reference', async ({
|
||||||
page,
|
page,
|
||||||
|
leftPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await page.getByTestId('study-browser-thumbnail').nth(2).dblclick();
|
await leftPanelPageObject.loadSeriesByDescription('Apparent Diffusion Coefficient');
|
||||||
|
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await viewportPageObject.getById('default').overlayMenu.dataOverlay.toggle();
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-default').click();
|
await viewportPageObject
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
.getById('default')
|
||||||
await page.getByTestId('T2 Weighted Axial Segmentations').click();
|
.overlayMenu.dataOverlay.addSegmentation('T2 Weighted Axial Segmentations');
|
||||||
|
|
||||||
// Adding an overlay should not show the LOAD button.
|
// Adding an overlay should not show the LOAD button.
|
||||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||||
|
|
||||||
// Hide the overlay menu.
|
// Hide the overlay menu.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await viewportPageObject.getById('default').overlayMenu.dataOverlay.toggle();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
|||||||
@ -10,19 +10,20 @@ test.beforeEach(async ({ page }) => {
|
|||||||
test('should launch MPR with unhydrated SEG chosen from the data overlay menu', async ({
|
test('should launch MPR with unhydrated SEG chosen from the data overlay menu', async ({
|
||||||
page,
|
page,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
await rightPanelPageObject.toggle();
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await viewportPageObject.getById('default').overlayMenu.dataOverlay.toggle();
|
||||||
await page.getByTestId('AddSegmentationDataOverlay-default').click();
|
await viewportPageObject
|
||||||
await page.getByText('SELECT A SEGMENTATION').click();
|
.getById('default')
|
||||||
await page.getByTestId('Segmentation').click();
|
.overlayMenu.dataOverlay.addSegmentation('Segmentation');
|
||||||
|
|
||||||
// Adding an overlay should not show the LOAD button.
|
// Adding an overlay should not show the LOAD button.
|
||||||
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
assertNumberOfModalityLoadBadges({ page, expectedCount: 0 });
|
||||||
|
|
||||||
// Hide the overlay menu.
|
// Hide the overlay menu.
|
||||||
await viewportPageObject.getById('default').overlayMenu.dataOverlay.click();
|
await viewportPageObject.getById('default').overlayMenu.dataOverlay.toggle();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,15 @@
|
|||||||
import { Page } from '@playwright/test';
|
import { Page } from '@playwright/test';
|
||||||
|
|
||||||
import { ViewportPageObject } from './pages';
|
import { RightPanelPageObject, ViewportPageObject } from './pages';
|
||||||
import { checkForScreenshot, expect, screenShotPaths, test, visitStudy } from './utils';
|
import { checkForScreenshot, expect, screenShotPaths, test, visitStudy } from './utils';
|
||||||
import { press } from './utils/keyboardUtils';
|
import { press } from './utils/keyboardUtils';
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page, rightPanelPageObject }) => {
|
||||||
const studyInstanceUID = '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046';
|
const studyInstanceUID = '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046';
|
||||||
const mode = 'segmentation';
|
const mode = 'segmentation';
|
||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
|
|
||||||
await page.getByTestId('panelSegmentationWithToolsLabelMap-btn').click();
|
await rightPanelPageObject.labelMapSegmentationPanel.addSegmentationButton.click();
|
||||||
await page.getByTestId('addSegmentation').click();
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
});
|
});
|
||||||
@ -18,9 +17,10 @@ test.beforeEach(async ({ page }) => {
|
|||||||
async function performDrawingToolInteraction(
|
async function performDrawingToolInteraction(
|
||||||
page: Page,
|
page: Page,
|
||||||
toolName: string,
|
toolName: string,
|
||||||
|
rightPanelPageObject: RightPanelPageObject,
|
||||||
viewportPageObject: ViewportPageObject
|
viewportPageObject: ViewportPageObject
|
||||||
) {
|
) {
|
||||||
const brushRadiusInput = page.getByTestId(`${toolName}-radius`).locator('input');
|
const brushRadiusInput = rightPanelPageObject.labelMapSegmentationPanel.tools[toolName].input;
|
||||||
const circle = viewportPageObject.active.svg('circle').first();
|
const circle = viewportPageObject.active.svg('circle').first();
|
||||||
|
|
||||||
await expect(brushRadiusInput).toHaveValue('25');
|
await expect(brushRadiusInput).toHaveValue('25');
|
||||||
@ -57,10 +57,14 @@ async function performDrawingToolInteraction(
|
|||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
test('should resize segmentation brush tool', async ({ page, viewportPageObject }) => {
|
test('should resize segmentation brush tool', async ({
|
||||||
|
page,
|
||||||
|
rightPanelPageObject,
|
||||||
|
viewportPageObject,
|
||||||
|
}) => {
|
||||||
await page.getByTestId('Brush-btn').click();
|
await page.getByTestId('Brush-btn').click();
|
||||||
|
|
||||||
await performDrawingToolInteraction(page, 'brush', viewportPageObject);
|
await performDrawingToolInteraction(page, 'brush', rightPanelPageObject, viewportPageObject);
|
||||||
|
|
||||||
await checkForScreenshot(
|
await checkForScreenshot(
|
||||||
page,
|
page,
|
||||||
@ -69,7 +73,11 @@ test('should resize segmentation brush tool', async ({ page, viewportPageObject
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should resize segmentation eraser tool', async ({ page, viewportPageObject }) => {
|
test('should resize segmentation eraser tool', async ({
|
||||||
|
page,
|
||||||
|
rightPanelPageObject,
|
||||||
|
viewportPageObject,
|
||||||
|
}) => {
|
||||||
await page.getByTestId('Brush-btn').click();
|
await page.getByTestId('Brush-btn').click();
|
||||||
|
|
||||||
await page.getByTestId('brush-radius').locator('input').fill('99.5');
|
await page.getByTestId('brush-radius').locator('input').fill('99.5');
|
||||||
@ -82,7 +90,7 @@ test('should resize segmentation eraser tool', async ({ page, viewportPageObject
|
|||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
await performDrawingToolInteraction(page, 'eraser', viewportPageObject);
|
await performDrawingToolInteraction(page, 'eraser', rightPanelPageObject, viewportPageObject);
|
||||||
|
|
||||||
await checkForScreenshot(
|
await checkForScreenshot(
|
||||||
page,
|
page,
|
||||||
@ -91,8 +99,12 @@ test('should resize segmentation eraser tool', async ({ page, viewportPageObject
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should resize segmentation threshold tool', async ({ page, viewportPageObject }) => {
|
test('should resize segmentation threshold tool', async ({
|
||||||
|
page,
|
||||||
|
rightPanelPageObject,
|
||||||
|
viewportPageObject,
|
||||||
|
}) => {
|
||||||
await page.getByTestId('Threshold-btn').click();
|
await page.getByTestId('Threshold-btn').click();
|
||||||
|
|
||||||
await performDrawingToolInteraction(page, 'threshold', viewportPageObject);
|
await performDrawingToolInteraction(page, 'threshold', rightPanelPageObject, viewportPageObject);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { test } from 'playwright-test-coverage';
|
import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils';
|
||||||
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils';
|
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.256467663913010332776401703474716742458';
|
const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.256467663913010332776401703474716742458';
|
||||||
@ -7,9 +6,14 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should hydrate SEG reports correctly', async ({ page }) => {
|
test('should hydrate SEG reports correctly', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
await leftPanelPageObject.loadSeriesByDescription('SEG');
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.segHydration.segPreHydration);
|
await checkForScreenshot(page, page, screenShotPaths.segHydration.segPreHydration);
|
||||||
@ -33,7 +37,7 @@ test('should hydrate SEG reports correctly', async ({ page }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.segHydration.segPostHydration);
|
await checkForScreenshot(page, page, screenShotPaths.segHydration.segPostHydration);
|
||||||
|
|||||||
@ -16,6 +16,8 @@ test.beforeEach(async ({ page }) => {
|
|||||||
test.describe('3D four up SEG hydration', async () => {
|
test.describe('3D four up SEG hydration', async () => {
|
||||||
test('should properly hydrate SEG from 3D four up layout', async ({
|
test('should properly hydrate SEG from 3D four up layout', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
await mainToolbarPageObject.layoutSelection.threeDFourUp.click();
|
await mainToolbarPageObject.layoutSelection.threeDFourUp.click();
|
||||||
@ -30,7 +32,7 @@ test.describe('3D four up SEG hydration', async () => {
|
|||||||
screenShotPaths.segHydrationFrom3DFourUp.threeDFourUpBeforeSEG
|
screenShotPaths.segHydrationFrom3DFourUp.threeDFourUpBeforeSEG
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByDescription('SEG');
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(
|
await checkForScreenshot(
|
||||||
@ -39,7 +41,7 @@ test.describe('3D four up SEG hydration', async () => {
|
|||||||
screenShotPaths.segHydrationFrom3DFourUp.threeDFourUpAfterSEG
|
screenShotPaths.segHydrationFrom3DFourUp.threeDFourUpAfterSEG
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(
|
await checkForScreenshot(
|
||||||
|
|||||||
@ -6,20 +6,26 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should properly display MPR for MR', async ({ page, mainToolbarPageObject }) => {
|
test('should properly display MPR for MR', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
|
||||||
await mainToolbarPageObject.layoutSelection.MPR.click();
|
await mainToolbarPageObject.layoutSelection.MPR.click();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprBeforeSEG);
|
await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprBeforeSEG);
|
||||||
|
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByDescription('SEG');
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprAfterSEG);
|
await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprAfterSEG);
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprAfterSegHydrated);
|
await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprAfterSegHydrated);
|
||||||
|
|||||||
@ -6,11 +6,17 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should properly display MPR for MR', async ({ page, mainToolbarPageObject }) => {
|
test('should properly display MPR for MR', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
await leftPanelPageObject.loadSeriesByDescription('SEG');
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.segHydrationThenMPR.segPostHydration);
|
await checkForScreenshot(page, page, screenShotPaths.segHydrationThenMPR.segPostHydration);
|
||||||
|
|||||||
@ -6,9 +6,14 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should launch MPR with unhydrated SEG', async ({ page, mainToolbarPageObject }) => {
|
test('should launch MPR with unhydrated SEG', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
leftPanelPageObject,
|
||||||
|
mainToolbarPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
await leftPanelPageObject.loadSeriesByDescription('SEG');
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { test } from 'playwright-test-coverage';
|
import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils';
|
||||||
import { visitStudy, checkForScreenshot, screenShotPaths } from './utils';
|
|
||||||
|
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.7695.4007.324475281161490036195179843543';
|
const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.7695.4007.324475281161490036195179843543';
|
||||||
@ -7,10 +6,15 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should hydrate SR reports correctly', async ({ page }) => {
|
test('should hydrate SR reports correctly', async ({
|
||||||
await page.getByTestId('side-panel-header-right').click();
|
page,
|
||||||
await page.getByTestId('trackedMeasurements-btn').click();
|
DOMOverlayPageObject,
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
|
}) => {
|
||||||
|
await rightPanelPageObject.toggle();
|
||||||
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
|
await leftPanelPageObject.loadSeriesByModality('SR');
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.srHydration.srPreHydration);
|
await checkForScreenshot(page, page, screenShotPaths.srHydration.srPreHydration);
|
||||||
|
|
||||||
@ -33,7 +37,7 @@ test('should hydrate SR reports correctly', async ({ page }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
await checkForScreenshot(page, page, screenShotPaths.srHydration.srPostHydration);
|
await checkForScreenshot(page, page, screenShotPaths.srHydration.srPostHydration);
|
||||||
|
|
||||||
@ -56,7 +60,7 @@ test('should hydrate SR reports correctly', async ({ page }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await page.getByTestId('data-row').first().click();
|
await rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).click();
|
||||||
|
|
||||||
await checkForScreenshot(page, page, screenShotPaths.srHydration.srJumpToMeasurement);
|
await checkForScreenshot(page, page, screenShotPaths.srHydration.srJumpToMeasurement);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -21,17 +21,20 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should hydrate SCOORD3D probe measurements correctly', async ({
|
test('should hydrate SCOORD3D probe measurements correctly', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
// Wait for the side panel to be visible and clickable
|
// Wait for the side panel to be visible and clickable
|
||||||
await page.waitForTimeout(3000);
|
await page.waitForTimeout(3000);
|
||||||
|
|
||||||
// Navigate to the tracked measurements panel
|
// Navigate to the tracked measurements panel
|
||||||
await page.getByTestId('side-panel-header-right').click({ timeout: 15000 });
|
await rightPanelPageObject.toggle();
|
||||||
await page.getByTestId('trackedMeasurements-btn').click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
|
|
||||||
// Double-click on the study browser thumbnail to load the SR
|
// Double-click on the study browser thumbnail to load the SR
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('SR');
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
// Wait for the SR to load and stabilize before taking screenshot
|
// Wait for the SR to load and stabilize before taking screenshot
|
||||||
@ -68,10 +71,13 @@ test('should hydrate SCOORD3D probe measurements correctly', async ({
|
|||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
// Wait for the hydrate button to be visible and clickable
|
// Wait for the hydrate button to be visible and clickable
|
||||||
await page.getByTestId('yes-hydrate-btn').waitFor({ state: 'visible', timeout: 15000 });
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.button.waitFor({
|
||||||
|
state: 'visible',
|
||||||
|
timeout: 15000,
|
||||||
|
});
|
||||||
|
|
||||||
// Click the hydrate button to load the SCOORD3D probe measurements
|
// Click the hydrate button to load the SCOORD3D probe measurements
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
// Wait for hydration to complete and rendering to stabilize
|
// Wait for hydration to complete and rendering to stabilize
|
||||||
await page.waitForTimeout(3000);
|
await page.waitForTimeout(3000);
|
||||||
@ -86,14 +92,17 @@ test('should hydrate SCOORD3D probe measurements correctly', async ({
|
|||||||
// Verify the measurements list has the correct probe measurements
|
// Verify the measurements list has the correct probe measurements
|
||||||
const measurementRows = page.getByTestId('data-row');
|
const measurementRows = page.getByTestId('data-row');
|
||||||
const rowCount = await measurementRows.count();
|
const rowCount = await measurementRows.count();
|
||||||
expect(rowCount).toBeGreaterThan(0);
|
expect(await rightPanelPageObject.measurementsPanel.panel.getMeasurementCount()).toBeGreaterThan(
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
// Verify that the measurements are probe measurements (not other types)
|
// Verify that the measurements are probe measurements (not other types)
|
||||||
for (let i = 0; i < rowCount; i++) {
|
for (let i = 0; i < rowCount; i++) {
|
||||||
const row = measurementRows.nth(i);
|
const measurementText = await rightPanelPageObject.measurementsPanel.panel
|
||||||
const rowText = await row.textContent();
|
.nthMeasurement(i)
|
||||||
|
.locator.textContent();
|
||||||
// Probe measurements should be present, verify they're not other measurement types
|
// Probe measurements should be present, verify they're not other measurement types
|
||||||
expect(rowText).toBeTruthy();
|
expect(measurementText).toBeTruthy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test jumping to a specific measurement by scrolling and clicking
|
// Test jumping to a specific measurement by scrolling and clicking
|
||||||
@ -117,7 +126,7 @@ test('should hydrate SCOORD3D probe measurements correctly', async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Click on a data row to jump to the measurement
|
// Click on a data row to jump to the measurement
|
||||||
await page.getByTestId('data-row').first().click();
|
await rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).click();
|
||||||
|
|
||||||
// Take screenshot showing the jump to measurement functionality - use viewport locator
|
// Take screenshot showing the jump to measurement functionality - use viewport locator
|
||||||
await checkForScreenshot(
|
await checkForScreenshot(
|
||||||
@ -129,20 +138,26 @@ test('should hydrate SCOORD3D probe measurements correctly', async ({
|
|||||||
|
|
||||||
test('should display SCOORD3D probe measurements correctly', async ({
|
test('should display SCOORD3D probe measurements correctly', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
// Wait for the side panel to be visible and clickable
|
// Wait for the side panel to be visible and clickable
|
||||||
await page.waitForTimeout(3000);
|
await page.waitForTimeout(3000);
|
||||||
|
|
||||||
// First hydrate the SR to load the measurements
|
// First hydrate the SR to load the measurements
|
||||||
await page.getByTestId('side-panel-header-right').click({ timeout: 15000 });
|
await rightPanelPageObject.toggle();
|
||||||
await page.getByTestId('trackedMeasurements-btn').click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('SR');
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
// Wait for the hydrate button to be visible and clickable
|
// Wait for the hydrate button to be visible and clickable
|
||||||
await page.getByTestId('yes-hydrate-btn').waitFor({ state: 'visible', timeout: 15000 });
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.button.waitFor({
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
state: 'visible',
|
||||||
|
timeout: 15000,
|
||||||
|
});
|
||||||
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
// Zoom to show the probe measurements clearly
|
// Zoom to show the probe measurements clearly
|
||||||
@ -175,15 +190,15 @@ test('should display SCOORD3D probe measurements correctly', async ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Verify the measurements list has the correct probe measurements and not others
|
// Verify the measurements list has the correct probe measurements and not others
|
||||||
const measurementRows = page.getByTestId('data-row');
|
const rowCount = await rightPanelPageObject.measurementsPanel.panel.getMeasurementCount();
|
||||||
const rowCount = await measurementRows.count();
|
|
||||||
expect(rowCount).toBeGreaterThan(0);
|
expect(rowCount).toBeGreaterThan(0);
|
||||||
|
|
||||||
// Verify that the measurements are probe measurements (not other types like rectangle)
|
// Verify that the measurements are probe measurements (not other types like rectangle)
|
||||||
for (let i = 0; i < rowCount; i++) {
|
for (let i = 0; i < rowCount; i++) {
|
||||||
const row = measurementRows.nth(i);
|
const measurementText = await rightPanelPageObject.measurementsPanel.panel
|
||||||
const rowText = await row.textContent();
|
.nthMeasurement(i)
|
||||||
|
.locator.textContent();
|
||||||
// Probe measurements should be present, verify they're not other measurement types
|
// Probe measurements should be present, verify they're not other measurement types
|
||||||
expect(rowText).toBeTruthy();
|
expect(measurementText).toBeTruthy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -22,17 +22,20 @@ test.beforeEach(async ({ page }) => {
|
|||||||
//
|
//
|
||||||
test('should hydrate SCOORD rectangle measurements correctly', async ({
|
test('should hydrate SCOORD rectangle measurements correctly', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
// Wait for the side panel to be visible and clickable
|
// Wait for the side panel to be visible and clickable
|
||||||
await page.waitForTimeout(3000);
|
await page.waitForTimeout(3000);
|
||||||
|
|
||||||
// Navigate to the tracked measurements panel
|
// Navigate to the tracked measurements panel
|
||||||
await page.getByTestId('side-panel-header-right').click({ timeout: 15000 });
|
await rightPanelPageObject.toggle();
|
||||||
await page.getByTestId('trackedMeasurements-btn').click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
|
|
||||||
// Double-click on the study browser thumbnail to load the SR
|
// Double-click on the study browser thumbnail to load the SR
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('SR');
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
// Wait for the SR to load and stabilize before taking screenshot
|
// Wait for the SR to load and stabilize before taking screenshot
|
||||||
@ -69,10 +72,13 @@ test('should hydrate SCOORD rectangle measurements correctly', async ({
|
|||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
// Wait for the hydrate button to be visible and clickable
|
// Wait for the hydrate button to be visible and clickable
|
||||||
await page.getByTestId('yes-hydrate-btn').waitFor({ state: 'visible', timeout: 15000 });
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.button.waitFor({
|
||||||
|
state: 'visible',
|
||||||
|
timeout: 15000,
|
||||||
|
});
|
||||||
|
|
||||||
// Click the hydrate button to load the SCOORD rectangle measurements
|
// Click the hydrate button to load the SCOORD rectangle measurements
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
|
|
||||||
// Wait for hydration to complete and rendering to stabilize
|
// Wait for hydration to complete and rendering to stabilize
|
||||||
await page.waitForTimeout(3000);
|
await page.waitForTimeout(3000);
|
||||||
@ -85,16 +91,16 @@ test('should hydrate SCOORD rectangle measurements correctly', async ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Verify the measurements list has the correct rectangle measurements
|
// Verify the measurements list has the correct rectangle measurements
|
||||||
const measurementRows = page.getByTestId('data-row');
|
const rowCount = await rightPanelPageObject.measurementsPanel.panel.getMeasurementCount();
|
||||||
const rowCount = await measurementRows.count();
|
|
||||||
expect(rowCount).toBeGreaterThan(0);
|
expect(rowCount).toBeGreaterThan(0);
|
||||||
|
|
||||||
// Verify that the measurements are rectangle measurements (not other types)
|
// Verify that the measurements are rectangle measurements (not other types)
|
||||||
for (let i = 0; i < rowCount; i++) {
|
for (let i = 0; i < rowCount; i++) {
|
||||||
const row = measurementRows.nth(i);
|
const measurementText = await rightPanelPageObject.measurementsPanel.panel
|
||||||
const rowText = await row.textContent();
|
.nthMeasurement(i)
|
||||||
|
.locator.textContent();
|
||||||
// Rectangle measurements should be present, verify they're not other measurement types
|
// Rectangle measurements should be present, verify they're not other measurement types
|
||||||
expect(rowText).toBeTruthy();
|
expect(measurementText).toBeTruthy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test jumping to a specific measurement by scrolling and clicking
|
// Test jumping to a specific measurement by scrolling and clicking
|
||||||
@ -118,7 +124,7 @@ test('should hydrate SCOORD rectangle measurements correctly', async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Click on a data row to jump to the measurement
|
// Click on a data row to jump to the measurement
|
||||||
await page.getByTestId('data-row').first().click();
|
await rightPanelPageObject.measurementsPanel.panel.nthMeasurement(0).click();
|
||||||
|
|
||||||
// Take screenshot showing the jump to measurement functionality - use viewport locator
|
// Take screenshot showing the jump to measurement functionality - use viewport locator
|
||||||
await checkForScreenshot(
|
await checkForScreenshot(
|
||||||
@ -130,20 +136,26 @@ test('should hydrate SCOORD rectangle measurements correctly', async ({
|
|||||||
|
|
||||||
test('should display SCOORD rectangle measurements correctly', async ({
|
test('should display SCOORD rectangle measurements correctly', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
// Wait for the side panel to be visible and clickable
|
// Wait for the side panel to be visible and clickable
|
||||||
await page.waitForTimeout(3000);
|
await page.waitForTimeout(3000);
|
||||||
|
|
||||||
// First hydrate the SR to load the measurements
|
// First hydrate the SR to load the measurements
|
||||||
await page.getByTestId('side-panel-header-right').click({ timeout: 15000 });
|
await rightPanelPageObject.toggle();
|
||||||
await page.getByTestId('trackedMeasurements-btn').click();
|
await rightPanelPageObject.measurementsPanel.select();
|
||||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
await leftPanelPageObject.loadSeriesByModality('SR');
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
// Wait for the hydrate button to be visible and clickable
|
// Wait for the hydrate button to be visible and clickable
|
||||||
await page.getByTestId('yes-hydrate-btn').waitFor({ state: 'visible', timeout: 15000 });
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.button.waitFor({
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
state: 'visible',
|
||||||
|
timeout: 15000,
|
||||||
|
});
|
||||||
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
// Zoom to show the rectangle measurements clearly
|
// Zoom to show the rectangle measurements clearly
|
||||||
@ -176,15 +188,15 @@ test('should display SCOORD rectangle measurements correctly', async ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Verify the measurements list has the correct rectangle measurements and not others
|
// Verify the measurements list has the correct rectangle measurements and not others
|
||||||
const measurementRows = page.getByTestId('data-row');
|
const rowCount = await rightPanelPageObject.measurementsPanel.panel.getMeasurementCount();
|
||||||
const rowCount = await measurementRows.count();
|
|
||||||
expect(rowCount).toBeGreaterThan(0);
|
expect(rowCount).toBeGreaterThan(0);
|
||||||
|
|
||||||
// Verify that the measurements are rectangle measurements (not other types like probe)
|
// Verify that the measurements are rectangle measurements (not other types like probe)
|
||||||
for (let i = 0; i < rowCount; i++) {
|
for (let i = 0; i < rowCount; i++) {
|
||||||
const row = measurementRows.nth(i);
|
const measurementText = await rightPanelPageObject.measurementsPanel.panel
|
||||||
const rowText = await row.textContent();
|
.nthMeasurement(i)
|
||||||
|
.locator.textContent();
|
||||||
// Rectangle measurements should be present, verify they're not other measurement types
|
// Rectangle measurements should be present, verify they're not other measurement types
|
||||||
expect(rowText).toBeTruthy();
|
expect(measurementText).toBeTruthy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,55 +7,39 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('checks basic add, rename, delete segments from panel', async ({ page }) => {
|
test('checks basic add, rename, delete segments from panel', async ({ rightPanelPageObject }) => {
|
||||||
// Segmentation Panel should already be open
|
// Segmentation Panel should already be open
|
||||||
const segmentationPanel = page.getByTestId('panelSegmentationWithToolsLabelMap-btn');
|
const segmentationPanel = rightPanelPageObject.labelMapSegmentationPanel.menuButton;
|
||||||
await expect(segmentationPanel).toBeVisible();
|
await expect(segmentationPanel).toBeVisible();
|
||||||
|
|
||||||
// Switch to labelmap tab.
|
// Switch to labelmap tab.
|
||||||
segmentationPanel.click();
|
segmentationPanel.click();
|
||||||
|
|
||||||
// Add segmentation
|
// Add segmentation
|
||||||
const addSegmentationBtn = page.getByTestId('addSegmentation');
|
await rightPanelPageObject.labelMapSegmentationPanel.addSegmentationButton.click();
|
||||||
await addSegmentationBtn.click();
|
|
||||||
|
|
||||||
// Expect new segmentation and blank segment named "Segment 1"
|
// Expect new segmentation and blank segment named "Segment 1"
|
||||||
await expect(page.getByTestId('data-row')).toHaveCount(1);
|
const segment1 = rightPanelPageObject.labelMapSegmentationPanel.panel.nthSegmentation(0);
|
||||||
await expect(page.getByTestId('data-row')).toContainText('Segment 1');
|
expect(await rightPanelPageObject.labelMapSegmentationPanel.panel.getSegmentationCount()).toBe(1);
|
||||||
|
await expect(segment1.locator).toContainText('Segment 1');
|
||||||
|
|
||||||
// Rename
|
// Rename
|
||||||
const segment1Dropdown = page
|
await segment1.actions.rename('Segment One');
|
||||||
.getByTestId('data-row')
|
|
||||||
.first()
|
|
||||||
.getByRole('button', { name: 'Actions' });
|
|
||||||
await segment1Dropdown.click();
|
|
||||||
|
|
||||||
const renameButton = page.getByRole('menuitem', { name: 'Rename' });
|
await expect(segment1.locator).toContainText('Segment One');
|
||||||
await expect(renameButton).toBeVisible();
|
await expect(segment1.locator).not.toContainText('Segment 1');
|
||||||
await renameButton.click();
|
|
||||||
|
|
||||||
const renameDialog = page.getByRole('dialog', { name: 'Edit Segment Label' });
|
|
||||||
await expect(renameDialog).toBeVisible();
|
|
||||||
|
|
||||||
const renameInput = page.getByRole('textbox', { name: 'Enter new label' });
|
|
||||||
await renameInput.fill('Segment One');
|
|
||||||
|
|
||||||
await page.getByTestId('input-dialog-save-button').click();
|
|
||||||
|
|
||||||
await expect(page.getByTestId('data-row')).toContainText('Segment One');
|
|
||||||
await expect(page.getByTestId('data-row')).not.toContainText('Segment 1');
|
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
await segment1Dropdown.click();
|
await segment1.actions.delete();
|
||||||
const deleteButton = page.getByRole('menuitem', { name: 'Delete' });
|
|
||||||
await expect(deleteButton).toBeVisible();
|
|
||||||
await deleteButton.click();
|
|
||||||
|
|
||||||
await expect(page.getByTestId('data-row')).toHaveCount(0);
|
expect(await rightPanelPageObject.labelMapSegmentationPanel.panel.getSegmentationCount()).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('checks saved segmentations loads and jumps to slices', async ({
|
test('checks saved segmentations loads and jumps to slices', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
leftPanelPageObject,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
const viewportInfoBottomRight = viewportPageObject.active.overlayText.bottomRight;
|
const viewportInfoBottomRight = viewportPageObject.active.overlayText.bottomRight;
|
||||||
@ -63,39 +47,34 @@ test('checks saved segmentations loads and jumps to slices', async ({
|
|||||||
await expect(viewportInfoBottomRight).toContainText('1/', { timeout: 10000 });
|
await expect(viewportInfoBottomRight).toContainText('1/', { timeout: 10000 });
|
||||||
|
|
||||||
// Add Segmentations
|
// Add Segmentations
|
||||||
const segmentationsThumbnail = page
|
await leftPanelPageObject.loadSeriesByModality('SEG');
|
||||||
.getByTestId('study-browser-thumbnail-no-image')
|
|
||||||
.getByRole('button', { name: 'Segmentation' });
|
|
||||||
await segmentationsThumbnail.dblclick();
|
|
||||||
|
|
||||||
await page.waitForTimeout(3000);
|
await page.waitForTimeout(3000);
|
||||||
|
|
||||||
// Confirm open segmentation
|
// Confirm open segmentation
|
||||||
const viewportNotification = page.getByTestId('viewport-notification');
|
await expect(DOMOverlayPageObject.viewport.segmentationHydration.locator).toBeVisible();
|
||||||
await expect(viewportNotification).toBeVisible();
|
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||||
await page.getByTestId('yes-hydrate-btn').click();
|
|
||||||
|
|
||||||
// Segmentation Panel should already be open
|
// Segmentation Panel should already be open
|
||||||
const segmentationPanel = page.getByTestId('panelSegmentationWithToolsLabelMap-btn');
|
const segmentationPanel = rightPanelPageObject.labelMapSegmentationPanel.menuButton;
|
||||||
await expect(segmentationPanel).toBeVisible();
|
await expect(segmentationPanel).toBeVisible();
|
||||||
|
|
||||||
// Confirm spleen jumps to slice 17
|
// Confirm spleen jumps to slice 17
|
||||||
// First iteration repeat to account for segmentation loading delays
|
// First iteration repeat to account for segmentation loading delays
|
||||||
const spleenRow = page.getByTestId('data-row').filter({ hasText: 'Spleen' });
|
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await spleenRow.click();
|
await rightPanelPageObject.labelMapSegmentationPanel.panel.segmentationByText('Spleen').click();
|
||||||
await expect(viewportInfoBottomRight).toContainText('17/');
|
await expect(viewportInfoBottomRight).toContainText('17/');
|
||||||
}).toPass({
|
}).toPass({
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Esophagus - 5
|
// Esophagus - 5
|
||||||
const esophagusRow = page.getByTestId('data-row').filter({ hasText: 'Esophagus' });
|
await rightPanelPageObject.labelMapSegmentationPanel.panel
|
||||||
await esophagusRow.click();
|
.segmentationByText('Esophagus')
|
||||||
|
.click();
|
||||||
await expect(viewportInfoBottomRight).toContainText('5/');
|
await expect(viewportInfoBottomRight).toContainText('5/');
|
||||||
|
|
||||||
// Pancreas - 22
|
// Pancreas - 22
|
||||||
const pancreasRow = page.getByTestId('data-row').filter({ hasText: 'Pancreas' });
|
await rightPanelPageObject.labelMapSegmentationPanel.panel.segmentationByText('Pancreas').click();
|
||||||
await pancreasRow.click();
|
|
||||||
await expect(viewportInfoBottomRight).toContainText('22/');
|
await expect(viewportInfoBottomRight).toContainText('22/');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,6 +8,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
|
|
||||||
test('should display the spline tool', async ({
|
test('should display the spline tool', async ({
|
||||||
page,
|
page,
|
||||||
|
DOMOverlayPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -20,6 +21,6 @@ test('should display the spline tool', async ({
|
|||||||
{ x: 482, y: 493 },
|
{ x: 482, y: 493 },
|
||||||
{ x: 383, y: 461 },
|
{ x: 383, y: 461 },
|
||||||
]);
|
]);
|
||||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
await DOMOverlayPageObject.viewport.measurementTracking.confirm.click();
|
||||||
await checkForScreenshot(page, page, screenShotPaths.spline.splineDisplayedCorrectly);
|
await checkForScreenshot(page, page, screenShotPaths.spline.splineDisplayedCorrectly);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,21 +3,22 @@ import { downloadAsString } from './utils/download';
|
|||||||
|
|
||||||
test('should create and download the TMTV CSV report correctly', async ({
|
test('should create and download the TMTV CSV report correctly', async ({
|
||||||
page,
|
page,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
||||||
const mode = 'tmtv';
|
const mode = 'tmtv';
|
||||||
await visitStudy(page, studyInstanceUID, mode, 10000);
|
await visitStudy(page, studyInstanceUID, mode, 10000);
|
||||||
|
|
||||||
await page.getByTestId('addSegmentation').click();
|
await rightPanelPageObject.tmtvPanel.addSegmentationButton.click();
|
||||||
await page.getByTestId('Brush-btn').click();
|
await rightPanelPageObject.tmtvPanel.tools.brush.click();
|
||||||
|
|
||||||
await viewportPageObject.getById('ctAXIAL').normalizedClickAt([{ x: 0.5, y: 0.5 }]);
|
await viewportPageObject.getById('ctAXIAL').normalizedClickAt([{ x: 0.5, y: 0.5 }]);
|
||||||
|
|
||||||
await page.waitForTimeout(5000);
|
await page.waitForTimeout(5000);
|
||||||
|
|
||||||
const downloadPromise = page.waitForEvent('download');
|
const downloadPromise = page.waitForEvent('download');
|
||||||
await page.getByTestId('exportTmtvCsvReport').click();
|
await rightPanelPageObject.tmtvPanel.exportTmtvCsvReport();
|
||||||
const download = await downloadPromise;
|
const download = await downloadPromise;
|
||||||
|
|
||||||
expect(download.suggestedFilename(), 'Not the correct file name for the TMTV CSV report.').toBe(
|
expect(download.suggestedFilename(), 'Not the correct file name for the TMTV CSV report.').toBe(
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { expect, clearAllAnnotations, getTMTVModalityUnit, test, visitStudy } fr
|
|||||||
|
|
||||||
test.skip('pets where SUV cannot be calculated should show same unit in TMTV as in Basic Viewer.', async ({
|
test.skip('pets where SUV cannot be calculated should show same unit in TMTV as in Basic Viewer.', async ({
|
||||||
page,
|
page,
|
||||||
|
leftPanelPageObject,
|
||||||
mainToolbarPageObject,
|
mainToolbarPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
@ -10,7 +11,7 @@ test.skip('pets where SUV cannot be calculated should show same unit in TMTV as
|
|||||||
await visitStudy(page, studyInstanceUID, mode, 10000);
|
await visitStudy(page, studyInstanceUID, mode, 10000);
|
||||||
|
|
||||||
// Show sidebar
|
// Show sidebar
|
||||||
await page.getByTestId('side-panel-header-left').click();
|
await leftPanelPageObject.toggle();
|
||||||
|
|
||||||
// Change to image where SUV cannot be calculated
|
// Change to image where SUV cannot be calculated
|
||||||
await viewportPageObject.getNth(3).normalizedClickAt([{ x: 0.5, y: 0.5 }]);
|
await viewportPageObject.getNth(3).normalizedClickAt([{ x: 0.5, y: 0.5 }]);
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { expect, test, visitStudy } from './utils';
|
|||||||
|
|
||||||
test('should restrict the percentage of max SUV to be between 0 and 1', async ({
|
test('should restrict the percentage of max SUV to be between 0 and 1', async ({
|
||||||
page,
|
page,
|
||||||
|
rightPanelPageObject,
|
||||||
viewportPageObject,
|
viewportPageObject,
|
||||||
}) => {
|
}) => {
|
||||||
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
const studyInstanceUID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
||||||
@ -10,49 +11,51 @@ test('should restrict the percentage of max SUV to be between 0 and 1', async ({
|
|||||||
|
|
||||||
await viewportPageObject.getById('ptAXIAL').normalizedClickAt([{ x: 0.5, y: 0.5 }]);
|
await viewportPageObject.getById('ptAXIAL').normalizedClickAt([{ x: 0.5, y: 0.5 }]);
|
||||||
|
|
||||||
await page.getByTestId('addSegmentation').click();
|
await rightPanelPageObject.tmtvPanel.addSegmentationButton.click();
|
||||||
await page.getByTestId('RectangleROIStartEndThreshold-btn').click();
|
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('0');
|
const rectangleROIThreshold = rightPanelPageObject.tmtvPanel.tools.rectangleROIThreshold;
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('0');
|
await rectangleROIThreshold.click();
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('0.27');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('0');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('0.27');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('0');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('0.9467');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('0.27');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('0.9467');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('0.27');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('.');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('0.9467');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('0.');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('0.9467');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('1');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('.');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('1');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('0.');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('1.1');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('1');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('1');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('1');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('1806');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('1.1');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('1');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('1');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('1806');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('1');
|
||||||
|
|
||||||
|
await rectangleROIThreshold.setPercentageOfMaxSUV('');
|
||||||
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('');
|
||||||
|
|
||||||
// Add some valid input for the tests that follow. Note that when invalid input is
|
// Add some valid input for the tests that follow. Note that when invalid input is
|
||||||
// entered the previous valid input is retained.
|
// entered the previous valid input is retained.
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('0.275');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('0.275');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('9');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('9');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('0.275');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('0.275');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('-678');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('-678');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('0.275');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('0.275');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('+');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('+');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('0.275');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('0.275');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('-');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('-');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('0.275');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('0.275');
|
||||||
|
|
||||||
await page.getByTestId('percentage-of-max-suv-input').fill('e');
|
await rectangleROIThreshold.setPercentageOfMaxSUV('e');
|
||||||
expect(await page.getByTestId('percentage-of-max-suv-input').inputValue()).toBe('0.275');
|
expect(await rectangleROIThreshold.getPercentageOfMaxSUV()).toBe('0.275');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -25,13 +25,13 @@ test('should render scroll bars with the correct look-and-feel', async ({ page }
|
|||||||
// Wait for the expanded row to be visible and rendered
|
// Wait for the expanded row to be visible and rendered
|
||||||
await expandedStudyRow.waitFor({ state: 'visible', timeout: 10000 });
|
await expandedStudyRow.waitFor({ state: 'visible', timeout: 10000 });
|
||||||
await expandedStudyRow.scrollIntoViewIfNeeded();
|
await expandedStudyRow.scrollIntoViewIfNeeded();
|
||||||
|
|
||||||
// Wait for content to load and stabilize, including any lazy-loaded items
|
// Wait for content to load and stabilize, including any lazy-loaded items
|
||||||
await page.waitForTimeout(2000);
|
await page.waitForTimeout(2000);
|
||||||
|
|
||||||
// Wait for network to be idle to ensure all content is loaded
|
// Wait for network to be idle to ensure all content is loaded
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Additional wait to ensure scrollbar rendering is stable
|
// Additional wait to ensure scrollbar rendering is stable
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
|
|||||||
134
tests/pages/DOMOverlayPageObject.ts
Normal file
134
tests/pages/DOMOverlayPageObject.ts
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import { Locator, Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export class DOMOverlayPageObject {
|
||||||
|
readonly page: Page;
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
get dialog() {
|
||||||
|
const page = this.page;
|
||||||
|
|
||||||
|
return {
|
||||||
|
get confirmation() {
|
||||||
|
const cancelButton = page.getByTestId('untracked-series-modal-cancel-button');
|
||||||
|
const confirmButton = page.getByTestId('untracked-series-modal-confirm-button');
|
||||||
|
return {
|
||||||
|
cancel: {
|
||||||
|
button: cancelButton,
|
||||||
|
click: async () => {
|
||||||
|
await cancelButton.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
confirm: {
|
||||||
|
button: confirmButton,
|
||||||
|
click: async () => {
|
||||||
|
await confirmButton.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
get input() {
|
||||||
|
const locator = page.getByTestId('dialog-input');
|
||||||
|
const saveButton = page.getByTestId('input-dialog-save-button');
|
||||||
|
return {
|
||||||
|
locator,
|
||||||
|
fill: async (text: string) => {
|
||||||
|
await locator.fill(text);
|
||||||
|
},
|
||||||
|
fillAndSave: async (text: string) => {
|
||||||
|
await locator.fill(text);
|
||||||
|
await saveButton.click();
|
||||||
|
},
|
||||||
|
save: async () => {
|
||||||
|
await saveButton.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
title: page.locator('[role="dialog"] h2'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get viewport() {
|
||||||
|
const page = this.page;
|
||||||
|
|
||||||
|
return {
|
||||||
|
get annotationContextMenu() {
|
||||||
|
return {
|
||||||
|
get addLabel() {
|
||||||
|
const button = page.getByTestId('context-menu-item').filter({ hasText: 'Add Label' });
|
||||||
|
return {
|
||||||
|
locator: button,
|
||||||
|
click: async () => {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
get delete() {
|
||||||
|
const button = page.getByTestId('context-menu-item').filter({ hasText: 'Delete' });
|
||||||
|
return {
|
||||||
|
locator: button,
|
||||||
|
click: async () => {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
open: async (annotation: Locator) => {
|
||||||
|
await annotation.click({ button: 'right', force: true });
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
get measurementTracking() {
|
||||||
|
const cancelButton = page.getByTestId('prompt-begin-tracking-cancel-btn');
|
||||||
|
const noAndNotAskAgainButton = page.getByTestId(
|
||||||
|
'prompt-begin-tracking-no-do-not-ask-again-btn'
|
||||||
|
);
|
||||||
|
const confirmButton = page.getByTestId('prompt-begin-tracking-yes-btn');
|
||||||
|
return {
|
||||||
|
locator: page.getByTestId('viewport-notification'),
|
||||||
|
cancel: {
|
||||||
|
button: cancelButton,
|
||||||
|
click: async () => {
|
||||||
|
await cancelButton.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
noAndNotAskAgain: {
|
||||||
|
button: noAndNotAskAgainButton,
|
||||||
|
click: async () => {
|
||||||
|
await noAndNotAskAgainButton.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
confirm: {
|
||||||
|
button: confirmButton,
|
||||||
|
click: async () => {
|
||||||
|
await confirmButton.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
get segmentationHydration() {
|
||||||
|
const noButton = page.getByTestId('no-hydrate-btn');
|
||||||
|
const yesButton = page.getByTestId('yes-hydrate-btn');
|
||||||
|
return {
|
||||||
|
locator: page.getByTestId('viewport-notification'),
|
||||||
|
no: {
|
||||||
|
button: noButton,
|
||||||
|
click: async () => {
|
||||||
|
await noButton.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yes: {
|
||||||
|
button: yesButton,
|
||||||
|
click: async () => {
|
||||||
|
await yesButton.click();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async getModalityLoadBadgeCount() {
|
||||||
|
return await page.locator('css=div[data-cy^="ModalityLoadBadge-"]').count();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
29
tests/pages/DataOverlayPageObject.ts
Normal file
29
tests/pages/DataOverlayPageObject.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export class DataOverlayPageObject {
|
||||||
|
readonly page: Page;
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggle(viewportId: string = 'default') {
|
||||||
|
await this.page.getByTestId(`dataOverlayMenu-${viewportId}-btn`).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async addSegmentation(segmentation: string, viewportId: string = 'default') {
|
||||||
|
await this.page.getByTestId(`AddSegmentationDataOverlay-${viewportId}`).click();
|
||||||
|
await this.page.getByText('SELECT A SEGMENTATION').click();
|
||||||
|
await this.page.getByTestId(segmentation).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async changeSegmentation(from: string, to: string) {
|
||||||
|
await this.page.getByTestId(`overlay-ds-select-value-${from.toUpperCase()}`).click();
|
||||||
|
await this.page.getByTestId(`${to}-SEG`).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(segmentation: string) {
|
||||||
|
await this.page.getByTestId(`overlay-ds-more-button-${segmentation}`).click();
|
||||||
|
await this.page.getByTestId(`overlay-ds-remove-button-${segmentation}`).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
35
tests/pages/LeftPanelPageObject.ts
Normal file
35
tests/pages/LeftPanelPageObject.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export class LeftPanelPageObject {
|
||||||
|
readonly page: Page;
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggle() {
|
||||||
|
await this.page.getByTestId('side-panel-header-left').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
get thumbnails() {
|
||||||
|
return this.page.locator('[data-cy^="study-browser-thumbnail"]');
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadSeriesByModality(modality: string, nth: number = 0) {
|
||||||
|
const matchingThumbnail = this.thumbnails
|
||||||
|
.filter({
|
||||||
|
has: this.page.locator('[data-cy="series-modality-label"]', { hasText: modality }),
|
||||||
|
})
|
||||||
|
.nth(nth);
|
||||||
|
await matchingThumbnail.dblclick();
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadSeriesByDescription(description: string, nth: number = 0) {
|
||||||
|
const matchingThumbnail = this.thumbnails
|
||||||
|
.filter({
|
||||||
|
has: this.page.locator('[data-cy="series-description-label"]', { hasText: description }),
|
||||||
|
})
|
||||||
|
.nth(nth);
|
||||||
|
await matchingThumbnail.dblclick();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,15 @@ export class MainToolbarPageObject {
|
|||||||
this.page = page;
|
this.page = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get crosshairs() {
|
||||||
|
const button = this.page.getByTestId('Crosshairs');
|
||||||
|
return {
|
||||||
|
button,
|
||||||
|
async click() {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
get layoutSelection() {
|
get layoutSelection() {
|
||||||
const page = this.page;
|
const page = this.page;
|
||||||
|
|
||||||
@ -96,6 +105,15 @@ export class MainToolbarPageObject {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...measurementTools,
|
...measurementTools,
|
||||||
|
get selectedTool() {
|
||||||
|
const button = page.getByTestId('MeasurementTools-split-button-primary');
|
||||||
|
return {
|
||||||
|
button,
|
||||||
|
async click() {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
get arrowAnnotate() {
|
get arrowAnnotate() {
|
||||||
const button = page.getByTestId('ArrowAnnotate');
|
const button = page.getByTestId('ArrowAnnotate');
|
||||||
return {
|
return {
|
||||||
|
|||||||
271
tests/pages/RightPanelPageObject.ts
Normal file
271
tests/pages/RightPanelPageObject.ts
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
import { Locator, Page } from '@playwright/test';
|
||||||
|
|
||||||
|
import { DOMOverlayPageObject } from './DOMOverlayPageObject';
|
||||||
|
|
||||||
|
export class RightPanelPageObject {
|
||||||
|
readonly page: Page;
|
||||||
|
private readonly DOMOverlayPageObject: DOMOverlayPageObject;
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
this.DOMOverlayPageObject = new DOMOverlayPageObject(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getActionsMenu(row: Locator) {
|
||||||
|
const actionsButton = row.getByTestId('actionsMenuTrigger');
|
||||||
|
|
||||||
|
return {
|
||||||
|
button: actionsButton,
|
||||||
|
click: async () => {
|
||||||
|
await actionsButton.click();
|
||||||
|
},
|
||||||
|
delete: async () => {
|
||||||
|
await actionsButton.click();
|
||||||
|
await this.page.getByTestId('Delete').click();
|
||||||
|
},
|
||||||
|
toggleLock: async () => {
|
||||||
|
await actionsButton.click();
|
||||||
|
await this.page.getByTestId('LockToggle').click();
|
||||||
|
},
|
||||||
|
unlock: async () => {
|
||||||
|
await actionsButton.click();
|
||||||
|
await this.page.getByTestId('Unlock').click();
|
||||||
|
},
|
||||||
|
rename: async (text: string) => {
|
||||||
|
await actionsButton.click();
|
||||||
|
await this.page.getByTestId('Rename').click();
|
||||||
|
await this.DOMOverlayPageObject.dialog.input.fillAndSave(text);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPanelRowDataObject(row: Locator) {
|
||||||
|
const getActionsMenu = (row: Locator) => this.getActionsMenu.bind(this)(row);
|
||||||
|
|
||||||
|
return {
|
||||||
|
get actions() {
|
||||||
|
return getActionsMenu(row);
|
||||||
|
},
|
||||||
|
click: async () => {
|
||||||
|
await row.click();
|
||||||
|
},
|
||||||
|
locator: row,
|
||||||
|
toggleVisibility: async () => {
|
||||||
|
await row.getByTestId('data-row-visibility-toggle').click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPanelRowByIdx(index: number) {
|
||||||
|
const row = this.page.getByTestId('data-row').nth(index);
|
||||||
|
return this.getPanelRowDataObject(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPanelRowByText(text: string) {
|
||||||
|
const row = this.page.getByTestId('data-row').filter({ hasText: text });
|
||||||
|
return this.getPanelRowDataObject(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggle() {
|
||||||
|
await this.page.getByTestId('side-panel-header-right').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
get measurementsPanel() {
|
||||||
|
const page = this.page;
|
||||||
|
const getMeasurementByIdx = (index: number) => this.getPanelRowByIdx(index);
|
||||||
|
const getMeasurementByText = (text: string) => this.getPanelRowByText(text);
|
||||||
|
const menuButton = page.getByTestId('trackedMeasurements-btn');
|
||||||
|
|
||||||
|
return {
|
||||||
|
menuButton,
|
||||||
|
panel: {
|
||||||
|
deleteAll: async () => {
|
||||||
|
await page.getByRole('button', { name: 'Delete' }).click();
|
||||||
|
},
|
||||||
|
getMeasurementCount: async () => {
|
||||||
|
return await page.getByTestId('data-row').count();
|
||||||
|
},
|
||||||
|
locator: page.getByTestId('trackedMeasurements-panel').last(),
|
||||||
|
nthMeasurement(index: number) {
|
||||||
|
return getMeasurementByIdx(index);
|
||||||
|
},
|
||||||
|
measurementByText(text: string) {
|
||||||
|
return getMeasurementByText(text);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: async () => {
|
||||||
|
await menuButton.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private get addSegmentationButton() {
|
||||||
|
const button = this.page.getByTestId('addSegmentation');
|
||||||
|
return {
|
||||||
|
button,
|
||||||
|
click: async () => {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private get segmentationPanel() {
|
||||||
|
const page = this.page;
|
||||||
|
const getSegmentationByIdx = (index: number) => this.getPanelRowByIdx(index);
|
||||||
|
const getSegmentationByText = (text: string) => this.getPanelRowByText(text);
|
||||||
|
|
||||||
|
return {
|
||||||
|
getSegmentationCount: async () => {
|
||||||
|
return await page.getByTestId('data-row').count();
|
||||||
|
},
|
||||||
|
// No data-cy exists in this panel, using Segmentation header button
|
||||||
|
locator: page.getByRole('button', { name: 'Segmentations' }),
|
||||||
|
nthSegmentation(index: number) {
|
||||||
|
return getSegmentationByIdx(index);
|
||||||
|
},
|
||||||
|
segmentationByText(text: string) {
|
||||||
|
return getSegmentationByText(text);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get contourSegmentationPanel() {
|
||||||
|
const page = this.page;
|
||||||
|
const addSegmentationButton = this.addSegmentationButton;
|
||||||
|
const panel = this.segmentationPanel;
|
||||||
|
const menuButton = page.getByTestId('panelSegmentationWithToolsContour-btn');
|
||||||
|
|
||||||
|
return {
|
||||||
|
addSegmentationButton,
|
||||||
|
menuButton,
|
||||||
|
panel,
|
||||||
|
select: async () => {
|
||||||
|
await menuButton.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
get labelMapSegmentationPanel() {
|
||||||
|
const page = this.page;
|
||||||
|
const addSegmentationButton = this.addSegmentationButton;
|
||||||
|
const panel = this.segmentationPanel;
|
||||||
|
const menuButton = page.getByTestId('panelSegmentationWithToolsLabelMap-btn');
|
||||||
|
|
||||||
|
return {
|
||||||
|
addSegmentationButton,
|
||||||
|
menuButton,
|
||||||
|
panel,
|
||||||
|
select: async () => {
|
||||||
|
await menuButton.click();
|
||||||
|
},
|
||||||
|
tools: {
|
||||||
|
get brush() {
|
||||||
|
const button = page.getByTestId('Brush-btn');
|
||||||
|
const input = page.locator(`css=div[data-cy="brush-radius"] input`);
|
||||||
|
return {
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
click: async () => {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
setRadius: async (radius: number) => {
|
||||||
|
await input.fill(radius.toString());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
get eraser() {
|
||||||
|
const button = page.getByTestId('Eraser-btn');
|
||||||
|
const input = page.locator(`css=div[data-cy="eraser-radius"] input`);
|
||||||
|
return {
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
click: async () => {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
setRadius: async (radius: number) => {
|
||||||
|
await input.fill(radius.toString());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
get threshold() {
|
||||||
|
const button = page.getByTestId('Threshold-btn');
|
||||||
|
const input = page.locator(`css=div[data-cy="threshold-radius"] input`);
|
||||||
|
return {
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
click: async () => {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
setRadius: async (radius: number) => {
|
||||||
|
await input.fill(radius.toString());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get noToolsSegmentationPanel() {
|
||||||
|
const page = this.page;
|
||||||
|
const panel = this.segmentationPanel;
|
||||||
|
const menuButton = page.getByTestId(/^panelSegmentation.*-btn$/).first();
|
||||||
|
|
||||||
|
return {
|
||||||
|
menuButton,
|
||||||
|
panel,
|
||||||
|
select: async () => {
|
||||||
|
await menuButton.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get tmtvPanel() {
|
||||||
|
const page = this.page;
|
||||||
|
|
||||||
|
return {
|
||||||
|
get addSegmentationButton() {
|
||||||
|
const button = page.getByTestId('addSegmentation');
|
||||||
|
return {
|
||||||
|
button,
|
||||||
|
click: async () => {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async exportTmtvCsvReport() {
|
||||||
|
await page.getByTestId('exportTmtvCsvReport').click();
|
||||||
|
},
|
||||||
|
tools: {
|
||||||
|
get brush() {
|
||||||
|
const button = page.getByTestId('Brush-btn');
|
||||||
|
const input = page.locator(`css=div[data-cy="brush-radius"] input`);
|
||||||
|
return {
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
click: async () => {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
setRadius: async (radius: number) => {
|
||||||
|
await input.fill(radius.toString());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
get rectangleROIThreshold() {
|
||||||
|
const button = page.getByTestId('RectangleROIStartEndThreshold-btn');
|
||||||
|
const input = page.getByTestId('percentage-of-max-suv-input');
|
||||||
|
return {
|
||||||
|
button,
|
||||||
|
click: async () => {
|
||||||
|
await button.click();
|
||||||
|
},
|
||||||
|
getPercentageOfMaxSUV: async () => {
|
||||||
|
return await input.inputValue();
|
||||||
|
},
|
||||||
|
setPercentageOfMaxSUV: async (percentage: string) => {
|
||||||
|
await input.fill(percentage);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,13 @@
|
|||||||
import { Locator, Page } from '@playwright/test';
|
import { Locator, Page } from '@playwright/test';
|
||||||
import {
|
import {
|
||||||
|
getMousePosition,
|
||||||
simulateClicksOnElement,
|
simulateClicksOnElement,
|
||||||
simulateDoubleClickOnElement,
|
simulateDoubleClickOnElement,
|
||||||
simulateNormalizedClicksOnElement,
|
simulateNormalizedClicksOnElement,
|
||||||
simulateNormalizedDragOnElement,
|
simulateNormalizedDragOnElement,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
import { DataOverlayPageObject } from './DataOverlayPageObject';
|
||||||
|
import { DOMOverlayPageObject } from './DOMOverlayPageObject';
|
||||||
|
|
||||||
type SvgInnerElement = 'circle' | 'path' | 'd';
|
type SvgInnerElement = 'circle' | 'path' | 'd';
|
||||||
|
|
||||||
@ -15,11 +18,18 @@ type NormalizedDragParams = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface IViewportPageObject {
|
export interface IViewportPageObject {
|
||||||
doubleClickAt: (point: { x: number; y: number }) => Promise<void>;
|
nthAnnotation(nth: number): {
|
||||||
|
locator: Locator;
|
||||||
|
click: () => Promise<void>;
|
||||||
|
contextMenu: {
|
||||||
|
open: () => Promise<void>;
|
||||||
|
};
|
||||||
|
};
|
||||||
clickAt: (
|
clickAt: (
|
||||||
points: { x: number; y: number }[],
|
points: { x: number; y: number }[],
|
||||||
button?: 'left' | 'right' | 'middle'
|
button?: 'left' | 'right' | 'middle'
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
|
doubleClickAt: (point: { x: number; y: number }) => Promise<void>;
|
||||||
normalizedClickAt: (
|
normalizedClickAt: (
|
||||||
normalizedPoints: { x: number; y: number }[],
|
normalizedPoints: { x: number; y: number }[],
|
||||||
button?: 'left' | 'right' | 'middle'
|
button?: 'left' | 'right' | 'middle'
|
||||||
@ -38,10 +48,7 @@ export interface IViewportPageObject {
|
|||||||
bottomRight: Locator;
|
bottomRight: Locator;
|
||||||
};
|
};
|
||||||
overlayMenu: {
|
overlayMenu: {
|
||||||
dataOverlay: {
|
dataOverlay: DataOverlayPageObject;
|
||||||
button: Locator;
|
|
||||||
click: () => Promise<void>;
|
|
||||||
};
|
|
||||||
orientation: {
|
orientation: {
|
||||||
button: Locator;
|
button: Locator;
|
||||||
click: () => Promise<void>;
|
click: () => Promise<void>;
|
||||||
@ -57,9 +64,29 @@ export interface IViewportPageObject {
|
|||||||
|
|
||||||
export class ViewportPageObject {
|
export class ViewportPageObject {
|
||||||
readonly page: Page;
|
readonly page: Page;
|
||||||
|
private readonly dataOverlayPageObject: DataOverlayPageObject;
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
|
this.dataOverlayPageObject = new DataOverlayPageObject(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAnnotation(viewport: Locator, nth: number) {
|
||||||
|
const page = this.page;
|
||||||
|
const domOverlayPageObject = new DOMOverlayPageObject(page);
|
||||||
|
const annotation = viewport.locator('g[data-annotation-uid]').nth(nth);
|
||||||
|
|
||||||
|
return {
|
||||||
|
locator: annotation,
|
||||||
|
click: async () => {
|
||||||
|
await annotation.click();
|
||||||
|
},
|
||||||
|
contextMenu: {
|
||||||
|
open: async () => {
|
||||||
|
await domOverlayPageObject.viewport.annotationContextMenu.open(annotation);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private getOrientationMarkers(viewport: Locator) {
|
private getOrientationMarkers(viewport: Locator) {
|
||||||
@ -82,15 +109,7 @@ export class ViewportPageObject {
|
|||||||
|
|
||||||
private getOverlayMenu(viewport: Locator) {
|
private getOverlayMenu(viewport: Locator) {
|
||||||
return {
|
return {
|
||||||
get dataOverlay() {
|
dataOverlay: this.dataOverlayPageObject,
|
||||||
const button = viewport.locator('[data-cy^="dataOverlayMenu"]').first();
|
|
||||||
return {
|
|
||||||
button,
|
|
||||||
async click() {
|
|
||||||
await button.click();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
get orientation() {
|
get orientation() {
|
||||||
const button = viewport.locator('[data-cy^="orientationMenu"]');
|
const button = viewport.locator('[data-cy^="orientationMenu"]');
|
||||||
return {
|
return {
|
||||||
@ -118,6 +137,7 @@ export class ViewportPageObject {
|
|||||||
|
|
||||||
private viewportPageObjectFactory(viewport: Locator): IViewportPageObject {
|
private viewportPageObjectFactory(viewport: Locator): IViewportPageObject {
|
||||||
return {
|
return {
|
||||||
|
nthAnnotation: (nth: number) => this.getAnnotation(viewport, nth),
|
||||||
doubleClickAt: async (point: { x: number; y: number }) => {
|
doubleClickAt: async (point: { x: number; y: number }) => {
|
||||||
await simulateDoubleClickOnElement({
|
await simulateDoubleClickOnElement({
|
||||||
locator: viewport,
|
locator: viewport,
|
||||||
@ -166,6 +186,70 @@ export class ViewportPageObject {
|
|||||||
return this.viewportPageObjectFactory(viewport);
|
return this.viewportPageObjectFactory(viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get crosshairs() {
|
||||||
|
const page = this.page;
|
||||||
|
|
||||||
|
async function increaseSlabThickness(locator: Locator, lineNumber: number, axis: string) {
|
||||||
|
const lineLocator = locator.locator('line').nth(lineNumber);
|
||||||
|
await lineLocator.click({ force: true });
|
||||||
|
await lineLocator.hover({ force: true });
|
||||||
|
|
||||||
|
const circleLocator = locator.locator('rect').first();
|
||||||
|
await circleLocator.hover({ force: true });
|
||||||
|
|
||||||
|
await page.mouse.down();
|
||||||
|
|
||||||
|
const position = await getMousePosition(page);
|
||||||
|
switch (axis) {
|
||||||
|
case 'x':
|
||||||
|
await page.mouse.move(position.x + 100, position.y);
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
await page.mouse.move(position.x, position.y + 100);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await page.mouse.up();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function rotateCrosshairs(locator: Locator, lineNumber: number) {
|
||||||
|
const lineLocator = locator.locator('line').nth(lineNumber);
|
||||||
|
await lineLocator.click({ force: true });
|
||||||
|
await lineLocator.hover({ force: true });
|
||||||
|
|
||||||
|
const circleLocator = locator.locator('circle').nth(1);
|
||||||
|
await circleLocator.hover({ force: true });
|
||||||
|
|
||||||
|
await page.mouse.down();
|
||||||
|
|
||||||
|
const position = await getMousePosition(page);
|
||||||
|
await page.mouse.move(position.x, position.y + 100);
|
||||||
|
await page.mouse.up();
|
||||||
|
}
|
||||||
|
|
||||||
|
function crosshairsFactory(
|
||||||
|
locator: Locator,
|
||||||
|
increaseLineNumber: number,
|
||||||
|
increaseAxis: 'x' | 'y',
|
||||||
|
rotateLineNumber: number
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
increase: async () => {
|
||||||
|
await increaseSlabThickness(locator, increaseLineNumber, increaseAxis);
|
||||||
|
},
|
||||||
|
locator,
|
||||||
|
rotate: () => {
|
||||||
|
return rotateCrosshairs(locator, rotateLineNumber);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
axial: crosshairsFactory(page.locator('#svg-layer-mpr-axial'), 0, 'x', 3),
|
||||||
|
sagittal: crosshairsFactory(page.locator('#svg-layer-mpr-sagittal'), 2, 'x', 0),
|
||||||
|
coronal: crosshairsFactory(page.locator('#svg-layer-mpr-coronal'), 0, 'y', 0),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async getAll(): Promise<IViewportPageObject[]> {
|
async getAll(): Promise<IViewportPageObject[]> {
|
||||||
const viewports = await this.page.getByTestId('viewport-pane').all();
|
const viewports = await this.page.getByTestId('viewport-pane').all();
|
||||||
return viewports.map(viewport => this.viewportPageObjectFactory(viewport));
|
return viewports.map(viewport => this.viewportPageObjectFactory(viewport));
|
||||||
|
|||||||
@ -1,4 +1,13 @@
|
|||||||
|
import { DOMOverlayPageObject } from './DOMOverlayPageObject';
|
||||||
import { MainToolbarPageObject } from './MainToolbarPageObject';
|
import { MainToolbarPageObject } from './MainToolbarPageObject';
|
||||||
|
import { LeftPanelPageObject } from './LeftPanelPageObject';
|
||||||
|
import { RightPanelPageObject } from './RightPanelPageObject';
|
||||||
import { ViewportPageObject } from './ViewportPageObject';
|
import { ViewportPageObject } from './ViewportPageObject';
|
||||||
|
|
||||||
export { MainToolbarPageObject, ViewportPageObject };
|
export {
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
MainToolbarPageObject,
|
||||||
|
LeftPanelPageObject,
|
||||||
|
RightPanelPageObject,
|
||||||
|
ViewportPageObject,
|
||||||
|
};
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { type Page, expect } from '@playwright/test';
|
import { type Page, expect } from '@playwright/test';
|
||||||
|
|
||||||
|
import { MainToolbarPageObject, ViewportPageObject } from '../pages';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the optional parameters for the addLengthMeasurement function.
|
* Defines the optional parameters for the addLengthMeasurement function.
|
||||||
*/
|
*/
|
||||||
@ -22,13 +24,16 @@ export async function addLengthMeasurement(
|
|||||||
page: Page,
|
page: Page,
|
||||||
options: AddLengthMeasurementOptions = {}
|
options: AddLengthMeasurementOptions = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const mainToolbarPageObject = new MainToolbarPageObject(page);
|
||||||
|
const viewportPageObject = new ViewportPageObject(page);
|
||||||
|
|
||||||
// Set default values for the click coordinates
|
// Set default values for the click coordinates
|
||||||
const { firstClick = [150, 100], secondClick = [130, 170] } = options;
|
const { firstClick = [150, 100], secondClick = [130, 170] } = options;
|
||||||
const [x1, y1] = firstClick;
|
const [x1, y1] = firstClick;
|
||||||
const [x2, y2] = secondClick;
|
const [x2, y2] = secondClick;
|
||||||
|
|
||||||
const lengthButton = page.getByTestId('MeasurementTools-split-button-primary');
|
const lengthButton = mainToolbarPageObject.measurementTools.selectedTool.button;
|
||||||
const viewport = page.locator('.cornerstone-viewport-element').first();
|
const viewport = viewportPageObject.active;
|
||||||
|
|
||||||
// Assert that the primary measurement button is 'Length' tool
|
// Assert that the primary measurement button is 'Length' tool
|
||||||
await expect(lengthButton).toHaveAttribute('data-tool', 'Length');
|
await expect(lengthButton).toHaveAttribute('data-tool', 'Length');
|
||||||
@ -43,10 +48,10 @@ export async function addLengthMeasurement(
|
|||||||
await expect(lengthButton).toHaveAttribute('data-active', 'true');
|
await expect(lengthButton).toHaveAttribute('data-active', 'true');
|
||||||
|
|
||||||
// Perform the two clicks on the viewport canvas to draw the line
|
// Perform the two clicks on the viewport canvas to draw the line
|
||||||
await viewport.click({ position: { x: x1, y: y1 } });
|
await viewport.clickAt([{ x: x1, y: y1 }]);
|
||||||
|
|
||||||
// Delay to allow canvas actions to finish/update
|
// Delay to allow canvas actions to finish/update
|
||||||
await page.waitForTimeout(200);
|
await page.waitForTimeout(200);
|
||||||
|
|
||||||
await viewport.click({ position: { x: x2, y: y2 } });
|
await viewport.clickAt([{ x: x2, y: y2 }]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { Page } from '@playwright/test';
|
import { Page } from '@playwright/test';
|
||||||
import { expect } from 'playwright-test-coverage';
|
import { expect } from 'playwright-test-coverage';
|
||||||
|
|
||||||
|
import { DOMOverlayPageObject } from '../pages';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts the number of Modality Load Badges present on the page.
|
* Asserts the number of Modality Load Badges present on the page.
|
||||||
*/
|
*/
|
||||||
@ -11,5 +13,8 @@ export async function assertNumberOfModalityLoadBadges({
|
|||||||
page: Page;
|
page: Page;
|
||||||
expectedCount: number;
|
expectedCount: number;
|
||||||
}) {
|
}) {
|
||||||
await expect(page.locator('css=div[data-cy^="ModalityLoadBadge-"]')).toHaveCount(expectedCount);
|
const domOverlayPageObject = new DOMOverlayPageObject(page);
|
||||||
|
const count = await domOverlayPageObject.viewport.getModalityLoadBadgeCount();
|
||||||
|
|
||||||
|
expect(count).toBe(expectedCount);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,33 @@
|
|||||||
import { test as base } from 'playwright-test-coverage';
|
import { test as base } from 'playwright-test-coverage';
|
||||||
import { MainToolbarPageObject, ViewportPageObject } from '../pages';
|
import {
|
||||||
|
DOMOverlayPageObject,
|
||||||
|
MainToolbarPageObject,
|
||||||
|
LeftPanelPageObject,
|
||||||
|
RightPanelPageObject,
|
||||||
|
ViewportPageObject,
|
||||||
|
} from '../pages';
|
||||||
|
|
||||||
type PageObjects = {
|
type PageObjects = {
|
||||||
|
DOMOverlayPageObject: DOMOverlayPageObject;
|
||||||
mainToolbarPageObject: MainToolbarPageObject;
|
mainToolbarPageObject: MainToolbarPageObject;
|
||||||
|
leftPanelPageObject: LeftPanelPageObject;
|
||||||
|
rightPanelPageObject: RightPanelPageObject;
|
||||||
viewportPageObject: ViewportPageObject;
|
viewportPageObject: ViewportPageObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const test = base.extend<PageObjects>({
|
export const test = base.extend<PageObjects>({
|
||||||
|
DOMOverlayPageObject: async ({ page }, use) => {
|
||||||
|
await use(new DOMOverlayPageObject(page));
|
||||||
|
},
|
||||||
mainToolbarPageObject: async ({ page }, use) => {
|
mainToolbarPageObject: async ({ page }, use) => {
|
||||||
await use(new MainToolbarPageObject(page));
|
await use(new MainToolbarPageObject(page));
|
||||||
},
|
},
|
||||||
|
leftPanelPageObject: async ({ page }, use) => {
|
||||||
|
await use(new LeftPanelPageObject(page));
|
||||||
|
},
|
||||||
|
rightPanelPageObject: async ({ page }, use) => {
|
||||||
|
await use(new RightPanelPageObject(page));
|
||||||
|
},
|
||||||
viewportPageObject: async ({ page }, use) => {
|
viewportPageObject: async ({ page }, use) => {
|
||||||
await use(new ViewportPageObject(page));
|
await use(new ViewportPageObject(page));
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user