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