features/support/steps.js (135 lines of code) (raw):

/** * Copyright (c) 2016-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var {Given, Then, When} = require('cucumber'); var CommandLine = require('../../bin/dist/commandline'); var colors = require('cli-color'); var diff = require('diff'); var exec = require('child_process').exec; var fs = require('fs'); var main = require('../../bin/dist/main'); var mkdirp = require('mkdirp'); var Promise = require('../../bin/dist/promise'); function pathToFile(fileName) { if (fileName.indexOf('/') == -1) { return ''; } else { var splitArray = fileName.split('/'); splitArray.pop(); return splitArray.join('/'); } } function writeFile(fileName, fileContent, tmpDirectoryPath) { var filePath = tmpDirectoryPath + '/' + pathToFile(fileName); var fileLocation = tmpDirectoryPath + '/' + fileName; mkdirp.sync(filePath); fs.writeFileSync(fileLocation, fileContent, 'utf8'); } function fastrun(args, tmpDirectoryPath, callback) { var curdir = process.cwd(); process.chdir(tmpDirectoryPath); var promise; try { promise = main.main(CommandLine.parseArgs(args), true); } catch (err) { process.chdir(curdir); callback('error running subprocess: ' + err + '\n' + err.stack); return; } // If you try to delete this, you'll get lots of errors // about missing output files. Need to sequence inspecting the // output of the tool *after* the promises finish resolving! (and // yes, it did take me way too long to realize I needed to do this.) if (promise) { Promise.then(() => { process.chdir(curdir); callback(); }, promise); } } function run(cmd, tmpDirectoryPath, callback) { var localCommand = 'cd ' + tmpDirectoryPath + ' && ' + cmd; exec(localCommand, function (error, stdout, stderr) { callback(); }); } function displayDiff(diff) { if (diff.added != null) { return colors.green(diff.value); } else if (diff.removed != null) { return colors.red(diff.value); } else { return colors.white(diff.value); } } function toFeatureFileDocstring(s) { const sixSpaces = ' '; return ( `${sixSpaces}"""\n` + s .split('\n') .map((line) => (line === '' ? line : `${sixSpaces}${line}`)) .join('\n') + `\n${sixSpaces}"""` ); } function fixFeature(testCase, expected, actual) { const uri = testCase.sourceLocation.uri; const featureContents = fs.readFileSync(uri, 'utf8'); const expectedDocstring = toFeatureFileDocstring(expected); const actualDocstring = toFeatureFileDocstring(actual); const patched = featureContents.replace(expectedDocstring, actualDocstring); fs.writeFileSync(uri, patched); } Given( /^a file named "([^"]*)" with:$/, function (fileName, fileContent, callback) { writeFile(fileName, fileContent, this.tmpDirectoryPath); callback(); }, ); When(/^I run `([^`]*)`$/, function (cmd, callback) { cmd = unescape(cmd); const knownCommand = '../../bin/generate '; if (cmd.indexOf(knownCommand) === 0) { fastrun(cmd.split(' ').slice(1), this.tmpDirectoryPath, callback); } else { run(unescape(cmd), this.tmpDirectoryPath, callback); } }); Given(/^a directory named "([^"]*)":$/, function (dirName, callback) { mkdirp.sync(this.tmpDirectoryPath + '/' + dirName); callback(); }); Then( /^the file "([^"]*)" should contain:$/, function (fileName, expectedContents, callback) { var fileLocation = this.tmpDirectoryPath + '/' + fileName; var actualContents = fs.readFileSync(fileLocation, 'utf8'); if (this.parameters.forceResnapshot) { fixFeature(this.testCase, expectedContents, actualContents); callback(); return; } if (actualContents.indexOf(expectedContents) !== -1) { callback(); } else { if (this.parameters.resnapshot) { fixFeature(this.testCase, expectedContents, actualContents); } var differences = diff .diffLines(actualContents, expectedContents) .map(displayDiff) .join('\n'); callback( 'Within "' + this.tmpDirectoryPath + ' the file "' + fileName + ' did had the following differences: \n' + differences, ); } }, ); Then(/^the file "([^"]*)" should not exist$/, function (fileName, callback) { var fileLocation = this.tmpDirectoryPath + '/' + fileName; if (!fs.existsSync(fileLocation)) { callback(); } else { callback(colors.red('File "' + fileName + '" should not exist')); } });