cypress 15.3.0 → 15.4.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/cli.js CHANGED
@@ -124,6 +124,7 @@ const descriptions = {
124
124
  parallel: 'enables concurrent runs and automatic load balancing of specs across multiple machines or processes',
125
125
  port: 'runs Cypress on a specific port. overrides any value in cypress.config.{js,ts,mjs,cjs}.',
126
126
  project: 'path to the project',
127
+ posixExitCodes: 'use POSIX exit codes for error handling',
127
128
  quiet: 'run quietly, using only the configured reporter',
128
129
  record: 'records the run. sends test results, screenshots and videos to Cypress Cloud.',
129
130
  reporter: 'runs a specific mocha reporter. pass a path to use a custom reporter. defaults to "spec"',
@@ -236,6 +237,7 @@ const addCypressRunCommand = (program) => {
236
237
  .option('--parallel', text('parallel'))
237
238
  .option('-p, --port <port>', text('port'))
238
239
  .option('-P, --project <project-path>', text('project'))
240
+ .option('--posix-exit-codes', text('posixExitCodes'))
239
241
  .option('-q, --quiet', text('quiet'))
240
242
  .option('--record [bool]', text('record'), coerceFalse)
241
243
  .option('-r, --reporter <reporter>', text('reporter'))
package/dist/exec/info.js CHANGED
@@ -13,7 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  /* eslint-disable no-console */
16
- const spawn_1 = __importDefault(require("./spawn"));
16
+ const spawn_1 = require("./spawn");
17
17
  const util_1 = __importDefault(require("../util"));
18
18
  const state_1 = __importDefault(require("../tasks/state"));
19
19
  const os_1 = __importDefault(require("os"));
@@ -49,7 +49,7 @@ const formatCypressVariables = () => {
49
49
  };
50
50
  methods.start = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (options = {}) {
51
51
  const args = ['--mode=info'];
52
- yield spawn_1.default.start(args, {
52
+ yield (0, spawn_1.start)(args, {
53
53
  dev: options.dev,
54
54
  });
55
55
  console.log();
package/dist/exec/open.js CHANGED
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.start = exports.processOpenOptions = void 0;
16
16
  const debug_1 = __importDefault(require("debug"));
17
17
  const util_1 = __importDefault(require("../util"));
18
- const spawn_1 = __importDefault(require("./spawn"));
18
+ const spawn_1 = require("./spawn");
19
19
  const verify_1 = require("../tasks/verify");
20
20
  const shared_1 = require("./shared");
21
21
  const errors_1 = require("../errors");
@@ -78,7 +78,7 @@ const start = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (o
78
78
  function open() {
79
79
  try {
80
80
  const args = (0, exports.processOpenOptions)(options);
81
- return spawn_1.default.start(args, {
81
+ return (0, spawn_1.start)(args, {
82
82
  dev: options.dev,
83
83
  detached: Boolean(options.detached),
84
84
  });
package/dist/exec/run.js CHANGED
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const lodash_1 = __importDefault(require("lodash"));
16
16
  const debug_1 = __importDefault(require("debug"));
17
17
  const util_1 = __importDefault(require("../util"));
18
- const spawn_1 = __importDefault(require("./spawn"));
18
+ const spawn_1 = require("./spawn");
19
19
  const verify_1 = require("../tasks/verify");
20
20
  const errors_1 = require("../errors");
21
21
  const shared_1 = require("./shared");
@@ -100,6 +100,9 @@ const processRunOptions = (options = {}) => {
100
100
  if (options.parallel) {
101
101
  args.push('--parallel');
102
102
  }
103
+ if (options.posixExitCodes) {
104
+ args.push('--posix-exit-codes');
105
+ }
103
106
  if (options.port) {
104
107
  args.push('--port', options.port);
105
108
  }
@@ -155,7 +158,7 @@ const runModule = {
155
158
  try {
156
159
  const args = processRunOptions(options);
157
160
  debug('run to spawn.start args %j', args);
158
- return spawn_1.default.start(args, {
161
+ return (0, spawn_1.start)(args, {
159
162
  dev: options.dev,
160
163
  });
161
164
  }
@@ -45,6 +45,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
45
45
  return (mod && mod.__esModule) ? mod : { "default": mod };
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.start = start;
48
49
  const lodash_1 = __importDefault(require("lodash"));
49
50
  const os_1 = __importDefault(require("os"));
50
51
  const child_process_1 = __importDefault(require("child_process"));
@@ -59,6 +60,7 @@ const errors_1 = require("../errors");
59
60
  const readline_1 = __importDefault(require("readline"));
60
61
  const process_1 = require("process");
61
62
  const debug = (0, debug_1.default)('cypress:cli');
63
+ const DBUS_ERROR_PATTERN = /ERROR:dbus\/(bus|object_proxy)\.cc/;
62
64
  function isPlatform(platform) {
63
65
  return os_1.default.platform() === platform;
64
66
  }
@@ -72,7 +74,7 @@ function needsStderrPiped(needsXvfb) {
72
74
  function needsEverythingPipedDirectly() {
73
75
  return isPlatform('win32');
74
76
  }
75
- function getStdio(needsXvfb) {
77
+ function getStdioStrategy(needsXvfb) {
76
78
  if (needsEverythingPipedDirectly()) {
77
79
  return 'pipe';
78
80
  }
@@ -87,215 +89,223 @@ function getStdio(needsXvfb) {
87
89
  }
88
90
  return 'inherit';
89
91
  }
90
- const spawnModule = {
91
- start(args_1) {
92
- return __awaiter(this, arguments, void 0, function* (args, options = {}) {
93
- const needsXvfb = xvfb_1.default.isNeeded();
94
- let executable = state_1.default.getPathToExecutable(state_1.default.getBinaryDir());
95
- if (util_1.default.getEnv('CYPRESS_RUN_BINARY')) {
96
- executable = path_1.default.resolve(util_1.default.getEnv('CYPRESS_RUN_BINARY'));
92
+ function createSpawnFunction(executable, args, options) {
93
+ return (overrides = {}) => {
94
+ return new bluebird_1.default((resolve, reject) => {
95
+ lodash_1.default.defaults(overrides, {
96
+ onStderrData: false,
97
+ });
98
+ const { onStderrData } = overrides;
99
+ const envOverrides = util_1.default.getEnvOverrides(options);
100
+ const electronArgs = [];
101
+ const node11WindowsFix = isPlatform('win32');
102
+ let startScriptPath;
103
+ if (options.dev) {
104
+ executable = 'node';
105
+ // if we're in dev then reset
106
+ // the launch cmd to be 'npm run dev'
107
+ startScriptPath = path_1.default.resolve(__dirname, '..', '..', '..', 'scripts', 'start.js');
108
+ debug('in dev mode the args became %o', args);
97
109
  }
98
- debug('needs to start own Xvfb?', needsXvfb);
99
- // Always push cwd into the args
100
- // which additionally acts as a signal to the
101
- // binary that it was invoked through the NPM module
102
- args = args || [];
103
- if (typeof args === 'string') {
104
- args = [args];
110
+ if (!options.dev && (0, verify_1.needsSandbox)()) {
111
+ electronArgs.push('--no-sandbox');
105
112
  }
106
- args = [...args, '--cwd', process.cwd(), '--userNodePath', process.execPath, '--userNodeVersion', process.versions.node];
107
- lodash_1.default.defaults(options, {
108
- dev: false,
109
- env: process.env,
110
- detached: false,
111
- stdio: getStdio(needsXvfb),
112
- });
113
- const spawn = (overrides = {}) => {
114
- return new bluebird_1.default((resolve, reject) => {
115
- lodash_1.default.defaults(overrides, {
116
- onStderrData: false,
113
+ // strip dev out of child process options
114
+ /**
115
+ * @type {import('child_process').ForkOptions}
116
+ */
117
+ let stdioOptions = lodash_1.default.pick(options, 'env', 'detached', 'stdio');
118
+ // figure out if we're going to be force enabling or disabling colors.
119
+ // also figure out whether we should force stdout and stderr into thinking
120
+ // it is a tty as opposed to a pipe.
121
+ stdioOptions.env = lodash_1.default.extend({}, stdioOptions.env, envOverrides);
122
+ if (node11WindowsFix) {
123
+ stdioOptions = lodash_1.default.extend({}, stdioOptions, { windowsHide: false });
124
+ }
125
+ if (util_1.default.isPossibleLinuxWithIncorrectDisplay()) {
126
+ // make sure we use the latest DISPLAY variable if any
127
+ debug('passing DISPLAY', process.env.DISPLAY);
128
+ stdioOptions.env.DISPLAY = process.env.DISPLAY;
129
+ }
130
+ if (stdioOptions.env.ELECTRON_RUN_AS_NODE) {
131
+ // Since we are running electron as node, we need to add an entry point file.
132
+ startScriptPath = path_1.default.join(state_1.default.getBinaryPkgPath(path_1.default.dirname(executable)), '..', 'index.js');
133
+ }
134
+ else {
135
+ // Start arguments with "--" so Electron knows these are OUR
136
+ // arguments and does not try to sanitize them. Otherwise on Windows
137
+ // an url in one of the arguments crashes it :(
138
+ // https://github.com/cypress-io/cypress/issues/5466
139
+ args = [...electronArgs, '--', ...args];
140
+ }
141
+ if (startScriptPath) {
142
+ args.unshift(startScriptPath);
143
+ }
144
+ if (process.env.CYPRESS_INTERNAL_DEV_DEBUG) {
145
+ args.unshift(process.env.CYPRESS_INTERNAL_DEV_DEBUG);
146
+ }
147
+ debug('spawn args %o %o', args, lodash_1.default.omit(stdioOptions, 'env'));
148
+ debug('spawning Cypress with executable: %s', executable);
149
+ const child = child_process_1.default.spawn(executable, args, stdioOptions);
150
+ function resolveOn(event) {
151
+ return function (code, signal) {
152
+ return __awaiter(this, void 0, void 0, function* () {
153
+ debug('child event fired %o', { event, code, signal });
154
+ if (code === null) {
155
+ const errorObject = errors_1.errors.childProcessKilled(event, signal);
156
+ const err = yield (0, errors_1.getError)(errorObject);
157
+ return reject(err);
158
+ }
159
+ resolve(code);
117
160
  });
118
- const { onStderrData } = overrides;
119
- const envOverrides = util_1.default.getEnvOverrides(options);
120
- const electronArgs = [];
121
- const node11WindowsFix = isPlatform('win32');
122
- let startScriptPath;
123
- if (options.dev) {
124
- executable = 'node';
125
- // if we're in dev then reset
126
- // the launch cmd to be 'npm run dev'
127
- startScriptPath = path_1.default.resolve(__dirname, '..', '..', '..', 'scripts', 'start.js');
128
- debug('in dev mode the args became %o', args);
129
- }
130
- if (!options.dev && (0, verify_1.needsSandbox)()) {
131
- electronArgs.push('--no-sandbox');
132
- }
133
- // strip dev out of child process options
134
- /**
135
- * @type {import('child_process').ForkOptions}
136
- */
137
- let stdioOptions = lodash_1.default.pick(options, 'env', 'detached', 'stdio');
138
- // figure out if we're going to be force enabling or disabling colors.
139
- // also figure out whether we should force stdout and stderr into thinking
140
- // it is a tty as opposed to a pipe.
141
- stdioOptions.env = lodash_1.default.extend({}, stdioOptions.env, envOverrides);
142
- if (node11WindowsFix) {
143
- stdioOptions = lodash_1.default.extend({}, stdioOptions, { windowsHide: false });
144
- }
145
- if (util_1.default.isPossibleLinuxWithIncorrectDisplay()) {
146
- // make sure we use the latest DISPLAY variable if any
147
- debug('passing DISPLAY', process.env.DISPLAY);
148
- stdioOptions.env.DISPLAY = process.env.DISPLAY;
161
+ };
162
+ }
163
+ child.on('close', resolveOn('close'));
164
+ child.on('exit', resolveOn('exit'));
165
+ child.on('error', reject);
166
+ if (isPlatform('win32')) {
167
+ const rl = readline_1.default.createInterface({
168
+ input: process_1.stdin,
169
+ output: process_1.stdout,
170
+ });
171
+ // on windows, SIGINT does not propagate to the child process when ctrl+c is pressed
172
+ // this makes sure all nested processes are closed(ex: firefox inside the server)
173
+ rl.on('SIGINT', function () {
174
+ return __awaiter(this, void 0, void 0, function* () {
175
+ const kill = (yield Promise.resolve().then(() => __importStar(require('tree-kill')))).default;
176
+ kill(child.pid, 'SIGINT');
177
+ });
178
+ });
179
+ }
180
+ // if stdio options is set to 'pipe', then
181
+ // we should set up pipes:
182
+ // process STDIN (read stream) => child STDIN (writeable)
183
+ // child STDOUT => process STDOUT
184
+ // child STDERR => process STDERR with additional filtering
185
+ if (child.stdin) {
186
+ debug('piping process STDIN into child STDIN');
187
+ process_1.stdin.pipe(child.stdin);
188
+ }
189
+ if (child.stdout) {
190
+ debug('piping child STDOUT to process STDOUT');
191
+ child.stdout.pipe(process_1.stdout);
192
+ }
193
+ // if this is defined then we are manually piping for linux
194
+ // to filter out the garbage
195
+ if (child.stderr) {
196
+ debug('piping child STDERR to process STDERR');
197
+ child.stderr.on('data', (data) => {
198
+ const str = data.toString();
199
+ // if we have a callback and this explicitly returns
200
+ // false then bail
201
+ if (onStderrData && onStderrData(str)) {
202
+ return;
149
203
  }
150
- if (stdioOptions.env.ELECTRON_RUN_AS_NODE) {
151
- // Since we are running electron as node, we need to add an entry point file.
152
- startScriptPath = path_1.default.join(state_1.default.getBinaryPkgPath(path_1.default.dirname(executable)), '..', 'index.js');
204
+ if (str.match(DBUS_ERROR_PATTERN)) {
205
+ debug(str);
153
206
  }
154
207
  else {
155
- // Start arguments with "--" so Electron knows these are OUR
156
- // arguments and does not try to sanitize them. Otherwise on Windows
157
- // an url in one of the arguments crashes it :(
158
- // https://github.com/cypress-io/cypress/issues/5466
159
- args = [...electronArgs, '--', ...args];
160
- }
161
- if (startScriptPath) {
162
- args.unshift(startScriptPath);
163
- }
164
- if (process.env.CYPRESS_INTERNAL_DEV_DEBUG) {
165
- args.unshift(process.env.CYPRESS_INTERNAL_DEV_DEBUG);
166
- }
167
- debug('spawn args %o %o', args, lodash_1.default.omit(stdioOptions, 'env'));
168
- debug('spawning Cypress with executable: %s', executable);
169
- const child = child_process_1.default.spawn(executable, args, stdioOptions);
170
- function resolveOn(event) {
171
- return function (code, signal) {
172
- return __awaiter(this, void 0, void 0, function* () {
173
- debug('child event fired %o', { event, code, signal });
174
- if (code === null) {
175
- const errorObject = errors_1.errors.childProcessKilled(event, signal);
176
- const err = yield (0, errors_1.getError)(errorObject);
177
- return reject(err);
178
- }
179
- resolve(code);
180
- });
181
- };
182
- }
183
- child.on('close', resolveOn('close'));
184
- child.on('exit', resolveOn('exit'));
185
- child.on('error', reject);
186
- if (isPlatform('win32')) {
187
- const rl = readline_1.default.createInterface({
188
- input: process_1.stdin,
189
- output: process_1.stdout,
190
- });
191
- // on windows, SIGINT does not propagate to the child process when ctrl+c is pressed
192
- // this makes sure all nested processes are closed(ex: firefox inside the server)
193
- rl.on('SIGINT', function () {
194
- return __awaiter(this, void 0, void 0, function* () {
195
- const kill = (yield Promise.resolve().then(() => __importStar(require('tree-kill')))).default;
196
- kill(child.pid, 'SIGINT');
197
- });
198
- });
199
- }
200
- // if stdio options is set to 'pipe', then
201
- // we should set up pipes:
202
- // process STDIN (read stream) => child STDIN (writeable)
203
- // child STDOUT => process STDOUT
204
- // child STDERR => process STDERR with additional filtering
205
- if (child.stdin) {
206
- debug('piping process STDIN into child STDIN');
207
- process_1.stdin.pipe(child.stdin);
208
- }
209
- if (child.stdout) {
210
- debug('piping child STDOUT to process STDOUT');
211
- child.stdout.pipe(process_1.stdout);
212
- }
213
- // if this is defined then we are manually piping for linux
214
- // to filter out the garbage
215
- if (child.stderr) {
216
- debug('piping child STDERR to process STDERR');
217
- child.stderr.on('data', (data) => {
218
- const str = data.toString();
219
- // if we have a callback and this explicitly returns
220
- // false then bail
221
- if (onStderrData && onStderrData(str)) {
222
- return;
223
- }
224
- // else pass it along!
225
- process_1.stderr.write(data);
226
- });
227
- }
228
- // https://github.com/cypress-io/cypress/issues/1841
229
- // https://github.com/cypress-io/cypress/issues/5241
230
- // In some versions of node, it will throw on windows
231
- // when you close the parent process after piping
232
- // into the child process. unpiping does not seem
233
- // to have any effect. so we're just catching the
234
- // error here and not doing anything.
235
- process_1.stdin.on('error', (err) => {
236
- if (['EPIPE', 'ENOTCONN'].includes(err.code)) {
237
- return;
238
- }
239
- throw err;
240
- });
241
- if (stdioOptions.detached) {
242
- child.unref();
208
+ // else pass it along!
209
+ process_1.stderr.write(data);
243
210
  }
244
211
  });
245
- };
246
- const spawnInXvfb = () => __awaiter(this, void 0, void 0, function* () {
247
- try {
248
- yield xvfb_1.default.start();
249
- const code = yield userFriendlySpawn();
250
- return code;
251
- }
252
- finally {
253
- yield xvfb_1.default.stop();
212
+ }
213
+ // https://github.com/cypress-io/cypress/issues/1841
214
+ // https://github.com/cypress-io/cypress/issues/5241
215
+ // In some versions of node, it will throw on windows
216
+ // when you close the parent process after piping
217
+ // into the child process. unpiping does not seem
218
+ // to have any effect. so we're just catching the
219
+ // error here and not doing anything.
220
+ process_1.stdin.on('error', (err) => {
221
+ if (['EPIPE', 'ENOTCONN'].includes(err.code)) {
222
+ return;
254
223
  }
224
+ throw err;
255
225
  });
256
- const userFriendlySpawn = (linuxWithDisplayEnv) => __awaiter(this, void 0, void 0, function* () {
257
- debug('spawning, should retry on display problem?', Boolean(linuxWithDisplayEnv));
258
- let brokenGtkDisplay = false;
259
- const overrides = {};
260
- if (linuxWithDisplayEnv) {
261
- lodash_1.default.extend(overrides, {
262
- electronLogging: true,
263
- onStderrData(str) {
264
- // if we receive a broken pipe anywhere
265
- // then we know that's why cypress exited early
266
- if (util_1.default.isBrokenGtkDisplay(str)) {
267
- brokenGtkDisplay = true;
268
- }
269
- },
270
- });
271
- }
272
- try {
273
- const code = yield spawn(overrides);
274
- if (code !== 0 && brokenGtkDisplay) {
275
- util_1.default.logBrokenGtkDisplayWarning();
276
- return spawnInXvfb();
277
- }
278
- return code;
279
- }
280
- catch (error) {
281
- // we can format and handle an error message from the code above
282
- // prevent wrapping error again by using "known: undefined" filter
283
- if (error.known === undefined) {
284
- const raiseErrorFn = (0, errors_1.throwFormErrorText)(errors_1.errors.unexpected);
285
- yield raiseErrorFn(error.message);
226
+ if (stdioOptions.detached) {
227
+ child.unref();
228
+ }
229
+ });
230
+ };
231
+ }
232
+ function spawnInXvfb(spawn) {
233
+ return __awaiter(this, void 0, void 0, function* () {
234
+ try {
235
+ yield xvfb_1.default.start();
236
+ const code = yield userFriendlySpawn(spawn);
237
+ return code;
238
+ }
239
+ finally {
240
+ yield xvfb_1.default.stop();
241
+ }
242
+ });
243
+ }
244
+ function userFriendlySpawn(spawn, linuxWithDisplayEnv) {
245
+ return __awaiter(this, void 0, void 0, function* () {
246
+ debug('spawning, should retry on display problem?', Boolean(linuxWithDisplayEnv));
247
+ let brokenGtkDisplay = false;
248
+ const overrides = {};
249
+ if (linuxWithDisplayEnv) {
250
+ lodash_1.default.extend(overrides, {
251
+ electronLogging: true,
252
+ onStderrData(str) {
253
+ // if we receive a broken pipe anywhere
254
+ // then we know that's why cypress exited early
255
+ if (util_1.default.isBrokenGtkDisplay(str)) {
256
+ brokenGtkDisplay = true;
286
257
  }
287
- throw error;
288
- }
258
+ },
289
259
  });
290
- if (needsXvfb) {
291
- return spawnInXvfb();
260
+ }
261
+ try {
262
+ const code = yield spawn(overrides);
263
+ if (code !== 0 && brokenGtkDisplay) {
264
+ util_1.default.logBrokenGtkDisplayWarning();
265
+ return spawnInXvfb(spawn);
292
266
  }
293
- // if we are on linux and there's already a DISPLAY
294
- // set, then we may need to rerun cypress after
295
- // spawning our own Xvfb server
296
- const linuxWithDisplayEnv = util_1.default.isPossibleLinuxWithIncorrectDisplay();
297
- return userFriendlySpawn(linuxWithDisplayEnv);
298
- });
299
- },
300
- };
301
- exports.default = spawnModule;
267
+ return code;
268
+ }
269
+ catch (error) {
270
+ // we can format and handle an error message from the code above
271
+ // prevent wrapping error again by using "known: undefined" filter
272
+ if (error.known === undefined) {
273
+ const raiseErrorFn = (0, errors_1.throwFormErrorText)(errors_1.errors.unexpected);
274
+ yield raiseErrorFn(error.message);
275
+ }
276
+ throw error;
277
+ }
278
+ });
279
+ }
280
+ function start(args_1) {
281
+ return __awaiter(this, arguments, void 0, function* (args, options = {}) {
282
+ var _a, _b, _c, _d;
283
+ let executable = util_1.default.getEnv('CYPRESS_RUN_BINARY') ?
284
+ path_1.default.resolve(util_1.default.getEnv('CYPRESS_RUN_BINARY')) :
285
+ state_1.default.getPathToExecutable(state_1.default.getBinaryDir());
286
+ // Always push cwd into the args
287
+ // which additionally acts as a signal to the
288
+ // binary that it was invoked through the NPM module
289
+ const baseArgs = args ? (typeof args === 'string' ? [args] : args) : [];
290
+ const decoratedArgs = baseArgs.concat([
291
+ '--cwd', process.cwd(),
292
+ '--userNodePath', process.execPath,
293
+ '--userNodeVersion', process.versions.node,
294
+ ]);
295
+ const needsXvfb = xvfb_1.default.isNeeded();
296
+ debug('needs to start own Xvfb?', needsXvfb);
297
+ const stdio = (_a = options.stdio) !== null && _a !== void 0 ? _a : getStdioStrategy(needsXvfb);
298
+ const dev = (_b = options.dev) !== null && _b !== void 0 ? _b : false;
299
+ const detached = (_c = options.detached) !== null && _c !== void 0 ? _c : false;
300
+ const env = (_d = options.env) !== null && _d !== void 0 ? _d : process.env;
301
+ const spawn = createSpawnFunction(executable, decoratedArgs, { stdio, dev, detached, env });
302
+ if (needsXvfb) {
303
+ return spawnInXvfb(spawn);
304
+ }
305
+ // if we are on linux and there's already a DISPLAY
306
+ // set, then we may need to rerun cypress after
307
+ // spawning our own Xvfb server
308
+ const linuxWithDisplayEnv = util_1.default.isPossibleLinuxWithIncorrectDisplay();
309
+ return userFriendlySpawn(spawn, linuxWithDisplayEnv);
310
+ });
311
+ }
package/dist/util.js CHANGED
@@ -159,7 +159,7 @@ const dequote = (str) => {
159
159
  return str;
160
160
  };
161
161
  const parseOpts = (opts) => {
162
- opts = lodash_1.default.pick(opts, 'autoCancelAfterFailures', 'browser', 'cachePath', 'cacheList', 'cacheClear', 'cachePrune', 'ciBuildId', 'ct', 'component', 'config', 'configFile', 'cypressVersion', 'destination', 'detached', 'dev', 'e2e', 'exit', 'env', 'force', 'global', 'group', 'headed', 'headless', 'inspect', 'inspectBrk', 'key', 'path', 'parallel', 'port', 'project', 'quiet', 'reporter', 'reporterOptions', 'record', 'runnerUi', 'runProject', 'spec', 'tag');
162
+ opts = lodash_1.default.pick(opts, 'autoCancelAfterFailures', 'browser', 'cachePath', 'cacheList', 'cacheClear', 'cachePrune', 'ciBuildId', 'ct', 'component', 'config', 'configFile', 'cypressVersion', 'destination', 'detached', 'dev', 'e2e', 'exit', 'env', 'force', 'global', 'group', 'headed', 'headless', 'inspect', 'inspectBrk', 'key', 'path', 'parallel', 'port', 'posixExitCodes', 'project', 'quiet', 'reporter', 'reporterOptions', 'record', 'runnerUi', 'runProject', 'spec', 'tag');
163
163
  if (opts.exit) {
164
164
  opts = lodash_1.default.omit(opts, 'exit');
165
165
  }
@@ -354,7 +354,6 @@ const util = {
354
354
  function _getRealArch() {
355
355
  return __awaiter(this, void 0, void 0, function* () {
356
356
  const osPlatform = os_1.default.platform();
357
- // eslint-disable-next-line no-restricted-syntax
358
357
  const osArch = os_1.default.arch();
359
358
  debug('detecting arch %o', { osPlatform, osArch });
360
359
  if (osArch === 'arm64')
@@ -375,7 +374,6 @@ const util = {
375
374
  if (['aarch64_be', 'aarch64', 'armv8b', 'armv8l'].includes(stdout))
376
375
  return 'arm64';
377
376
  }
378
- // eslint-disable-next-line no-restricted-syntax
379
377
  const pkgArch = (0, arch_1.default)();
380
378
  if (pkgArch === 'x86')
381
379
  return 'ia32';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cypress",
3
- "version": "15.3.0",
3
+ "version": "15.4.0",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "postinstall": "node dist/index.js --exec install",
@@ -106,6 +106,9 @@
106
106
  "require": "./svelte/dist/cypress-svelte.cjs.js"
107
107
  }
108
108
  },
109
+ "lint-staged": {
110
+ "**/*.{js,jsx,ts,tsx,json,vue}": "eslint --fix"
111
+ },
109
112
  "nx": {
110
113
  "targets": {
111
114
  "build-cli": {
@@ -124,8 +127,8 @@
124
127
  },
125
128
  "buildInfo": {
126
129
  "commitBranch": "develop",
127
- "commitSha": "556243acd780b95ad2ff7a1635fdd5cec56a97b6",
128
- "commitDate": "2025-09-23T16:51:17.000Z",
130
+ "commitSha": "9005a7b9ca793b903fcad167e1fb3f629b0b44bd",
131
+ "commitDate": "2025-10-07T18:50:02.000Z",
129
132
  "stable": true
130
133
  },
131
134
  "description": "Cypress is a next generation front end testing tool built for the modern web",
@@ -68,6 +68,10 @@ declare namespace CypressCommandLine {
68
68
  * Override default port
69
69
  */
70
70
  port: number
71
+ /**
72
+ * Use POSIX exit codes for error handling
73
+ */
74
+ posixExitCodes: boolean
71
75
  /**
72
76
  * Run quietly, using only the configured reporter
73
77
  */
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
1
  /// <reference path="./cypress-npm-api.d.ts" />
3
2
  /// <reference path="./cypress-eventemitter.d.ts" />
4
3
  /// <reference path="./cypress-type-helpers.d.ts" />
@@ -59,6 +58,9 @@ declare namespace Cypress {
59
58
  interface ObjectLike {
60
59
  [key: string]: any
61
60
  }
61
+ interface PromptOptions {
62
+ placeholders?: Record<string, string>
63
+ }
62
64
  interface Auth {
63
65
  username: string
64
66
  password: string
@@ -684,22 +686,22 @@ declare namespace Cypress {
684
686
  Keyboard: {
685
687
  defaults(options: Partial<KeyboardDefaultsOptions>): void
686
688
  Keys: {
687
- DOWN: 'ArrowDown',
688
- LEFT: 'ArrowLeft',
689
- RIGHT: 'ArrowRight',
690
- UP: 'ArrowUp',
691
- END: 'End',
692
- HOME: 'Home',
693
- PAGEDOWN: 'PageDown',
694
- PAGEUP: 'PageUp',
695
- ENTER: 'Enter',
696
- TAB: 'Tab',
697
- BACKSPACE: 'Backspace',
698
- SPACE: 'Space',
699
- DELETE: 'Delete',
700
- INSERT: 'Insert',
701
- ESC: 'Escape',
702
- },
689
+ DOWN: 'ArrowDown'
690
+ LEFT: 'ArrowLeft'
691
+ RIGHT: 'ArrowRight'
692
+ UP: 'ArrowUp'
693
+ END: 'End'
694
+ HOME: 'Home'
695
+ PAGEDOWN: 'PageDown'
696
+ PAGEUP: 'PageUp'
697
+ ENTER: 'Enter'
698
+ TAB: 'Tab'
699
+ BACKSPACE: 'Backspace'
700
+ SPACE: 'Space'
701
+ DELETE: 'Delete'
702
+ INSERT: 'Insert'
703
+ ESC: 'Escape'
704
+ }
703
705
  }
704
706
 
705
707
  /**
@@ -755,7 +757,7 @@ declare namespace Cypress {
755
757
  * Trigger action
756
758
  * @private
757
759
  */
758
- action: <T = (any[] | void) >(action: string, ...args: any[]) => T
760
+ action: <T = (any[] | void)>(action: string, ...args: any[]) => T
759
761
 
760
762
  /**
761
763
  * Load files
@@ -1691,7 +1693,7 @@ declare namespace Cypress {
1691
1693
  * cy.get('h1').should('equal', 'Example Domain')
1692
1694
  * })
1693
1695
  */
1694
- origin<T extends any>(urlOrDomain: string, fn: () => void): Chainable<T>
1696
+ origin<T>(urlOrDomain: string, fn: () => void): Chainable<T>
1695
1697
 
1696
1698
  /**
1697
1699
  * Enables running Cypress commands in a secondary origin.
@@ -1702,7 +1704,7 @@ declare namespace Cypress {
1702
1704
  * expect(foo).to.equal('foo')
1703
1705
  * })
1704
1706
  */
1705
- origin<T, S extends any>(urlOrDomain: string, options: {
1707
+ origin<T, S>(urlOrDomain: string, options: {
1706
1708
  args: T
1707
1709
  }, fn: (args: T) => void): Chainable<S>
1708
1710
 
@@ -1849,7 +1851,12 @@ declare namespace Cypress {
1849
1851
  * @see https://on.cypress.io/prevuntil
1850
1852
  */
1851
1853
  prevUntil<E extends Node = HTMLElement>(element: E | JQuery<E>, filter?: string, options?: Partial<Loggable & Timeoutable>): Chainable<JQuery<E>>
1852
-
1854
+ /**
1855
+ * An AI-powered command that generates Cypress commands from natural language test steps.
1856
+ *
1857
+ * @see https://on.cypress.io/prompt
1858
+ */
1859
+ prompt<T>(steps: string[], options?: PromptOptions): Chainable<T>
1853
1860
  /**
1854
1861
  * Read a file and yield its contents.
1855
1862
  *
@@ -2898,8 +2905,8 @@ declare namespace Cypress {
2898
2905
  }
2899
2906
 
2900
2907
  type RetryStrategyWithModeSpecs = RetryStrategy & {
2901
- openMode: boolean; // defaults to false
2902
- runMode: boolean; // defaults to true
2908
+ openMode: boolean // defaults to false
2909
+ runMode: boolean // defaults to true
2903
2910
  }
2904
2911
 
2905
2912
  type RetryStrategy =
@@ -2907,18 +2914,18 @@ declare namespace Cypress {
2907
2914
  | RetryStrategyDetectFlakeButAlwaysFailType
2908
2915
 
2909
2916
  interface RetryStrategyDetectFlakeAndPassOnThresholdType {
2910
- experimentalStrategy: "detect-flake-and-pass-on-threshold"
2917
+ experimentalStrategy: 'detect-flake-and-pass-on-threshold'
2911
2918
  experimentalOptions?: {
2912
- maxRetries: number; // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0
2913
- passesRequired: number; // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0 and <= maxRetries
2919
+ maxRetries: number // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0
2920
+ passesRequired: number // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0 and <= maxRetries
2914
2921
  }
2915
2922
  }
2916
2923
 
2917
2924
  interface RetryStrategyDetectFlakeButAlwaysFailType {
2918
- experimentalStrategy: "detect-flake-but-always-fail"
2925
+ experimentalStrategy: 'detect-flake-but-always-fail'
2919
2926
  experimentalOptions?: {
2920
- maxRetries: number; // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0
2921
- stopIfAnyPassed: boolean; // defaults to false if experimentalOptions is not provided
2927
+ maxRetries: number // defaults to 2 if experimentalOptions is not provided, must be a whole number > 0
2928
+ stopIfAnyPassed: boolean // defaults to false if experimentalOptions is not provided
2922
2929
  }
2923
2930
  }
2924
2931
  interface ResolvedConfigOptions<ComponentDevServerOpts = any> {
@@ -3140,7 +3147,7 @@ declare namespace Cypress {
3140
3147
  * @see https://on.cypress.io/experiments#Experimental-CSP-Allow-List
3141
3148
  * @default false
3142
3149
  */
3143
- experimentalCspAllowList: boolean | experimentalCspAllowedDirectives[],
3150
+ experimentalCspAllowList: boolean | experimentalCspAllowedDirectives[]
3144
3151
  /**
3145
3152
  * Allows listening to the `before:run`, `after:run`, `before:spec`, and `after:spec` events in the plugins file during interactive mode.
3146
3153
  * @default false
@@ -3272,6 +3279,11 @@ declare namespace Cypress {
3272
3279
  * @default false
3273
3280
  */
3274
3281
  experimentalOriginDependencies?: boolean
3282
+ /**
3283
+ * Enables support for `cy.prompt`, an AI-powered command that turns natural language steps into executable Cypress test code.
3284
+ * @default false
3285
+ */
3286
+ experimentalPromptCommand?: boolean
3275
3287
  }
3276
3288
 
3277
3289
  /**