Skip to content

Commit 79cd588

Browse files
authored
Merge pull request #43 from relekang/adapter-tests
Add unit tests for adapters
2 parents 3f3ff19 + 4294132 commit 79cd588

File tree

5 files changed

+755
-644
lines changed

5 files changed

+755
-644
lines changed

adapter-tests/unit-tests.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
module.exports = function testAdapter(options) {
2+
describe('micro-analytics adapter ' + options.name, () => {
3+
const adapter = require(options.modulePath);
4+
5+
if (typeof options.beforeEach === 'function') {
6+
beforeEach(async () => { await options.beforeEach(adapter); });
7+
}
8+
9+
if (typeof options.afterEach === 'function') {
10+
afterEach(async () => { await options.afterEach(adapter); });
11+
}
12+
13+
if (typeof options.beforeAll === 'function') {
14+
beforeAll(async () => { await options.beforeAll(adapter); });
15+
}
16+
17+
if (typeof options.afterAll === 'function') {
18+
afterAll(async () => {
19+
await options.afterAll(adapter);
20+
if (typeof adapter.close === 'function') {
21+
await adapter.close();
22+
}
23+
});
24+
}
25+
26+
it('should save and read', async () => {
27+
await adapter.put('/a-key', { views: [{ time: 1490623474639 }] });
28+
29+
expect(await adapter.get('/a-key')).toEqual({
30+
views: [{ time: 1490623474639 }],
31+
});
32+
});
33+
34+
it('should return all saves on getAll', async () => {
35+
await adapter.put('/a-key', { views: [{ time: 1490623474639 }] });
36+
await adapter.put('/another-key', { views: [{ time: 1490623474639 }] });
37+
38+
expect(await adapter.getAll({ pathname: '/' })).toEqual({
39+
'/a-key': { views: [{ time: 1490623474639 }] },
40+
'/another-key': { views: [{ time: 1490623474639 }] },
41+
});
42+
});
43+
44+
it('should have check whether a key is stored with has', async () => {
45+
await adapter.put('/a-key', { views: [{ time: 1490623474639 }] });
46+
47+
expect(await adapter.has('/a-key')).toEqual(true);
48+
expect(await adapter.has('/non-existing-key')).toEqual(false);
49+
});
50+
51+
if (typeof adapter.subscribe === "function") {
52+
53+
it('should allow subscription with observables', async () => {
54+
const listener = jest.fn();
55+
const unsubscribe = adapter.subscribe(listener);
56+
57+
await adapter.put('/a-key', { views: [{ time: 1490623474639 }] });
58+
59+
expect(listener).toHaveBeenCalledWith({
60+
key: '/a-key',
61+
value: { views: [{ time: 1490623474639 }] },
62+
});
63+
});
64+
65+
it('should allow multiple subscription with observables and handle unsubscribption', async () => {
66+
const listener1 = jest.fn();
67+
const listener2 = jest.fn();
68+
const subscription = adapter.subscribe(listener1);
69+
adapter.subscribe(listener2);
70+
71+
await adapter.put('/a-key', { views: [{ time: 1490623474639 }] });
72+
subscription.unsubscribe();
73+
await adapter.put('/b-key', { views: [{ time: 1490623474639 }] });
74+
75+
expect(listener1).toHaveBeenCalledWith({
76+
key: '/a-key',
77+
value: { views: [{ time: 1490623474639 }] },
78+
});
79+
expect(listener1).not.toHaveBeenCalledWith({
80+
key: '/b-key',
81+
value: { views: [{ time: 1490623474639 }] },
82+
});
83+
expect(listener2).toHaveBeenCalledWith({
84+
key: '/a-key',
85+
value: { views: [{ time: 1490623474639 }] },
86+
});
87+
expect(listener2).toHaveBeenCalledWith({
88+
key: '/b-key',
89+
value: { views: [{ time: 1490623474639 }] },
90+
});
91+
});
92+
}
93+
});
94+
};

adapter-tests/unit-tests.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const { mockDb } = require('../tests/utils')
2+
3+
jest.mock('flat-file-db', () => mockDb)
4+
5+
const test = require('./unit-tests')
6+
7+
test({
8+
name: 'flat-file-db',
9+
modulePath: 'micro-analytics-adapter-flat-file-db',
10+
beforeEach: async () => {
11+
mockDb._reset()
12+
},
13+
})

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@
3333
},
3434
"devDependencies": {
3535
"async-to-gen": "^1.3.0",
36-
"babel-jest": "^18.0.0",
36+
"babel-jest": "^19.0.0",
3737
"babel-plugin-transform-async-to-generator": "^6.16.0",
3838
"babel-polyfill": "^6.20.0",
3939
"babel-preset-node6": "^11.0.0",
40-
"jest": "^18.1.0",
40+
"jest": "^19.0.2",
4141
"request-promise": "^4.1.1"
4242
},
4343
"execMap": {

writing-adapters.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,26 @@ subscription.unsubscribe()
184184
```
185185

186186
> **Note:** If your database of choice does not support subscriptions, it is fine not to have `adapter.subscribe` as long as you mention that visibly in your documentation.
187+
188+
## Tests
189+
190+
There is pre-written tests for adapters that you can use to make sure you adapter is implemented
191+
correctly. These can be easily used by adding jest and micro-analytics-cli as a dev dependency to your adapter(e.g. `npm install --save-dev micro-analytics-cli jest`). Then create a test file like the one below.
192+
193+
```js
194+
const test = require('micro-analytics-cli/adapter-tests/unit-tests')
195+
196+
test({
197+
name: 'adapter-name',
198+
modulePath: path.resolve(__dirname, './index.js'),
199+
})
200+
```
201+
202+
The option object takes the following properties.
203+
204+
* `name` - The name of the adapter
205+
* `modulePath` - The absolute path to the file you refer to in main in package.json
206+
* `beforeEach` - Will be called in jest beforeEach hook, return a promise if it needs to do something async. We recommend cleaning the database here.
207+
* `afterEach` - Will be called in jest afterEach hook, return a promise if it needs to do something async.
208+
* `beforeAll` - Will be called in jest beforeAll hook, return a promise if it needs to do something async.
209+
* `afterAll` - Will be called in jest afterAll hook, return a promise if it needs to do something async.

0 commit comments

Comments
 (0)