cypress 9.6.0 → 10.0.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.
Files changed (44) hide show
  1. package/index.mjs +15 -0
  2. package/lib/cli.js +72 -23
  3. package/lib/errors.js +16 -1
  4. package/lib/exec/open.js +45 -10
  5. package/lib/exec/run.js +17 -10
  6. package/lib/exec/shared.js +30 -9
  7. package/lib/exec/spawn.js +4 -0
  8. package/lib/exec/xvfb.js +1 -0
  9. package/lib/util.js +10 -3
  10. package/mount-utils/CHANGELOG.md +20 -0
  11. package/mount-utils/README.md +14 -0
  12. package/mount-utils/dist/index.d.ts +54 -0
  13. package/mount-utils/dist/index.js +134 -0
  14. package/mount-utils/package.json +31 -0
  15. package/package.json +39 -4
  16. package/react/CHANGELOG.md +373 -0
  17. package/react/README.md +414 -0
  18. package/react/dist/cypress-react.browser.js +497 -0
  19. package/react/dist/cypress-react.cjs.js +495 -0
  20. package/react/dist/cypress-react.esm-bundler.js +467 -0
  21. package/react/dist/getDisplayName.d.ts +8 -0
  22. package/react/dist/index.d.ts +2 -0
  23. package/react/dist/mount.d.ts +143 -0
  24. package/react/dist/mountHook.d.ts +11 -0
  25. package/react/package.json +105 -0
  26. package/types/bluebird/index.d.ts +18 -4
  27. package/types/cypress-eventemitter.d.ts +1 -1
  28. package/types/cypress-global-vars.d.ts +2 -2
  29. package/types/cypress-npm-api.d.ts +4 -10
  30. package/types/cypress.d.ts +180 -120
  31. package/types/minimatch/index.d.ts +15 -5
  32. package/vue/CHANGELOG.md +380 -0
  33. package/vue/README.md +678 -0
  34. package/vue/dist/cypress-vue.cjs.js +13535 -0
  35. package/vue/dist/cypress-vue.esm-bundler.js +13511 -0
  36. package/vue/dist/index.d.ts +56 -0
  37. package/vue/package.json +86 -0
  38. package/vue2/CHANGELOG.md +5 -0
  39. package/vue2/README.md +693 -0
  40. package/vue2/dist/cypress-vue2.browser.js +20191 -0
  41. package/vue2/dist/cypress-vue2.cjs.js +20188 -0
  42. package/vue2/dist/cypress-vue2.esm-bundler.js +20179 -0
  43. package/vue2/dist/index.d.ts +171 -0
  44. package/vue2/package.json +59 -0
