[Pkg-javascript-commits] [node-tap] 49/186: a little util for making and saving snapshots
Bastien Roucariès
rouca at moszumanska.debian.org
Fri Dec 1 16:40:42 UTC 2017
This is an automated email from the git hooks/post-receive script.
rouca pushed a commit to branch master
in repository node-tap.
commit 0f3dc9b4b214143227321c340e9e3da7d6f8cb81
Author: isaacs <i at izs.me>
Date: Mon Oct 30 22:52:45 2017 -0700
a little util for making and saving snapshots
First pass, possibly bad. Need to play test it a little bit.
---
lib/snapshot.js | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
lib/test.js | 34 ++++++++++++++++++++++++++++++++++
package-lock.json | 32 ++++++++++++++++++++------------
package.json | 1 +
unit/snapshot.js | 44 ++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 150 insertions(+), 12 deletions(-)
diff --git a/lib/snapshot.js b/lib/snapshot.js
new file mode 100644
index 0000000..6fed645
--- /dev/null
+++ b/lib/snapshot.js
@@ -0,0 +1,51 @@
+'use strict'
+
+const writeFile = require('write-file-atomic')
+const fs = require('fs')
+const mkdirp = require('mkdirp')
+const path = require('path')
+
+class Snapshot {
+ constructor (test) {
+ this.indexes = new Map()
+ this.test = test
+ this.file = path.resolve(
+ process.cwd(),
+ 'tap-snapshots',
+ this.test.fullname.replace(/[^a-zA-Z0-9\._\-]+/g, '-')
+ )
+ this.snapshot = null
+ }
+
+ // should only ever call _one_ of match/save
+ match (data, message) {
+ // XXX test line-by-line instead of all at once
+ const index = this.indexes.get(message) || 0
+ this.indexes.set(message, index + 1)
+ try {
+ this.snapshot = this.snapshot || require(this.file)
+ } catch (er) {
+ throw new Error('Snapshot file not found\n' +
+ 'Run with TAP_SNAPSHOT=1 in the environment\n' +
+ 'to create snapshot files')
+ }
+ return this.snapshot[message + '_' + index] === data
+ }
+
+ snap (data, message) {
+ const index = this.indexes.get(message) || 0
+ this.indexes.set(message, index + 1)
+ this.snapshot = this.snapshot || {}
+ this.snapshot[message + '_' + index] = data
+ }
+
+ save () {
+ const data = `'use strict'\n` + (
+ Object.keys(this.snapshot).map(s =>
+ `exports[\`${s}\`] = \`${this.snapshot[s]}\`\n`).join('\n'))
+ mkdirp.sync(path.dirname(this.file))
+ writeFile.sync(this.file, data, 'utf8')
+ }
+}
+
+module.exports = Snapshot
diff --git a/lib/test.js b/lib/test.js
index d92938a..a15a18a 100644
--- a/lib/test.js
+++ b/lib/test.js
@@ -25,6 +25,7 @@ const Pool = require('yapool')
const TestPoint = require('./point.js')
const parseTestArgs = require('./parse-test-args.js')
const loop = require('function-loop')
+const path = require('path')
const extraFromError = require('./extra-from-error.js')
const tsame = require('tsame') // same thing, strict or not
@@ -46,6 +47,8 @@ const IMPLICIT = Symbol('implicit t.end()')
const EOF = Symbol('EOF')
const _end = Symbol('_end')
+const _snapshot = Symbol('_snapshot')
+const Snapshot = require('./snapshot.js')
const hasOwn = (obj, key) =>
Object.prototype.hasOwnProperty.call(obj, key)
@@ -56,6 +59,13 @@ class Test extends Base {
super(options)
this.pushedEnd = false
this.jobs = ownOr(options, 'jobs', 1)
+
+ this[_snapshot] = new Snapshot(this)
+ this.writeSnapshot = ownOrEnv(
+ options, 'snapshot', 'TAP_SNAPSHOT', true)
+ if (this.writeSnapshot)
+ this.teardown(_ => this[_snapshot].save())
+
this.subtests = []
this.pool = new Pool()
this.queue = ['TAP version 13\n']
@@ -928,6 +938,30 @@ class Test extends Base {
return this.notOk(tsame.strict(found, wanted), message, extra)
}
+ get fullname () {
+ return (this.parent ? this.parent.fullname
+ : path.basename(process.argv[1])) +
+ ' ' + (this.name || '').trim()
+ }
+
+ matchSnapshot (found, message, extra) {
+ if (!this.currentAssert)
+ this.currentAssert = Test.prototype.matchSnapshot
+
+ if (message && typeof message === 'object')
+ extra = message, message = 'must match snapshot'
+
+ if (!extra)
+ extra = {}
+
+ // use notOk because snap doesn't return a truthy value
+ return this.writeSnapshot
+ ? this.notOk(this[_snapshot].snap(found, message),
+ message, extra)
+ : this.ok(this[_snapshot].match(found, message),
+ message, extra)
+ }
+
match (found, wanted, message, extra) {
if (!this.currentAssert)
this.currentAssert = Test.prototype.match
diff --git a/package-lock.json b/package-lock.json
index ac6552f..3809e72 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -795,8 +795,7 @@
"graceful-fs": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
- "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
- "dev": true
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
},
"har-validator": {
"version": "2.0.6",
@@ -852,8 +851,7 @@
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
- "dev": true
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
},
"inflight": {
"version": "1.0.6",
@@ -2925,14 +2923,6 @@
"xtend": "4.0.1"
}
},
- "string_decoder": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
- "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
- "requires": {
- "safe-buffer": "5.1.1"
- }
- },
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@@ -2944,6 +2934,14 @@
"strip-ansi": "3.0.1"
}
},
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
"stringstream": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
@@ -3207,6 +3205,16 @@
"mkdirp": "0.5.1"
}
},
+ "write-file-atomic": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz",
+ "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "imurmurhash": "0.1.4",
+ "signal-exit": "3.0.2"
+ }
+ },
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
diff --git a/package.json b/package.json
index 314124e..acbb05a 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"tmatch": "^3.1.0",
"trivial-deferred": "^1.0.1",
"tsame": "^1.1.2",
+ "write-file-atomic": "^2.3.0",
"yapool": "^1.0.0"
},
"keywords": [
diff --git a/unit/snapshot.js b/unit/snapshot.js
new file mode 100644
index 0000000..25f1cae
--- /dev/null
+++ b/unit/snapshot.js
@@ -0,0 +1,44 @@
+'use strict'
+const t = require('../')
+const Snapshot = require('../lib/snapshot.js')
+const rimraf = require('rimraf')
+const mkdirp = require('mkdirp')
+const path = require('path')
+const dir = path.resolve(__dirname, 'snapshot')
+const fs = require('fs')
+
+t.test('cleanup first', t => {
+ rimraf.sync(dir)
+ mkdirp.sync(dir)
+ process.chdir(dir)
+ t.end()
+})
+
+t.test('actual test', t => {
+ t.comment('not using subtests, because snapshots are per-test')
+
+ t.test('checking snapshot without creating throws', t => {
+ const s = new Snapshot(t)
+ t.throws(_ => s.match('asdf', 'asdf'))
+ t.end()
+ })
+
+ const s = new Snapshot(t)
+ t.comment('create some snapshots')
+ s.snap(fs.readFileSync(__filename, 'utf8'), 'this file')
+ s.snap('this is fine', 'a statement of acceptance')
+ s.save()
+
+ t.comment('now check that the snapshots are valid')
+ const ss = new Snapshot(t)
+ t.ok(ss.match(fs.readFileSync(__filename, 'utf8'), 'this file'))
+ t.ok(ss.match('this is fine', 'a statement of acceptance'))
+
+ t.end()
+})
+
+t.test('cleanup after', t => {
+ rimraf.sync(dir)
+ process.chdir(__dirname)
+ t.end()
+})
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-tap.git
More information about the Pkg-javascript-commits
mailing list