cypress 10.10.0 → 11.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. package/angular/CHANGELOG.md +27 -0
  2. package/angular/dist/index.d.ts +124 -1
  3. package/angular/dist/index.js +59 -59
  4. package/lib/cli.js +15 -1
  5. package/lib/tasks/download.js +3 -7
  6. package/lib/util.js +2 -2
  7. package/mount-utils/CHANGELOG.md +7 -63
  8. package/mount-utils/README.md +5 -23
  9. package/mount-utils/dist/index.d.ts +25 -39
  10. package/mount-utils/dist/index.js +33 -112
  11. package/mount-utils/package.json +1 -0
  12. package/package.json +5 -4
  13. package/react/CHANGELOG.md +12 -55
  14. package/react/README.md +2 -22
  15. package/react/dist/cypress-react.cjs.js +92 -219
  16. package/react/dist/cypress-react.esm-bundler.js +92 -220
  17. package/react/dist/index.d.ts +111 -4
  18. package/react18/CHANGELOG.md +6 -106
  19. package/react18/dist/cypress-react.cjs.js +117 -180
  20. package/react18/dist/cypress-react.esm-bundler.js +103 -167
  21. package/react18/dist/index.d.ts +78 -6
  22. package/react18/package.json +1 -0
  23. package/svelte/CHANGELOG.md +20 -0
  24. package/svelte/dist/cypress-svelte.cjs.js +19 -114
  25. package/svelte/dist/cypress-svelte.esm-bundler.js +19 -114
  26. package/svelte/dist/index.d.ts +201 -1
  27. package/types/cypress-npm-api.d.ts +1 -1
  28. package/types/cypress.d.ts +43 -21
  29. package/vue/CHANGELOG.md +13 -101
  30. package/vue/README.md +4 -8
  31. package/vue/dist/cypress-vue.cjs.js +70 -153
  32. package/vue/dist/cypress-vue.esm-bundler.js +70 -153
  33. package/vue/dist/index.d.ts +1352 -104
  34. package/vue/package.json +1 -1
  35. package/vue2/CHANGELOG.md +15 -50
  36. package/vue2/README.md +3 -7
  37. package/vue2/dist/cypress-vue2.cjs.js +87 -211
  38. package/vue2/dist/cypress-vue2.esm-bundler.js +86 -210
  39. package/vue2/dist/index.d.ts +341 -172
  40. package/vue2/package.json +1 -3
  41. package/angular/dist/mount.d.ts +0 -112
  42. package/react/dist/createMount.d.ts +0 -31
  43. package/react/dist/getDisplayName.d.ts +0 -8
  44. package/react/dist/mount.d.ts +0 -8
  45. package/react/dist/mountHook.d.ts +0 -12
  46. package/react/dist/types.d.ts +0 -45
  47. package/svelte/dist/mount.d.ts +0 -30
  48. package/vue/dist/@vue/test-utils/baseWrapper.d.ts +0 -63
  49. package/vue/dist/@vue/test-utils/components/RouterLinkStub.d.ts +0 -21
  50. package/vue/dist/@vue/test-utils/config.d.ts +0 -30
  51. package/vue/dist/@vue/test-utils/constants/dom-events.d.ts +0 -900
  52. package/vue/dist/@vue/test-utils/createDomEvent.d.ts +0 -9
  53. package/vue/dist/@vue/test-utils/domWrapper.d.ts +0 -18
  54. package/vue/dist/@vue/test-utils/emit.d.ts +0 -5
  55. package/vue/dist/@vue/test-utils/errorWrapper.d.ts +0 -1
  56. package/vue/dist/@vue/test-utils/index.d.ts +0 -11
  57. package/vue/dist/@vue/test-utils/interfaces/wrapperLike.d.ts +0 -56
  58. package/vue/dist/@vue/test-utils/mount.d.ts +0 -35
  59. package/vue/dist/@vue/test-utils/stubs.d.ts +0 -22
  60. package/vue/dist/@vue/test-utils/types.d.ts +0 -125
  61. package/vue/dist/@vue/test-utils/utils/autoUnmount.d.ts +0 -5
  62. package/vue/dist/@vue/test-utils/utils/compileSlots.d.ts +0 -2
  63. package/vue/dist/@vue/test-utils/utils/componentName.d.ts +0 -4
  64. package/vue/dist/@vue/test-utils/utils/find.d.ts +0 -10
  65. package/vue/dist/@vue/test-utils/utils/flushPromises.d.ts +0 -1
  66. package/vue/dist/@vue/test-utils/utils/getRootNodes.d.ts +0 -2
  67. package/vue/dist/@vue/test-utils/utils/isElement.d.ts +0 -1
  68. package/vue/dist/@vue/test-utils/utils/isElementVisible.d.ts +0 -6
  69. package/vue/dist/@vue/test-utils/utils/matchName.d.ts +0 -1
  70. package/vue/dist/@vue/test-utils/utils/stringifyNode.d.ts +0 -1
  71. package/vue/dist/@vue/test-utils/utils/vueCompatSupport.d.ts +0 -8
  72. package/vue/dist/@vue/test-utils/utils/vueShared.d.ts +0 -3
  73. package/vue/dist/@vue/test-utils/utils.d.ts +0 -13
  74. package/vue/dist/@vue/test-utils/vueWrapper.d.ts +0 -35
  75. package/vue/dist/@vue/test-utils/wrapperFactory.d.ts +0 -14