@@ -0,0 +1,497 @@
1
+
2
+ /**
3
+ * @cypress/react v0.0.0-development
4
+ * (c) 2022 Cypress.io
5
+ * Released under the MIT License
6
+ */
7
+
8
+ var CypressReact = (function (exports, React, ReactDOM) {
9
+ 'use strict';
10
+
11
+ function _interopNamespace(e) {
12
+ if (e && e.__esModule) return e;
13
+ var n = Object.create(null);
14
+ if (e) {
15
+ Object.keys(e).forEach(function (k) {
16
+ if (k !== 'default') {
17
+ var d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: function () { return e[k]; }
21
+ });
22
+ }
23
+ });
24
+ }
25
+ n["default"] = e;
26
+ return Object.freeze(n);
27
+ }
28
+
29
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
30
+ var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM);
31
+
32
+ /*! *****************************************************************************
33
+ Copyright (c) Microsoft Corporation.
34
+
35
+ Permission to use, copy, modify, and/or distribute this software for any
36
+ purpose with or without fee is hereby granted.
37
+
38
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
39
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
40
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
41
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
42
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
43
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
44
+ PERFORMANCE OF THIS SOFTWARE.
45
+ ***************************************************************************** */
46
+
47
+ var __assign = function() {
48
+ __assign = Object.assign || function __assign(t) {
49
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
50
+ s = arguments[i];
51
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
52
+ }
53
+ return t;
54
+ };
55
+ return __assign.apply(this, arguments);
56
+ };
57
+
58
+ var cachedDisplayNames = new WeakMap();
59
+ /**
60
+ * Gets the display name of the component when possible.
61
+ * @param type {JSX} The type object returned from creating the react element.
62
+ * @param fallbackName {string} The alias, or fallback name to use when the name cannot be derived.
63
+ * @link https://github.com/facebook/react-devtools/blob/master/backend/getDisplayName.js
64
+ */
65
+ function getDisplayName(type, fallbackName) {
66
+ if (fallbackName === void 0) { fallbackName = 'Unknown'; }
67
+ var nameFromCache = cachedDisplayNames.get(type);
68
+ if (nameFromCache != null) {
69
+ return nameFromCache;
70
+ }
71
+ var displayName = null;
72
+ // The displayName property is not guaranteed to be a string.
73
+ // It's only safe to use for our purposes if it's a string.
74
+ // github.com/facebook/react-devtools/issues/803
75
+ if (typeof type.displayName === 'string') {
76
+ displayName = type.displayName;
77
+ }
78
+ if (!displayName) {
79
+ displayName = type.name || fallbackName;
80
+ }
81
+ // Facebook-specific hack to turn "Image [from Image.react]" into just "Image".
82
+ // We need displayName with module name for error reports but it clutters the DevTools.
83
+ var match = displayName.match(/^(.*) \[from (.*)\]$/);
84
+ if (match) {
85
+ var componentName = match[1];
86
+ var moduleName = match[2];
87
+ if (componentName && moduleName) {
88
+ if (moduleName === componentName ||
89
+ moduleName.startsWith(componentName + ".")) {
90
+ displayName = componentName;
91
+ }
92
+ }
93
+ }
94
+ try {
95
+ cachedDisplayNames.set(type, displayName);
96
+ }
97
+ catch (e) {
98
+ // do nothing
99
+ }
100
+ return displayName;
101
+ }
102
+
103
+ const ROOT_SELECTOR = '[data-cy-root]';
104
+ const getContainerEl = () => {
105
+ const el = document.querySelector(ROOT_SELECTOR);
106
+ if (el) {
107
+ return el;
108
+ }
109
+ throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please use the mount utils to mount it properly`);
110
+ };
111
+ /**
112
+ * Remove any style or extra link elements from the iframe placeholder
113
+ * left from any previous test
114
+ *
115
+ */
116
+ function cleanupStyles() {
117
+ const styles = document.body.querySelectorAll('[data-cy=injected-style-tag]');
118
+ styles.forEach((styleElement) => {
119
+ if (styleElement.parentElement) {
120
+ styleElement.parentElement.removeChild(styleElement);
121
+ }
122
+ });
123
+ const links = document.body.querySelectorAll('[data-cy=injected-stylesheet]');
124
+ links.forEach((link) => {
125
+ if (link.parentElement) {
126
+ link.parentElement.removeChild(link);
127
+ }
128
+ });
129
+ }
130
+ /**
131
+ * Insert links to external style resources.
132
+ */
133
+ function insertStylesheets(stylesheets, document, el) {
134
+ stylesheets.forEach((href) => {
135
+ const link = document.createElement('link');
136
+ link.type = 'text/css';
137
+ link.rel = 'stylesheet';
138
+ link.href = href;
139
+ link.dataset.cy = 'injected-stylesheet';
140
+ document.body.insertBefore(link, el);
141
+ });
142
+ }
143
+ /**
144
+ * Inserts a single stylesheet element
145
+ */
146
+ function insertStyles(styles, document, el) {
147
+ styles.forEach((style) => {
148
+ const styleElement = document.createElement('style');
149
+ styleElement.dataset.cy = 'injected-style-tag';
150
+ styleElement.appendChild(document.createTextNode(style));
151
+ document.body.insertBefore(styleElement, el);
152
+ });
153
+ }
154
+ function insertSingleCssFile(cssFilename, document, el, log) {
155
+ return cy.readFile(cssFilename, { log }).then((css) => {
156
+ const style = document.createElement('style');
157
+ style.appendChild(document.createTextNode(css));
158
+ document.body.insertBefore(style, el);
159
+ });
160
+ }
161
+ /**
162
+ * Reads the given CSS file from local file system
163
+ * and adds the loaded style text as an element.
164
+ */
165
+ function insertLocalCssFiles(cssFilenames, document, el, log) {
166
+ return Cypress.Promise.mapSeries(cssFilenames, (cssFilename) => {
167
+ return insertSingleCssFile(cssFilename, document, el, log);
168
+ });
169
+ }
170
+ /**
171
+ * Injects custom style text or CSS file or 3rd party style resources
172
+ * into the given document.
173
+ */
174
+ const injectStylesBeforeElement = (options, document, el) => {
175
+ if (!el)
176
+ return;
177
+ // first insert all stylesheets as Link elements
178
+ let stylesheets = [];
179
+ if (typeof options.stylesheet === 'string') {
180
+ stylesheets.push(options.stylesheet);
181
+ }
182
+ else if (Array.isArray(options.stylesheet)) {
183
+ stylesheets = stylesheets.concat(options.stylesheet);
184
+ }
185
+ if (typeof options.stylesheets === 'string') {
186
+ options.stylesheets = [options.stylesheets];
187
+ }
188
+ if (options.stylesheets) {
189
+ stylesheets = stylesheets.concat(options.stylesheets);
190
+ }
191
+ insertStylesheets(stylesheets, document, el);
192
+ // insert any styles as <style>...</style> elements
193
+ let styles = [];
194
+ if (typeof options.style === 'string') {
195
+ styles.push(options.style);
196
+ }
197
+ else if (Array.isArray(options.style)) {
198
+ styles = styles.concat(options.style);
199
+ }
200
+ if (typeof options.styles === 'string') {
201
+ styles.push(options.styles);
202
+ }
203
+ else if (Array.isArray(options.styles)) {
204
+ styles = styles.concat(options.styles);
205
+ }
206
+ insertStyles(styles, document, el);
207
+ // now load any css files by path and add their content
208
+ // as <style>...</style> elements
209
+ let cssFiles = [];
210
+ if (typeof options.cssFile === 'string') {
211
+ cssFiles.push(options.cssFile);
212
+ }
213
+ else if (Array.isArray(options.cssFile)) {
214
+ cssFiles = cssFiles.concat(options.cssFile);
215
+ }
216
+ if (typeof options.cssFiles === 'string') {
217
+ cssFiles.push(options.cssFiles);
218
+ }
219
+ else if (Array.isArray(options.cssFiles)) {
220
+ cssFiles = cssFiles.concat(options.cssFiles);
221
+ }
222
+ return insertLocalCssFiles(cssFiles, document, el, options.log);
223
+ };
224
+ function setupHooks(optionalCallback) {
225
+ // When running component specs, we cannot allow "cy.visit"
226
+ // because it will wipe out our preparation work, and does not make much sense
227
+ // thus we overwrite "cy.visit" to throw an error
228
+ Cypress.Commands.overwrite('visit', () => {
229
+ throw new Error('cy.visit from a component spec is not allowed');
230
+ });
231
+ // @ts-ignore
232
+ Cypress.on('test:before:run', () => {
233
+ optionalCallback === null || optionalCallback === void 0 ? void 0 : optionalCallback();
234
+ cleanupStyles();
235
+ });
236
+ }
237
+
238
+ /**
239
+ * Inject custom style text or CSS file or 3rd party style resources
240
+ */
241
+ var injectStyles = function (options) {
242
+ return function () {
243
+ var el = getContainerEl();
244
+ return injectStylesBeforeElement(options, document, el);
245
+ };
246
+ };
247
+ /**
248
+ * Mount a React component in a blank document; register it as an alias
249
+ * To access: use an alias or original component reference
250
+ * @function mount
251
+ * @param {React.ReactElement} jsx - component to mount
252
+ * @param {MountOptions} [options] - options, like alias, styles
253
+ * @see https://github.com/bahmutov/@cypress/react
254
+ * @see https://glebbahmutov.com/blog/my-vision-for-component-tests/
255
+ * @example
256
+ ```
257
+ import Hello from './hello.jsx'
258
+ import { mount } from '@cypress/react'
259
+ it('works', () => {
260
+ mount(<Hello onClick={cy.stub()} />)
261
+ // use Cypress commands
262
+ cy.contains('Hello').click()
263
+ })
264
+ ```
265
+ **/
266
+ var mount = function (jsx, options) {
267
+ if (options === void 0) { options = {}; }
268
+ return _mount('mount', jsx, options);
269
+ };
270
+ var lastMountedReactDom;
271
+ /**
272
+ * @see `mount`
273
+ * @param type The type of mount executed
274
+ * @param rerenderKey If specified, use the provided key rather than generating a new one
275
+ */
276
+ var _mount = function (type, jsx, options, rerenderKey) {
277
+ if (options === void 0) { options = {}; }
278
+ // Get the display name property via the component constructor
279
+ // @ts-ignore FIXME
280
+ var componentName = getDisplayName(jsx.type, options.alias);
281
+ var displayName = options.alias || componentName;
282
+ var jsxComponentName = "<" + componentName + " ... />";
283
+ var message = options.alias
284
+ ? jsxComponentName + " as \"" + options.alias + "\""
285
+ : jsxComponentName;
286
+ return cy
287
+ .then(injectStyles(options))
288
+ .then(function () {
289
+ var _a, _b, _c;
290
+ var reactDomToUse = options.ReactDom || ReactDOM__namespace;
291
+ lastMountedReactDom = reactDomToUse;
292
+ var el = getContainerEl();
293
+ if (!el) {
294
+ throw new Error([
295
+ "[@cypress/react] \uD83D\uDD25 Hmm, cannot find root element to mount the component. Searched for " + ROOT_SELECTOR,
296
+ ].join(' '));
297
+ }
298
+ var key = rerenderKey !== null && rerenderKey !== void 0 ? rerenderKey :
299
+ // @ts-ignore provide unique key to the the wrapped component to make sure we are rerendering between tests
300
+ (((_c = (_b = (_a = Cypress === null || Cypress === void 0 ? void 0 : Cypress.mocha) === null || _a === void 0 ? void 0 : _a.getRunner()) === null || _b === void 0 ? void 0 : _b.test) === null || _c === void 0 ? void 0 : _c.title) || '') + Math.random();
301
+ var props = {
302
+ key: key,
303
+ };
304
+ var reactComponent = React__namespace.createElement(options.strict ? React__namespace.StrictMode : React__namespace.Fragment, props, jsx);
305
+ // since we always surround the component with a fragment
306
+ // let's get back the original component
307
+ var userComponent = reactComponent.props.children;
308
+ reactDomToUse.render(reactComponent, el);
309
+ if (options.log !== false) {
310
+ Cypress.log({
311
+ name: type,
312
+ type: 'parent',
313
+ message: [message],
314
+ // @ts-ignore
315
+ $el: el.children.item(0),
316
+ consoleProps: function () {
317
+ return {
318
+ // @ts-ignore protect the use of jsx functional components use ReactNode
319
+ props: jsx.props,
320
+ description: type === 'mount' ? 'Mounts React component' : 'Rerenders mounted React component',
321
+ home: 'https://github.com/cypress-io/cypress',
322
+ };
323
+ },
324
+ }).snapshot('mounted').end();
325
+ }
326
+ return (
327
+ // Separate alias and returned value. Alias returns the component only, and the thenable returns the additional functions
328
+ cy.wrap(userComponent, { log: false })
329
+ .as(displayName)
330
+ .then(function () {
331
+ return cy.wrap({
332
+ component: userComponent,
333
+ rerender: function (newComponent) { return _mount('rerender', newComponent, options, key); },
334
+ unmount: function () { return _unmount({ boundComponentMessage: jsxComponentName, log: true }); },
335
+ }, { log: false });
336
+ })
337
+ // by waiting, we delaying test execution for the next tick of event loop
338
+ // and letting hooks and component lifecycle methods to execute mount
339
+ // https://github.com/bahmutov/cypress-react-unit-test/issues/200
340
+ .wait(0, { log: false }));
341
+ // Bluebird types are terrible. I don't think the return type can be carried without this cast
342
+ });
343
+ };
344
+ /**
345
+ * Removes the mounted component. Notice this command automatically
346
+ * queues up the `unmount` into Cypress chain, thus you don't need `.then`
347
+ * to call it.
348
+ * @see https://github.com/cypress-io/cypress/tree/develop/npm/react/cypress/component/basic/unmount
349
+ * @example
350
+ ```
351
+ import { mount, unmount } from '@cypress/react'
352
+ it('works', () => {
353
+ mount(...)
354
+ // interact with the component using Cypress commands
355
+ // whenever you want to unmount
356
+ unmount()
357
+ })
358
+ ```
359
+ */
360
+ // @ts-ignore
361
+ var unmount = function (options) {
362
+ if (options === void 0) { options = { log: true }; }
363
+ return _unmount(options);
364
+ };
365
+ var _unmount = function (options) {
366
+ return cy.then(function () {
367
+ return cy.get(ROOT_SELECTOR, { log: false }).then(function ($el) {
368
+ var _a;
369
+ if (lastMountedReactDom) {
370
+ var wasUnmounted = lastMountedReactDom.unmountComponentAtNode($el[0]);
371
+ if (wasUnmounted && options.log) {
372
+ Cypress.log({
373
+ name: 'unmount',
374
+ type: 'parent',
375
+ message: [(_a = options.boundComponentMessage) !== null && _a !== void 0 ? _a : 'Unmounted component'],
376
+ consoleProps: function () {
377
+ return {
378
+ description: 'Unmounts React component',
379
+ parent: $el[0],
380
+ home: 'https://github.com/cypress-io/cypress',
381
+ };
382
+ },
383
+ });
384
+ }
385
+ }
386
+ });
387
+ });
388
+ };
389
+ // Cleanup before each run
390
+ // NOTE: we cannot use unmount here because
391
+ // we are not in the context of a test
392
+ var preMountCleanup = function () {
393
+ var el = getContainerEl();
394
+ if (el && lastMountedReactDom) {
395
+ lastMountedReactDom.unmountComponentAtNode(el);
396
+ }
397
+ };
398
+ /**
399
+ * Creates new instance of `mount` function with default options
400
+ * @function createMount
401
+ * @param {MountOptions} [defaultOptions] - defaultOptions for returned `mount` function
402
+ * @returns new instance of `mount` with assigned options
403
+ * @example
404
+ * ```
405
+ * import Hello from './hello.jsx'
406
+ * import { createMount } from '@cypress/react'
407
+ *
408
+ * const mount = createMount({ strict: true, cssFile: 'path/to/any/css/file.css' })
409
+ *
410
+ * it('works', () => {
411
+ * mount(<Hello />)
412
+ * // use Cypress commands
413
+ * cy.get('button').should('have.css', 'color', 'rgb(124, 12, 109)')
414
+ * })
415
+ ```
416
+ **/
417
+ var createMount = function (defaultOptions) {
418
+ return function (element, options) {
419
+ return mount(element, __assign(__assign({}, defaultOptions), options));
420
+ };
421
+ };
422
+ // it is required to unmount component in beforeEach hook in order to provide a clean state inside test
423
+ // because `mount` can be called after some preparation that can side effect unmount
424
+ // @see npm/react/cypress/component/advanced/set-timeout-example/loading-indicator-spec.js
425
+ setupHooks(preMountCleanup);
426
+
427
+ // mounting hooks inside a test component mostly copied from
428
+ // https://github.com/testing-library/react-hooks-testing-library/blob/master/src/pure.js
429
+ function resultContainer() {
430
+ var value = null;
431
+ var error = null;
432
+ var resolvers = [];
433
+ var result = {
434
+ get current() {
435
+ if (error) {
436
+ throw error;
437
+ }
438
+ return value;
439
+ },
440
+ get error() {
441
+ return error;
442
+ },
443
+ };
444
+ var updateResult = function (val, err) {
445
+ if (err === void 0) { err = null; }
446
+ value = val;
447
+ error = err;
448
+ resolvers.splice(0, resolvers.length).forEach(function (resolve) { return resolve(); });
449
+ };
450
+ return {
451
+ result: result,
452
+ addResolver: function (resolver) {
453
+ resolvers.push(resolver);
454
+ },
455
+ setValue: function (val) { return updateResult(val); },
456
+ setError: function (err) { return updateResult(undefined, err); },
457
+ };
458
+ }
459
+ function TestHook(_a) {
460
+ var callback = _a.callback, onError = _a.onError, children = _a.children;
461
+ try {
462
+ children(callback());
463
+ }
464
+ catch (err) {
465
+ if ('then' in err) {
466
+ throw err;
467
+ }
468
+ else {
469
+ onError(err);
470
+ }
471
+ }
472
+ return null;
473
+ }
474
+ /**
475
+ * Mounts a React hook function in a test component for testing.
476
+ *
477
+ */
478
+ var mountHook = function (hookFn) {
479
+ var _a = resultContainer(), result = _a.result, setValue = _a.setValue, setError = _a.setError;
480
+ var componentTest = React__namespace.createElement(TestHook, {
481
+ callback: hookFn,
482
+ onError: setError,
483
+ children: setValue,
484
+ });
485
+ return mount(componentTest).then(function () { return result; });
486
+ };
487
+
488
+ exports.createMount = createMount;
489
+ exports.mount = mount;
490
+ exports.mountHook = mountHook;
491
+ exports.unmount = unmount;
492
+
493
+ Object.defineProperty(exports, '__esModule', { value: true });
494
+
495
+ return exports;
496
+
497
+ })({}, React, ReactDOM);