approvals
Version:
Approval Tests Library - Capturing Human Intelligence
281 lines (279 loc) • 12.7 kB
JavaScript
;
/*jshint freeze:false */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.reporters = exports.scrubbers = void 0;
exports.configure = configure;
exports.getConfig = getConfig;
exports.mocha = mocha;
exports.verify = verify;
exports.verifyAsJSON = verifyAsJSON;
exports.verifyAsJSONAndScrub = verifyAsJSONAndScrub;
exports.verifyWithControl = verifyWithControl;
/**
* Approvals module.
* @module approvals
*/
const callsite_1 = __importDefault(require("callsite"));
const path_1 = __importDefault(require("path"));
const url_1 = require("url");
const cfg = __importStar(require("./config"));
const BinaryWriter_1 = require("./Writers/BinaryWriter");
const FileApprover_1 = require("./FileApprover");
const FinalMessages_1 = require("./FinalMessages");
const ManualNamer_1 = require("./ManualNamer");
const ReporterFactory_1 = require("./Reporting/ReporterFactory");
const Scrubbers_1 = require("./Scrubbers/Scrubbers");
Object.defineProperty(exports, "scrubbers", { enumerable: true, get: function () { return Scrubbers_1.Scrubbers; } });
const StringWriter_1 = require("./StringWriter");
const postRunCleanup_1 = require("./postRunCleanup");
const AUtils_1 = require("./AUtils");
// if someone tries to call 'require("approvals")...' without calling ".mocha(...) or
// they won't get a helpful error. So we put this in there - just in case"
const MochaNamer_1 = require("./Providers/Mocha/MochaNamer");
const BeforeEachVerifierBase_1 = require("./Providers/BeforeEachVerifierBase");
if (typeof beforeEach === "function") {
beforeEach(function () {
if (!this) {
return;
}
this.verify = function () {
throw new Error("You must call either .mocha()");
};
});
}
// keep track of approved files we run into with tests
const listOfApprovedFiles = [];
process.on("approvalFileApproved", function (fileName) {
if (listOfApprovedFiles.indexOf(fileName) === -1) {
listOfApprovedFiles.push(fileName);
}
});
process.on("exit", function () {
const options = cfg.currentConfig();
(0, postRunCleanup_1.postRunCleanup)(options, listOfApprovedFiles);
const finalMessages = FinalMessages_1.FinalMessages.getMessages();
if (finalMessages.length) {
console.log("******************************");
console.log("* Approvals Report: WARNING!");
finalMessages.forEach((message) => {
console.log(`* - ${message}`);
});
console.log("******************************");
}
});
/**
* Allows you to provide overrides to the default configuration.
*
* @example
* const approvals = require('approvals');
* approvals.configure({
* reporters: ['p4merge']
* });
*
* @param {*} overrideOptions
*/
function configure(overrideOptions) {
cfg.configure(overrideOptions);
return module.exports;
}
/**
* Allows the creation of an approvals configuration object using any passed in options to override the defaults.
* @param {Object} overrideOptions
* @returns {Object} approvals config object with any options overridden.
*/
function getConfig(overrideOptions) {
return cfg.getConfig(overrideOptions);
}
/**
* Configure approvals to hook into Mocha tests.
* @param {*} optionalBaseDir - An optional folder to save approval files to.
*/
function mocha(optionalBaseDir) {
// if not providing a base dir, fallback to the current calling code's directory
if (!optionalBaseDir) {
let fileName = (0, callsite_1.default)()[1].getFileName();
if (fileName.startsWith("file://")) {
fileName = (0, url_1.fileURLToPath)(fileName);
}
optionalBaseDir = path_1.default.dirname(fileName);
}
(0, BeforeEachVerifierBase_1.beforeEachVerifierBase)(MochaNamer_1.MochaNamer, "require('Approvals').mocha();", optionalBaseDir);
return module.exports;
}
/**
* `reporters` gives access to the `MultiReporter`
*
* @example
* const MultiReporter = approvals.reporters.MultiReporter
*/
exports.reporters = {
/**
* This allows access to the MultiReporter constructor.
* You can use this to run multiple reporters at the same time.
*
* @example
* approvals.verify(__dirname, "multi-reporter-example", "some data", {
* reporters: [
* new MultiReporter('p4merge', 'copycommand')
* ]
* });
*/
MultiReporter: require("./Reporting/Reporters/multiReporter").default,
};
/**
* Use this to apply the scrubber function to any data before running verify.
*
* @example
* // basic approval test with a custom scrubber
* const approvals = require('approvals');
* const scrubber = approvals.scrubbers.multiScrubber([
* function (data) {
* return (data || '').replace("some text", "some other text");
* },
* approvals.scrubbers.guidScrubber // to remove guids from the received data
* });
* approvals.verifyAndScrub(__dirname, 'sample-approval-test', "some text to verify", scrubber);
*
* @param {string} dirName - Typically `__dirname` but could be the base-directory (anywhere) to store both approved and received files.
* @param {string} testName - A file name safe string to call the file associated with this test.
* @param {(string|Buffer)} data - Either the string to save as a text file or a Buffer that represents an image
* @param {*} scrubber - A function that takes a string and returns a string. Approvals will call this if it exists to scrub the "data" before writing to any files.
* @param {*} optionsOverride - An object that can contain configurational overrides as defined in the approvals configuration object.
*/
function verifyAndScrub(dirName, testName, data, scrubber, optionsOverride) {
scrubber = scrubber || Scrubbers_1.Scrubbers.noScrubber;
// backwards compatible option
if (Array.isArray(optionsOverride)) {
optionsOverride = {
reporters: optionsOverride,
};
const stringReporters = JSON.stringify(optionsOverride.reporters);
console.error('For the last arg of the approvals.verify(...) function, if you passed in an array of reporters, something like ["opendiff","nodediff"], this has been deprecated and replaced by passing in a config object. Please re-evaluate if you can remove this parameter alltogether and use individual user configs in ~/.approvalConfig, if not then replace this: ' +
stringReporters +
" with this { reporters: " +
stringReporters +
"}.");
}
const newOptions = cfg.getConfig(optionsOverride);
const namer = new ManualNamer_1.ManualNamer(dirName, testName);
let writer;
if (data instanceof Buffer) {
writer = new BinaryWriter_1.BinaryWriter(data);
}
else {
data = scrubber(data);
writer = new StringWriter_1.StringWriter(newOptions, data);
}
verifyWithControl(namer, writer, null, newOptions);
}
/**
*
* @example
* // basic approval test
* const approvals = require('approvals');
* approvals.verify(__dirname, 'sample-approval-test', "some text to verify");
*
* @example
* // basic approval test providing an option to override configuration
* const approvals = require('approvals');
* approvals.verify(__dirname, 'sample-approval-test', "some text to verify", { normalizeLineEndingsTo: true });
*
* @param {string} dirName - Typically `__dirname` but could be the base-directory (anywhere) to store both approved and received files.
* @param {string} testName - A file name save string to call the file associated with this test.
* @param {(string|Buffer)} data - Either the string to save as a text file or a Buffer that represents an image
* @param {*} optionsOverride - An object that can contain configurational overrides as defined in the approvals configuration object.
*/
function verify(dirName, testName, data, optionsOverride) {
return verifyAndScrub(dirName, testName, data, Scrubbers_1.Scrubbers.noScrubber, optionsOverride);
}
/**
* You can pass as "data" any javascript object to be JSON.stringified and run verify against.
*
* @example
* const approvals = require('approvals');
* approvals.verifyAndScrub(__dirname, 'sample-approval-test', { a: "some text in an object" });
*
* @param {string} dirName - Typically `__dirname` but could be the base-directory (anywhere) to store both approved and received files.
* @param {string} testName - A file name safe string to call the file associated with this test.
* @param {(string|Buffer)} data - This can be any JavaScript object/array that will be JSON.stringified before running verify
* @param {*} optionsOverride - An object that can contain configurational overrides as defined in the approvals configuration object.
*/
function verifyAsJSON(dirName, testName, data, optionsOverride) {
return verifyAsJSONAndScrub(dirName, testName, data, Scrubbers_1.Scrubbers.noScrubber, optionsOverride);
}
/**
* You can pass as "data" any javascript object to be JSON.stringified. Before we run verify the scrubber will be run against the complete string before running verify against it.
* @example
* // basic approval test with a custom scrubber
* const approvals = require('approvals');
* const scrubber = approvals.scrubbers.multiScrubber([
* function (data) {
* return (data || '').replace("some text", "some other text");
* },
* approvals.scrubbers.guidScrubber // to remove guids from the received data
* });
* approvals.verifyAndScrub(__dirname, 'sample-approval-test', { a: "some text in an object" }, scrubber);
*
* @param {string} dirName - Typically `__dirname` but could be the base-directory (anywhere) to store both approved and received files.
* @param {string} testName - A file name safe string to call the file associated with this test.
* @param {(string|Buffer)} data - This can be any JavaScript object/array that will be JSON.stringified before running verify
* @param {*} scrubber - A function that takes a string and returns a string. Approvals will call this if it exists to scrub the "data" before writing to any files.
* @param {*} optionsOverride - An object that can contain configurational overrides as defined in the approvals configuration object.
*/
function verifyAsJSONAndScrub(dirName, testName, data, scrubber, optionsOverride) {
return verifyAndScrub(dirName, testName, (0, AUtils_1.stringifyKeysInOrder)(data), scrubber, optionsOverride);
}
/**
* This allows you to take full control of naming and writing files before verifying.
*
* For an example that we use to generate the docs within the readme, check out the [test/readmeTests.mts](test/readmeTests.mts) in this project.
*
* @param {Object} namer
* @param {Object} writer
* @param {Function} [reporterFactory]
* @param {Object} [optionsOverride]
*/
function verifyWithControl(namer, writer, reporterFactory, optionsOverride) {
const newOptions = cfg.getConfig(optionsOverride);
const loader = reporterFactory ||
function () {
return [ReporterFactory_1.ReporterFactory.loadReporter(newOptions.reporters)];
};
FileApprover_1.FileApprover.verify(namer, writer, loader, newOptions);
}