diff --git a/src/drivers/playwright/index.ts b/src/drivers/playwright/index.ts index 5dae87d..08bf1b8 100644 --- a/src/drivers/playwright/index.ts +++ b/src/drivers/playwright/index.ts @@ -191,151 +191,6 @@ if (page) { }, ], }, - { - title: "Locators", - items: [ - { - signature: "page.getByRole(role[, options])", - description: "Locates elements by ARIA role or HTML tag.", - example: `const page = getCurrentPage(); -if (page) { - await page.getByRole('button', { name: 'Submit' }).click(); -}`, - guidelines: [ - "Always check if page exists first.", - "Preferred way to locate interactive elements.", - "Improves test accessibility coverage.", - ], - }, - { - signature: "page.getByText(text[, options])", - description: "Locates elements by their text content.", - example: `const page = getCurrentPage(); -if (page) { - await page.getByText('Welcome').isVisible(); -}`, - guidelines: [ - "Always check if page exists first.", - "Good for finding visible text on page.", - "Can use exact or fuzzy matching.", - ], - }, - { - signature: "page.getByLabel(text)", - description: "Locates form control by associated label.", - example: `const page = getCurrentPage(); -if (page) { - await page.getByLabel('Username').fill('john'); -}`, - guidelines: [ - "Always check if page exists first.", - "Best practice for form inputs.", - "More reliable than selectors.", - ], - }, - ], - }, - { - title: "Actions", - items: [ - { - signature: "await locator.click([options])", - description: "Clicks on the element.", - example: `const page = getCurrentPage(); -if (page) { - await page.getByRole('button').click(); -}`, - guidelines: [ - "Always check if page exists first.", - "Automatically waits for element.", - "Handles scrolling automatically.", - ], - }, - { - signature: "await locator.fill(value)", - description: "Fills form field with value.", - example: `const page = getCurrentPage(); -if (page) { - await page.getByLabel('Password').fill('secret'); -}`, - guidelines: [ - "Always check if page exists first.", - "Preferred over type() for forms.", - "Clears existing value first.", - ], - }, - { - signature: "await page.goBack([options])", - description: "Navigates back in the browser history.", - example: `const page = getCurrentPage(); - if (page) { - await page.goBack(); - }`, - guidelines: [ - "Simulates clicking the browser's back button.", - "Waits for the navigation to complete.", - "Options can modify waiting behavior.", - "Useful for testing multi-page flows.", - ], - }, - { - signature: "await page.dragAndDrop(source, target, [options])", - description: "Drags an element to a target element or position.", - example: `const page = getCurrentPage(); - if (page) { - await page.dragAndDrop('#item', '#destination'); - }`, - guidelines: [ - "Source and target can be selectors or locators.", - "Automatically waits for elements to be visible and enabled.", - "Handles mouse events to simulate drag-and-drop.", - "Options can control the delay and force of the action.", - ], - }, - { - signature: "await locator.check([options])", - description: "Checks a checkbox or radio button.", - example: `const page = getCurrentPage(); - if (page) { - await page.getByLabel('Accept Terms').check(); - }`, - guidelines: [ - "Use for input elements of type checkbox or radio.", - "Automatically waits for the element to be visible and enabled.", - "Ensures the element is checked; does nothing if already checked.", - "Handles any necessary scrolling into view.", - ], - }, - { - signature: "await locator.uncheck([options])", - description: "Unchecks a checkbox.", - example: `const page = getCurrentPage(); - if (page) { - await page.getByLabel('Subscribe to newsletter').uncheck(); - }`, - guidelines: [ - "Use for input elements of type checkbox.", - "Automatically waits for the element to be visible and enabled.", - "Ensures the element is unchecked; does nothing if already unchecked.", - "Handles any necessary scrolling into view.", - ], - }, - { - signature: "await locator.scrollIntoViewIfNeeded()", - description: - "Scrolls the element into view if it is not already visible.", - example: `const page = getCurrentPage(); - if (page) { - await page.getByText('Load More').scrollIntoViewIfNeeded(); - }`, - guidelines: [ - "Use when the element might be outside the viewport.", - "Automatically waits for the element to be in the DOM.", - "Useful before performing actions that require the element to be in view.", - ], - }, - ], - }, { title: "State Checks", items: [ diff --git a/src/utils/SnapshotManager.ts b/src/utils/SnapshotManager.ts index fe323f0..0978663 100644 --- a/src/utils/SnapshotManager.ts +++ b/src/utils/SnapshotManager.ts @@ -3,6 +3,7 @@ import { SnapshotComparator } from "@/utils/SnapshotComparator"; import crypto from "crypto"; import gm from "gm"; +const MAX_PIXELS = 2000000; const DEFAULT_POLL_INTERVAL = 500; // ms const DEFAULT_TIMEOUT = 5000; // ms const DEFAULT_STABILITY_THRESHOLD = 0.05; @@ -86,17 +87,38 @@ export class SnapshotManager { } private async downscaleImage(imagePath: string): Promise { - const desiredWidth = 800; - + return new Promise((resolve, reject) => { gm(imagePath) - .resize(desiredWidth) - .write(imagePath, (err: any) => { + .size(function (err: any, size: { width: number; height: number }) { if (err) { - console.error("Error downscaling image:", err); + console.error("Error getting image size:", err); reject(err); } else { - resolve(imagePath); + const originalWidth = size.width; + const originalHeight = size.height; + const originalTotalPixels = originalWidth * originalHeight; + + if (originalTotalPixels <= MAX_PIXELS) { + resolve(imagePath); + } else { + const aspectRatio = originalWidth / originalHeight; + const newHeight = Math.sqrt(MAX_PIXELS / aspectRatio); + const newWidth = newHeight * aspectRatio; + const roundedWidth = Math.round(newWidth); + const roundedHeight = Math.round(newHeight); + + gm(imagePath) + .resize(roundedWidth, roundedHeight) + .write(imagePath, (err: any) => { + if (err) { + console.error("Error downscaling image:", err); + reject(err); + } else { + resolve(imagePath); + } + }); + } } }); }); diff --git a/src/utils/snapshotHashing/pHash.test.ts b/src/utils/snapshotHashing/pHash.test.ts index 04ad4db..df622bc 100644 --- a/src/utils/snapshotHashing/pHash.test.ts +++ b/src/utils/snapshotHashing/pHash.test.ts @@ -1,7 +1,7 @@ import { pHash } from "./pHash"; import { getSnapshotImage } from "@/test-utils/SnapshotComparatorTestImages/SnapshotImageGetter"; -describe.skip("pHash algorithm", () => { +describe("pHash algorithm", () => { const snapshotComparator = new pHash(); it("should hash a snapshot", async () => { const snapshot = getSnapshotImage("baseline");