Skip to content

Commit

Permalink
feat: load custom pre-compare, compare and store functions 350 (#351)
Browse files Browse the repository at this point in the history
* feat: adding compare fn module option

* chore: passing tests with custom functions

* feat: add pre-compare function
  • Loading branch information
bahmutov authored May 7, 2019
1 parent 185e54c commit 273fcea
Show file tree
Hide file tree
Showing 16 changed files with 246 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
node_modules/
.DS_Store
npm-debug.log
temp-test-*
temp-*
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,27 @@ Run with environment variable `DEBUG=snap-shot-it ...` to see log messages.
Because under the hood it uses [snap-shot-core][snap-shot-core] you might
want to show messages from both libraries with `DEBUG=snap-shot* ...`

## Data callbacks

You can pass your own NPM modules as `pre-compare`, `compare` and `store` functions using `package.json`. For example, to use both local and 3rd party NPM modules

```json
{
"config": {
"snap-shot-it": {
"pre-compare": "./pre-compare",
"compare": "snap-shot-compare",
"store": "./store"
}
}
}
```

Each NPM module in this case should export a definition of a function that matches the expected core function

- `pre-compare` is simply an identity or transformation function
- `compare` should match [snap-shot-core#compare-function](/~https://github.com/bahmutov/snap-shot-core#compare-function), for example see [snap-shot-compare](/~https://github.com/bahmutov/snap-shot-compare)
- `store` is another identity or transformation function, see [snap-shot-core#store-function](/~https://github.com/bahmutov/snap-shot-core#store-function)

## Nested snapshots

Expand Down
14 changes: 11 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"dont-crack": "1.2.1",
"eslint": "5.16.0",
"eslint-plugin-immutable": "1.0.0",
"folktale": "2.3.2",
"git-issues": "1.3.1",
"lazy-ass": "1.6.0",
"license-checker": "25.0.1",
Expand Down
78 changes: 78 additions & 0 deletions src/subfolders-spec.js → src/e2e-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const copyFolder = (sourceFolder, tempFolder) => {
shell.rm('-rf', tempFolder)
shell.mkdir(tempFolder)
shell.cp(join(sourceFolder, 'package.json'), tempFolder)
shell.cp(join(sourceFolder, '*.js'), tempFolder)
shell.cp('-R', join(sourceFolder, 'specs'), tempFolder)
}

Expand Down Expand Up @@ -172,3 +173,80 @@ describe('snapshots in same folder', () => {
})
})
})

describe('custom compare function', () => {
// folder with specs to run
const sourceFolder = join(__dirname, '..', 'test-custom-compare-fn')
// temp folder to copy to before running tests
const tempFolder = join(__dirname, '..', 'temp-custom-compare-fn')

beforeEach(() => {
copyFolder(sourceFolder, tempFolder)
})

it('transforms value ', function () {
this.timeout(5000)

execa.shellSync('npm test', {
cwd: tempFolder,
stdio: 'inherit',
// only use the limited environment keys
// without "CI=1" value
env: limitedEnv,
extendEnv: false
})

checkSnapshots(tempFolder, {
'spec.js': {
'random string as 10 As 1': '\naaaaaaaaaa\n'
}
})

// run the tests again to check if values are not clashing
// but with CI=1 to avoid writing new files accidentally
execa.shellSync('npm test', {
cwd: tempFolder,
stdio: 'inherit',
env: { CI: '1' }
})
})
})

describe('custom pre-compare function', () => {
// folder with specs to run
const sourceFolder = join(__dirname, '..', 'test-custom-pre-fn')
// temp folder to copy to before running tests
const tempFolder = join(__dirname, '..', 'temp-custom-pre-fn')

beforeEach(() => {
copyFolder(sourceFolder, tempFolder)
})

it('transforms value before comparison', function () {
this.timeout(5000)

execa.shellSync('npm test', {
cwd: tempFolder,
stdio: 'inherit',
// only use the limited environment keys
// without "CI=1" value
env: limitedEnv,
extendEnv: false
})

checkSnapshots(tempFolder, {
'spec.js': {
'stores string as number 1': 5,
'stores string as number 2': 3
}
})

// run the tests again to check if values are not clashing
// but with CI=1 to avoid writing new files accidentally
execa.shellSync('npm test', {
cwd: tempFolder,
stdio: 'inherit',
env: { CI: '1' }
})
})
})
14 changes: 12 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

