@argos-ci/cypress 2.2.7 → 2.3.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.
package/dist/support.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { ViewportOption } from "@argos-ci/browser";
1
+ import { ViewportOption, StabilizationOptions } from '@argos-ci/browser';
2
+
2
3
  type ArgosScreenshotOptions = Partial<Cypress.Loggable & Cypress.Timeoutable & Cypress.ScreenshotOptions> & {
3
4
  /**
4
5
  * Viewports to take screenshots of.
@@ -14,6 +15,13 @@ type ArgosScreenshotOptions = Partial<Cypress.Loggable & Cypress.Timeoutable & C
14
15
  * @default 0.5
15
16
  */
16
17
  threshold?: number;
18
+ /**
19
+ * Wait for the UI to stabilize before taking the screenshot.
20
+ * Set to `false` to disable stabilization.
21
+ * Pass an object to customize the stabilization.
22
+ * @default true
23
+ */
24
+ stabilize?: boolean | StabilizationOptions;
17
25
  };
18
26
  declare global {
19
27
  namespace Cypress {
@@ -0,0 +1,141 @@
1
+ // src/support.ts
2
+ import "cypress-wait-until";
3
+ import {
4
+ resolveViewport
5
+ } from "@argos-ci/browser";
6
+ import { getGlobalScript } from "@argos-ci/browser";
7
+ import {
8
+ getMetadataPath,
9
+ getScreenshotName,
10
+ validateThreshold
11
+ } from "@argos-ci/util/browser";
12
+
13
+ // package.json
14
+ var version = "2.2.7";
15
+
16
+ // src/support.ts
17
+ function injectArgos() {
18
+ cy.window({ log: false }).then((window) => {
19
+ if (typeof window.__ARGOS__ !== "undefined") return;
20
+ window.eval(getGlobalScript());
21
+ });
22
+ }
23
+ function setup(options) {
24
+ const { argosCSS } = options;
25
+ const fullPage = !options.capture || options.capture === "fullPage";
26
+ cy.window({ log: false }).then(
27
+ (window) => window.__ARGOS__.setup({ fullPage, argosCSS })
28
+ );
29
+ return () => {
30
+ cy.window({ log: false }).then(
31
+ (window) => window.__ARGOS__.teardown({
32
+ fullPage,
33
+ argosCSS
34
+ })
35
+ );
36
+ };
37
+ }
38
+ Cypress.Commands.add(
39
+ "argosScreenshot",
40
+ { prevSubject: ["optional", "element", "window", "document"] },
41
+ (subject, name, options = {}) => {
42
+ const {
43
+ viewports,
44
+ argosCSS,
45
+ stabilize = true,
46
+ ...cypressOptions
47
+ } = options;
48
+ if (!name) {
49
+ throw new Error("The `name` argument is required.");
50
+ }
51
+ Cypress.log({
52
+ name: "argosScreenshot",
53
+ displayName: `Argos Screenshot`,
54
+ message: name
55
+ });
56
+ injectArgos();
57
+ const teardown = setup(options);
58
+ function stabilizeAndScreenshot(name2) {
59
+ if (stabilize) {
60
+ const stabilizationOptions = typeof stabilize === "object" ? stabilize : {};
61
+ cy.waitUntil(
62
+ () => cy.window({ log: false }).then((window) => {
63
+ const isStable = window.__ARGOS__.checkIsStable(stabilizationOptions);
64
+ if (isStable) {
65
+ return true;
66
+ }
67
+ const failureReasons = window.__ARGOS__.getStabilityFailureReasons(stabilizationOptions);
68
+ failureReasons.forEach((reason) => {
69
+ cy.log(`[argos] stability: ${reason}`);
70
+ });
71
+ return false;
72
+ })
73
+ );
74
+ }
75
+ let ref = {};
76
+ cy.wrap(subject).screenshot(name2, {
77
+ blackout: ['[data-visual-test="blackout"]'].concat(
78
+ options.blackout || []
79
+ ),
80
+ onAfterScreenshot: (_$el, props) => {
81
+ ref.props = props;
82
+ },
83
+ ...cypressOptions
84
+ });
85
+ cy.window({ log: false }).then((window) => {
86
+ const mediaType = window.__ARGOS__.getMediaType();
87
+ const colorScheme = window.__ARGOS__.getColorScheme();
88
+ const metadata = {
89
+ url: window.location.href,
90
+ viewport: {
91
+ width: window.innerWidth,
92
+ height: window.innerHeight
93
+ },
94
+ colorScheme,
95
+ mediaType,
96
+ test: {
97
+ title: Cypress.currentTest.title,
98
+ titlePath: Cypress.currentTest.titlePath,
99
+ retry: Cypress.currentRetry,
100
+ // @ts-ignore
101
+ retries: cy.state("runnable")._retries
102
+ },
103
+ browser: {
104
+ name: Cypress.browser.name,
105
+ version: Cypress.browser.version
106
+ },
107
+ automationLibrary: {
108
+ name: "cypress",
109
+ version: Cypress.version
110
+ },
111
+ sdk: {
112
+ name: "@argos-ci/cypress",
113
+ version
114
+ }
115
+ };
116
+ metadata.transient = {};
117
+ if (options.threshold !== void 0) {
118
+ validateThreshold(options.threshold);
119
+ metadata.transient.threshold = options.threshold;
120
+ }
121
+ cy.writeFile(getMetadataPath(ref.props.path), JSON.stringify(metadata));
122
+ });
123
+ }
124
+ if (viewports) {
125
+ for (const viewport of viewports) {
126
+ const viewportSize = resolveViewport(viewport);
127
+ cy.viewport(viewportSize.width, viewportSize.height);
128
+ stabilizeAndScreenshot(
129
+ getScreenshotName(name, { viewportWidth: viewportSize.width })
130
+ );
131
+ }
132
+ cy.viewport(
133
+ Cypress.config("viewportWidth"),
134
+ Cypress.config("viewportHeight")
135
+ );
136
+ } else {
137
+ stabilizeAndScreenshot(name);
138
+ }
139
+ teardown();
140
+ }
141
+ );
package/dist/task.cjs CHANGED
@@ -1,56 +1,72 @@
1
- 'use strict';
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
2
19
 
3
- var core = require('@argos-ci/core');
4
- var node_path = require('node:path');
5
- var promises = require('node:fs/promises');
6
-
7
- /// <reference types="cypress" />
20
+ // src/task.ts
21
+ var task_exports = {};
22
+ __export(task_exports, {
23
+ registerArgosTask: () => registerArgosTask
24
+ });
25
+ module.exports = __toCommonJS(task_exports);
26
+ var import_core = require("@argos-ci/core");
27
+ var import_node_path = require("path");
28
+ var import_promises = require("fs/promises");
8
29
  function checkIsCypressFailedResult(results) {
9
- return "status" in results && results.status === "failed";
30
+ return "status" in results && results.status === "failed";
10
31
  }
11
32
  function registerArgosTask(on, config, options) {
12
- on("after:screenshot", async (details)=>{
13
- // Get the base filename without extension
14
- const baseName = node_path.basename(details.path, node_path.extname(details.path));
15
- // Remove attempt from the filename
16
- const newBaseName = baseName.replace(/ \(attempt \d+\)/, "");
17
- // Construct a new path with the original file extension
18
- const newPath = node_path.join(node_path.dirname(details.path), newBaseName + node_path.extname(details.path));
19
- // Rename the file
20
- await promises.rename(details.path, newPath);
21
- return {
22
- path: newPath
23
- };
24
- });
25
- on("after:run", async (results)=>{
26
- const { screenshotsFolder } = config;
27
- if (!screenshotsFolder) {
28
- return;
33
+ on("after:screenshot", async (details) => {
34
+ const baseName = (0, import_node_path.basename)(details.path, (0, import_node_path.extname)(details.path));
35
+ const newBaseName = baseName.replace(/ \(attempt \d+\)/, "");
36
+ const newPath = (0, import_node_path.join)(
37
+ (0, import_node_path.dirname)(details.path),
38
+ newBaseName + (0, import_node_path.extname)(details.path)
39
+ );
40
+ await (0, import_promises.rename)(details.path, newPath);
41
+ return { path: newPath };
42
+ });
43
+ on("after:run", async (results) => {
44
+ const { screenshotsFolder } = config;
45
+ if (!screenshotsFolder) {
46
+ return;
47
+ }
48
+ const { uploadToArgos = true } = options || {};
49
+ if (!uploadToArgos) {
50
+ return;
51
+ }
52
+ const res = await (0, import_core.upload)({
53
+ ...options,
54
+ files: ["**/*.png"],
55
+ root: screenshotsFolder,
56
+ metadata: {
57
+ testReport: checkIsCypressFailedResult(results) ? { status: "failed" } : {
58
+ status: "passed",
59
+ stats: {
60
+ startTime: results.startedTestsAt,
61
+ duration: results.totalDuration
62
+ }
29
63
  }
30
- const { uploadToArgos = true } = options || {};
31
- if (!uploadToArgos) {
32
- return;
33
- }
34
- const res = await core.upload({
35
- ...options,
36
- files: [
37
- "**/*.png"
38
- ],
39
- root: screenshotsFolder,
40
- metadata: {
41
- testReport: checkIsCypressFailedResult(results) ? {
42
- status: "failed"
43
- } : {
44
- status: "passed",
45
- stats: {
46
- startTime: results.startedTestsAt,
47
- duration: results.totalDuration
48
- }
49
- }
50
- }
51
- });
52
- console.log(`✅ Argos build created: ${res.build.url}`);
64
+ }
53
65
  });
66
+ console.log(`\u2705 Argos build created: ${res.build.url}`);
67
+ });
54
68
  }
55
-
56
- exports.registerArgosTask = registerArgosTask;
69
+ // Annotate the CommonJS export names for ESM import in node:
70
+ 0 && (module.exports = {
71
+ registerArgosTask
72
+ });
@@ -0,0 +1,12 @@
1
+ import { UploadParameters } from '@argos-ci/core';
2
+
3
+ type RegisterArgosTaskOptions = Omit<UploadParameters, "files" | "root"> & {
4
+ /**
5
+ * Upload the report to Argos.
6
+ * @default true
7
+ */
8
+ uploadToArgos?: boolean;
9
+ };
10
+ declare function registerArgosTask(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions, options?: RegisterArgosTaskOptions): void;
11
+
12
+ export { type RegisterArgosTaskOptions, registerArgosTask };
package/dist/task.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { UploadParameters } from "@argos-ci/core";
1
+ import { UploadParameters } from '@argos-ci/core';
2
+
2
3
  type RegisterArgosTaskOptions = Omit<UploadParameters, "files" | "root"> & {
3
4
  /**
4
5
  * Upload the report to Argos.
@@ -7,4 +8,5 @@ type RegisterArgosTaskOptions = Omit<UploadParameters, "files" | "root"> & {
7
8
  uploadToArgos?: boolean;
8
9
  };
9
10
  declare function registerArgosTask(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions, options?: RegisterArgosTaskOptions): void;
10
- export { RegisterArgosTaskOptions, registerArgosTask };
11
+
12
+ export { type RegisterArgosTaskOptions, registerArgosTask };
package/dist/task.js ADDED
@@ -0,0 +1,47 @@
1
+ // src/task.ts
2
+ import { upload } from "@argos-ci/core";
3
+ import { basename, extname, join, dirname } from "node:path";
4
+ import { rename } from "node:fs/promises";
5
+ function checkIsCypressFailedResult(results) {
6
+ return "status" in results && results.status === "failed";
7
+ }
8
+ function registerArgosTask(on, config, options) {
9
+ on("after:screenshot", async (details) => {
10
+ const baseName = basename(details.path, extname(details.path));
11
+ const newBaseName = baseName.replace(/ \(attempt \d+\)/, "");
12
+ const newPath = join(
13
+ dirname(details.path),
14
+ newBaseName + extname(details.path)
15
+ );
16
+ await rename(details.path, newPath);
17
+ return { path: newPath };
18
+ });
19
+ on("after:run", async (results) => {
20
+ const { screenshotsFolder } = config;
21
+ if (!screenshotsFolder) {
22
+ return;
23
+ }
24
+ const { uploadToArgos = true } = options || {};
25
+ if (!uploadToArgos) {
26
+ return;
27
+ }
28
+ const res = await upload({
29
+ ...options,
30
+ files: ["**/*.png"],
31
+ root: screenshotsFolder,
32
+ metadata: {
33
+ testReport: checkIsCypressFailedResult(results) ? { status: "failed" } : {
34
+ status: "passed",
35
+ stats: {
36
+ startTime: results.startedTestsAt,
37
+ duration: results.totalDuration
38
+ }
39
+ }
40
+ }
41
+ });
42
+ console.log(`\u2705 Argos build created: ${res.build.url}`);
43
+ });
44
+ }
45
+ export {
46
+ registerArgosTask
47
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@argos-ci/cypress",
3
3
  "description": "Cypress SDK for visual testing with Argos.",
4
- "version": "2.2.7",
4
+ "version": "2.3.0",
5
5
  "author": "Smooth Code",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -30,12 +30,12 @@
30
30
  "exports": {
31
31
  "./support": {
32
32
  "types": "./dist/support.d.ts",
33
- "import": "./dist/support.mjs",
34
- "default": "./dist/support.mjs"
33
+ "import": "./dist/support.js",
34
+ "default": "./dist/support.js"
35
35
  },
36
36
  "./task": {
37
37
  "types": "./dist/task.d.ts",
38
- "import": "./dist/task.mjs",
38
+ "import": "./dist/task.js",
39
39
  "require": "./dist/task.cjs",
40
40
  "default": "./dist/task.cjs"
41
41
  },
@@ -45,27 +45,26 @@
45
45
  "node": ">=18.0.0"
46
46
  },
47
47
  "dependencies": {
48
- "@argos-ci/browser": "2.1.6",
49
- "@argos-ci/core": "2.9.2",
50
- "@argos-ci/util": "2.1.2",
48
+ "@argos-ci/browser": "2.2.0",
49
+ "@argos-ci/core": "2.10.0",
50
+ "@argos-ci/util": "2.2.0",
51
51
  "cypress-wait-until": "^3.0.2"
52
52
  },
53
53
  "peerDependencies": {
54
54
  "cypress": "^12.0.0 || ^13.0.0"
55
55
  },
56
56
  "devDependencies": {
57
- "@argos-ci/cli": "2.4.7",
57
+ "@argos-ci/cli": "2.5.0",
58
58
  "@argos-ci/cypress": "workspace:.",
59
59
  "@types/node": "^18.19.44",
60
- "cypress": "^13.13.3",
60
+ "cypress": "^13.15.1",
61
61
  "eslint-plugin-cypress": "^3.5.0",
62
62
  "eslint-plugin-html": "^8.1.1"
63
63
  },
64
64
  "scripts": {
65
- "prebuild": "rm -rf dist",
66
- "build": "rollup -c",
65
+ "build": "tsup",
67
66
  "test": "pnpm exec cypress run",
68
67
  "e2e": "UPLOAD_TO_ARGOS=true pnpm run test"
69
68
  },
70
- "gitHead": "d0fa8cd790ffd2343d1cd32706bcb757c4f3b26e"
69
+ "gitHead": "fe6e055a43e955e7df362ddaec59c84dc274bbb2"
71
70
  }
package/dist/support.mjs DELETED
@@ -1,121 +0,0 @@
1
- import 'cypress-wait-until';
2
- import { resolveViewport, getGlobalScript } from '@argos-ci/browser';
3
- import { getScreenshotName, validateThreshold, getMetadataPath } from '@argos-ci/util/browser';
4
-
5
- var version = "2.2.6";
6
-
7
- function injectArgos() {
8
- cy.window({
9
- log: false
10
- }).then((window)=>{
11
- if (typeof window.__ARGOS__ !== "undefined") return;
12
- window.eval(getGlobalScript());
13
- });
14
- }
15
- function setup(options) {
16
- const { argosCSS } = options;
17
- const fullPage = !options.capture || options.capture === "fullPage";
18
- cy.window({
19
- log: false
20
- }).then((window)=>window.__ARGOS__.setup({
21
- fullPage,
22
- argosCSS
23
- }));
24
- return ()=>{
25
- cy.window({
26
- log: false
27
- }).then((window)=>window.__ARGOS__.teardown({
28
- fullPage,
29
- argosCSS
30
- }));
31
- };
32
- }
33
- Cypress.Commands.add("argosScreenshot", {
34
- prevSubject: [
35
- "optional",
36
- "element",
37
- "window",
38
- "document"
39
- ]
40
- }, (subject, name, options = {})=>{
41
- const { viewports, argosCSS, ...cypressOptions } = options;
42
- if (!name) {
43
- throw new Error("The `name` argument is required.");
44
- }
45
- Cypress.log({
46
- name: "argosScreenshot",
47
- displayName: `Argos Screenshot`,
48
- message: name
49
- });
50
- injectArgos();
51
- const teardown = setup(options);
52
- function stabilizeAndScreenshot(name) {
53
- cy.waitUntil(()=>cy.window({
54
- log: false
55
- }).then((window)=>window.__ARGOS__.waitForStability()));
56
- let ref = {};
57
- cy.wrap(subject).screenshot(name, {
58
- blackout: [
59
- '[data-visual-test="blackout"]'
60
- ].concat(options.blackout || []),
61
- onAfterScreenshot: (_$el, props)=>{
62
- ref.props = props;
63
- },
64
- ...cypressOptions
65
- });
66
- cy.window({
67
- log: false
68
- }).then((window)=>{
69
- const mediaType = window.__ARGOS__.getMediaType();
70
- const colorScheme = window.__ARGOS__.getColorScheme();
71
- const metadata = {
72
- url: window.location.href,
73
- viewport: {
74
- width: window.innerWidth,
75
- height: window.innerHeight
76
- },
77
- colorScheme,
78
- mediaType,
79
- test: {
80
- title: Cypress.currentTest.title,
81
- titlePath: Cypress.currentTest.titlePath,
82
- retry: Cypress.currentRetry,
83
- // @ts-ignore
84
- retries: cy.state("runnable")._retries
85
- },
86
- browser: {
87
- name: Cypress.browser.name,
88
- version: Cypress.browser.version
89
- },
90
- automationLibrary: {
91
- name: "cypress",
92
- version: Cypress.version
93
- },
94
- sdk: {
95
- name: "@argos-ci/cypress",
96
- version
97
- }
98
- };
99
- metadata.transient = {};
100
- if (options.threshold !== undefined) {
101
- validateThreshold(options.threshold);
102
- metadata.transient.threshold = options.threshold;
103
- }
104
- cy.writeFile(getMetadataPath(ref.props.path), JSON.stringify(metadata));
105
- });
106
- }
107
- if (viewports) {
108
- for (const viewport of viewports){
109
- const viewportSize = resolveViewport(viewport);
110
- cy.viewport(viewportSize.width, viewportSize.height);
111
- stabilizeAndScreenshot(getScreenshotName(name, {
112
- viewportWidth: viewportSize.width
113
- }));
114
- }
115
- // Restore the original viewport
116
- cy.viewport(Cypress.config("viewportWidth"), Cypress.config("viewportHeight"));
117
- } else {
118
- stabilizeAndScreenshot(name);
119
- }
120
- teardown();
121
- });
package/dist/task.mjs DELETED
@@ -1,54 +0,0 @@
1
- import { upload } from '@argos-ci/core';
2
- import { basename, extname, join, dirname } from 'node:path';
3
- import { rename } from 'node:fs/promises';
4
-
5
- /// <reference types="cypress" />
6
- function checkIsCypressFailedResult(results) {
7
- return "status" in results && results.status === "failed";
8
- }
9
- function registerArgosTask(on, config, options) {
10
- on("after:screenshot", async (details)=>{
11
- // Get the base filename without extension
12
- const baseName = basename(details.path, extname(details.path));
13
- // Remove attempt from the filename
14
- const newBaseName = baseName.replace(/ \(attempt \d+\)/, "");
15
- // Construct a new path with the original file extension
16
- const newPath = join(dirname(details.path), newBaseName + extname(details.path));
17
- // Rename the file
18
- await rename(details.path, newPath);
19
- return {
20
- path: newPath
21
- };
22
- });
23
- on("after:run", async (results)=>{
24
- const { screenshotsFolder } = config;
25
- if (!screenshotsFolder) {
26
- return;
27
- }
28
- const { uploadToArgos = true } = options || {};
29
- if (!uploadToArgos) {
30
- return;
31
- }
32
- const res = await upload({
33
- ...options,
34
- files: [
35
- "**/*.png"
36
- ],
37
- root: screenshotsFolder,
38
- metadata: {
39
- testReport: checkIsCypressFailedResult(results) ? {
40
- status: "failed"
41
- } : {
42
- status: "passed",
43
- stats: {
44
- startTime: results.startedTestsAt,
45
- duration: results.totalDuration
46
- }
47
- }
48
- }
49
- });
50
- console.log(`✅ Argos build created: ${res.build.url}`);
51
- });
52
- }
53
-
54
- export { registerArgosTask };