{"id":16256356,"url":"https://github.com/hmsk/jest-matcher-vue-test-utils","last_synced_at":"2025-04-09T23:15:22.638Z","repository":{"id":38238635,"uuid":"145022121","full_name":"hmsk/jest-matcher-vue-test-utils","owner":"hmsk","description":"✨ Cute jest matchers to test Vue components with vue-test-utils","archived":false,"fork":false,"pushed_at":"2025-04-08T14:06:57.000Z","size":1381,"stargazers_count":33,"open_issues_count":24,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-09T23:15:16.463Z","etag":null,"topics":["jest","jest-matchers","vue","vue-test-utils"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hmsk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"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},"funding":{"custom":["https://www.buymeacoffee.com/hmsk"]}},"created_at":"2018-08-16T17:55:43.000Z","updated_at":"2023-09-29T20:57:24.000Z","dependencies_parsed_at":"2024-02-13T12:54:31.054Z","dependency_job_id":"7244b2ee-5269-4e6c-8aff-75859632ba68","html_url":"https://github.com/hmsk/jest-matcher-vue-test-utils","commit_stats":{"total_commits":522,"total_committers":5,"mean_commits":104.4,"dds":0.5019157088122606,"last_synced_commit":"6da64ead26e7561547713ab21201cb4ae495f5e8"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hmsk%2Fjest-matcher-vue-test-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hmsk%2Fjest-matcher-vue-test-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hmsk%2Fjest-matcher-vue-test-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hmsk%2Fjest-matcher-vue-test-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hmsk","download_url":"https://codeload.github.com/hmsk/jest-matcher-vue-test-utils/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248125591,"owners_count":21051770,"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":["jest","jest-matchers","vue","vue-test-utils"],"created_at":"2024-10-10T15:45:00.994Z","updated_at":"2025-04-09T23:15:22.620Z","avatar_url":"https://github.com/hmsk.png","language":"TypeScript","funding_links":["https://www.buymeacoffee.com/hmsk"],"categories":[],"sub_categories":[],"readme":"# jest-matcher-vue-test-utils\n\n[![npm](https://img.shields.io/npm/v/jest-matcher-vue-test-utils.svg?style=for-the-badge)](https://www.npmjs.com/package/jest-matcher-vue-test-utils)\n[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/hmsk/jest-matcher-vue-test-utils/Node%20CI?style=for-the-badge)](https://github.com/hmsk/jest-matcher-vue-test-utils/actions?query=workflow%3A%22Node+CI%22)\n\nCute matchers for [Jest](https://facebook.github.io/jest) to test Vue components with [Vue Test Utils](https://vue-test-utils.vuejs.org/).\n\nYou can write tests for Vue component/store intuitively ⚡️\n\n```ts\nit(\"Emits 'select' event by clicking PrimaryButton\", () =\u003e {\n  const wrapper = shallowMount(Component);\n  \n  expect(wrapper.emitted().select).toBeUndefined();\n  wrapper.find(PrimaryButton).vm.$emit(\"click\");\n  expect(wrapper.emitted().select[0]).toBeTruthy();\n});\n```\n\nbecomes\n\n```ts\nit(\"Emits 'select' event by clicking PrimaryButton\", () =\u003e {\n  const wrapper = shallowMount(Component);\n  \n  expect(() =\u003e {\n    wrapper.find(PrimaryButton).vm.$emit(\"click\");\n  }).toEmit(wrapper, \"select\");\n});\n```\n\nAnd all matchers have type definition and doc 💇‍♂️\n\n![190607_jest_matcher_infer](https://user-images.githubusercontent.com/85887/59101871-316fb600-88df-11e9-9ce1-54e5231c2bf6.gif)\n\n# Installation\n\nGet from npm:\n\n```sh\n$ npm install -D jest-matcher-vue-test-utils\n```\n\nThen, register matchers on your jest process:\n\n```js\nimport vueTestUtilMatchers from \"jest-matcher-vue-test-utils\";\nexpect.extend({ ...vueTestUtilMatchers });\n```\n\n## Provided Matchers\n\n### Existence on Wrapper\n\n#### `toShow`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert the function shows a content on Wrapper of vue-test-utils\u003c/summary\u003e\n\n```js\n// error-message.vue\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cp v-if=\"isError\" class=\"error\"\u003emessage\u003c/p\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n...\n\ndata: function () {\n  return {\n    isError: false\n  }\n},\nmethods: {\n  showError () {\n    this.isError = true;\n  }\n}\n```\n\n```js\nimport Component from \"./error-message.vue\";\n\nit(\"show error by showError\", async () =\u003e {\n  return expect(async () =\u003e {\n    wrapper.vm.showError();\n    await wrapper.vm.$nextTick();\n  }).toShow(wrapper, \"p.error\"); // Passes\n});\n```\n\u003c/details\u003e\n\n#### `toHide`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert the function hides a content on Wrapper of vue-test-utils\u003c/summary\u003e\n\n```js\n// error-message.vue\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cp v-if=\"isError\" class=\"error\"\u003emessage\u003c/p\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n...\n\ndata: function () {\n  return {\n    isError: true\n  }\n},\nmethods: {\n  hideError () {\n    this.isError = false;\n  }\n}\n```\n\n```js\nimport Component from \"./error-message.vue\";\n\nit(\"show error by showError\", async () =\u003e {\n  return expect(async () =\u003e {\n    wrapper.vm.hideError();\n    await wrapper.vm.$nextTick();\n  }).toHide(wrapper, \"p.error\"); // Passes\n});\n```\n\n\u003c/details\u003e\n\n### Events on Wrapper\n\n#### `toEmit` / `toEmitOnRoot`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert the action emits the event (with the payload optionally) on Wrapper of vue-test-utils\u003c/summary\u003e\n\n```js\n// event.vue\n\u003ctemplate\u003e\n  \u003cdiv @click=\"emitEvent('clicked')\"\u003e\n    Click Me\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nmodule.exports = {\n  methods: {\n    emitEvent (e) {\n      this.$emit(\"special\", e);\n    }\n  }\n}\n\u003c/script\u003e\n```\n\n```js\nimport Component from \"./event.vue\";\n\nit(\"emits special event by click\", () =\u003e {\n  const wrapper = shallowMount(Component);\n  expect(() =\u003e wrapper.trigger(\"click\")).toEmit(wrapper, \"special\"); // Passes\n  expect(() =\u003e wrapper.trigger(\"click\")).toEmit(wrapper, \"special\", \"clicked\"); // Passes\n});\n```\n\nAsync function is supported as well.\n\n```js\nit(\"emits special event by click\", async () =\u003e {\n  const wrapper = shallowMount(Component);\n  return expect(async () =\u003e triggersEventAsynchronously()).toEmit(wrapper, \"special\", \"clicked\"); // Passes\n});\n```\n\n`toEmitOnRoot` inspects whether the event is emitted on `$root` of Vue instance.\n\n\u003c/details\u003e\n\n#### `toHaveEmitted` / `toHaveEmittedOnRoot`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert the event is emitted (with the payload optionally) on Wrapper of vue-test-utils\u003c/summary\u003e\n\n```js\n// event.vue\n\u003ctemplate\u003e\n  \u003cdiv @click=\"emitEvent('clicked')\"\u003e\n    Click Me\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nmodule.exports = {\n  methods: {\n    emitEvent (e) {\n      this.$emit(\"special\", e);\n    }\n  }\n}\n\u003c/script\u003e\n```\n\n```js\nimport Component from \"./event.vue\";\n\nit(\"emits special event by click\", () =\u003e {\n  const wrapper = shallowMount(Component);\n  wrapper.trigger(\"click\");\n  expect(wrapper).toHaveEmitted(\"special\"); // Passes\n  expect(wrapper).toHaveEmitted(\"special\", \"clicked\"); // Passes\n});\n```\n\n`toHaveEmittedOnRoot` inspects whether the event is emitted on `$root` of Vue instance.\n\u003c/details\u003e\n\n### Vuex actions/mutations\n\n#### `toDispatch`\n\n\u003cdetails\u003e\n\u003csummary\u003eAssert the function dispatches Vuex action on the component\u003c/summary\u003e\n\n```js\n// click-store.vue\n\u003ctemplate\u003e\n  \u003cdiv @click=\"dispatchStore('click')\"\u003e\n    Click Me\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nmodule.exports = {\n  methods: {\n    dispatchStore (e) {\n      this.$store.dispatch('awesomeAction', e);\n    }\n  }\n}\n\u003c/script\u003e\n```\n\n```js\nimport Component from \"./click-store.vue\";\n\nit(\"Dispatches the action on store by click\", () =\u003e {\n  const wrapper = shallowMount(Component);\n  expect(() =\u003e {\n    wrapper.trigger(\"click\");\n  }).toDispatch(wrapper, \"awesomeAction\"); // Passes\n\n  expect(() =\u003e {\n    wrapper.trigger(\"click\");\n  }).toDispatch(wrapper, \"awesomeAction\", 'click'); // Passes\n});\n```\n\nAsync function is supported as well.\n\n```js\nit(\"dispatches the action on store by click\", async () =\u003e {\n  return expect(async () =\u003e {\n    dispatchEventAsynchronosly();\n  }).toDispatch(wrapper, \"awesomeAction\", 'click'); // Passes\n});\n```\n\u003c/details\u003e\n\n#### `toCommit` (TBD)\n\n\u003cdetails\u003e\n\u003csummary\u003eAssert the store mutation is committed\u003c/summary\u003e\n\n```js\n// click-store.vue\n\u003ctemplate\u003e\n  \u003cdiv @click=\"commitStore('click')\"\u003e\n    Click Me\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nmodule.exports = {\n  methods: {\n    commitStore (e) {\n      this.$store.commit('importantMutation', e);\n    }\n  }\n}\n\u003c/script\u003e\n```\n\n```js\nimport Component from \"./click-store.vue\";\n\nit(\"Commits the mutation on store by click\", () =\u003e {\n  const wrapper = shallowMount(Component);\n  expect(() =\u003e {\n    wrapper.trigger(\"click\");\n  }).toCommit(wrapper, \"importantMutation\"); // Passes\n\n  expect(() =\u003e {\n    wrapper.trigger(\"click\");\n  }).toCommit(wrapper, \"importantMutation\", 'click'); // Passes\n});\n```\n\u003c/details\u003e\n\n#### `toHaveDispatched`\n\n\u003cdetails\u003e\n\u003csummary\u003eAssert a component has dispatched Vuex action\u003c/summary\u003e\n\n```js\n// click-store.vue\n\u003ctemplate\u003e\n  \u003cdiv @click=\"dispatchStore('click')\"\u003e\n    Click Me\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nmodule.exports = {\n  methods: {\n    dispatchStore (e) {\n      this.$store.dispatch('awesomeAction', e);\n    }\n  }\n}\n\u003c/script\u003e\n```\n\n```js\nimport Component from \"./click-store.vue\";\nimport { vuexPlugin } from \"jest-matcher-vue-test-utils\";\n\nit(\"Dispatches the action on store by click\", () =\u003e {\n  const store = new Vuex.Store({\n    actions: dispatchStore() {},\n    plugins: [vuexPlugin()] // Requires adding plugin to use `toHaveDispatched` matcher\n  });\n\n  const wrapper = shallowMount(Component, { store })\n  wrapper.trigger(\"click\");\n  expect(wrapper).toHaveDispatched(\"awesomeAction\"); // Passes\n  expect(wrapper).toHaveDispatched(\"awesomeAction\", \"click\"); // Passes\n});\n```\n\u003c/details\u003e\n\n### Prop Validations\n\n#### `toBeValidProps`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert that a prop set is valid for a component\u003c/summary\u003e\n\n```js\n// name-require-and-fullname-is-validated-component.vue\nprops: {\n  name: {\n    type: String,\n    required: true\n  }\n  fullname: {\n    validator: function (val) {\n      return !!val \u0026\u0026 val.match(/.+\\s.+/);\n    }\n  }\n}\n```\n\n```js\nimport Component from \"./name-require-and-fullname-is-validated-component.vue\";\n\nit(\"component validates props\", () =\u003e {\n  expect(Component).toBeValidProps({ name: \"required name\", fullName: \"Kengo Hamasaki\" }); // Passes\n  expect(Component).toBeValidProps({ fullName: \"Kengo Hamasaki\" }); // Fails\n  expect(Component).toBeValidProps({ name: \"required name\", fullName: \"Kengo\" }); // Fails\n});\n```\n\u003c/details\u003e\n\n#### `toBeValidProp`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert that a single prop is valid for a component\u003c/summary\u003e\n\n```js\n// name-require-component.vue\nprops: {\n  name: {\n    type: String,\n    required: true\n  }\n}\n```\n\n```js\nimport Component from \"./name-require-component.vue\";\n\nit(\"component validates props\", () =\u003e {\n  expect(Component).toBeValidProp(\"name\", \"Required Name\"); // Passes\n  expect(Component).toBeValidProp(\"name\", null); // Fails as required\n  expect(Component).toBeValidProp(\"name\", 123}); // Fails as typecheck\n});\n```\n\u003c/details\u003e\n\n\n\n#### `toRequireProp`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert that a component requires a prop\u003c/summary\u003e\n\n```js\n// name-require-component.vue\nprops: {\n  name: {\n    type: String,\n    required: true\n  }\n}\n```\n\n```js\nimport Component from \"./name-require-component.vue\";\n\nit(\"component requires name prop\", () =\u003e {\n  expect(Component).toRequireProp(\"name\"); // Passes\n  expect(Component).toRequireProp(\"birthday\"); // Fails\n});\n```\n\u003c/details\u003e\n\n#### `toHaveDefaultProp`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert that a component gives default to a prop\u003c/summary\u003e\n\n```js\n// default-address-component.vue\nprops: {\n  address: {\n    type: String,\n    default: \"Kitakyushu, Japan\"\n  }\n}\n```\n\n```js\nimport Component from \"./default-address-component.vue\";\n\nit(\"component gives default value for address prop\", () =\u003e {\n  expect(Component).toHaveDefaultProp(\"address\", \"Kitakyushu, Japan\"); // Passes\n  expect(Component).toHaveDefaultProp(\"address\", \"San Francisco, US\"); // Fails\n});\n```\n\u003c/details\u003e\n\n#### `toBeValidPropWithTypeCheck`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert that a component validates a prop with type\u003c/summary\u003e\n\n```js\n// takes-zipcode-component.vue\nprops: {\n  zipcode: {\n    type: String\n  }\n}\n```\n\n```js\nimport Component from \"./takes-zipcode-component.vue\";\n\nit(\"component validates zipcode prop\", () =\u003e {\n  expect(Component).toBeValidPropWithTypeCheck(\"zipcode\", \"94103\"); // Passes\n  expect(Component).toBeValidPropWithTypeCheck(\"zipcode\", 94103); // Fails\n});\n```\n\u003c/details\u003e\n\n#### `toBeValidPropWithCustomValidator`\n\n\u003cdetails\u003e\n  \u003csummary\u003eAssert that a component validates a prop with custom validator\u003c/summary\u003e\n\n```js\n// fullname-is-validated-component.vue\nprops: {\n  fullname: {\n    validator: function (val) {\n      return !!val \u0026\u0026 val.match(/.+\\s.+/);\n    }\n  }\n}\n```\n\n```js\nimport Component from \"./fullname-is-validated-component.vue\";\n\nit(\"component validates fullname prop\", () =\u003e {\n  expect(Component).toBeValidPropWithCustomValidator(\"fullname\", \"Kengo Hamasaki\"); // Passes\n  expect(Component).toBeValidPropWithCustomValidator(\"fullname\", \"Kengo\"); // Fails\n});\n```\n\u003c/details\u003e\n\n# Config\n\nWe can configure the matchers. Currently accepting *mountOptions* property to give options for `shallowMount` which is running in inside of matchers.\n\n```js\nimport vueTestUtilMatchers, { config } from \"jest-matcher-vue-test-utils\";\nimport { createLocalVue } from \"@vue/test-utils\";\n\nconfig({\n  mountOptions: { localVue: createLocalVue() }\n});\n```\n\n# License\n\nMIT, Copyright (c) 2018- Kengo Hamasaki\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhmsk%2Fjest-matcher-vue-test-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhmsk%2Fjest-matcher-vue-test-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhmsk%2Fjest-matcher-vue-test-utils/lists"}