@augment-vir/test 31.64.0 → 31.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { RuntimeEnvError } from '@augment-vir/core';
2
2
  export { type MenuOptionOptions } from '../test-playwright/get-option.js';
3
3
  export { type NavOptions } from '../test-playwright/nav.js';
4
- export { type LocatorScreenshotOptions, type SaveScreenshotOptions, type TakeScreenshotOptions, } from '../test-playwright/screenshot.js';
4
+ export { type LocatorScreenshotOptions, type SaveScreenshotOptions, type TakeScreenshotOptions, } from '../test-playwright/playwright-screenshot.js';
5
5
  declare function importPlaywrightTestApi(this: void): Promise<RuntimeEnvError | {
6
6
  navigation: {
7
7
  /** Navigate to a URL in Playwright via given paths. */
@@ -31,17 +31,19 @@ declare function importPlaywrightTestApi(this: void): Promise<RuntimeEnvError |
31
31
  /**
32
32
  * Similar to Playwright's `expect().toHaveScreenshot` but allows images to have
33
33
  * different sizes and has default comparison threshold options that are wide enough to
34
- * allow testing between different operating systems without failure (usually).
34
+ * allow testing between different operating systems without failure.
35
+ *
36
+ * Update screenshots with `--update`.
35
37
  */
36
- expectScreenshot: typeof import("../test-playwright/screenshot.js").expectScreenshot;
38
+ expectScreenshot: typeof import("../test-playwright/playwright-screenshot.js").expectPlaywrightScreenshot;
37
39
  /** Get the path to save the given screenshot file name to. */
38
- getScreenshotPath: typeof import("../test-playwright/screenshot.js").getScreenshotPath;
40
+ getScreenshotPath: typeof import("../test-playwright/playwright-screenshot.js").getScreenshotPath;
39
41
  /**
40
42
  * Take and immediately save a screenshot.
41
43
  *
42
44
  * @returns The path that the screenshot was saved to.
43
45
  */
44
- takeScreenshot: typeof import("../test-playwright/screenshot.js").takeScreenshot;
46
+ takeScreenshot: typeof import("../test-playwright/playwright-screenshot.js").takeScreenshot;
45
47
  };
46
48
  }>;
47
49
  /**
@@ -7,7 +7,7 @@ async function importPlaywrightTestApi() {
7
7
  const { enterTextByLabel } = await import('../test-playwright/enter-text.js');
8
8
  const { expectAllVisible } = await import('../test-playwright/all-visible.js');
9
9
  const { getMenuOption } = await import('../test-playwright/get-option.js');
10
- const { getScreenshotPath, takeScreenshot, expectScreenshot } = await import('../test-playwright/screenshot.js');
10
+ const { getScreenshotPath, takeScreenshot, expectPlaywrightScreenshot } = await import('../test-playwright/playwright-screenshot.js');
11
11
  const { handleNewPageOrDownload } = await import('../test-playwright/new-page-or-download.js');
12
12
  const { navigateTo, extractNavUrl } = await import('../test-playwright/nav.js');
13
13
  const { readLocalStorage } = await import('../test-playwright/local-storage.js');
@@ -40,9 +40,11 @@ async function importPlaywrightTestApi() {
40
40
  /**
41
41
  * Similar to Playwright's `expect().toHaveScreenshot` but allows images to have
42
42
  * different sizes and has default comparison threshold options that are wide enough to
43
- * allow testing between different operating systems without failure (usually).
43
+ * allow testing between different operating systems without failure.
44
+ *
45
+ * Update screenshots with `--update`.
44
46
  */
45
- expectScreenshot,
47
+ expectScreenshot: expectPlaywrightScreenshot,
46
48
  /** Get the path to save the given screenshot file name to. */
47
49
  getScreenshotPath,
48
50
  /**
@@ -17,10 +17,9 @@ declare function importWebTestApi(this: void): Promise<RuntimeEnvError | {
17
17
  /**
18
18
  * Test a screenshot against an already established screenshot.
19
19
  *
20
- * To update screenshots, run the test command with `--update` or
21
- * `--update-visual-baseline`.
20
+ * To update screenshots, run the test command with `--update`.
22
21
  */
