UNPKG

5.58 kBMarkdownView Raw
1# schema-shot
2
3> Framework-agnostic snapshot testing using "schema by example" for highly dynamic data
4
5[![NPM][npm-icon] ][npm-url]
6
7[![Build status][ci-image] ][ci-url]
8[![semantic-release][semantic-image] ][semantic-url]
9[![js-standard-style][standard-image]][standard-url]
10
11If you like [snap-shot][snap-shot] (snapshot testing for any JS framework),
12but have data that is hard to pin down, maybe this package will be useful.
13Instead of storing *literal* data snapshot, it stores [json-schema][json-schema]
14derived from a the snapshot object seen **first time** (using
15[validate-by-example][validate-by-example] to derive it). Next time an object
16arrives, it will be validated against the *schema*. Any missing property,
17or new one will trigger an exception.
18
19## Example
20
21Imagine we are fetching most popular item from an API service. Obviously
22it changes often, so we cannot just store it as a snapshot for direct
23comparison. We could massage the data and derive
24[invariant snapshots][snapshot testing], but that is boilerplate code!
25
26Instead, use `schema-shot`!
27
28```sh
29npm install --save-dev schema-shot
30```
31
32In your test
33
34```js
35// spec.js
36const schemaShot = require('schema-shot')
37it('returns most popular item', () => {
38 const top = api.getMostPopularItem()
39 schemaShot(top)
40})
41```
42
43Suppose first time it runs, the API returns `top = {id: '45a12e'}` - an object
44with just its `id` property. The `__snapshots__/spec.js.schema-shot` file
45will be saved with
46
47```js
48exports['returns most popular item 1'] = {
49 "$schema": "http://json-schema.org/draft-04/schema#",
50 "type": "object",
51 "properties": {
52 "id": {
53 "type": "string",
54 "required": true
55 }
56 },
57 "additionalProperties": false
58}
59```
60
61Now imagine the same day later running again. The API returns something else,
62but the object still has same *shape*, just a different id `{id: 8812f0}`.
63This object passes the schema validation step.
64
65A week later, the new API version gets deployed. Now it returns the top
66item, but instead of `id` property, it returns `uuid` property. The test
67will fail!
68
69```sh
70$ npm test
71Error: schema difference
72 data has additional properties
73 data.id: is required
74```
75
76[json-schema]: http://json-schema.org/
77[validate-by-example]: https://github.com/bahmutov/validate-by-example
78[snapshot testing]: https://glebbahmutov.com/blog/snapshot-testing/
79
80## Difference with snapshot testing
81
82The schema shots do not store the direct information. A good example is
83a test using [snap-shot][snap-shot] and [fake-todos][fake-todos] in
84[test/todos-spec.js](test/todos-spec.js). The snapshot test always fails
85on the second run, because a returned todo is *different*. The JSON
86schema on the other hand stays consistent, as long as *fake-todos*
87returns objects with same shape.
88
89```js
90const snapshot = require('snap-shot')
91const schemaShot = require('schema-shot')
92const generate = require('fake-todos')
93describe('fake-todos', () => {
94 it.skip('returns a different todo', () => {
95 const todos = generate(1)
96 snapshot(todos[0])
97 /*
98 Fails of course, because every todo is different
99 1) fake-todos returns a different todo:
100 Error: snapshot difference
101 {
102 id: "4e040570-..." => "129a55b4-..."
103 what: "do adults" => "skip chess"
104 }
105 */
106 })
107 it('returns a todo', () => {
108 const todos = generate(1)
109 schemaShot(todos[0])
110 })
111})
112```
113
114[snap-shot]: https://github.com/bahmutov/snap-shot
115[fake-todos]: https://github.com/bahmutov/fake-todos
116
117### Small print
118
119Author: Gleb Bahmutov <gleb.bahmutov@gmail.com> © 2017
120
121* [@bahmutov](https://twitter.com/bahmutov)
122* [glebbahmutov.com](http://glebbahmutov.com)
123* [blog](http://glebbahmutov.com/blog)
124
125License: MIT - do anything with the code, but don't blame me if it does not work.
126
127Support: if you find any problems with this module, email / tweet /
128[open issue](https://github.com/bahmutov/schema-shot/issues) on Github
129
130## MIT License
131
132Copyright (c) 2017 Gleb Bahmutov <gleb.bahmutov@gmail.com>
133
134Permission is hereby granted, free of charge, to any person
135obtaining a copy of this software and associated documentation
136files (the "Software"), to deal in the Software without
137restriction, including without limitation the rights to use,
138copy, modify, merge, publish, distribute, sublicense, and/or sell
139copies of the Software, and to permit persons to whom the
140Software is furnished to do so, subject to the following
141conditions:
142
143The above copyright notice and this permission notice shall be
144included in all copies or substantial portions of the Software.
145
146THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
147EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
148OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
149NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
150HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
151WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
152FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
153OTHER DEALINGS IN THE SOFTWARE.
154
155[npm-icon]: https://nodei.co/npm/schema-shot.svg?downloads=true
156[npm-url]: https://npmjs.org/package/schema-shot
157[ci-image]: https://travis-ci.org/bahmutov/schema-shot.svg?branch=master
158[ci-url]: https://travis-ci.org/bahmutov/schema-shot
159[semantic-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
160[semantic-url]: https://github.com/semantic-release/semantic-release
161[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg
162[standard-url]: http://standardjs.com/