cypress 9.7.0 → 10.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) 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-npm-api.d.ts +4 -10
  28. package/types/cypress.d.ts +172 -120
  29. package/types/minimatch/index.d.ts +15 -5
  30. package/vue/CHANGELOG.md +380 -0
  31. package/vue/README.md +678 -0
  32. package/vue/dist/cypress-vue.cjs.js +13535 -0
  33. package/vue/dist/cypress-vue.esm-bundler.js +13511 -0
  34. package/vue/dist/index.d.ts +56 -0
  35. package/vue/package.json +86 -0
  36. package/vue2/CHANGELOG.md +5 -0
  37. package/vue2/README.md +693 -0
  38. package/vue2/dist/cypress-vue2.browser.js +20191 -0
  39. package/vue2/dist/cypress-vue2.cjs.js +20188 -0
  40. package/vue2/dist/cypress-vue2.esm-bundler.js +20179 -0
  41. package/vue2/dist/index.d.ts +171 -0
  42. 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);