[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