Skip to content

Commit 8979d00

Browse files
committed
Adds a middleware spec example
1 parent f46dd4e commit 8979d00

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

docs/_sidebar.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [Returning promises](examples/promise.md)
1414
- [ES5 usage](examples/es5.md)
1515
- [Browser usage](examples/browser.md)
16+
- [Testing a middleware](examples/testing.md)
1617

1718
- Ecosystem
1819
- [Github](https://github.com/emileber/axios-middleware)

docs/examples/testing.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Middleware spec
2+
3+
One of the great feature of this module is the ability to create easy-to-test self-contained middlewares. In order to be up to the task, it's still needed to design the middlewares in a way that makes testing easy.
4+
5+
One rule that we should follow when implementing a middleware class is to use dependency injection over locally imported modules.
6+
7+
```javascript
8+
/**
9+
* When a request fails, this middleware adds a toast message using the
10+
* injected toast service.
11+
*/
12+
export default class ApiErrorMiddleware {
13+
/**
14+
* @param {Object} i18n
15+
* @param {Object} toast message service
16+
*/
17+
constructor(i18n, toast) {
18+
this.toast = toast;
19+
this.i18n = i18n;
20+
}
21+
22+
/**
23+
* @param {Object} err
24+
*/
25+
onResponseError(err = {}) {
26+
let key = 'errors.default';
27+
const { response } = err;
28+
29+
if (response && this.i18n.te(`errors.${response.status}`)) {
30+
key = `errors.${response.status}`;
31+
} else if (err.message === 'Network Error') {
32+
key = 'errors.network-error';
33+
}
34+
35+
this.toast.error(this.i18n.t(key));
36+
throw err;
37+
}
38+
}
39+
```
40+
41+
Then, this is a spec example using [Jest](https://jestjs.io/).
42+
43+
```javascript
44+
import ApiErrorMiddleware from '@/middlewares/ApiErrorMiddleware';
45+
46+
let hasKey = false;
47+
48+
// Simple translation mock, making it easier to compare results.
49+
const i18n = {
50+
t: key => key,
51+
te: () => hasKey,
52+
};
53+
54+
const errors = {
55+
unhandledCode: { response: { status: 999 } },
56+
notfound: { response: { status: 404 } },
57+
unhandledMessage: { message: 'test message' },
58+
networkError: { message: 'Network Error' },
59+
};
60+
61+
describe('ApiErrorMiddleware', () => {
62+
let toast;
63+
let middleware;
64+
65+
/**
66+
* Jest needs a function when we're expecting an error to be thrown.
67+
*
68+
* @param {Object} err
69+
* @return {function(): *}
70+
*/
71+
function onResponseError(err) {
72+
return () => middleware.onResponseError(err);
73+
}
74+
75+
beforeEach(() => {
76+
toast = { error: jest.fn() };
77+
middleware = new ApiErrorMiddleware(i18n, toast);
78+
});
79+
80+
it('sends a default error message if not handled', () => {
81+
expect(onResponseError()).toThrow();
82+
expect(toast.error).toHaveBeenLastCalledWith('errors.default');
83+
84+
expect(onResponseError(errors.unhandledCode)).toThrow();
85+
expect(toast.error).toHaveBeenLastCalledWith('errors.default');
86+
87+
expect(onResponseError(errors.unhandledMessage)).toThrow();
88+
expect(toast.error).toHaveBeenLastCalledWith('errors.default');
89+
});
90+
91+
it('sends a code error message', () => {
92+
hasKey = true;
93+
expect(onResponseError(errors.notfound)).toThrow();
94+
expect(toast.error).toHaveBeenLastCalledWith('errors.404');
95+
});
96+
97+
it('sends a network error message', () => {
98+
hasKey = false;
99+
expect(onResponseError(errors.networkError)).toThrow();
100+
expect(toast.error).toHaveBeenLastCalledWith('errors.network-error');
101+
});
102+
});
103+
```

0 commit comments

Comments
 (0)