diff --git a/.eslintrc b/.eslintrc index 12522b91f..0dd4ea09d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -12,7 +12,7 @@ "indent": [2, 4], "strict": 0, "import/no-extraneous-dependencies": [2, { - "devDependencies": ["**/*.spec.js"] + "devDependencies": ["**/*.spec.js", "**/utils.js"] }] } } diff --git a/.lintstagedrc b/.lintstagedrc index 4070c7eab..41f6ca342 100644 --- a/.lintstagedrc +++ b/.lintstagedrc @@ -4,7 +4,6 @@ "eslint --fix", "git add" ], - "*.md": "yaspeller", - ".*rc": "jsonlint" + "*.md": "yaspeller" } } diff --git a/test/gitWorkflow.spec.js b/test/gitWorkflow.spec.js index 7799d88ea..d1480095c 100644 --- a/test/gitWorkflow.spec.js +++ b/test/gitWorkflow.spec.js @@ -5,6 +5,7 @@ import expect from 'expect' import rewire from 'rewire' import fsp from 'fs-promise' import tmp from 'tmp' +import { toEventuallyEqual } from './utils' const gitflow = rewire('../src/gitWorkflow') @@ -13,8 +14,10 @@ let wcDirPath let gitOpts = { cwd: 'test/__fixtures__' } tmp.setGracefulCleanup() +expect.extend(toEventuallyEqual) const execaSpy = expect.createSpy().andReturn(new Promise(resolve => resolve())) +const gitStatus = opts => gitflow.execGit(['status', '--porcelain'], opts) describe('gitWorkflow', () => { @@ -143,122 +146,90 @@ describe('gitWorkflow', () => { .then(() => fsp.writeFile(path.join(wcDirPath, 'test.js'), `module.exports = { test: 'test2' }`)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect both are modified - expect(res.stdout).toEqual(' M test.css\n M test.js') - }) + // Expect both are modified + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual(' M test.css\n M test.js')) .then(() => gitflow.execGit(['add', 'test.js'], gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect one is in index - expect(res.stdout).toEqual(' M test.css\nM test.js') - }) + // Expect one is in index + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual(' M test.css\nM test.js')) .then(() => gitflow.gitStashSave(gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect only one file from indexed - expect(res.stdout).toEqual('M test.js') - }) - + // Expect only one file from indexed + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual('M test.js')) // Restoring state .then(() => gitflow.gitStashPop(gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect stashed files to be back. Indexed file remains indexed - expect(res.stdout).toEqual(' M test.css\nM test.js') - done() - }) + // Expect stashed files to be back. Indexed file remains indexed + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual(' M test.css\nM test.js')) + .then(() => { done() }) }) - it('should stash and restore WC state after commit', (done) => { + it('should stash and restore WC state with additional edits without a commit', (done) => { // Update one of the files fsp.writeFile(path.join(wcDirPath, 'test.css'), '.test { border: red; }') // Update one of the files .then(() => fsp.writeFile(path.join(wcDirPath, 'test.js'), `module.exports = { test: 'test2' }`)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect both are modified - expect(res.stdout).toEqual(' M test.css\n M test.js') - }) + // Expect both are modified + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual(' M test.css\n M test.js')) .then(() => gitflow.execGit(['add', 'test.js'], gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect one is in index - expect(res.stdout).toEqual(' M test.css\nM test.js') - }) + // Expect one is in index + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual(' M test.css\nM test.js')) .then(() => gitflow.gitStashSave(gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect only one file from indexed - expect(res.stdout).toEqual('M test.js') - }) - - .then(() => gitflow.execGit(['commit', '-m', 'second commit'], gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect clean WC - expect(res.stdout).toEqual('') - }) + // Expect only one file from indexed + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual('M test.js')) + // Do additional edits (imitate eslint --fix) + .then(() => fsp.writeFile(path.join(wcDirPath, 'test.js'), `module.exports = { + test: 'test2', +};`)) + // Expect both indexed and modified state on one file + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual('MM test.js')) // Restoring state .then(() => gitflow.gitStashPop(gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect stashed files to be back. Commited file is gone. - expect(res.stdout).toEqual(' M test.css') + // Expect stashed files to be back. Commited file is gone. + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual(' M test.css\nM test.js')) + .then(() => { + const jsContent = fsp.readFileSync(path.join(wcDirPath, 'test.js'), { encoding: 'utf-8' }) + expect(jsContent).toEqual(`module.exports = { + test: 'test2' +}`) done() }) }) - it('should stash and restore WC state with additional edits without a commit', (done) => { + it('should stash and restore WC state with additional edits before a commit', (done) => { // Update one of the files fsp.writeFile(path.join(wcDirPath, 'test.css'), '.test { border: red; }') // Update one of the files .then(() => fsp.writeFile(path.join(wcDirPath, 'test.js'), `module.exports = { test: 'test2' }`)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect both are modified - expect(res.stdout).toEqual(' M test.css\n M test.js') - }) - .then(() => gitflow.execGit(['add', 'test.js'], gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect one is in index - expect(res.stdout).toEqual(' M test.css\nM test.js') - }) + // Expect both are modified + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual(' M test.css\n M test.js')) + .then(() => gitflow.execGit(['add', '.'], gitOpts)) + // Expect both are in index + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual('M test.css\nM test.js')) .then(() => gitflow.gitStashSave(gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect only one file from indexed - expect(res.stdout).toEqual('M test.js') - }) - - // Do additional edits (imitate eslint --fix) + // Expect both are in index + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual('M test.css\nM test.js')) + // Do additional edits (simulate eslint --fix) .then(() => fsp.writeFile(path.join(wcDirPath, 'test.js'), `module.exports = { test: 'test2', };`)) - - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { - // Expect both indexed and modified state on one file - expect(res.stdout).toEqual('MM test.js') - }) - + // Expect both indexed and modified state on one file + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual('M test.css\nMM test.js')) + // Add additional changes to the commit + .then(() => gitflow.execGit(['add', 'test.js'], gitOpts)) + // Expect both files are in the index + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual('M test.css\nM test.js')) // Restoring state .then(() => gitflow.gitStashPop(gitOpts)) - .then(() => gitflow.execGit(['status', '--porcelain'], gitOpts)) - .then((res) => { + // Expect stashed files to be back. Index changes are persisted. + .then(() => expect(gitStatus(gitOpts)).toEventuallyEqual('M test.css\nM test.js')) + .then(() => { const jsContent = fsp.readFileSync(path.join(wcDirPath, 'test.js'), { encoding: 'utf-8' }) - // Expect stashed files to be back. Commited file is gone. - expect(res.stdout).toEqual(' M test.css\nM test.js') expect(jsContent).toEqual(`module.exports = { - test: 'test2' -}`) + test: 'test2', +};`) done() }) }) diff --git a/test/runScript.spec.js b/test/runScript.spec.js index 8955d8f99..e5f614873 100644 --- a/test/runScript.spec.js +++ b/test/runScript.spec.js @@ -1,21 +1,12 @@ /* eslint no-underscore-dangle: 0 */ import expect from 'expect' -import isPromise from 'is-promise' import rewire from 'rewire' +import testUtils from './utils' -const runScript = rewire('../src/runScript') +expect.extend(testUtils) -expect.extend({ - toBeAPromise() { - expect.assert( - isPromise(this.actual), - 'expected %s to be a Promise', - this.actual - ) - return this - } -}) +const runScript = rewire('../src/runScript') const packageJSON = { scripts: { diff --git a/test/utils.js b/test/utils.js new file mode 100644 index 000000000..c5d672c11 --- /dev/null +++ b/test/utils.js @@ -0,0 +1,26 @@ +import expect, { assert } from 'expect' +import isPromise from 'is-promise' + +export function toBeAPromise() { + assert( + isPromise(this.actual), + 'expected %s to be a Promise', + this.actual + ) + return this +} + +export function toEventuallyEqual(value) { + if (!isPromise(this.actual)) { + assert(false, '%s is not a Promise', this.actual) + } + return this.actual + .then(res => expect(res.stdout).toEqual(value)) + .catch(err => assert(false, 'Error in Promise %s', err)) + +} + +export default { + toBeAPromise, + toEventuallyEqual +} diff --git a/wallaby.js b/wallaby.js index e57cf2a3e..7b73a298e 100644 --- a/wallaby.js +++ b/wallaby.js @@ -3,6 +3,7 @@ module.exports = function (wallaby) { files: [ { pattern: 'test/__fixtures__/*', instrument: false }, { pattern: 'test/__fixtures__/**/*', instrument: false }, + 'test/utils.js', 'src/*.js' ],