Skip to content

Commit df40f88

Browse files
committed
docs: Add documentation for custom matchers
1 parent c972b8c commit df40f88

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Testing with Custom Matchers
2+
3+
Testing utilities like Jasmine, and Jest often provide conditionals like `toBeEqual` or `toHaveBeenCalledWith` to check that a piece of code has an expected outcome. However, more often than not, a project might have a unique set of conditions that it might want to check against that are not included in Jasmine or Jest. For example, if you wanted to test that something is a component, you could could create a method called `isAComponent` and check whether the return value of that method is true
4+
5+
```JS
6+
import BaseComponent from './BaseComponent'
7+
import { isPlainObject } from 'lodash'
8+
9+
describe('@components/baseComponent', () => {
10+
let isAComponent
11+
beforeEach(() => {
12+
isAComponent = (comp) => {
13+
return isPlainObject(comp) && typeof comp.render === 'function'
14+
}
15+
})
16+
it('exports a valid component', () => {
17+
const isValidComponent = isAComponent(BaseComponent)
18+
expect(isValidComponent).toBe(true)
19+
})
20+
})
21+
```
22+
23+
While testing in this manner works, your code will have to be replicated when you have to test for whether something is a component across multiple specs. Thankfully, test libraries like Jest and Jasmine offer a solution to this problem via custom matchers.
24+
25+
## Custom Matchers
26+
27+
Custom matchers allow you to encapsulate custom matching code for use across multiple tests. A custom matcher is a comparison function that compares an actual value with an expected value. Ideally, a custom matcher is created in a beforeEach block or in a separate setup file that your test library uses to run tests.
28+
29+
### Jasmine
30+
31+
To create a custom matcher and append it to Jasmine, you can use `jasmine.addMatchers`. For the exact documentation of this API, refer to the [Jasmine docs](https://jasmine.github.io/2.0/custom_matcher.html).
32+
33+
34+
```JS
35+
import BaseComponent from './BaseComponent'
36+
37+
describe('@components', () => {
38+
beforeEach(() => {
39+
jasmine.addMatchers({
40+
toBeAComponent: () => {
41+
const isAComponent = () => {
42+
return _.isPlainObject(options) && typeof options.render === 'function'
43+
}
44+
return {
45+
compare: (options) => {
46+
const result = isAComponent(options)
47+
if(result.pass) {
48+
result.message = `expected ${this.utils.printReceived(
49+
options
50+
)} not to be a Vue component`
51+
} else {
52+
result.message = `expected ${this.utils.printReceived(
53+
options
54+
)} to be a valid Vue component, exported from a .vue file`
55+
}
56+
return result
57+
}
58+
}
59+
}
60+
})
61+
})
62+
describe('@components/baseComponent', () => {
63+
it('exports a valid component', () => {
64+
const isValidComponent = isAComponent(BaseComponent)
65+
expect(isValidComponent).toBeAComponent()
66+
})
67+
})
68+
})
69+
```
70+
71+
### Jest
72+
73+
To create a custom matcher and append it to Jest, you can use `expect.extend`. For the exact documentation of this API, refer to the [Jest docs](https://facebook.github.io/jest/docs/en/expect.html#expectextendmatchers).
74+
75+
```JS
76+
import BaseComponent from './BaseComponent'
77+
78+
describe('@components', () => {
79+
beforeEach(() => {
80+
expect.extend({
81+
toBeAComponent: (options) => {
82+
if (isAComponent()) {
83+
return {
84+
message: () =>
85+
`expected ${this.utils.printReceived(
86+
options
87+
)} not to be a Vue component`,
88+
pass: true,
89+
}
90+
} else {
91+
return {
92+
message: () =>
93+
`expected ${this.utils.printReceived(
94+
options
95+
)} to be a valid Vue component, exported from a .vue file`,
96+
pass: false,
97+
}
98+
}
99+
function isAComponent() {
100+
return _.isPlainObject(options) && typeof options.render === 'function'
101+
}
102+
}
103+
})
104+
})
105+
describe('@components/baseComponent', () => {
106+
it('exports a valid component', () => {
107+
const isValidComponent = isAComponent(BaseComponent)
108+
expect(isValidComponent).toBeAComponent()
109+
})
110+
})
111+
})
112+
```
113+
114+
You can also extrapolate the code in the beforeEach block into a separate file and then update your `jest.config` file to include the matcher file to ensure that jest accounts for custom matchers when it runs your tests.
115+
116+
```JS
117+
const customMatchers = {}
118+
customMatchers.isAComponent = () => {...}
119+
global.expect.extend(customMatchers)
120+
```
121+
122+
```JS
123+
module.exports = {
124+
...
125+
setupTestFrameworkScriptFile: '<rootDir>/tests/unit/matchers'
126+
};
127+
```

0 commit comments

Comments
 (0)