const debug = require('debug')('snap-shot-it')
const { core, restore, prune } = require('snap-shot-core')
const compare = require('snap-shot-compare')
const { isDataDriven, dataDriven } = require('@bahmutov/data-driven')
const { isNamedSnapshotArguments } = require('./named-snapshots')
const utils = require('./utils')
Expand Down Expand Up @@ -140,11 +139,22 @@ function snapshot (value) {
debug('package config options %o', packageConfigOptions)
debug('merged options %o', opts)

const compare = opts.compare
? utils.load(cwd, opts.compare)
: require('snap-shot-compare')
const store = opts.store ? utils.load(cwd, opts.store) : null

const preCompare = opts['pre-compare']
? utils.load(cwd, opts['pre-compare'])
: R.identity
const what = preCompare(value)

const snap = {
what: value,
what,
file: currentTest.file,
ext: EXTENSION,
compare,
store,
opts
}

Expand Down
20 changes: 18 additions & 2 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
const fs = require('fs')
const path = require('path')
const R = require('ramda')
const debug = require('debug')('snap-shot-it')

const defaults = {
useRelativePath: false
useRelativePath: false,
'pre-compare': null,
compare: null,
store: null
}
/**
* Pick only the keys we know about from whatever the user
Expand All @@ -30,4 +34,16 @@ const getPackageConfigOptions = cwd => {
return pickKnownKeys(options)
}

module.exports = { getPackageConfigOptions, defaults }
const load = (cwd, modulePath) => {
debug('loading module %s from cwd %s', modulePath, cwd)
if (!path.isAbsolute(modulePath)) {
const resolved = path.resolve(cwd, modulePath)
debug('resolved path: %s', resolved)
return require(resolved)
} else {
debug('trying to load NPM module %s', modulePath)
return require(modulePath)
}
}

module.exports = { getPackageConfigOptions, defaults, load }
5 changes: 5 additions & 0 deletions test-custom-compare-fn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# test-custom-compare-fn

This repo shows how `snap-shot-it` can load a custom compare function via config in `package.json` file.

See /~https://github.com/bahmutov/snap-shot-it/issues/350
24 changes: 24 additions & 0 deletions test-custom-compare-fn/compaaaaaare.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const Result = require('folktale/result')
const debug = require('debug')('snap-shot-it')

const compare = ({ expected, value }) => {
debug('in compaaaaare.js')

// convert "expected" to string of same length, but with "a" characters
const aaas = value.replace(/./g, 'a')
debug('original value: %s', value)
debug('aaas: %s', aaas)
debug('expected value: %s', expected)

if (aaas === expected) {
return Result.Ok()
} else {
return Result.Error({
message: 'Hmm, not the same "aaaa..."',
expected,
value: aaas
})
}
}

module.exports = compare
18 changes: 18 additions & 0 deletions test-custom-compare-fn/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "test-custom-compare-fn",
"version": "1.0.0",
"description": "shows custom compare function",
"main": "index.js",
"scripts": {
"test": "../node_modules/.bin/mocha 'specs/**/*.js'"
},
"keywords": [],
"author": "",
"license": "ISC",
"config": {
"snap-shot-it": {
"compare": "./compaaaaaare",
"store": "./store"
}
}
}
11 changes: 11 additions & 0 deletions test-custom-compare-fn/specs/spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const snapshot = require('../..')

/* eslint-env mocha */
it('random string as 10 As', () => {
// our custom compare function replaces strings with
// same length of "aaaa..." :)
const s = Math.random()
.toString()
.substr(0, 10)
snapshot(s)
})
11 changes: 11 additions & 0 deletions test-custom-compare-fn/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const debug = require('debug')('snap-shot-it')

const store = value => {
// converts value before storing it on disk
const transformed = value.replace(/./g, 'a')
debug('original value: %s', value)
debug('transformed: %s', transformed)
return transformed
}

module.exports = store
5 changes: 5 additions & 0 deletions test-custom-pre-fn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# test-custom-pre-fn

This repo shows how `snap-shot-it` can load a custom pre-compare function via config in `package.json` file and use it to clean up data before comparing.

See /~https://github.com/bahmutov/snap-shot-it/issues/350
17 changes: 17 additions & 0 deletions test-custom-pre-fn/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "test-custom-pre-fn",
"version": "1.0.0",
"description": "shows custom pre-compare function",
"main": "index.js",
"scripts": {
"test": "../node_modules/.bin/mocha 'specs/**/*.js'"
},
"keywords": [],
"author": "",
"license": "ISC",
"config": {
"snap-shot-it": {
"pre-compare": "./pre-compare"
}
}
}
6 changes: 6 additions & 0 deletions test-custom-pre-fn/pre-compare.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const preCompare = value => {
// assuming the value is a string
return value.length
}

module.exports = preCompare
8 changes: 8 additions & 0 deletions test-custom-pre-fn/specs/spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const snapshot = require('../..')

/* eslint-env mocha */
it('stores string as number', () => {
// should be saved as the length of the string
snapshot('aaaaa')
snapshot('aaa')
})

0 comments on commit 273fcea

Please sign in to comment.