package/vue/README.md CHANGED
@@ -34,23 +34,19 @@ describe('HelloWorld component', () => {
34
34
 
35
35
  Look at the examples in [cypress/component](cypress/component) folder. Here is the list of examples showing various testing scenarios.
36
36
 
37
- ### Options
37
+ ### Styles
38
38
 
39
- You can pass additional styles, css files and external stylesheets to load, see [docs/styles.md](./docs/styles.md) for full list.
39
+ One option for styling your components is to import stylesheets into your test file. See [docs/styles.md](./docs/styles.md) for full list of options.
40
40
 
41
41
  ```js
42
42
  import Todo from './Todo.vue'
43
+ import '../styles/main.css'
43
44
  const todo = {
44
45
  id: '123',
45
46
  title: 'Write more tests',
46
47
  }
47
48
 
48
- mount(Todo, {
49
- propsData: { todo },
50
- stylesheets: [
51
- 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css',
52
- ],
53
- })
49
+ mount(Todo, { props: { todo } })
54
50
  ```
55
51
 
56
52
  ### Global Vue Options
@@ -59,6 +59,11 @@ function __rest(s, e) {
59
59
  }
60
60
 
61
61
  const ROOT_SELECTOR = '[data-cy-root]';
62
+ /**
63
+ * Gets the root element used to mount the component.
64
+ * @returns {HTMLElement} The root element
65
+ * @throws {Error} If the root element is not found
66
+ */
62
67
  const getContainerEl = () => {
63
68
  const el = document.querySelector(ROOT_SELECTOR);
64
69
  if (el) {
@@ -66,122 +71,19 @@ const getContainerEl = () => {
66
71
  }
67
72
  throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please add a root element with data-cy-root attribute to your "component-index.html" file so that Cypress can attach your component to the DOM.`);
68
73
  };
69
- /**
70
- * Remove any style or extra link elements from the iframe placeholder
71
- * left from any previous test
72
- *
73
- */
74
- function cleanupStyles() {
75
- const styles = document.body.querySelectorAll('[data-cy=injected-style-tag]');
76
- styles.forEach((styleElement) => {
77
- if (styleElement.parentElement) {
78
- styleElement.parentElement.removeChild(styleElement);
79
- }
80
- });
81
- const links = document.body.querySelectorAll('[data-cy=injected-stylesheet]');
82
- links.forEach((link) => {
83
- if (link.parentElement) {
84
- link.parentElement.removeChild(link);
74
+ function checkForRemovedStyleOptions(mountingOptions) {
75
+ for (const key of ['cssFile', 'cssFiles', 'style', 'styles', 'stylesheet', 'stylesheets']) {
76
+ if (mountingOptions[key]) {
77
+ Cypress.utils.throwErrByPath('mount.removed_style_mounting_options', key);
85
78
  }
86
- });
87
- }
88
- /**
89
- * Insert links to external style resources.
90
- */
91
- function insertStylesheets(stylesheets, document, el) {
92
- stylesheets.forEach((href) => {
93
- const link = document.createElement('link');
94
- link.type = 'text/css';
95
- link.rel = 'stylesheet';
96
- link.href = href;
97
- link.dataset.cy = 'injected-stylesheet';
98
- document.body.insertBefore(link, el);
99
- });
100
- }
101
- /**
102
- * Inserts a single stylesheet element
103
- */
104
- function insertStyles(styles, document, el) {
105
- styles.forEach((style) => {
106
- const styleElement = document.createElement('style');
107
- styleElement.dataset.cy = 'injected-style-tag';
108
- styleElement.appendChild(document.createTextNode(style));
109
- document.body.insertBefore(styleElement, el);
110
- });
111
- }
112
- function insertSingleCssFile(cssFilename, document, el, log) {
113
- return cy.readFile(cssFilename, { log }).then((css) => {
114
- const style = document.createElement('style');
115
- style.appendChild(document.createTextNode(css));
116
- document.body.insertBefore(style, el);
117
- });
118
- }
119
- /**
120
- * Reads the given CSS file from local file system
121
- * and adds the loaded style text as an element.
122
- */
123
- function insertLocalCssFiles(cssFilenames, document, el, log) {
124
- return Cypress.Promise.mapSeries(cssFilenames, (cssFilename) => {
125
- return insertSingleCssFile(cssFilename, document, el, log);
126
- });
79
+ }
127
80
  }
128
81
  /**
129
- * Injects custom style text or CSS file or 3rd party style resources
130
- * into the given document.
82
+ * Utility function to register CT side effects and run cleanup code during the "test:before:run" Cypress hook
83
+ * @param optionalCallback Callback to be called before the next test runs
131
84
  */
132
- const injectStylesBeforeElement = (options, document, el) => {
133
- if (!el)
134
- return;
135
- // first insert all stylesheets as Link elements
136
- let stylesheets = [];
137
- if (typeof options.stylesheet === 'string') {
138
- stylesheets.push(options.stylesheet);
139
- }
140
- else if (Array.isArray(options.stylesheet)) {
141
- stylesheets = stylesheets.concat(options.stylesheet);
142
- }
143
- if (typeof options.stylesheets === 'string') {
144
- options.stylesheets = [options.stylesheets];
145
- }
146
- if (options.stylesheets) {
147
- stylesheets = stylesheets.concat(options.stylesheets);
148
- }
149
- insertStylesheets(stylesheets, document, el);
150
- // insert any styles as <style>...</style> elements
151
- let styles = [];
152
- if (typeof options.style === 'string') {
153
- styles.push(options.style);
154
- }
155
- else if (Array.isArray(options.style)) {
156
- styles = styles.concat(options.style);
157
- }
158
- if (typeof options.styles === 'string') {
159
- styles.push(options.styles);
160
- }
161
- else if (Array.isArray(options.styles)) {
162
- styles = styles.concat(options.styles);
163
- }
164
- insertStyles(styles, document, el);
165
- // now load any css files by path and add their content
166
- // as <style>...</style> elements
167
- let cssFiles = [];
168
- if (typeof options.cssFile === 'string') {
169
- cssFiles.push(options.cssFile);
170
- }
171
- else if (Array.isArray(options.cssFile)) {
172
- cssFiles = cssFiles.concat(options.cssFile);
173
- }
174
- if (typeof options.cssFiles === 'string') {
175
- cssFiles.push(options.cssFiles);
176
- }
177
- else if (Array.isArray(options.cssFiles)) {
178
- cssFiles = cssFiles.concat(options.cssFiles);
179
- }
180
- return insertLocalCssFiles(cssFiles, document, el, options.log);
181
- };
182
85
  function setupHooks(optionalCallback) {
183
- // Consumed by the framework "mount" libs. A user might register their own mount in the scaffolded 'commands.js'
184
- // file that is imported by e2e and component support files by default. We don't want CT side effects to run when e2e
86
+ // We don't want CT side effects to run when e2e
185
87
  // testing so we early return.
186
88
  // System test to verify CT side effects do not pollute e2e: system-tests/test/e2e_with_mount_import_spec.ts
187
89
  if (Cypress.testingType !== 'component') {
@@ -196,7 +98,6 @@ function setupHooks(optionalCallback) {
196
98
  // @ts-ignore
197
99
  Cypress.on('test:before:run', () => {
198
100
  optionalCallback === null || optionalCallback === void 0 ? void 0 : optionalCallback();
199
- cleanupStyles();
200
101
  });
201
102
  }
202
103
 
@@ -13792,42 +13693,40 @@ mount: VTUmount,
13792
13693
  // available on the `VueTestUtils` import.
13793
13694
  shallowMount } = _VueTestUtils, VueTestUtils = __rest(_VueTestUtils, ["mount", "shallowMount"]);
13794
13695
  const DEFAULT_COMP_NAME = 'unknown';
13795
- Cypress.on('run:start', () => {
13796
- // `mount` is designed to work with component testing only.
13797
- // it assumes ROOT_SELECTOR exists, which is not the case in e2e.
13798
- // if the user registers a custom command that imports `cypress/vue`,
13799
- // this event will be registered and cause an error when the user
13800
- // launches e2e (since it's common to use Cypress for both CT and E2E.
13801
- // https://github.com/cypress-io/cypress/issues/17438
13802
- if (Cypress.testingType !== 'component') {
13803
- return;
13804
- }
13805
- Cypress.on('test:before:run', () => {
13806
- var _a;
13807
- (_a = Cypress.vueWrapper) === null || _a === void 0 ? void 0 : _a.unmount();
13808
- const el = getContainerEl();
13809
- el.innerHTML = '';
13810
- });
13811
- });
13812
- // implementation
13696
+ const VUE_ROOT = '__cy_vue_root';
13697
+ const cleanup = () => {
13698
+ var _a;
13699
+ (_a = Cypress.vueWrapper) === null || _a === void 0 ? void 0 : _a.unmount();
13700
+ Cypress.$(`#${VUE_ROOT}`).remove();
13701
+ Cypress.vueWrapper = null;
13702
+ Cypress.vue = null;
13703
+ };
13704
+ /**
13705
+ * Mounts a component and returns an object containing the component and VueWrapper
13706
+ * @param componentOptions
13707
+ * @param options
13708
+ * @returns {Cypress.Chainable<{wrapper: VueWrapper<T>, component: T}>}
13709
+ * @see {@link https://on.cypress.io/mounting-vue} for more details.
13710
+ * @example
13711
+ * import { mount } from '@cypress/vue'
13712
+ * import { Stepper } from './Stepper.vue'
13713
+ *
13714
+ * it('mounts', () => {
13715
+ * cy.mount(Stepper)
13716
+ * cy.get('[data-cy=increment]').click()
13717
+ * cy.get('[data-cy=counter]').should('have.text', '1')
13718
+ * })
13719
+ */
13813
13720
  function mount(componentOptions, options = {}) {
13814
- // TODO: get the real displayName and props from VTU shallowMount
13815
- const componentName = getComponentDisplayName(componentOptions);
13816
- const message = `<${componentName} ... />`;
13817
- let logInstance;
13721
+ checkForRemovedStyleOptions(options);
13722
+ // Remove last mounted component if cy.mount is called more than once in a test
13723
+ cleanup();
13818
13724
  // then wait for cypress to load
13819
13725
  return cy.then(() => {
13820
13726
  var _a, _b;
13821
- if (options.log !== false) {
13822
- logInstance = Cypress.log({
13823
- name: 'mount',
13824
- message: [message],
13825
- });
13826
- }
13827
13727
  // @ts-ignore
13828
13728
  const document = cy.state('document');
13829
13729
  const el = getContainerEl();
13830
- injectStylesBeforeElement(options, document, el);
13831
13730
  // merge the extensions with global
13832
13731
  if (options.extensions) {
13833
13732
  options.extensions.plugins = (_a = []) === null || _a === void 0 ? void 0 : _a.concat(options.extensions.plugins || [], options.extensions.use || []);
@@ -13835,29 +13734,43 @@ function mount(componentOptions, options = {}) {
13835
13734
  options.global = Object.assign(Object.assign({}, options.extensions), options.global);
13836
13735
  }
13837
13736
  const componentNode = document.createElement('div');
13838
- componentNode.id = '__cy_vue_root';
13737
+ componentNode.id = VUE_ROOT;
13839
13738
  el.append(componentNode);
13840
13739
  // mount the component using VTU and return the wrapper in Cypress.VueWrapper
13841
13740
  const wrapper = VTUmount(componentOptions, Object.assign({ attachTo: componentNode }, options));
13842
13741
  Cypress.vueWrapper = wrapper;
13843
13742
  Cypress.vue = wrapper.vm;
13844
13743
  return cy
13845
- .wrap(wrapper, { log: false })
13846
13744
  .wait(1, { log: false })
13847
13745
  .then(() => {
13848
- if (logInstance) {
13849
- logInstance.snapshot('mounted');
13850
- logInstance.end();
13746
+ if (options.log !== false) {
13747
+ // TODO: get the real displayName and props from VTU shallowMount
13748
+ const message = `<${getComponentDisplayName(componentOptions)} ... />`;
13749
+ Cypress.log({
13750
+ name: 'mount',
13751
+ message: [message],
13752
+ });
13851
13753
  }
13852
- // by returning undefined we keep the previous subject
13853
- // which is the mounted component
13854
- return undefined;
13754
+ const returnVal = {
13755
+ wrapper,
13756
+ component: wrapper.vm,
13757
+ };
13758
+ return new Proxy(Object.create(returnVal), {
13759
+ get(obj, prop) {
13760
+ // throw an error if it looks like the caller is trying to call a method on the VueWrapper that was originally returned
13761
+ if (Reflect.get(wrapper, prop)) {
13762
+ // @ts-expect-error - internal API
13763
+ Cypress.utils.throwErrByPath('mount.vue_yielded_value');
13764
+ }
13765
+ return Reflect.get(obj, prop);
13766
+ },
13767
+ });
13855
13768
  });
13856
13769
  });
13857
13770
  }
13858
13771
  /**
13859
- * Extract the compoennt name from the object passed to mount
13860
- * @param componentOptions the compoennt passed to mount
13772
+ * Extract the component name from the object passed to mount
13773
+ * @param componentOptions the component passed to mount
13861
13774
  * @returns name of the component
13862
13775
  */
13863
13776
  function getComponentDisplayName(componentOptions) {
@@ -13880,10 +13793,14 @@ function getComponentDisplayName(componentOptions) {
13880
13793
  * @example
13881
13794
  * import {mountCallback} from '@cypress/vue'
13882
13795
  * beforeEach(mountVue(component, options))
13796
+ *
13797
+ * Removed as of Cypress 11.0.0.
13798
+ * @see https://on.cypress.io/migration-11-0-0-component-testing-updates
13883
13799
  */
13884
13800
  function mountCallback(component, options = {}) {
13885
13801
  return () => {
13886
- return mount(component, options);
13802
+ // @ts-expect-error - undocumented API
13803
+ Cypress.utils.throwErrByPath('mount.mount_callback');
13887
13804
  };
13888
13805
  }
13889
13806
  // Side effects from "import { mount } from '@cypress/<my-framework>'" are annoying, we should avoid doing this
@@ -13894,7 +13811,7 @@ function mountCallback(component, options = {}) {
13894
13811
  // import { registerCT } from 'cypress/<my-framework>'
13895
13812
  // registerCT()
13896
13813
  // Note: This would be a breaking change
13897
- setupHooks();
13814
+ setupHooks(cleanup);
13898
13815
 
13899
13816
  exports.VueTestUtils = VueTestUtils;
13900
13817
  exports.mount = mount;
@@ -36,6 +36,11 @@ function __rest(s, e) {
36
36
  }
37
37
 
38
38
  const ROOT_SELECTOR = '[data-cy-root]';
39
+ /**
40
+ * Gets the root element used to mount the component.
41
+ * @returns {HTMLElement} The root element
42
+ * @throws {Error} If the root element is not found
43
+ */
39
44
  const getContainerEl = () => {
40
45
  const el = document.querySelector(ROOT_SELECTOR);
41
46
  if (el) {
@@ -43,122 +48,19 @@ const getContainerEl = () => {
43
48
  }
44
49
  throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please add a root element with data-cy-root attribute to your "component-index.html" file so that Cypress can attach your component to the DOM.`);
45
50
  };
46
- /**
47
- * Remove any style or extra link elements from the iframe placeholder
48
- * left from any previous test
49
- *
50
- */
51
- function cleanupStyles() {
52
- const styles = document.body.querySelectorAll('[data-cy=injected-style-tag]');
53
- styles.forEach((styleElement) => {
54
- if (styleElement.parentElement) {
55
- styleElement.parentElement.removeChild(styleElement);
56
- }
57
- });
58
- const links = document.body.querySelectorAll('[data-cy=injected-stylesheet]');
59
- links.forEach((link) => {
60
- if (link.parentElement) {
61
- link.parentElement.removeChild(link);
51
+ function checkForRemovedStyleOptions(mountingOptions) {
52
+ for (const key of ['cssFile', 'cssFiles', 'style', 'styles', 'stylesheet', 'stylesheets']) {
53
+ if (mountingOptions[key]) {
54
+ Cypress.utils.throwErrByPath('mount.removed_style_mounting_options', key);
62
55
  }
63
- });
64
- }
65
- /**
66
- * Insert links to external style resources.
67
- */
68
- function insertStylesheets(stylesheets, document, el) {
69
- stylesheets.forEach((href) => {
70
- const link = document.createElement('link');
71
- link.type = 'text/css';
72
- link.rel = 'stylesheet';
73
- link.href = href;
74
- link.dataset.cy = 'injected-stylesheet';
75
- document.body.insertBefore(link, el);
76
- });
77
- }
78
- /**
79
- * Inserts a single stylesheet element
80
- */
81
- function insertStyles(styles, document, el) {
82
- styles.forEach((style) => {
83
- const styleElement = document.createElement('style');
84
- styleElement.dataset.cy = 'injected-style-tag';
85
- styleElement.appendChild(document.createTextNode(style));
86
- document.body.insertBefore(styleElement, el);
87
- });
88
- }
89
- function insertSingleCssFile(cssFilename, document, el, log) {
90
- return cy.readFile(cssFilename, { log }).then((css) => {
91
- const style = document.createElement('style');
92
- style.appendChild(document.createTextNode(css));
93
- document.body.insertBefore(style, el);
94
- });
95
- }
96
- /**
97
- * Reads the given CSS file from local file system
98
- * and adds the loaded style text as an element.
99
- */
100
- function insertLocalCssFiles(cssFilenames, document, el, log) {
101
- return Cypress.Promise.mapSeries(cssFilenames, (cssFilename) => {
102
- return insertSingleCssFile(cssFilename, document, el, log);
103
- });
56
+ }
104
57
  }
105
58
  /**
106
- * Injects custom style text or CSS file or 3rd party style resources
107
- * into the given document.
59
+ * Utility function to register CT side effects and run cleanup code during the "test:before:run" Cypress hook
60
+ * @param optionalCallback Callback to be called before the next test runs
108
61
  */
109
- const injectStylesBeforeElement = (options, document, el) => {
110
- if (!el)
111
- return;
112
- // first insert all stylesheets as Link elements
113
- let stylesheets = [];
114
- if (typeof options.stylesheet === 'string') {
115
- stylesheets.push(options.stylesheet);
116
- }
117
- else if (Array.isArray(options.stylesheet)) {
118
- stylesheets = stylesheets.concat(options.stylesheet);
119
- }
120
- if (typeof options.stylesheets === 'string') {
121
- options.stylesheets = [options.stylesheets];
122
- }
123
- if (options.stylesheets) {
124
- stylesheets = stylesheets.concat(options.stylesheets);
125
- }
126
- insertStylesheets(stylesheets, document, el);
127
- // insert any styles as <style>...</style> elements
128
- let styles = [];
129
- if (typeof options.style === 'string') {
130
- styles.push(options.style);
131
- }
132
- else if (Array.isArray(options.style)) {
133
- styles = styles.concat(options.style);
134
- }
135
- if (typeof options.styles === 'string') {
136
- styles.push(options.styles);
137
- }
138
- else if (Array.isArray(options.styles)) {
139
- styles = styles.concat(options.styles);
140
- }
141
- insertStyles(styles, document, el);
142
- // now load any css files by path and add their content
143
- // as <style>...</style> elements
144
- let cssFiles = [];
145
- if (typeof options.cssFile === 'string') {
146
- cssFiles.push(options.cssFile);
147
- }
148
- else if (Array.isArray(options.cssFile)) {
149
- cssFiles = cssFiles.concat(options.cssFile);
150
- }
151
- if (typeof options.cssFiles === 'string') {
152
- cssFiles.push(options.cssFiles);
153
- }
154
- else if (Array.isArray(options.cssFiles)) {
155
- cssFiles = cssFiles.concat(options.cssFiles);
156
- }
157
- return insertLocalCssFiles(cssFiles, document, el, options.log);
158
- };
159
62
  function setupHooks(optionalCallback) {
160
- // Consumed by the framework "mount" libs. A user might register their own mount in the scaffolded 'commands.js'
161
- // file that is imported by e2e and component support files by default. We don't want CT side effects to run when e2e
63
+ // We don't want CT side effects to run when e2e
162
64
  // testing so we early return.
163
65
  // System test to verify CT side effects do not pollute e2e: system-tests/test/e2e_with_mount_import_spec.ts
164
66
  if (Cypress.testingType !== 'component') {
@@ -173,7 +75,6 @@ function setupHooks(optionalCallback) {
173
75
  // @ts-ignore
174
76
  Cypress.on('test:before:run', () => {
175
77
  optionalCallback === null || optionalCallback === void 0 ? void 0 : optionalCallback();
176
- cleanupStyles();
177
78
  });
178
79
  }
179
80
 
@@ -13769,42 +13670,40 @@ mount: VTUmount,
13769
13670
  // available on the `VueTestUtils` import.
13770
13671
  shallowMount } = _VueTestUtils, VueTestUtils = __rest(_VueTestUtils, ["mount", "shallowMount"]);
13771
13672
  const DEFAULT_COMP_NAME = 'unknown';
13772
- Cypress.on('run:start', () => {
13773
- // `mount` is designed to work with component testing only.
13774
- // it assumes ROOT_SELECTOR exists, which is not the case in e2e.
13775
- // if the user registers a custom command that imports `cypress/vue`,
13776
- // this event will be registered and cause an error when the user
13777
- // launches e2e (since it's common to use Cypress for both CT and E2E.
13778
- // https://github.com/cypress-io/cypress/issues/17438
13779
- if (Cypress.testingType !== 'component') {
13780
- return;
13781
- }
13782
- Cypress.on('test:before:run', () => {
13783
- var _a;
13784
- (_a = Cypress.vueWrapper) === null || _a === void 0 ? void 0 : _a.unmount();
13785
- const el = getContainerEl();
13786
- el.innerHTML = '';
13787
- });
13788
- });
13789
- // implementation
13673
+ const VUE_ROOT = '__cy_vue_root';
13674
+ const cleanup = () => {
13675
+ var _a;
13676
+ (_a = Cypress.vueWrapper) === null || _a === void 0 ? void 0 : _a.unmount();
13677
+ Cypress.$(`#${VUE_ROOT}`).remove();
13678
+ Cypress.vueWrapper = null;
13679
+ Cypress.vue = null;
13680
+ };
13681
+ /**
13682
+ * Mounts a component and returns an object containing the component and VueWrapper
13683
+ * @param componentOptions
13684
+ * @param options
13685
+ * @returns {Cypress.Chainable<{wrapper: VueWrapper<T>, component: T}>}
13686
+ * @see {@link https://on.cypress.io/mounting-vue} for more details.
13687
+ * @example
13688
+ * import { mount } from '@cypress/vue'
13689
+ * import { Stepper } from './Stepper.vue'
13690
+ *
13691
+ * it('mounts', () => {
13692
+ * cy.mount(Stepper)
13693
+ * cy.get('[data-cy=increment]').click()
13694
+ * cy.get('[data-cy=counter]').should('have.text', '1')
13695
+ * })
13696
+ */
13790
13697
  function mount(componentOptions, options = {}) {
13791
- // TODO: get the real displayName and props from VTU shallowMount
13792
- const componentName = getComponentDisplayName(componentOptions);
13793
- const message = `<${componentName} ... />`;
13794
- let logInstance;
13698
+ checkForRemovedStyleOptions(options);
13699
+ // Remove last mounted component if cy.mount is called more than once in a test
13700
+ cleanup();
13795
13701
  // then wait for cypress to load
13796
13702
  return cy.then(() => {
13797
13703
  var _a, _b;
13798
- if (options.log !== false) {
13799
- logInstance = Cypress.log({
13800
- name: 'mount',
13801
- message: [message],
13802
- });
13803
- }
13804
13704
  // @ts-ignore
13805
13705
  const document = cy.state('document');
13806
13706
  const el = getContainerEl();
13807
- injectStylesBeforeElement(options, document, el);
13808
13707
  // merge the extensions with global
13809
13708
  if (options.extensions) {
13810
13709
  options.extensions.plugins = (_a = []) === null || _a === void 0 ? void 0 : _a.concat(options.extensions.plugins || [], options.extensions.use || []);
@@ -13812,29 +13711,43 @@ function mount(componentOptions, options = {}) {
13812
13711
  options.global = Object.assign(Object.assign({}, options.extensions), options.global);
13813
13712
  }
13814
13713
  const componentNode = document.createElement('div');
13815
- componentNode.id = '__cy_vue_root';
13714
+ componentNode.id = VUE_ROOT;
13816
13715
  el.append(componentNode);
13817
13716
  // mount the component using VTU and return the wrapper in Cypress.VueWrapper
13818
13717
  const wrapper = VTUmount(componentOptions, Object.assign({ attachTo: componentNode }, options));
13819
13718
  Cypress.vueWrapper = wrapper;
13820
13719
  Cypress.vue = wrapper.vm;
13821
13720
  return cy
13822
- .wrap(wrapper, { log: false })
13823
13721
  .wait(1, { log: false })
13824
13722
  .then(() => {
13825
- if (logInstance) {
13826
- logInstance.snapshot('mounted');
13827
- logInstance.end();
13723
+ if (options.log !== false) {
13724
+ // TODO: get the real displayName and props from VTU shallowMount
13725
+ const message = `<${getComponentDisplayName(componentOptions)} ... />`;
13726
+ Cypress.log({
13727
+ name: 'mount',
13728
+ message: [message],
13729
+ });
13828
13730
  }
13829
- // by returning undefined we keep the previous subject
13830
- // which is the mounted component
13831
- return undefined;
13731
+ const returnVal = {
13732
+ wrapper,
13733
+ component: wrapper.vm,
13734
+ };
13735
+ return new Proxy(Object.create(returnVal), {
13736
+ get(obj, prop) {
13737
+ // throw an error if it looks like the caller is trying to call a method on the VueWrapper that was originally returned
13738
+ if (Reflect.get(wrapper, prop)) {
13739
+ // @ts-expect-error - internal API
13740
+ Cypress.utils.throwErrByPath('mount.vue_yielded_value');
13741
+ }
13742
+ return Reflect.get(obj, prop);
13743
+ },
13744
+ });
13832
13745
  });
13833
13746
  });
13834
13747
  }
13835
13748
  /**
13836
- * Extract the compoennt name from the object passed to mount
13837
- * @param componentOptions the compoennt passed to mount
13749
+ * Extract the component name from the object passed to mount
13750
+ * @param componentOptions the component passed to mount
13838
13751
  * @returns name of the component
13839
13752
  */
13840
13753
  function getComponentDisplayName(componentOptions) {
@@ -13857,10 +13770,14 @@ function getComponentDisplayName(componentOptions) {
13857
13770
  * @example
13858
13771
  * import {mountCallback} from '@cypress/vue'
13859
13772
  * beforeEach(mountVue(component, options))
13773
+ *
13774
+ * Removed as of Cypress 11.0.0.
13775
+ * @see https://on.cypress.io/migration-11-0-0-component-testing-updates
13860
13776
  */
13861
13777
  function mountCallback(component, options = {}) {
13862
13778
  return () => {
13863
- return mount(component, options);
13779
+ // @ts-expect-error - undocumented API
13780
+ Cypress.utils.throwErrByPath('mount.mount_callback');
13864
13781
  };
13865
13782
  }
13866
13783
  // Side effects from "import { mount } from '@cypress/<my-framework>'" are annoying, we should avoid doing this
@@ -13871,6 +13788,6 @@ function mountCallback(component, options = {}) {
13871
13788
  // import { registerCT } from 'cypress/<my-framework>'
13872
13789
  // registerCT()
13873
13790
  // Note: This would be a breaking change
13874
- setupHooks();
13791
+ setupHooks(cleanup);
13875
13792
 
13876
13793
  export { VueTestUtils, mount, mountCallback };