Co-authored-by: Alireza <ar.sedghi@gmail.com> Co-authored-by: Dan Rukas <dan.rukas@gmail.com> Co-authored-by: Tang Cheng <45505657+tctco@users.noreply.github.com>
This commit is contained in:
44 files changed
+516
-258
No files matched your search
@@ -27,8 +27,7 @@ test.describe('3D four up Test', async () => {
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
screenShotPaths.threeDFourUp.threeDFourUpDisplayedCorrectly,
|
||||
200
|
||||
screenShotPaths.threeDFourUp.threeDFourUpDisplayedCorrectly
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -22,11 +22,6 @@ test.describe('3D main Test', async () => {
|
||||
.first()
|
||||
.click();
|
||||
await attemptAction(() => reduce3DViewportSize(page), 10, 100);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
screenShotPaths.threeDMain.threeDMainDisplayedCorrectly,
|
||||
200
|
||||
);
|
||||
await checkForScreenshot(page, page, screenShotPaths.threeDMain.threeDMainDisplayedCorrectly);
|
||||
});
|
||||
});
|
||||
@@ -22,11 +22,12 @@ test.describe('3D only Test', async () => {
|
||||
.first()
|
||||
.click();
|
||||
await attemptAction(() => reduce3DViewportSize(page), 10, 100);
|
||||
await checkForScreenshot(
|
||||
// Use a 4 percent diff pixel ratio to account for slight color differences in the 3D viewport
|
||||
await checkForScreenshot({
|
||||
page,
|
||||
page,
|
||||
screenShotPaths.threeDOnly.threeDOnlyDisplayedCorrectly,
|
||||
200
|
||||
);
|
||||
locator: page,
|
||||
screenshotPath: screenShotPaths.threeDOnly.threeDOnlyDisplayedCorrectly,
|
||||
maxDiffPixelRatio: 0.04,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -26,8 +26,7 @@ test.describe('3D primary Test', async () => {
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
screenShotPaths.threeDPrimary.threeDPrimaryDisplayedCorrectly,
|
||||
200
|
||||
screenShotPaths.threeDPrimary.threeDPrimaryDisplayedCorrectly
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -18,8 +18,7 @@ test.describe('Axial Primary Test', async () => {
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
screenShotPaths.axialPrimary.axialPrimaryDisplayedCorrectly,
|
||||
200
|
||||
screenShotPaths.axialPrimary.axialPrimaryDisplayedCorrectly
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import { test } from 'playwright-test-coverage';
|
||||
import {
|
||||
visitStudy,
|
||||
checkForScreenshot,
|
||||
screenShotPaths,
|
||||
simulateNormalizedClicksOnElement,
|
||||
simulateNormalizedClickOnElement,
|
||||
} from './utils';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5';
|
||||
const mode = 'viewer';
|
||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||
});
|
||||
|
||||
test('should the context menu completely on screen and is not clipped for a point near the bottom edge of the screen', async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.getByTestId('MeasurementTools-split-button-secondary').click();
|
||||
await page.locator('css=div[data-cy="Length"]').click();
|
||||
const locator = page.getByTestId('viewport-pane').locator('canvas');
|
||||
await simulateNormalizedClicksOnElement({
|
||||
locator,
|
||||
normalizedPoints: [
|
||||
{
|
||||
x: 0.45,
|
||||
y: 0.98,
|
||||
},
|
||||
{
|
||||
x: 0.55,
|
||||
y: 0.98,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await page.getByTestId('prompt-begin-tracking-yes-btn').click();
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.contextMenu.preContextMenuNearBottomEdge);
|
||||
|
||||
await simulateNormalizedClickOnElement({
|
||||
locator,
|
||||
normalizedPoint: {
|
||||
x: 0.55,
|
||||
y: 0.98,
|
||||
},
|
||||
button: 'right',
|
||||
});
|
||||
|
||||
await checkForScreenshot({
|
||||
page,
|
||||
locator: page,
|
||||
screenshotPath: screenShotPaths.contextMenu.contextMenuNearBottomEdgeNotClipped,
|
||||
});
|
||||
});
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
visitStudy,
|
||||
checkForScreenshot,
|
||||
screenShotPaths,
|
||||
initilizeMousePositionTracker,
|
||||
initializeMousePositionTracker,
|
||||
getMousePosition,
|
||||
} from './utils/index.js';
|
||||
|
||||
@@ -42,7 +42,7 @@ test.beforeEach(async ({ page }) => {
|
||||
const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785';
|
||||
const mode = 'viewer';
|
||||
await visitStudy(page, studyInstanceUID, mode, 2000);
|
||||
await initilizeMousePositionTracker(page);
|
||||
await initializeMousePositionTracker(page);
|
||||
});
|
||||
|
||||
test.describe('Crosshairs Test', async () => {
|
||||
@@ -105,8 +105,6 @@ test.describe('Crosshairs Test', async () => {
|
||||
|
||||
await page.getByTestId('study-browser-thumbnail').nth(1).dblclick();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsNewDisplayset);
|
||||
});
|
||||
});
|
||||
@@ -87,8 +87,6 @@ test('should hydrate in MPR correctly', async ({ page }) => {
|
||||
|
||||
await page.getByTestId('data-row').first().click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.jumpToMeasurementStack);
|
||||
|
||||
await page.getByTestId('Layout').click();
|
||||
@@ -105,14 +103,11 @@ test('should hydrate in MPR correctly', async ({ page }) => {
|
||||
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.jumpInMPR);
|
||||
|
||||
await page.locator(':text("S:3")').first().dblclick();
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.jumpToMeasurementMPR.changeSeriesInMPR);
|
||||
|
||||
await page.getByTestId('data-row').first().click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -15,7 +15,6 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('MPR').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
@@ -32,7 +31,6 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me
|
||||
// Hide the overlay menu.
|
||||
await page.getByTestId('dataOverlayMenu-mpr-sagittal-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -15,7 +15,6 @@ test('should launch MPR with unhydrated SEG chosen from the data overlay menu',
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('MPR').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
@@ -32,7 +31,6 @@ test('should launch MPR with unhydrated SEG chosen from the data overlay menu',
|
||||
// Hide the overlay menu.
|
||||
await page.getByTestId('dataOverlayMenu-mpr-sagittal-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -19,7 +19,6 @@ test('should overlay an unhydrated RTSTRUCT over a display set that the RTSTRUCT
|
||||
// Hide the overlay menu.
|
||||
await page.getByTestId('dataOverlayMenu-default-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
@@ -29,7 +28,6 @@ test('should overlay an unhydrated RTSTRUCT over a display set that the RTSTRUCT
|
||||
// Navigate to the middle image of the default viewport.
|
||||
await press({ page, key: 'ArrowDown', nTimes: 23 });
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -19,7 +19,6 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me
|
||||
// Hide the overlay menu.
|
||||
await page.getByTestId('dataOverlayMenu-default-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
@@ -29,7 +28,6 @@ test('should launch MPR with unhydrated RTSTRUCT chosen from the data overlay me
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('MPR').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -13,27 +13,19 @@ test('should hydrate an RTSTRUCT from MPR', async ({ page }) => {
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('MPR').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.rtHydrationFromMPR.mprBeforeRT);
|
||||
|
||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.rtHydrationFromMPR.mprAfterRT);
|
||||
|
||||
await page.getByTestId('yes-hydrate-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.rtHydrationFromMPR.mprAfterRTHydrated);
|
||||
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('Axial Primary').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -13,13 +13,11 @@ test('should hydrate an RTSTRUCT and then launch MPR', async ({ page }) => {
|
||||
|
||||
await page.getByTestId('yes-hydrate-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(page, page, screenShotPaths.rtHydrationThenMPR.rtPostHydration);
|
||||
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('Axial Primary').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -11,12 +11,10 @@ test('should launch MPR with unhydrated RTSTRUCT', async ({ page }) => {
|
||||
await page.getByTestId('side-panel-header-right').click();
|
||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(page, page, screenShotPaths.rtNoHydrationThenMPR.rtNoHydrationPreMPR);
|
||||
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('MPR').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(page, page, screenShotPaths.rtNoHydrationThenMPR.rtNoHydrationPostMPR);
|
||||
});
|
||||
@@ -19,7 +19,6 @@ test('should overlay an unhydrated SEG over a display set that the SEG does NOT
|
||||
// Hide the overlay menu.
|
||||
await page.getByTestId('dataOverlayMenu-default-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
@@ -29,7 +28,6 @@ test('should overlay an unhydrated SEG over a display set that the SEG does NOT
|
||||
// Navigate to the middle image of the default viewport.
|
||||
await press({ page, key: 'ArrowDown', nTimes: 9 });
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -19,7 +19,6 @@ test('should launch MPR with unhydrated SEG chosen from the data overlay menu',
|
||||
// Hide the overlay menu.
|
||||
await page.getByTestId('dataOverlayMenu-default-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
@@ -29,7 +28,6 @@ test('should launch MPR with unhydrated SEG chosen from the data overlay menu',
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('MPR').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -13,27 +13,19 @@ test('should properly display MPR for MR', async ({ page }) => {
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('MPR').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprBeforeSEG);
|
||||
|
||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprAfterSEG);
|
||||
|
||||
await page.getByTestId('yes-hydrate-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.segHydrationFromMPR.mprAfterSegHydrated);
|
||||
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('Axial Primary').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -13,13 +13,11 @@ test('should properly display MPR for MR', async ({ page }) => {
|
||||
|
||||
await page.getByTestId('yes-hydrate-btn').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(page, page, screenShotPaths.segHydrationThenMPR.segPostHydration);
|
||||
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('Axial Primary').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(
|
||||
page,
|
||||
page,
|
||||
|
||||
@@ -11,12 +11,10 @@ test('should launch MPR with unhydrated SEG', async ({ page }) => {
|
||||
await page.getByTestId('side-panel-header-right').click();
|
||||
await page.getByTestId('study-browser-thumbnail-no-image').dblclick();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(page, page, screenShotPaths.segNoHydrationThenMPR.segNoHydrationPreMPR);
|
||||
|
||||
await page.getByTestId('Layout').click();
|
||||
await page.getByTestId('MPR').click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await checkForScreenshot(page, page, screenShotPaths.segNoHydrationThenMPR.segNoHydrationPostMPR);
|
||||
});
|
||||
@@ -57,6 +57,6 @@ test('should hydrate SR reports correctly', async ({ page }) => {
|
||||
});
|
||||
|
||||
await page.getByTestId('data-row').first().click();
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await checkForScreenshot(page, page, screenShotPaths.srHydration.srJumpToMeasurement);
|
||||
});
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 304 KiB After Width: | Height: | Size: 307 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 253 KiB |
@@ -1,28 +1,34 @@
|
||||
import { expect } from 'playwright-test-coverage';
|
||||
import { Locator, Page } from 'playwright';
|
||||
|
||||
/**
|
||||
* @param page - The page to interact with
|
||||
* @param locator - The element to check for screenshot
|
||||
* @param screenshotPath - The path to save the screenshot
|
||||
* @param attempts - The number of attempts to check for screenshot
|
||||
* @param delay - The delay between attempts
|
||||
* @returns True if the screenshot matches, otherwise throws an error
|
||||
*/
|
||||
const checkForScreenshot = async (
|
||||
page: Page,
|
||||
locator: Locator | Page,
|
||||
screenshotPath: string,
|
||||
attempts = 10,
|
||||
delay = 100
|
||||
) => {
|
||||
type CheckForScreenshotProps = {
|
||||
page: Page;
|
||||
locator: Locator | Page;
|
||||
screenshotPath: string;
|
||||
attempts?: number;
|
||||
delay?: number;
|
||||
maxDiffPixelRatio?: number;
|
||||
threshold?: number;
|
||||
};
|
||||
|
||||
const _checkForScreenshot = async (props: CheckForScreenshotProps) => {
|
||||
const {
|
||||
page,
|
||||
locator,
|
||||
screenshotPath,
|
||||
attempts = 10,
|
||||
delay = 500,
|
||||
maxDiffPixelRatio = 0.02,
|
||||
threshold = 0.05,
|
||||
} = props;
|
||||
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
for (let i = 0; i < attempts; i++) {
|
||||
try {
|
||||
await expect(locator).toHaveScreenshot(screenshotPath, {
|
||||
// 4% tolerance for screenshot comparison
|
||||
maxDiffPixelRatio: 0.04,
|
||||
maxDiffPixelRatio,
|
||||
threshold,
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
@@ -38,4 +44,36 @@ const checkForScreenshot = async (
|
||||
throw new Error('Screenshot comparison failed: loop exited without match or proper error');
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a screenshot of a specific element matches the expected screenshot.
|
||||
* It retries the check for a specified number of attempts with a delay between each attempt.
|
||||
* By default, the number of attempts is 10 and the delay is 500 milliseconds which results in a maximum wait time of 5 seconds.
|
||||
* Instead of sleeping idle prior to calling this function, simply adjust the attempts and delay parameters to achieve the desired wait time.
|
||||
* @param pageOrProps - The page to interact with or an object containing page and other properties
|
||||
* @param locator - The element to check for screenshot
|
||||
* @param screenshotPath - The path to save the screenshot
|
||||
* @param attempts - The number of attempts to check for screenshot
|
||||
* @param delay - The delay between attempts
|
||||
* @returns True if the screenshot matches, otherwise throws an error
|
||||
*/
|
||||
const checkForScreenshot = async (
|
||||
pageOrProps: Page | CheckForScreenshotProps,
|
||||
locator?: Locator | Page,
|
||||
screenshotPath?: string,
|
||||
attempts?: number,
|
||||
delay?: number
|
||||
) => {
|
||||
if (typeof pageOrProps === 'object' && 'page' in pageOrProps) {
|
||||
return await _checkForScreenshot(pageOrProps as CheckForScreenshotProps);
|
||||
} else {
|
||||
return await _checkForScreenshot({
|
||||
page: pageOrProps as Page,
|
||||
locator,
|
||||
screenshotPath,
|
||||
attempts,
|
||||
delay,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export { checkForScreenshot };
|
||||
@@ -1,9 +1,13 @@
|
||||
import { visitStudy } from './visitStudy';
|
||||
import { checkForScreenshot } from './checkForScreenshot';
|
||||
import { screenShotPaths } from './screenShotPaths';
|
||||
import { simulateClicksOnElement } from './simulateClicksOnElement';
|
||||
import {
|
||||
simulateClicksOnElement,
|
||||
simulateNormalizedClickOnElement,
|
||||
simulateNormalizedClicksOnElement,
|
||||
} from './simulateClicksOnElement';
|
||||
import { reduce3DViewportSize } from './reduce3DviewportSize';
|
||||
import { getMousePosition, initilizeMousePositionTracker } from './mouseUtils';
|
||||
import { getMousePosition, initializeMousePositionTracker } from './mouseUtils';
|
||||
import { getSUV } from './getSUV';
|
||||
import { getTMTVModalityUnit } from './getTMTVModalityUnit';
|
||||
import { clearAllAnnotations } from './clearAllAnnotations';
|
||||
@@ -16,9 +20,11 @@ export {
|
||||
checkForScreenshot,
|
||||
screenShotPaths,
|
||||
simulateClicksOnElement,
|
||||
simulateNormalizedClickOnElement,
|
||||
simulateNormalizedClicksOnElement,
|
||||
reduce3DViewportSize,
|
||||
getMousePosition,
|
||||
initilizeMousePositionTracker,
|
||||
initializeMousePositionTracker,
|
||||
getSUV,
|
||||
getTMTVModalityUnit,
|
||||
clearAllAnnotations,
|
||||
|
||||
@@ -5,21 +5,21 @@ interface WindowWithMousePosition extends Window {
|
||||
mouseY: number;
|
||||
}
|
||||
|
||||
export const initilizeMousePositionTracker = async (page: Page) => {
|
||||
const window = await page.evaluateHandle("window") as any;
|
||||
export const initializeMousePositionTracker = async (page: Page) => {
|
||||
const window = (await page.evaluateHandle('window')) as any;
|
||||
await page.evaluate((window: WindowWithMousePosition) => {
|
||||
window.mouseX = 0;
|
||||
window.mouseY = 0;
|
||||
window.addEventListener("mousemove", (event) => {
|
||||
window.addEventListener('mousemove', event => {
|
||||
window.mouseX = event.clientX;
|
||||
window.mouseY = event.clientY;
|
||||
});
|
||||
}, window);
|
||||
}
|
||||
};
|
||||
|
||||
export const getMousePosition = async (page: Page) => {
|
||||
const window = await page.evaluateHandle("window") as any;
|
||||
const window = (await page.evaluateHandle('window')) as any;
|
||||
return await page.evaluate((window: WindowWithMousePosition) => {
|
||||
return { x: window.mouseX, y: window.mouseY };
|
||||
}, window);
|
||||
}
|
||||
};
|
||||
@@ -14,6 +14,10 @@ const screenShotPaths = {
|
||||
cobbangle: {
|
||||
cobbangleDisplayedCorrectly: 'cobbangleDisplayedCorrectly.png',
|
||||
},
|
||||
contextMenu: {
|
||||
preContextMenuNearBottomEdge: 'preContextMenuNearBottomEdge.png',
|
||||
contextMenuNearBottomEdgeNotClipped: 'contextMenuNearBottomEdgeNotClipped.png',
|
||||
},
|
||||
ellipse: {
|
||||
ellipseDisplayedCorrectly: 'ellipseDisplayedCorrectly.png',
|
||||
},
|
||||
|
||||
@@ -17,3 +17,49 @@ export async function simulateClicksOnElement({
|
||||
await locator.click({ delay: 100, position: { x, y } });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates clicks on an element at a normalized point.
|
||||
*
|
||||
* @param locator - The locator to click on.
|
||||
* @param normalizedPoint - The point with x and y coordinates, normalized to the element's bounding box.
|
||||
* @param button - The mouse button to use for the click (default is 'left').
|
||||
*/
|
||||
export async function simulateNormalizedClickOnElement({
|
||||
locator,
|
||||
normalizedPoint,
|
||||
button = 'left',
|
||||
}: {
|
||||
locator: Locator;
|
||||
normalizedPoint: { x: number; y: number };
|
||||
button?: 'left' | 'right' | 'middle';
|
||||
}) {
|
||||
const bBox = await locator.boundingBox();
|
||||
const position = { x: normalizedPoint.x * bBox.width, y: normalizedPoint.y * bBox.height };
|
||||
await locator.click({ delay: 100, position, button });
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates clicks on an element at normalized points.
|
||||
*
|
||||
* @param locator - The locator to click on.
|
||||
* @param normalizedPoints - An array of points with x and y coordinates, normalized to the element's bounding box.
|
||||
* @param button - The mouse button to use for the click (default is 'left').
|
||||
*/
|
||||
export async function simulateNormalizedClicksOnElement({
|
||||
locator,
|
||||
normalizedPoints,
|
||||
button = 'left',
|
||||
}: {
|
||||
locator: Locator;
|
||||
normalizedPoints: { x: number; y: number }[];
|
||||
button?: 'left' | 'right' | 'middle';
|
||||
}) {
|
||||
for (const normalizedPoint of normalizedPoints) {
|
||||
await simulateNormalizedClickOnElement({
|
||||
locator,
|
||||
normalizedPoint,
|
||||
button,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user