{"id":16439157,"url":"https://github.com/posva/vue-router-mock","last_synced_at":"2025-05-15T10:01:27.894Z","repository":{"id":36971706,"uuid":"310250542","full_name":"posva/vue-router-mock","owner":"posva","description":"🧪 Easily mock routing interactions in your Vue apps","archived":false,"fork":false,"pushed_at":"2025-05-12T20:11:19.000Z","size":1333,"stargazers_count":211,"open_issues_count":5,"forks_count":8,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-12T21:28:30.840Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/posva.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/funding.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"posva"}},"created_at":"2020-11-05T09:33:12.000Z","updated_at":"2025-05-12T15:35:15.000Z","dependencies_parsed_at":"2023-11-27T05:25:03.964Z","dependency_job_id":"406dbaba-4a37-4c12-8420-02439d1e7edf","html_url":"https://github.com/posva/vue-router-mock","commit_stats":{"total_commits":329,"total_committers":9,"mean_commits":36.55555555555556,"dds":0.6261398176291793,"last_synced_commit":"b9ba3d6b81ecf3f67f9d5a295f79cc519d295ee5"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":"posva/vue-ts-lib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posva%2Fvue-router-mock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posva%2Fvue-router-mock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posva%2Fvue-router-mock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posva%2Fvue-router-mock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/posva","download_url":"https://codeload.github.com/posva/vue-router-mock/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254319715,"owners_count":22051072,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T09:08:14.666Z","updated_at":"2025-05-15T10:01:27.072Z","avatar_url":"https://github.com/posva.png","language":"TypeScript","funding_links":["https://github.com/sponsors/posva"],"categories":["TypeScript"],"sub_categories":[],"readme":"# vue-router-mock [![test](https://github.com/posva/vue-router-mock/actions/workflows/test.yml/badge.svg)](https://github.com/posva/vue-router-mock/actions/workflows/test.yml) [![npm package](https://badgen.net/npm/v/vue-router-mock)](https://www.npmjs.com/package/vue-router-mock) [![codecov](https://codecov.io/gh/posva/vue-router-mock/graph/badge.svg?token=mEKj0wLUID)](https://codecov.io/gh/posva/vue-router-mock) [![thanks](https://badgen.net/badge/thanks/♥/pink)](https://github.com/posva/thanks)\n\n\u003e Easily mock routing interactions in your Vue 3 apps\n\n## Installation\n\n```sh\npnpm i -D vue-router-mock\n# or\nyarn add -D vue-router-mock\n# or\nnpm install -D vue-router-mock\n```\n\n## Requirements\n\nThis library\n\n- `@vue/test-utils` \u003e= 2.4.0\n- vue 3 and vue router 4\n\n## Goal\n\nThe goal of Vue Router Mock is to enable users to **unit and integration test** navigation scenarios. This means tests that are isolated enough to not be end to end tests (e.g. using [Cypress](https://www.cypress.io/)) or are edge cases (e.g. network failures). Because of this, some scenarios are more interesting as end to end tests, **using the real** vue router.\n\n## Introduction\n\nVue Router Mock exposes a few functions to be used individually and they are all documented through TS. But most of the time you want to globally inject the router in a _setupFilesAfterEnv_ file. Create a `tests/router-mock-setup.js` file at the root of your project (it can be named differently):\n\n```js\nimport {\n  VueRouterMock,\n  createRouterMock,\n  injectRouterMock,\n} from 'vue-router-mock'\nimport { config } from '@vue/test-utils'\n\n// create one router per test file\nconst router = createRouterMock()\nbeforeEach(() =\u003e {\n  router.reset() // reset the router state\n  injectRouterMock(router)\n})\n\n// Add properties to the wrapper\nconfig.plugins.VueWrapper.install(VueRouterMock)\n```\n\n\u003e Note: you might need to write this file in CommonJS for Jest. In Vite, you can write it in Typescript\n\nThen add this line to your `jest.config.js`:\n\n```js\n  setupFilesAfterEnv: ['\u003crootDir\u003e/tests/router-mock-setup.js'],\n```\n\nor to your `vitest.config.ts`:\n\n```ts\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    environment: 'happy-dom', // \u003c- or jsdom, needed to mount Vue Components\n    setupFiles: ['./tests/setup-router-mock.ts'],\n  },\n})\n```\n\nThis will inject a router in all your tests. If for specific tests, you need to inject a different version of the router, you can do so:\n\n```js\nimport { createRouterMock, injectRouterMock } from 'vue-router-mock'\n\ndescribe('SearchUsers', () =\u003e {\n  // create one mock instance, pass options\n  const router = createRouterMock({\n    // ...\n  })\n  beforeEach(() =\u003e {\n    // inject it globally to ensure `useRoute()`, `$route`, etc work\n    // properly and give you access to test specific functions\n    injectRouterMock(router)\n  })\n\n  it('should paginate', async () =\u003e {\n    const wrapper = mount(SearchUsers)\n\n    expect(wrapper.router).toBe(router)\n\n    // go to the next page\n    // this will internally trigger `router.push({ query: { page: 2 }})`\n    wrapper.find('button.next-page').click()\n\n    expect(wrapper.router.push).toHaveBeenCalledWith(\n      expect.objectContaining({ query: { page: 2 } })\n    )\n    expect(wrapper.router.push).toHaveBeenCalledTimes(1)\n\n    // if we had a navigation guard fetching the search results,\n    // waiting for it to be done will allow us to wait until it's done.\n    // Note you need to mock the fetch and to activate navigation\n    // guards as explained below\n    await router.getPendingNavigation()\n    // wait for the component to render again if we want to check\n    await wrapper.vm.nextTick()\n\n    expect(wrapper.find('#user-results .user').text()).toMatchSnapshot()\n  })\n})\n```\n\nIf you need to create a specific version of the router for one single test (or a nested suite of them), you should call the same functions:\n\n```js\nit('should paginate', async () =\u003e {\n  const router = createRouterMock()\n  injectRouterMock(router)\n  const wrapper = mount(SearchUsers)\n})\n```\n\n## Guide\n\n## Accessing the Router Mock instance\n\nYou can access the instance of the router mock in multiple ways:\n\n- Access `wrapper.router`:\n\n  ```js\n  it('tests something', async () =\u003e {\n    const wrapper = mount(MyComponent)\n    await wrapper.router.push('/new-location')\n  })\n  ```\n\n- Access it through `wrapper.vm`:\n\n  ```js\n  it('tests something', async () =\u003e {\n    const wrapper = mount(MyComponent)\n    await wrapper.vm.$router.push('/new-location')\n    expect(wrapper.vm.$route.name).toBe('NewLocation')\n  })\n  ```\n\n- Call `getRouter()` inside of a test:\n\n  ```js\n  it('tests something', async () =\u003e {\n    // can be called before creating the wrapper\n    const router = getRouter()\n    const wrapper = mount(MyComponent)\n    await router.push('/new-location')\n  })\n  ```\n\n### Setting parameters\n\n`setParams` allows you to change route `params` without triggering a navigation:\n\n```js\nit('should display the user details', async () =\u003e {\n  const wrapper = mount(UserDetails)\n  getRouter().setParams({ userId: 12 })\n\n  // test...\n})\n```\n\nIt can be awaited if you need to wait for Vue to render again:\n\n```js\nit('should display the user details', async () =\u003e {\n  const wrapper = mount(UserDetails)\n  await getRouter().setParams({ userId: 12 })\n\n  // test...\n})\n```\n\n`setQuery` and `setHash` are very similar.\nThey can be used to set the route query or hash without triggering a navigation,\nand can be awaited too.\n\n### Setting the initial location\n\nBy default the router mock starts on [`START_LOCATION`](https://next.router.vuejs.org/api/#start-location). In some scenarios this might need to be adjusted by pushing a new location and awaiting it before testing:\n\n```js\nit('should paginate', async () =\u003e {\n  await router.push('/users?q=haruno')\n  const wrapper = mount(SearchUsers)\n\n  // test...\n})\n```\n\nYou can also set the initial location for all your tests by passing an `initialLocation`:\n\n```js\nconst router = createRouterMock({\n  initialLocation: '/users?q=jolyne',\n})\n```\n\n`initialLocation` accepts anything that can be passed to `router.push()`.\n\n### Simulating navigation failures\n\nYou can simulate the failure of the next navigation\n\n### Simulating a navigation guard\n\nBy default, **all navigation guards are ignored** so that you can simulate the return of the next guard by using `setNextGuardReturn()` without depending on existing ones:\n\n```js\n// simulate a navigation guard that returns false\nrouter.setNextGuardReturn(false)\n// simulate a redirection\nrouter.setNextGuardReturn('/login')\n```\n\nIf you want to still run existing navigation guards inside component, you can active them when creating your router mock:\n\n```js\nconst router = createRouterMock({\n  // run `onBeforeRouteLeave()`, `onBeforeRouteUpdate()`, `beforeRouteEnter()`, `beforeRouteUpdate()`, and `beforeRouteLeave()`\n  runInComponentGuards: true,\n  // run `beforeEnter` of added routes. Note that you must manually add these routes with `router.addRoutes()`\n  runPerRouteGuards: true,\n})\n```\n\n### Stubs\n\nBy default, both `\u003crouter-link\u003e` and `\u003crouter-view\u003e` are stubbed but you can override them locally. This is specially useful when you have nested `\u003crouter-view\u003e` and you rely on them for a test:\n\n```js\nconst wrapper = mount(MyComponent, {\n  global: {\n    stubs: { RouterView: MyNestedComponent },\n  },\n})\n```\n\nYou need to manually specify the component that is supposed to be displayed because the mock won't be able to know the level of nesting.\n\nNOTE: this might change to become automatic if the necessary `routes` are provided.\n\n## Testing libraries\n\nVue Router Mock automatically detects if you are using [Sinon.js](https://sinonjs.org/), [Jest](https://jestjs.io/), or [Vitest](https://vitest.dev/) and use their _spying methods_. You can of course configure Vue Router Mock to use any spying library you want.\n\nFor example, if you use [Vitest with `globals: false`](https://vitest.dev/config/#globals),\nthen you need to manually configure the `spy` option and pass `vi.fn()` to it:\n\n```ts\nconst router = createRouterMock({\n  spy: {\n    create: fn =\u003e vi.fn(fn),\n    reset: spy =\u003e spy.mockClear(),\n  },\n})\n```\n\n## Caveats\n\n### Nested Routes\n\nBy default, the router mock comes with one single _catch all_ route. You can add routes calling the `router.addRoute()` function but **if you add nested routes and you are relying on running navigation guards**, you must manually set the _depth_ of the route you are displaying. This is because the router has no way to know which level of nesting you are trying to display. e.g. Imagine the following `routes`:\n\n```js\nconst routes = [\n  {\n    path: '/users',\n    // we are not testing this one so it doesn't matter\n    component: UserView,\n    children: [\n      // UserDetail must be the same component we are unit testing\n      { path: ':id', component: UserDetail },\n    ],\n  },\n]\n```\n\n```js\n// 0 would be if we were testing UserView at /users\nrouter.depth.value = 1\nconst wrapper = mount(UserDetail)\n```\n\nRemember, this is not necessary if you are not adding routes or if they are not nested.\n\n## Related\n\n- [Jest](https://jestjs.io/)\n- [Vitest](https://vitest.dev/)\n- [Sinon.js](https://sinonjs.org/)\n- [Vue Test Utils](https://github.com/vuejs/test-utils)\n- [Vue Router](https://github.com/vuejs/router)\n- [Vuex Mock Store](https://github.com/posva/vuex-mock-store) - A Vuex 3.x mock\n\n## License\n\n[MIT](http://opensource.org/licenses/MIT)\n\n\u003cdiv align=\"right\"\u003e\n\u003csub\u003e\u003cem\u003e\nThis project was created using the \u003ca href=\"https://github.com/posva/vue-ts-lib\" rel=\"nofollow\"\u003eVue Library template\u003c/a\u003e by \u003ca href=\"https://github.com/posva\" rel=\"nofollow\"\u003eposva\u003c/a\u003e\n\u003c/em\u003e\u003c/sub\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposva%2Fvue-router-mock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fposva%2Fvue-router-mock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposva%2Fvue-router-mock/lists"}