{
  "doc": {
    "id": "app/component-testing/vue/examples",
    "title": "Vue Examples",
    "description": "Examples for testing Vue components with Cypress.",
    "section": "app",
    "source_path": "/llm/markdown/app/component-testing/vue/examples.md",
    "version": "a76b2a262c508877f88464ce69558cb3d01b6132",
    "updated_at": "2026-05-14T14:39:51.688Z",
    "headings": [
      {
        "id": "app/component-testing/vue/examples#vue-examples",
        "text": "Vue Examples",
        "level": 1
      },
      {
        "id": "app/component-testing/vue/examples#what-youll-learn",
        "text": "What you'll learn",
        "level": 5
      },
      {
        "id": "app/component-testing/vue/examples#mounting-components",
        "text": "Mounting Components",
        "level": 2
      },
      {
        "id": "app/component-testing/vue/examples#using-cy-mount",
        "text": "Using cy.mount()",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#passing-data-to-a-component",
        "text": "Passing Data to a Component",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#testing-event-handlers",
        "text": "Testing Event Handlers",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#using-jsx",
        "text": "Using JSX",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#using-slots",
        "text": "Using Slots",
        "level": 2
      },
      {
        "id": "app/component-testing/vue/examples#default-slot",
        "text": "Default Slot",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#named-slot",
        "text": "Named Slot",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#using-vue-test-utils",
        "text": "Using Vue Test Utils",
        "level": 2
      },
      {
        "id": "app/component-testing/vue/examples#custom-mount-commands",
        "text": "Custom Mount Commands",
        "level": 2
      },
      {
        "id": "app/component-testing/vue/examples#customizing-cy-mount",
        "text": "Customizing cy.mount()",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#replicating-plugins",
        "text": "Replicating Plugins",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#replicating-the-expected-component-hierarchy",
        "text": "Replicating the expected Component Hierarchy",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#vue-router",
        "text": "Vue Router",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#vuex",
        "text": "Vuex",
        "level": 3
      },
      {
        "id": "app/component-testing/vue/examples#global-components",
        "text": "Global Components",
        "level": 3
      }
    ]
  },
  "content": {
    "type": "root",
    "children": [
      {
        "type": "heading",
        "depth": 1,
        "children": [
          {
            "type": "text",
            "value": "Vue Examples"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 5,
        "children": [
          {
            "type": "text",
            "value": "What you'll learn"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to mount Vue components in Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to pass props and events to components"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to use slots in components"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to use Vue Test Utils with Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to customize `cy.mount()` with Vue"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Mounting Components"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Using `cy.mount()`"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To mount a component with `cy.mount()`, import the component and pass it to the method:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { Stepper } from './Stepper.vue'it('mounts', () => {  cy.mount(Stepper)})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Passing Data to a Component"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You can pass props and events to a component by setting `props` in the options:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.mount(Stepper, {  props: {    initial: 100,  },})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Testing Event Handlers"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Pass a Cypress "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/guides/stubs-spies-and-clocks.md#Spies",
            "children": [
              {
                "type": "text",
                "value": "spy"
              }
            ]
          },
          {
            "type": "text",
            "value": " to an event prop and validate it was called:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "it('clicking + fires a change event with the incremented value', () => {  const onChangeSpy = cy.spy().as('onChangeSpy')  cy.mount(Stepper, { props: { onChange: onChangeSpy } })  cy.get('[data-cy=increment]').click()  cy.get('@onChangeSpy').should('have.been.calledWith', 1)})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Using JSX"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The mount command also supports JSX syntax (provided that you've configured your bundler to support transpiling JSX or TSX files). Some might find using JSX syntax beneficial when writing tests."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Sample with JSX:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "it('clicking + fires a change event with the incremented value', () => {  const onChangeSpy = cy.spy().as('onChangeSpy')  cy.mount(<Stepper initial={100} onChange={onChangeSpy} />)  cy.get('[data-cy=increment]').click()  cy.get('@onChangeSpy').should('have.been.calledWith', 101)})"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Using Slots"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Default Slot"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "DefaultSlot.cy.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "DefaultSlot.cy.jsx (JSX)"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "DefaultSlot.vue"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import DefaultSlot from './DefaultSlot.vue'describe('<DefaultSlot />', () => {  it('renders', () => {    cy.mount(DefaultSlot, {      slots: {        default: 'Hello there!',      },    })    cy.get('div.content').should('have.text', 'Hello there!')  })})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import DefaultSlot from './DefaultSlot.vue'describe('<DefaultSlot />', () => {  it('renders', () => {    cy.mount(<DefaultSlot>Hello there!</DefaultSlot>)    cy.get('div.content').should('have.text', 'Hello there!')  })})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "<template>  <div>    <div class=\"content\">      <slot />    </div>  </div></template><script setup></script>"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Named Slot"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "NamedSlot.cy.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "NamedSlot.cy.jsx (JSX)"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "NamedSlot.vue"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import NamedSlot from './NamedSlot.vue'describe('<NamedSlot />', () => {  it('renders', () => {    const slots = {      header: 'my header',      footer: 'my footer',    }    cy.mount(NamedSlot, {      slots,    })    cy.get('header').should('have.text', 'my header')    cy.get('footer').should('have.text', 'my footer')  })})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import NamedSlot from './NamedSlot.vue'describe('<NamedSlot />', () => {  it('renders', () => {    const slots = {      header: 'my header',      footer: 'my footer',    }    cy.mount(<NamedSlot>{{ ...slots }}</NamedSlot>)    cy.get('header').should('have.text', 'my header')    cy.get('footer').should('have.text', 'my footer')  })})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "<template>  <div>    <header>      <slot name=\"header\" />    </header>    <footer>      <slot name=\"footer\" />    </footer>  </div></template><script setup></script>"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "For more info on testing Vue components with slots, refer to the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://test-utils.vuejs.org/guide/advanced/slots.html",
            "children": [
              {
                "type": "text",
                "value": "Vue Test Utils Slots guide"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Using Vue Test Utils"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In order to encourage interoperability between your existing component tests and Cypress, we support using Vue Test Utils' API."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.mount(Stepper).then(({ wrapper, component }) => {  // `wrapper` is the Vue Test Utils wrapper  // `component` is the component instance itself})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you intend to use the `wrapper` frequently and use Vue Test Util's API, we recommend you write a "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/mount.md",
            "children": [
              {
                "type": "text",
                "value": "custom mount command"
              }
            ]
          },
          {
            "type": "text",
            "value": " and create a Cypress alias to get back at the `wrapper`."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { mount } from 'cypress/vue'Cypress.Commands.add('mount', (...args) => {  return mount(...args).then(({ wrapper }) => {    return cy.wrap(wrapper).as('vue')  })})// the \"@vue\" alias will now work anywhere// after you've mounted your componentcy.mount(Stepper).doStuff().get('@vue') // The subject is now the Vue Wrapper"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This means that you are able to get to the resulting `wrapper` returned from the `mount` command and use `wrapper.emitted()` in order to gain access to Native DOM events that were fired, as well as custom events that were emitted by your component under test."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Because `wrapper.emitted()` is only data, and NOT spy-based you will have to unpack its results to write assertions."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Your test failure messages will not be as helpful because you're not able to use the Sinon-Chai library that Cypress ships, which comes with methods such as `to.have.been.called` and `to.have.been.calledWith`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Usage of the `cy.get('@vue')` alias may look something like the below code snippet."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Notice that we're using the `'should'` function signature in order to take advantage of Cypress's "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/guides/test-retries.md",
            "children": [
              {
                "type": "text",
                "value": "retryability"
              }
            ]
          },
          {
            "type": "text",
            "value": ". If we chained using `cy.then` instead of `cy.should`, we may run into the kinds of issues you have in Vue Test Utils tests where you have to use `await` frequently in order to make sure the DOM has updated or any reactive events have fired."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "With emitted"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "With spies"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.mount(Stepper, { props: { initial: 100 } })cy.get(incrementSelector).click()cy.get('@vue').should(({ wrapper }) => {  expect(wrapper.emitted('change')).to.have.length  expect(wrapper.emitted('change')[0][0]).to.equal('101')})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const onChangeSpy = cy.spy().as('onChangeSpy')cy.mount(Stepper, { props: { initial: 100, onChange: onChangeSpy } })cy.get(incrementSelector).click()cy.get('@onChangeSpy').should('have.been.calledWith', '101')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Regardless of our recommendation to use spies instead of the internal Vue Test Utils API, you may decide to continue using `emitted` as it automatically records every single event emitted from the component, and so you won't have to create a spy for every event emitted."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This auto-spying behavior could be useful for components that emit many custom events."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Custom Mount Commands"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Customizing `cy.mount()`"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "While you can use the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/component-testing/vue/api.md#mount",
            "children": [
              {
                "type": "text",
                "value": "mount()"
              }
            ]
          },
          {
            "type": "text",
            "value": " function in your tests, we recommend using "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/mount.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.mount()`"
              }
            ]
          },
          {
            "type": "text",
            "value": ", which is a "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/cypress-api/custom-commands.md",
            "children": [
              {
                "type": "text",
                "value": "custom command"
              }
            ]
          },
          {
            "type": "text",
            "value": " that is defined in the cypress/support/component.js file:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { mount } from 'cypress/vue'Cypress.Commands.add('mount', mount)"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This allows you to use `cy.mount()` in any test without having to import the `mount()` function in each and every spec file."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "By default, `cy.mount()` is a simple passthrough to `mount()`, however, you can customize `cy.mount()` to fit your needs. For instance, if you are using plugins or other global app-level setups in your Vue app, you can configure them here."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Below are a few examples that demonstrate using a custom mount command. These examples can be adjusted for most other providers that you will need to support."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Replicating Plugins"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Most applications will have state management or routing. Both of these are Vue plugins."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress/support/component.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "With JSX"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { createPinia } from 'pinia' // or Vueximport { createI18n } from 'vue-i18n'import { mount } from 'cypress/vue'import { h } from 'vue'// We recommend that you pull this out// into a constants file that you share with// your main.js file.const i18nOptions = {  locale: 'en',  messages: {    en: {      hello: 'hello!',    },    ja: {      hello: 'こんにちは！',    },  },}Cypress.Commands.add('mount', (component, ...args) => {  args.global = args.global || {}  args.global.plugins = args.global.plugins || []  args.global.plugins.push(createPinia())  args.global.plugins.push(createI18n())  return mount(    () => {      return h(VApp, {}, component)    },    ...args  )})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { createPinia } from 'pinia' // or Vueximport { createI18n } from 'vue-i18n'import { mount } from 'cypress/vue'// We recommend that you pull this out// into a constants file that you share with// your main.js file.const i18nOptions = {  locale: 'en',  messages: {    en: {      hello: 'hello!',    },    ja: {      hello: 'こんにちは！',    },  },}Cypress.Commands.add('mount', (component, ...args) => {  args.global = args.global || {}  args.global.plugins = args.global.plugins || []  args.global.plugins.push(createPinia())  args.global.plugins.push(createI18n())  // <component> is a built-in component that comes with Vue  return mount(    () => (      <VApp>        <component is={component} />      </VApp>    ),    ...args  )})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Replicating the expected Component Hierarchy"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Some Vue applications, most famously Vue apps built on top of Vuetify, require certain components to be structured in a specific hierarchy."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "All Vuetify applications require that you wrap your app in a `VApp` component when you build it. This is an implementation detail of Vuetify, but once users try to test components that depend on Vuetify, they get Vuetify-specific compilation errors and quickly find out that they need to replicate that component hierarchy any time they need to mount a component that uses a Vuetify component!"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Custom `cy.mount` commands to the rescue! You may find the JSX syntax to be more straightforward."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You'll also need to replicate the plugin setup steps from the Vuetify docs for everything to compile."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress/support/component.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "With JSX"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import Vuetify from 'vuetify/lib'import { VApp } from 'vuetify'import { mount } from 'cypress/vue'import { h } from 'vue'// We recommend that you pull this out// into a constants file that you share with// your main.js file.const vuetifyOptions = {}Cypress.Commands.add('mount', (component, ...args) => {  args.global = args.global || {}  args.global.plugins = args.global.plugins || []  args.global.plugins.push(new Vuetify(vuetifyOptions))  return mount(    () => {      return h(VApp, {}, component)    },    ...args  )})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import Vuetify from 'vuetify/lib'import { VApp } from 'vuetify'import { mount } from 'cypress/vue'// We recommend that you pull this out// into a constants file that you share with// your main.js file.const vuetifyOptions = {}Cypress.Commands.add('mount', (component, ...args) => {  args.global = args.global || {}  args.global.plugins = args.global.plugins || []  args.global.plugins.push(new Vuetify(vuetifyOptions))  // <component> is a built-in component that comes with Vue  return mount(    () => (      <VApp>        <component is={component} />      </VApp>    ),    ...args  )})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Vue Router"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To use Vue Router, create a command to register the plugin and pass in a custom implementation of the router via the options param."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress/support/component.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Typings"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Spec Usage"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { mount } from 'cypress/vue'import { createMemoryHistory, createRouter } from 'vue-router'import { routes } from '../../src/router'Cypress.Commands.add('mount', (component, options = {}) => {  // Setup options object  options.global = options.global || {}  options.global.plugins = options.global.plugins || []  // create router if one is not provided  if (!options.router) {    options.router = createRouter({      routes: routes,      history: createMemoryHistory(),    })  }  // Add router plugin  options.global.plugins.push({    install(app) {      app.use(options.router)    },  })  return mount(component, options)})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { mount } from 'cypress/vue'import { Router } from 'vue-router'type MountParams = Parameters<typeof mount>type OptionsParam = MountParams[1] & { router?: Router }declare global {  namespace Cypress {    interface Chainable {      /**       * Helper mount function for Vue Components       * @param component Vue Component or JSX Element to mount       * @param options Options passed to Vue Test Utils       */      mount(component: any, options?: OptionsParam): Chainable<any>    }  }}"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import Navigation from './Navigation.vue'import { routes } from '../router'import { createMemoryHistory, createRouter } from 'vue-router'it('home link should be active when url is \"/\"', () => {  // No need to pass in custom router as default url is '/'  cy.mount(<Navigation />)  cy.get('a').contains('Home').should('have.class', 'router-link-active')})it('login link should be active when url is \"/login\"', () => {  // Create a new router instance for each test  const router = createRouter({    routes: routes,    history: createMemoryHistory(),  })  // Change location to `/login`,  // and await on the promise with cy.wrap  cy.wrap(router.push('/login'))  // Pass the already initialized router for use  cy.mount(<Navigation />, { router })  cy.get('a').contains('Login').should('have.class', 'router-link-active')})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Calling `router.push()` in the router for Vue 3 is an asynchronous operation. Use the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/wrap.md",
            "children": [
              {
                "type": "text",
                "value": "cy.wrap"
              }
            ]
          },
          {
            "type": "text",
            "value": " command to have Cypress await the promise's resolve before it continues with other commands:"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Vuex"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To use a component that uses "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://vuex.vuejs.org/",
            "children": [
              {
                "type": "text",
                "value": "Vuex"
              }
            ]
          },
          {
            "type": "text",
            "value": ", create a `mount` command that configures a Vuex store for your component."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress/support/component.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Typings"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Spec Usage"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { mount } from 'cypress/vue'import { getStore } from '../../src/plugins/store'Cypress.Commands.add('mount', (component, options = {}) => {  // Setup options object  options.global = options.global || {}  options.global.stubs = options.global.stubs || {}  options.global.stubs['transition'] = false  options.global.components = options.global.components || {}  options.global.plugins = options.global.plugins || []  // Use store passed in from options, or initialize a new one  const { store = getStore(), ...mountOptions } = options  // Add Vuex plugin  options.global.plugins.push({    install(app) {      app.use(store)    },  })  return mount(component, mountOptions)})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The `getStore` method is a factory method that initializes Vuex and creates a new store. It is important that the store be initialized with each new test to ensure changes to the store don't affect other tests."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { mount } from 'cypress/vue'import { Store } from 'vuex'type MountParams = Parameters<typeof mount>type OptionsParam = MountParams[1]declare global {  namespace Cypress {    interface Chainable {      /**       * Helper mount function for Vue Components       * @param component Vue Component or JSX Element to mount       * @param options Options passed to Vue Test Utils       */      mount(        component: any,        options?: OptionsParam & { store?: Store }      ): Chainable<any>    }  }}"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { getStore } from '@/plugins/store'import UserProfile from './UserProfile.vue'it.only('User profile should display user name', () => {  const user = { name: 'test person' }  // getStore is a factory method that creates a new store  const store = getStore()  // mutate the store with user  store.commit('setUser', user)  cy.mount(UserProfile, {    store,  })  cy.get('div.name').should('have.text', user.name)})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Global Components"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you have components that are registered globally in the main application file, set them up in your mount command so your component will render them properly:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { mount } from 'cypress/vue'import Button from '../../src/components/Button.vue'Cypress.Commands.add('mount', (component, options = {}) => {  // Setup options object  options.global = options.global || {}  options.global.components = options.global.components || {}  // Register global components  options.global.components['Button'] = Button  return mount(component, options)})"
      }
    ]
  },
  "token_estimate": 2735
}