mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
217 lines
7.0 KiB
JavaScript
217 lines
7.0 KiB
JavaScript
"use strict";
|
|
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const assert = require("assert");
|
|
const callerpath = require("caller-path");
|
|
const projectRoot = path.join(__dirname, "..");
|
|
const updateExpectations = process.env.hasOwnProperty("UPDATE_EXPECTATIONS");
|
|
const complain = require("complain");
|
|
const formatters = {};
|
|
|
|
module.exports = function autotest(fixturesName, run) {
|
|
const suiteDirectory = path.dirname(callerpath());
|
|
const suiteName = path.basename(suiteDirectory);
|
|
const fixturesDirectory = path.join(suiteDirectory, fixturesName);
|
|
|
|
describe(path.join(suiteName, fixturesName), () => {
|
|
let modes = [];
|
|
|
|
if (typeof run === "function") {
|
|
modes.push({ name: "", run });
|
|
} else {
|
|
Object.keys(run).forEach(modeName =>
|
|
modes.push({
|
|
name: modeName,
|
|
run: run[modeName]
|
|
})
|
|
);
|
|
}
|
|
|
|
fs.readdirSync(fixturesDirectory).forEach(fixtureName => {
|
|
let fixtureDirectory = path.join(fixturesDirectory, fixtureName);
|
|
let context = {};
|
|
if (fixtureName[0] === "~") {
|
|
// skip the fixture directory
|
|
} else if (modes.length > 1) {
|
|
describe(fixtureName, function() {
|
|
modes.forEach(mode => {
|
|
runFixtureTest(
|
|
mode.name,
|
|
fixtureDirectory,
|
|
mode.run,
|
|
mode.name,
|
|
context
|
|
);
|
|
});
|
|
});
|
|
} else {
|
|
runFixtureTest(fixtureName, fixtureDirectory, modes[0].run);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
function runFixtureTest(name, dir, run, mode, context = {}) {
|
|
const resolve = file => path.join(dir, file);
|
|
const mainPath = resolve("test.js");
|
|
const hasMainFile = fs.existsSync(mainPath);
|
|
const expectDeprecation =
|
|
/-deprecated|migrate/.test(dir) && !/parser/.test(dir);
|
|
let mochaTestFunction = it;
|
|
let mochaDetails;
|
|
|
|
if (hasMainFile) {
|
|
try {
|
|
complain.log = function(message) {
|
|
context.deprecation = context.deprecation || new Error(message);
|
|
};
|
|
const main = require(mainPath);
|
|
const skip = main.skip || main["skip_" + mode];
|
|
const fails = main.fails || main["fails_" + mode];
|
|
if (skip) {
|
|
mochaTestFunction = it.skip;
|
|
mochaDetails = skip;
|
|
} else if (fails) {
|
|
mochaTestFunction = it.fails;
|
|
mochaDetails = fails;
|
|
}
|
|
} catch (err) {
|
|
mochaTestFunction(name, () => {
|
|
throw err;
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
const snapshot = (actual, opts) => {
|
|
let prefix = opts && opts.name ? opts.name + "-" : "";
|
|
let ext =
|
|
typeof opts === "string" ? opts : (opts && opts.ext) || ".html";
|
|
let actualPath = resolve(prefix + "actual" + ext);
|
|
let expectedPath = resolve(prefix + "expected" + ext);
|
|
let format = (opts && opts.format) || formatters[ext];
|
|
let isObject = typeof actual === "string" ? false : true;
|
|
let actualString = isObject ? JSON.stringify(actual, null, 4) : actual;
|
|
let expectedString = loadExpected(expectedPath, isObject);
|
|
let expected;
|
|
|
|
fs.writeFileSync(actualPath, actualString, { encoding: "utf8" });
|
|
|
|
actual = normalize(actualString, isObject, format);
|
|
expected = normalize(expectedString, isObject, format);
|
|
|
|
try {
|
|
assert.deepEqual(actual, expected);
|
|
} catch (e) {
|
|
if (updateExpectations) {
|
|
fs.writeFileSync(expectedPath, actualString, {
|
|
encoding: "utf8"
|
|
});
|
|
} else {
|
|
e.stack = e.stack.slice(
|
|
e.stack.indexOf("\n", e.stack.indexOf("\n") + 1) + 1
|
|
);
|
|
e.message = `SnapshotError: ${path.relative(
|
|
process.cwd(),
|
|
actualPath
|
|
)}`;
|
|
throw e;
|
|
}
|
|
}
|
|
};
|
|
|
|
const test = fn => {
|
|
const withDeprecationAssertion = fn => {
|
|
const assertDeprecation = () => {
|
|
if (expectDeprecation) {
|
|
if (!context.deprecation) {
|
|
throw new Error(
|
|
"A deprecated test should log a deprecation warning using `complain`"
|
|
);
|
|
}
|
|
} else if (context.deprecation) {
|
|
throw context.deprecation;
|
|
}
|
|
};
|
|
if (fn.length > 0) {
|
|
return function(done) {
|
|
complain.log = function(message) {
|
|
if (!/NOTICE/.test(message)) {
|
|
context.deprecation =
|
|
context.deprecation || new Error(message);
|
|
}
|
|
};
|
|
return fn.call(this, err => {
|
|
if (err) {
|
|
done(err);
|
|
} else {
|
|
assertDeprecation();
|
|
done();
|
|
}
|
|
});
|
|
};
|
|
} else {
|
|
return function() {
|
|
complain.log = function(message) {
|
|
if (!/NOTICE/.test(message)) {
|
|
context.deprecation =
|
|
context.deprecation || new Error(message);
|
|
}
|
|
};
|
|
return Promise.resolve()
|
|
.then(() => fn.call(this))
|
|
.then(assertDeprecation);
|
|
};
|
|
}
|
|
};
|
|
const test = mochaTestFunction(name, withDeprecationAssertion(fn));
|
|
test.details = mochaDetails;
|
|
test.file = mainPath;
|
|
return test;
|
|
};
|
|
|
|
const skip = reason => {
|
|
const test = it.skip(name);
|
|
test.details = reason;
|
|
test.file = mainPath;
|
|
return test;
|
|
};
|
|
|
|
run({
|
|
resolve,
|
|
test,
|
|
skip,
|
|
dir,
|
|
snapshot,
|
|
mode,
|
|
context
|
|
});
|
|
}
|
|
|
|
function loadExpected(expectedPath, isObject) {
|
|
try {
|
|
return fs.readFileSync(expectedPath, { encoding: "utf8" });
|
|
} catch (e) {
|
|
let expected = `${path.basename(expectedPath)} does not exist`;
|
|
return isObject ? JSON.stringify(expected) : expected;
|
|
}
|
|
}
|
|
|
|
function normalize(content, isObject, format) {
|
|
if (isObject) {
|
|
content = JSON.parse(content);
|
|
} else {
|
|
content = replaceAll(content, projectRoot, "PROJECT_ROOT").replace(
|
|
/\r?\n$/g,
|
|
""
|
|
);
|
|
}
|
|
format = format || (content => content);
|
|
return format(content);
|
|
}
|
|
|
|
function replaceAll(str, substr, replacement) {
|
|
return str.split(substr).join(replacement);
|
|
}
|