23
- testScreenshot: typeof import("../test-web/test-screenshot.js").testScreenshot;
22
+ assertScreenshot: typeof import("../test-web/web-screenshot.js").assertWebScreenshot;
24
23
  /**
25
24
  * Renders a string or TemplateResult and puts it in the DOM via a fixtureWrapper.
26
25
  *
@@ -9,7 +9,7 @@ async function importWebTestApi() {
9
9
  const { fixtureCleanup, fixture } = await import('@open-wc/testing-helpers');
10
10
  const { renderElement } = await import('../test-web/render-element.js');
11
11
  const { elementCases } = await import('../test-web/element-cases.js');
12
- const { testScreenshot } = await import('../test-web/test-screenshot.js');
12
+ const { assertWebScreenshot } = await import('../test-web/web-screenshot.js');
13
13
  return {
14
14
  /**
15
15
  * Cleans up all rendered test HTML by removing the actual wrapper nodes. Common use case is
@@ -27,10 +27,9 @@ async function importWebTestApi() {
27
27
  /**
28
28
  * Test a screenshot against an already established screenshot.
29
29
  *
30
- * To update screenshots, run the test command with `--update` or
31
- * `--update-visual-baseline`.
30
+ * To update screenshots, run the test command with `--update`.
32
31
  */
33
- testScreenshot,
32
+ assertScreenshot: assertWebScreenshot,
34
33
  /**
35
34
  * Renders a string or TemplateResult and puts it in the DOM via a fixtureWrapper.
36
35
  *
@@ -83,5 +83,5 @@ export declare function takeScreenshot(testContext: Readonly<UniversalTestContex
83
83
  *
84
84
  * @category Internal
85
85
  */
86
- export declare function expectScreenshot(testContext: Readonly<UniversalTestContext>, options: Readonly<SaveScreenshotOptions>): Promise<void>;
86
+ export declare function expectPlaywrightScreenshot(testContext: Readonly<UniversalTestContext>, options: Readonly<SaveScreenshotOptions>): Promise<void>;
87
87
  export {};
@@ -2,11 +2,11 @@ import { assert } from '@augment-vir/assert';
2
2
  import { addSuffix, log } from '@augment-vir/common';
3
3
  import { writeFileAndDir } from '@augment-vir/node';
4
4
  import { expect } from '@playwright/test';
5
+ import { compareImages, defaultImageComparisonOptions, encodePng, } from '@virmator/test/dist/web-screenshot-plugin/compare-images.js';
5
6
  import { existsSync } from 'node:fs';
6
7
  import { readFile } from 'node:fs/promises';
7
8
  import { relative } from 'node:path';
8
9
  import { assertTestContext, assertWrapTestContext, TestEnv, } from '../augments/universal-testing-suite/universal-test-context.js';
9
- import { compareImages, defaultImageComparisonOptions, encodePng } from './compare-images.js';
10
10
  /** This is used for type extraction because Playwright does not export the types we need. */
