source: frontend/node_modules/eslint-plugin-jest/docs/rules/no-conditional-expect.md

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 13 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 3.3 KB
Line 
1# Prevent calling `expect` conditionally (`no-conditional-expect`)
2
3This rule prevents the use of `expect` in conditional blocks, such as `if`s &
4`catch`s.
5
6This includes using `expect` in callbacks to functions named `catch`, which are
7assumed to be promises.
8
9## Rule Details
10
11Jest only considers a test to have failed if it throws an error, meaning if
12calls to assertion functions like `expect` occur in conditional code such as a
13`catch` statement, tests can end up passing but not actually test anything.
14
15Additionally, conditionals tend to make tests more brittle and complex, as they
16increase the amount of mental thinking needed to understand what is actually
17being tested.
18
19While `expect.assertions` & `expect.hasAssertions` can help prevent tests from
20silently being skipped, when combined with conditionals they typically result in
21even more complexity being introduced.
22
23The following patterns are warnings:
24
25```js
26it('foo', () => {
27 doTest && expect(1).toBe(2);
28});
29
30it('bar', () => {
31 if (!skipTest) {
32 expect(1).toEqual(2);
33 }
34});
35
36it('baz', async () => {
37 try {
38 await foo();
39 } catch (err) {
40 expect(err).toMatchObject({ code: 'MODULE_NOT_FOUND' });
41 }
42});
43
44it('throws an error', async () => {
45 await foo().catch(error => expect(error).toBeInstanceOf(error));
46});
47```
48
49The following patterns are not warnings:
50
51```js
52it('foo', () => {
53 expect(!value).toBe(false);
54});
55
56function getValue() {
57 if (process.env.FAIL) {
58 return 1;
59 }
60
61 return 2;
62}
63
64it('foo', () => {
65 expect(getValue()).toBe(2);
66});
67
68it('validates the request', () => {
69 try {
70 processRequest(request);
71 } catch {
72 // ignore errors
73 } finally {
74 expect(validRequest).toHaveBeenCalledWith(request);
75 }
76});
77
78it('throws an error', async () => {
79 await expect(foo).rejects.toThrow(Error);
80});
81```
82
83### How to catch a thrown error for testing without violating this rule
84
85A common situation that comes up with this rule is when wanting to test
86properties on a thrown error, as Jest's `toThrow` matcher only checks the
87`message` property.
88
89Most people write something like this:
90
91```typescript
92describe('when the http request fails', () => {
93 it('includes the status code in the error', async () => {
94 try {
95 await makeRequest(url);
96 } catch (error) {
97 expect(error).toHaveProperty('statusCode', 404);
98 }
99 });
100});
101```
102
103As stated above, the problem with this is that if `makeRequest()` doesn't throw
104the test will still pass as if the `expect` had been called.
105
106While you can use `expect.assertions` & `expect.hasAssertions` for these
107situations, they only work with `expect`.
108
109A better way to handle this situation is to introduce a wrapper to handle the
110catching, and otherwise returns a specific "no error thrown" error if nothing is
111thrown by the wrapped function:
112
113```typescript
114class NoErrorThrownError extends Error {}
115
116const getError = async <TError>(call: () => unknown): Promise<TError> => {
117 try {
118 await call();
119
120 throw new NoErrorThrownError();
121 } catch (error: unknown) {
122 return error as TError;
123 }
124};
125
126describe('when the http request fails', () => {
127 it('includes the status code in the error', async () => {
128 const error = await getError(async () => makeRequest(url));
129
130 // check that the returned error wasn't that no error was thrown
131 expect(error).not.toBeInstanceOf(NoErrorThrownError);
132 expect(error).toHaveProperty('statusCode', 404);
133 });
134});
135```
Note: See TracBrowser for help on using the repository browser.