vue-function-tester makes method unit testing for Vue components easier and shorter by providing mock functions and helper objects.
Providing mock functions and helper objects for unit testing and they help to reduce steps and codes.
Supporting...
- methods
- lifecycle hooks
- computed
- watch
vue-function-helper dependents on Jest.
$ npm install -D vue-function-tester
or
$ yarn add -D vue-function-tester
See spec if you want more detailed examples.
// SampleComponent.vue
export default {
data() {
return {
liked: false
};
},
methods: {
sayHi() {
return 'Hi!';
},
sayHiWithName(firstname: string, lastname: string) {
return `Hi, ${firstname} ${lastname}`!;
},
like() {
this.liked = true;
},
callOtherMethod() {
return this.otherMethod();
},
otherMethod() {
// called by other methods
},
emitEvent () {
this.$emit('some-event', 'value')
},
async asyncMethod() {
let returnVal = '';
const sleep = () =>
new Promise((resolve) => {
setTimeout(() => {
returnVal = 'returned!';
resolve();
}, 100);
});
await sleep();
return returnVal;
},
}
}
// yourMethodsTest.spec.js
import SampleComponent from './SampleComponent.vue';
import { methods } from 'vue-function-tester';
describe('Methods', () => {
// extracts mock methods from your component.
const { sayHi, sayHiWithName, like, callOtherMethod, emitEvent, asyncMethod } = methods(SampleComponent);
it('returns value', () => {
const result = sayHi().run();
expect(result.return).toBe('Hi!');
});
it('returns value with args', () => {
const result = sayHiWithName('Tom', 'Smith').run();
expect(result.return).toBe('Hi, Tom Smith!');
});
it('chaneges context value', () => {
// like method changes data property `liked` to true
const result = like().run({ liked: false });
expect(result.liked).toBe(true);
});
it('calls other methods', () => {
// automatically setup jest.fn() inside target function.
const result = callOtherMethod().run();
expect(result.otherMethod).toBeCalled();
});
it('overrides default jest.fn()', () => {
const result = callOtherMethod().run({
otherMethod: jest.fn(() => 'override')
});
expect(result.return).toBe('override');
});
it('emits event', () => {
const result = emitEvent().run();
expect(result.$emit).toBeCalledWith('some-event', 'value');
});
it('returns val by async/await', async () => {
const result = await asyncMethod().run();
expect(result.return).toBe('returned!');
});
});
See spec if you want more detailed examples.
// SampleComponent.vue
export default {
data() {
return {
updatedCount: 0,
loading: false
};
},
async created () {
this.loading = true;
await this.asyncMethod();
this.loading = false;
},
mounted() {
this.otherMethod();
},
updated() {
this.updatedCount++;
},
beforeRouteEnter(_to: string, _from: string, next: Function) {
next();
},
methods: {
async asyncMethod () {
// ...
}
}
});
// yourHooksTest.spec.js
import SampleComponent from './SampleComponent.vue';
import { hooks } from 'vue-function-tester';
describe('Lifecycle Hooks', () => {
const { mounted, updated, beforeRouteEnter, created } = hooks(SampleComponent);
it('calls other method', () => {
expect(mounted().run().otherMethod).toBeCalled();
});
it('registers additional hooks', () => {
const { beforeRouteEnter } = hooks(
SampleComponent,
['beforeRouteEnter'] // be able to regist additional hooks like vue-router
);
const next = jest.fn();
beforeRouteEnter('', '', next).run()
expect(next).toBeCalled();
});
it('finishs loading with async method', async () => {
const result = await created.r();
expect(result.loading).toBe(false);
expect(result.asyncMethod).toBeCalled();
});
});
See spec if you want more detailed examples.
// SampleComponent.vue
export default {
computed: {
sayHello() {
return 'Hello!';
},
displayName: {
get() {
return `Mr. ${this.name}`;
},
set(newName) {
this.$emit('change-name', newName);
}
}
},
});
// yourComputedTest.spec.js
import SampleComponent from './SampleComponent.vue';
import { computed } from 'vue-function-tester';
describe('Computed', () => {
const { sayHello, displayName } = computed(SampleComponent);
it('returns value', () => {
expect(sayHello().run().return).toBe('Hello!');
expect(displayName.get().run().return).toContain('Mr');
});
describe('getter/setter', () => {
it('applys context value to getter', () => {
const result = displayName.get().run({ name: 'Tom' });
expect(result.return).toBe('Mr. Tom');
});
it('emits event by setter', () => {
const result = displayName.set('Tom').run();
expect(result.$emit).toBeCalledWith('change-name', 'Tom');
});
})
});
See spec if you want more detailed examples.
// SampleComponent.vue
export default {
props: {
count: {
type: Number,
required: true
}
},
data () {
return {
output: ''
}
},
watch: {
count (newVal) {
if (newVal % 15 === 0) {
this.output = 'Fizz Buzz'
} else {
this.otherMethod();
}
}
},
methods: {
otherMethod () { ... }
}
});
// yourWatchTest.spec.js
import SampleComponent from './SampleComponent.vue';
import { watch } from 'vue-function-tester';
describe('Watch', () => {
const { count } = watch(SampleComponent);
describe('mock methods', () => {
it('calls other method', () => {
expect(count(1).run().otherMethod).toBeCalled();
});
});
describe('context', () => {
it('chaneges output', () => {
const result = count(15).run({ output: '' });
expect(result.output).toBe('Fizz Buzz');
});
});
});
vue-function-test provides some alias.
// normal usage
expect(sayHi().run().return).toBe('Hi!');
// shorten run
expect(sayHi().r().return).toBe('Hi!');
// function properties
expect(sayHi.run().return).toBe('Hi!');
expect(sayHi.r().return).toBe('Hi!');
MIT