11
11
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
12
12
  function extractScreenshotMethod() {
@@ -76,7 +76,7 @@ export async function takeScreenshot(testContext, options) {
76
76
  *
77
77
  * @category Internal
78
78
  */
79
- export async function expectScreenshot(testContext, options) {
79
+ export async function expectPlaywrightScreenshot(testContext, options) {
80
80
  assertTestContext(testContext, TestEnv.Playwright);
81
81
  const currentScreenshotBuffer = await takeScreenshotBuffer(testContext, options);
82
82
  const screenshotFilePath = getScreenshotPath(testContext, options.screenshotBaseName);
@@ -0,0 +1,7 @@
1
+ import { type PartialWithUndefined, type SelectFrom } from '@augment-vir/common';
2
+ import { type CompareScreenshotCommandPayload } from '@virmator/test/dist/web-screenshot-plugin/screenshot-payload.js';
3
+ import { type UniversalTestContext } from '../augments/universal-testing-suite/universal-test-context.js';
4
+ export declare function assertWebScreenshot(element: Element, screenshotNameOrTestContext: string | UniversalTestContext, options?: Readonly<PartialWithUndefined<SelectFrom<CompareScreenshotCommandPayload, {
5
+ maxDiffPixelRatio: true;
6
+ threshold: true;
7
+ }>>>): Promise<void>;
@@ -0,0 +1,34 @@
1
+ import { getOrSet, randomString, } from '@augment-vir/common';
2
+ import { globalElementStoreKey, ScreenshotCommand, } from '@virmator/test/dist/web-screenshot-plugin/screenshot-payload.js';
3
+ import { executeServerCommand } from '@web/test-runner-commands';
4
+ import { extractTestNameAsDir, } from '../augments/universal-testing-suite/universal-test-context.js';
5
+ export async function assertWebScreenshot(element, screenshotNameOrTestContext, options) {
6
+ if (!element.isConnected) {
7
+ throw new Error('Element must be connected to the DOM.');
8
+ }
9
+ else if (element.ownerDocument !== document) {
10
+ throw new Error('Element must belong to the same document the tests are run in.');
11
+ }
12
+ const elementKey = randomString();
13
+ getOrSet(globalThis, globalElementStoreKey, () => {
14
+ return {};
15
+ })[elementKey] = element;
16
+ const screenshotName = typeof screenshotNameOrTestContext === 'string'
17
+ ? screenshotNameOrTestContext
18
+ : extractTestNameAsDir(screenshotNameOrTestContext);
19
+ const payload = {
20
+ ...options,
21
+ elementKey,
22
+ screenshotFileName: screenshotName,
23
+ };
24
+ const result = await executeServerCommand(ScreenshotCommand.CompareScreenshot, payload);
25
+ if (result.updated) {
26
+ /** Ignore updates. */
27
+ return;
28
+ }
29
+ else if (!result.passed) {
30
+ throw new Error(typeof screenshotNameOrTestContext === 'string'
31
+ ? `Screenshot comparison failed for '${screenshotNameOrTestContext}'`
32
+ : 'Screenshot comparison failed.');
33
+ }
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@augment-vir/test",
3
- "version": "31.64.0",
3
+ "version": "31.65.0",
4
4
  "description": "A universal testing suite that works with Mocha style test runners _and_ Node.js's built-in test runner.",
5
5
  "keywords": [
6
6
  "test",
@@ -44,10 +44,10 @@
44
44
  "test:web": "virmator test --no-deps web 'src/test-web/**/*.test.ts' 'src/augments/universal-testing-suite/**/*.test.ts'"
45
45
  },
46
46
  "dependencies": {
47
- "@augment-vir/assert": "^31.64.0",
48
- "@augment-vir/common": "^31.64.0",
47
+ "@augment-vir/assert": "^31.65.0",
48
+ "@augment-vir/common": "^31.65.0",
49
49
  "@date-vir/duration": "^8.1.1",
50
- "@virmator/test": "^14.5.5",
50
+ "@virmator/test": "^14.6.1",
51
51
  "type-fest": "^5.4.4"
52
52
  },
53
53
  "devDependencies": {
@@ -1,71 +0,0 @@
1
- import type { Dimensions } from '@augment-vir/common';
2
- import { PNG } from 'pngjs';
3
- /**
4
- * Options for image comparison thresholds.
5
- *
6
- * @category Internal
7
- */
8
- export type ImageComparisonOptions = {
9
- /**
10
- * Per-pixel color threshold for `pixelmatch` (0–1). Smaller values make comparison more
11
- * sensitive.
12
- */
13
- threshold: number;
14
- /** Maximum ratio of differing pixels allowed before the comparison is considered a failure. */
15
- maxDiffPixelRatio: number;
16
- };
17
- /**
18
- * Default image comparison options used in {@link compareImages}.
19
- *
20
- * @category Internal
21
- */
22
- export declare const defaultImageComparisonOptions: Readonly<ImageComparisonOptions>;
23
- /**
24
- * The result of comparing two images via {@link compareImages}.
25
- *
26
- * @category Internal
27
- */
28
- export type ImageComparisonResult = {
29
- /** Whether the images match within the allowed diff ratio. */
30
- passed: boolean;
31
- /** The number of differing pixels. */
32
- diffPixelCount: number;
33
- /** Total pixel count of the (padded) comparison canvas. */
34
- totalPixels: number;
35
- /** The ratio of differing pixels to total pixels. */
36
- diffRatio: number;
37
- /** The dimensions of the comparison canvas. */
38
- dimensions: Readonly<Dimensions>;
39
- /** PNG data for the base image (padded to the comparison canvas). */
40
- basePng: PNG;
41
- /** PNG data for the current image (padded to the comparison canvas). */
42
- currentPng: PNG;
43
- /** PNG data for the visual diff output. */
44
- diffPng: PNG;
45
- };
46
- /**
47
- * Pads both images to the same canvas size (max width/height of the two) without scaling, then
48
- * returns the decoded PNGs and the shared dimensions.
49
- *
50
- * @category Internal
51
- */
52
- export declare function padToSameCanvas(aBuf: Buffer, bBuf: Buffer): Promise<{
53
- aPng: import("pngjs").PNGWithMetadata;
54
- bPng: import("pngjs").PNGWithMetadata;
55
- dimensions: Readonly<Dimensions>;
56
- }>;
57
- /**
58
- * Compare two PNG image buffers pixel-by-pixel. The images may have different dimensions — they
59
- * will be padded to the same canvas size before comparison.
60
- *
61
- * This function is fully Playwright-agnostic and can be used in any Node.js context.
62
- *
63
- * @category Internal
64
- */
65
- export declare function compareImages(baseImageBuffer: Buffer, currentImageBuffer: Buffer, options?: Readonly<ImageComparisonOptions>): Promise<ImageComparisonResult>;
66
- /**
67
- * Encode a {@link PNG} instance to a `Buffer`.
68
- *
69
- * @category Internal
70
- */
71
- export declare function encodePng(png: PNG): Buffer;
@@ -1,87 +0,0 @@
1
- import pixelmatch from 'pixelmatch';
2
- import { PNG } from 'pngjs';
3
- import sharp from 'sharp';
4
- /**
5
- * Default image comparison options used in {@link compareImages}.
6
- *
7
- * @category Internal
8
- */
9
- export const defaultImageComparisonOptions = {
10
- threshold: 0.1,
11
- maxDiffPixelRatio: 0.08,
12
- };
13
- async function padImage(image, { height, width }) {
14
- return await sharp({
15
- create: { width, height, channels: 4, background: { r: 0, g: 0, b: 0, alpha: 0 } },
16
- })
17
- /** Top-left align. */
18
- .composite([{ input: image, left: 0, top: 0 }])
19
- .png()
20
- .toBuffer();
21
- }
22
- /**
23
- * Pads both images to the same canvas size (max width/height of the two) without scaling, then
24
- * returns the decoded PNGs and the shared dimensions.
25
- *
26
- * @category Internal
27
- */
28
- export async function padToSameCanvas(aBuf, bBuf) {
29
- const [aMeta, bMeta,] = await Promise.all([
30
- sharp(aBuf).metadata(),
31
- sharp(bBuf).metadata(),
32
- ]);
33
- if (!aMeta.width || !aMeta.height || !bMeta.width || !bMeta.height) {
34
- throw new Error('Unable to read image dimensions.');
35
- }
36
- const dimensions = {
37
- width: Math.max(aMeta.width, bMeta.width),
38
- height: Math.max(aMeta.height, bMeta.height),
39
- };
40
- const [aPadded, bPadded,] = await Promise.all([
41
- padImage(aBuf, dimensions),
42
- padImage(bBuf, dimensions),
43
- ]);
44
- const aPng = PNG.sync.read(aPadded);
45
- const bPng = PNG.sync.read(bPadded);
46
- return {
47
- aPng,
48
- bPng,
49
- dimensions,
50
- };
51
- }
52
- /**
53
- * Compare two PNG image buffers pixel-by-pixel. The images may have different dimensions — they
54
- * will be padded to the same canvas size before comparison.
55
- *
56
- * This function is fully Playwright-agnostic and can be used in any Node.js context.
57
- *
58
- * @category Internal
59
- */
60
- export async function compareImages(baseImageBuffer, currentImageBuffer, options = defaultImageComparisonOptions) {
61
- const { aPng: basePng, bPng: currentPng, dimensions, } = await padToSameCanvas(baseImageBuffer, currentImageBuffer);
62
- const diffPng = new PNG(dimensions);
63
- const diffPixelCount = pixelmatch(basePng.data, currentPng.data, diffPng.data, dimensions.width, dimensions.height, {
64
- threshold: options.threshold,
65
- });
66
- const totalPixels = dimensions.width * dimensions.height;
67
- const diffRatio = diffPixelCount / totalPixels;
68
- const passed = diffRatio <= options.maxDiffPixelRatio;
69
- return {
70
- passed,
71
- diffPixelCount,
72
- totalPixels,
73
- diffRatio,
74
- dimensions,
75
- basePng,
76
- currentPng,
77
- diffPng,
78
- };
79
- }
80
- /**
81
- * Encode a {@link PNG} instance to a `Buffer`.
82
- *
83
- * @category Internal
84
- */
85
- export function encodePng(png) {
86
- return PNG.sync.write(png);
87
- }
@@ -1 +0,0 @@
1
- export declare function testScreenshot(element: Node, screenshotName: string): Promise<void>;
@@ -1,5 +0,0 @@
1
- // @ts-expect-error: this package's export types are messed up
2
- import { visualDiff } from '@web/test-runner-visual-regression';
3
- export async function testScreenshot(element, screenshotName) {
4
- return await visualDiff(element, screenshotName);
5
- }