{"id":13536013,"url":"https://github.com/wrseward/vue-unit","last_synced_at":"2025-12-26T22:16:58.353Z","repository":{"id":65379110,"uuid":"89644558","full_name":"wrseward/vue-unit","owner":"wrseward","description":"Component testing utilities for Vue.js","archived":false,"fork":false,"pushed_at":"2018-06-04T15:50:22.000Z","size":79,"stargazers_count":208,"open_issues_count":5,"forks_count":10,"subscribers_count":5,"default_branch":"develop","last_synced_at":"2025-10-22T05:46:40.514Z","etag":null,"topics":["javascript","testing","unit-testing","vue"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/wrseward.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-27T22:13:33.000Z","updated_at":"2025-01-31T13:11:24.000Z","dependencies_parsed_at":"2023-01-20T08:35:42.265Z","dependency_job_id":null,"html_url":"https://github.com/wrseward/vue-unit","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/wrseward/vue-unit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wrseward%2Fvue-unit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wrseward%2Fvue-unit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wrseward%2Fvue-unit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wrseward%2Fvue-unit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wrseward","download_url":"https://codeload.github.com/wrseward/vue-unit/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wrseward%2Fvue-unit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28062460,"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","status":"online","status_checked_at":"2025-12-26T02:00:06.189Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["javascript","testing","unit-testing","vue"],"created_at":"2024-08-01T09:00:33.626Z","updated_at":"2025-12-26T22:16:58.326Z","avatar_url":"https://github.com/wrseward.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","实用库","叫研发工具组","Components \u0026 Libraries","Dev Tools","Dev Tools [🔝](#readme)"],"sub_categories":["试验","Dev Tools","Test"],"readme":"# VueUnit\n\n\u003e A library for Vue.js that makes it easier to create and unit test components.\n\n* Easily test props, events, and slots (including named slots)\n* Optionally shallow render components\n* Simulate simple DOM events (click, input, etc.)\n* Use any test runner / assertion library\n* Mock and stub vuex actions and getters\n\nUnlike other component testing libraries, VueUnit does not focus on DOM traversal. Instead it focuses on making programmatic manipulation of your components much easier. For DOM traversal and assertions it's strongly recommended to use a library such as [`chai-jquery`](http://chaijs.com/plugins/chai-jquery/) or [`jasmine-jquery`](https://github.com/velesin/jasmine-jquery).\n\n* [Installation](#installation)\n* [Usage](#usage)\n  * [Hooks](#hooks)\n  * [`mount()`](#mount)\n    * [Basic Component](#basic-component)\n    * [Component with props](#component-with-props)\n    * [Component with events](#component-with-events)\n    * [Component with default slot](#component-with-default-slot)\n    * [Component with multiple slots](#component-with-multiple-slots)\n    * [Component with injects](#component-with-injects)\n  * [Options Object](#options-object)\n  * [`shallow()`](#shallow)\n  * [`build()` and `buildShallow()`](#build-and-build-shallow)\n  * [`simulate(element, event)`](#simulate)\n  * [`waitForUpdate(cb)`](#wait-for-update)\n  * [`Vuex testing`](#vuex-testing)\n    * [`fakeGetters()`](#fake-getters)\n    * [`fakeActions()`](#fake-actions)\n  * [Examples](#examples)\n* [License](#license)\n\n## \u003ca name=\"installation\"\u003e\u003c/a\u003eInstallation\n\n`npm install --save-dev vue-unit`\n\nVueUnit requires `\"vue\": \"2.*\"` to be installed, using the [standalone build](https://vuejs.org/v2/guide/installation.html#Standalone-vs-Runtime-only-Build).\n\n## \u003ca name=\"usage\"\u003e\u003c/a\u003eUsage\n\nExamples shown are using [mocha](https://mochajs.org/), [chai](http://chaijs.com/), [sinon](http://sinonjs.org/), and [chai-jquery](http://chaijs.com/plugins/chai-jquery/) but you should be able to extrapolate to your framework of choice.\n\n### \u003ca name=\"hooks\"\u003e\u003c/a\u003eHooks\n\nVueUnit renders all components in the DOM and needs to handle setup and tear down. VueUnit provides two helpers for this: `beforeEachHooks()` and `afterEachHooks()` when need to be called before and after each test, respectively.\n\nFor example with mocha this would look like:\n\n```js\nimport { beforeEachHooks, afterEachHooks } from 'vue-unit'\n\ndescribe('My test', () =\u003e {\n  beforeEach(beforeEachHooks)\n\n  it('tests something', () =\u003e {\n    // test code\n  })\n\n  afterEach(afterEachHooks)\n})\n```\n\n**You should assume all example tests shown are using these hooks.**\n\n### \u003ca name=\"mount\"\u003e\u003c/a\u003e`mount()`\n\nThe `mount()` function renders components and allows setting props, listening for events, or putting content into slots.\n\n```js\nimport { mount } from 'vue-unit'\n```\n\n#### \u003ca name=\"basic-component\"\u003e\u003c/a\u003eBasic Component\n\n```js\nconst BasicComponent = {\n  template: `\u003cdiv class=\"component\"\u003eHello\u003c/div\u003e`\n}\n\nit('mounts a basic component', () =\u003e {\n  mount(BasicComponent)\n  expect($('.component')).to.contain('Hello')\n})\n```\n\nThe first argument `mount()` expects is a Vue component.\n\n#### \u003ca name=\"component-with-props\"\u003e\u003c/a\u003eComponent with props\n\n```js\nconst ComponentWithProps = {\n  template: `\n    \u003cdiv class=\"component\"\u003e\n      Hello {{ message }}\n    \u003c/div\u003e\n  `,\n  props: ['message']\n}\n\nit('sets props', () =\u003e {\n  mount(ComponentWithProps, { message: 'World' })\n  expect($('.component')).to.have.text('Hello World')\n})\n```\n\nAn object representing the data for props, can be passed the second argument.\n\n#### \u003ca name=\"component-with-events\"\u003e\u003c/a\u003eComponent with events\n\n```js\nconst ComponentWithEvent = {\n  template: `\n    \u003cbutton @click=\"$emit('foo', 'bar')\"\u003eClick\u003c/button\u003e\n  `\n}\n\nit('listens for events', () =\u003e {\n  const listener = sinon.spy()\n  mount(ComponentWithEvent, {}, { foo: listener })\n  simulate($('button'), 'click')\n  expect(listener).to.have.been.calledWith('bar')\n})\n```\n\nThe 3rd argument `mount()` accepts is an object with listener functions for events to emit. Here we are use the `simulate()` function to fire a click event.\n\n#### \u003ca name=\"component-with-default-slot\"\u003e\u003c/a\u003eComponent with default slot\n\n```js\nconst ComponentWithSlot = {\n  template: `\n    \u003cdiv class=\"component\"\u003e\n      \u003cslot\u003e\u003c/slot\u003e\n    \u003c/div\u003e\n  `\n}\n\nit('sets content for a default slot', () =\u003e {\n  mount(ComponentWithSlot, {}, {}, '\u003cp\u003eHello\u003c/p\u003e')\n  expect($('.component')).to.have.html('\u003cp\u003eHello\u003c/p\u003e')\n})\n```\n\n#### \u003ca name=\"component-with-multiple-slots\"\u003e\u003c/a\u003eComponent with multiple slots\n\n```js\nconst ComponentWithMultipleSlots = {\n  template: `\n    \u003cdiv class=\"component\"\u003e\n      \u003cslot\u003e\u003c/slot\u003e\n      \u003cslot name=\"foo\"\u003e\u003c/slot\u003e\n    \u003c/div\u003e\n  `\n}\n\nit('sets content for multiple slots', () =\u003e {\n  mount(ComponentWithMultipleSlots, {}, {}, { default: 'Hello World', foo: '\u003cp\u003eBar\u003c/p\u003e' })\n  expect($('.component')).to.have.html('Hello World \u003cp\u003eBar\u003c/p\u003e')\n})\n```\n\nThe 4th argument `mount()` accepts is an object with values available to be injected via the provide/inject behaviour. It is equivalent to defining `provide` on an ancestor component.\n\n#### \u003ca name=\"component-with-injects\"\u003e\u003c/a\u003eComponent with injects\n\n```js\nconst ComponentWithInjects = {\n  template: `\n    \u003cdiv class=\"component\"\u003e\n      Hello {{ message }}\n    \u003c/div\u003e\n  `,\n  inject: ['message']\n}\n\nit('provides values to be injected', () =\u003e {\n  mount(ComponentWithInjects, {}, {}, {}, { message: 'World' })\n  expect($('.component')).to.have.text('Hello World')\n})\n```\n\n### \u003ca name=\"options-object\"\u003e\u003c/a\u003eOptions Object\n\n```js\nconst ComponentWithAllOptions = {\n  template: `\n    \u003cdiv class=\"component\" @click=\"$emit('foo', message)\"\u003e\n      \u003cslot\u003e\u003c/slot\u003e\n      \u003cslot name=\"foo\"\u003e\u003c/slot\u003e\n    \u003c/div\u003e\n  `,\n  props: ['message'],\n  inject: ['messageFromAncestor']\n}\n\nit('uses an options object', () =\u003e {\n  const listener = sinon.spy()\n  const options = {\n    props: { message: 'bar' },\n    on: { foo: listener },\n    slots: { default: 'Hello World', foo: '\u003cp\u003eBar\u003c/p\u003e' },\n    provide: { messageFromAncestor, 'bar' }\n  }\n  vm = mount(ComponentWithAllOptions, options)\n  expect($('.component')).to.have.html('Hello World \u003cp\u003eBar\u003c/p\u003e')\n  simulate($('.component'), 'click')\n  expect(listener).to.have.been.calledWith('bar')\n  expect(vm.messageFromAncestor).to.equal('bar')\n})\n```\n\n| Option | Default | Type | Description |\n| --- | :---: | :---: | --- |\n| `props` | `{}` | `Object` | An object containing camelCased props to be passed to the component |\n| `on` | `{}` | `Object` | An object containing listeners to be called when an event is trigger by the component |\n| `slots` | `{}` | `Object` or `String` | String containing the template for the `default` slot of the component. Objects containing templates for slots (should be keyed by the slot name).\n| `provide` | `{}` | `Object` | An object simulating values given from parent components via Vue's `provide`. Available to the equivalent `inject` component property.\n\n### \u003ca name=\"shallow\"\u003e\u003c/a\u003e`shallow()`\n\nThe `shallow()` function has the same signature as the `mount()` function, however it will shallow render the component by replacing any **locally registered** child components with an empty kebab-cased tag of their name.\n\nThis enables you to test higher-level components without the concern of the required props or dependencies of nested child components.\n\nFor example:\n\n```js\nconst ChildComponent = {\n  name: 'child',\n  template: '\u003cspan\u003eWorld\u003c/span\u003e'\n}\nconst ComponentWithChild = {\n  template: '\u003cdiv\u003eHello \u003cchild\u003e\u003c/child\u003e\u003c/div\u003e',\n  components: { ChildComponent }\n}\n\nshallow(ComponentWithChild)\n```\n\nWould render:\n```html\n\u003cdiv\u003eHello \u003cchild\u003e\u003c/child\u003e\u003c/div\u003e\n```\n\nInstead of the actual child component.\n\n### \u003ca name=\"build-and-build-shallow\"\u003e\u003c/a\u003e`build()` and `buildShallow()`\n\nWhen testing components using `mount()` or `shallow()` it can be repetitive to list the component and select DOM elements. The `build()` and `buildShallow()` functions allow you to remove some of this repetitive by creating your own `mount()` or `shallow()` function with some default arguments and a callback.\n\nFor example given this component:\n\n```js\nconst SomeComponent = {\n  template: '\u003cp\u003e{{ message }}\u003c/p\u003e',\n  props: { foo: { default: 'default message' }}\n}\n```\n\nand this test:\n\n```js\nit('renders a default message', () =\u003e {\n  mount(SomeComponent)\n  expect($('p')).to.have.text('default message')\n})\n\nit('renders a message', () =\u003e {\n  mount(SomeComponent, { foo: 'bar' })\n  expect($('p')).to.have.text('bar')  \n})\n```\n\nWe could use `build()` like so:\n\n```js\nlet paragraph\nconst mount = build(SomeComponent, () =\u003e { paragraph = $('p') })\n\nit('renders a default message', () =\u003e {\n  mount()\n  expect(paragraph).to.have.text('default message')\n})\n\nit('renders a message', () =\u003e {\n  mount({ foo: 'bar' })\n  expect(paragraph).to.have.text('bar')  \n})\n```\n\nThis can be helpful when your components has many selectors you want to test.\n\n### \u003ca name=\"simulate\"\u003e\u003c/a\u003e`simulate(element, event)`\n\nThe `simulate()` function will trigger an HTML event on given DOM element. It can accept an DOM element or jQuery object.\n\nFor example, triggering a click event on a button would look like so:\n\n```js\nconst button1 = $('button')\nsimulate(button1, 'click')\n\nconst button2 = document.querySelector('button')\nsimulate(button2, 'click')\n```\n\n### \u003ca name=\"wait-for-update\"\u003e\u003c/a\u003e`waitForUpdate(cb)`\n\nThe `waitForUpdate()` helper function can be used to clean up a chain of async DOM assertions that you would normally have to use `Vue.nextTick()` for.\n\nFor example we could rewrite the following test:\n\n```js\nconst Component = {\n  template: `\u003cp\u003e{{ message }}\u003c/p\u003e`,\n  props: ['message']\n}\n\nit('tests message updates', () =\u003e {\n  const vm = mount(Component, { message: 'Hello' })\n  expect($(vm.$el)).to.have.text('Hello')\n  vm.message = 'World'\n  return vm.$nextTick().then(() =\u003e {\n    expect($(vm.$el)).to.have.text('World')\n    vm.message = 'VueUnit'\n    return vm.$nextTick()\n  }).then(() =\u003e {\n    expect($(vm.$el)).to.have.text('VueUnit')\n  })\n})\n```\n\nlike so:\n\n```js\nit('tests message updates', () =\u003e {\n  const vm = mount(Component, { message: 'Hello' })\n\n  expect($(vm.$el)).to.have.text('Hello')\n  vm.message = 'World'\n  waitForUpdate(() =\u003e {\n    expect($(vm.$el)).to.have.text('World')\n    vm.message = 'VueUnit'\n  }).then(() =\u003e {\n    expect($(vm.$el)).to.have.text('VueUnit')\n  }).end(done)\n```\n\nPlease note when using `waitForUpdate()` use **must** end your chain of assertions with `.end(done)` to avoid errors.\n\n### Vuex Testing\n\nVueUnit also provides helpers for isolating components from vuex getters and actions in form of `fakeGetters()` and `fakeActions()`. These functions must be called **before** mounting your component.\n\n#### \u003ca name=\"fake-getters\"\u003e\u003c/a\u003e`fakeGetters()`\n\nThe `fakeGetters()` function returns a [sinon](http://sinonjs.org/) stub which can be used to (optionally) control the value which the getter returns.\n\nFor example given this component:\n```js\nconst Component = {\n  template: '\u003cp\u003e\u003c/p\u003e',\n  computed: {\n    someValue () { return this.$store.getters.foo },\n    otherValue () { return this.$store.getters.bar }\n  }\n}\n```\nWe might test it like so:\n\n```js\nit('fakes a getter', () =\u003e {\n  const foo = fakeGetters('foo').returns(1234)\n  const vm = mount(Component)\n  expect(vm.someValue).to.equal(1234)\n})\n\nit('fakes a getter in a different way', () =\u003e {\n  fakeGetters('foo', 1234)\n  const vm = mount(Component)\n  expect(vm.someValue).to.equal(1234)\n})\n\nit('fakes multiple getters', () =\u003e {\n  fakeGetters({\n    foo: 1234,\n    bar: 5678\n  })\n  const vm = mount(Component)\n  expect(vm.someValue).to.equal(1234)\n  expect(vm.otherValue).to.equal(5678)\n})\n```\n\n#### \u003ca name=\"fake-actions\"\u003e\u003c/a\u003e`fakeActions()`\n\nThe `fakeActions()` function returns a [sinon](http://sinonjs.org/) stub which can be used to spy on the action and control what it returns.\n\nFor example given this component:\n\n```js\nconst Component = {\n  template: '\u003cp\u003e\u003c/p\u003e',\n  methods: {\n    someMethod (payload) { return this.$store.dispatch('foo', payload) },\n  }\n}\n```\n\nWe might test it like so:\n\n```js\nit ('dispatches an action', () =\u003e {\n  const fooAction = fakeActions('foo').returns('bar')\n  const vm = mount(Component)\n  return vm.someMethod(1234).then(value =\u003e {\n    expect(fooAction).to.have.been.calledOnce.and.calledWith(1234)\n    expect(value).to.equal('bar')\n  })\n})\n```\n\n### \u003ca name=\"examples\"\u003e\u003c/a\u003eExamples\n\nMore sample usage can be found in the [examples/](https://github.com/wrseward/vue-unit/tree/master/examples) directory.\n\n## \u003ca name=\"license\"\u003e\u003c/a\u003eLicense\n\n[MIT](https://github.com/wrseward/vue-unit/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwrseward%2Fvue-unit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwrseward%2Fvue-unit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwrseward%2Fvue-unit/lists"}