Convert from tape test harness to ava, address minor declaration file issue.

This commit is contained in:
David Anson 2021-01-10 20:46:00 -08:00
parent 80069552b4
commit 49945d6601
12 changed files with 665 additions and 679 deletions

View file

@ -3945,7 +3945,7 @@ module.exports = rules;
/***/ ((module) => { /***/ ((module) => {
"use strict"; "use strict";
module.exports = JSON.parse("{\"name\":\"markdownlint\",\"version\":\"0.22.0\",\"description\":\"A Node.js style checker and lint tool for Markdown/CommonMark files.\",\"main\":\"lib/markdownlint.js\",\"types\":\"lib/markdownlint.d.ts\",\"author\":\"David Anson (https://dlaa.me/)\",\"license\":\"MIT\",\"homepage\":\"https://github.com/DavidAnson/markdownlint\",\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/DavidAnson/markdownlint.git\"},\"bugs\":\"https://github.com/DavidAnson/markdownlint/issues\",\"scripts\":{\"build-config-schema\":\"node schema/build-config-schema.js\",\"build-declaration\":\"tsc --allowJs --declaration --emitDeclarationOnly --resolveJsonModule lib/markdownlint.js && rimraf 'lib/{c,md,r}*.d.ts' 'helpers/*.d.ts'\",\"build-demo\":\"cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && webpack --no-stats\",\"build-example\":\"npm install --no-save --ignore-scripts grunt grunt-cli gulp through2\",\"ci\":\"npm-run-all --continue-on-error --parallel test-cover lint declaration build-config-schema build-demo && git diff --exit-code\",\"clean-test-repos\":\"rimraf test-repos\",\"clone-test-repos\":\"mkdir test-repos && cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet\",\"clone-test-repos-large\":\"npm run clone-test-repos && cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet\",\"declaration\":\"npm run build-declaration && npm run test-declaration\",\"example\":\"cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint\",\"lint\":\"eslint --max-warnings 0 .\",\"lint-test-repos\":\"node test/markdownlint-test-repos.js\",\"test\":\"tape test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js\",\"test-cover\":\"c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test\",\"test-declaration\":\"cd example/typescript && tsc && node type-check.js\",\"test-extra\":\"node test/markdownlint-test-extra.js\"},\"engines\":{\"node\":\">=10\"},\"dependencies\":{\"markdown-it\":\"12.0.2\"},\"devDependencies\":{\"@types/node\":\"~14.14.9\",\"c8\":\"~7.3.5\",\"cpy-cli\":\"~3.1.1\",\"eslint\":\"~7.14.0\",\"eslint-plugin-jsdoc\":\"~30.7.8\",\"eslint-plugin-node\":\"~11.1.0\",\"eslint-plugin-unicorn\":\"~23.0.0\",\"globby\":\"~11.0.1\",\"js-yaml\":\"~3.14.0\",\"markdown-it-for-inline\":\"~0.1.1\",\"markdown-it-sub\":\"~1.0.0\",\"markdown-it-sup\":\"~1.0.0\",\"markdown-it-texmath\":\"~0.8.0\",\"markdownlint-rule-helpers\":\"~0.12.0\",\"npm-run-all\":\"~4.1.5\",\"rimraf\":\"~3.0.2\",\"strip-json-comments\":\"~3.1.1\",\"tape\":\"~5.0.1\",\"tape-player\":\"~0.1.1\",\"toml\":\"~3.0.0\",\"ts-loader\":\"~8.0.14\",\"tv4\":\"~1.3.0\",\"typescript\":\"~4.1.2\",\"webpack\":\"~5.11.1\",\"webpack-cli\":\"~4.3.1\"},\"keywords\":[\"markdown\",\"lint\",\"md\",\"CommonMark\",\"markdownlint\"]}"); module.exports = JSON.parse("{\"name\":\"markdownlint\",\"version\":\"0.22.0\",\"description\":\"A Node.js style checker and lint tool for Markdown/CommonMark files.\",\"main\":\"lib/markdownlint.js\",\"types\":\"lib/markdownlint.d.ts\",\"author\":\"David Anson (https://dlaa.me/)\",\"license\":\"MIT\",\"homepage\":\"https://github.com/DavidAnson/markdownlint\",\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/DavidAnson/markdownlint.git\"},\"bugs\":\"https://github.com/DavidAnson/markdownlint/issues\",\"scripts\":{\"build-config-schema\":\"node schema/build-config-schema.js\",\"build-declaration\":\"tsc --allowJs --declaration --emitDeclarationOnly --resolveJsonModule lib/markdownlint.js && rimraf 'lib/{c,md,r}*.d.ts' 'helpers/*.d.ts'\",\"build-demo\":\"cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && webpack --no-stats\",\"build-example\":\"npm install --no-save --ignore-scripts grunt grunt-cli gulp through2\",\"ci\":\"npm-run-all --continue-on-error --parallel test-cover lint declaration build-config-schema build-demo && git diff --exit-code\",\"clean-test-repos\":\"rimraf test-repos\",\"clone-test-repos\":\"mkdir test-repos && cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet\",\"clone-test-repos-large\":\"npm run clone-test-repos && cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet\",\"declaration\":\"npm run build-declaration && npm run test-declaration\",\"example\":\"cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint\",\"lint\":\"eslint --max-warnings 0 .\",\"lint-test-repos\":\"ava test/markdownlint-test-repos.js\",\"test\":\"ava test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js\",\"test-cover\":\"c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test\",\"test-declaration\":\"cd example/typescript && tsc && node type-check.js\",\"test-extra\":\"ava --timeout=3m test/markdownlint-test-extra.js\"},\"engines\":{\"node\":\">=10\"},\"dependencies\":{\"markdown-it\":\"12.0.2\"},\"devDependencies\":{\"@types/node\":\"~14.14.9\",\"ava\":\"~3.15.0\",\"c8\":\"~7.3.5\",\"cpy-cli\":\"~3.1.1\",\"eslint\":\"~7.14.0\",\"eslint-plugin-jsdoc\":\"~30.7.8\",\"eslint-plugin-node\":\"~11.1.0\",\"eslint-plugin-unicorn\":\"~23.0.0\",\"globby\":\"~11.0.1\",\"js-yaml\":\"~3.14.0\",\"markdown-it-for-inline\":\"~0.1.1\",\"markdown-it-sub\":\"~1.0.0\",\"markdown-it-sup\":\"~1.0.0\",\"markdown-it-texmath\":\"~0.8.0\",\"markdownlint-rule-helpers\":\"~0.12.0\",\"npm-run-all\":\"~4.1.5\",\"rimraf\":\"~3.0.2\",\"strip-json-comments\":\"~3.1.1\",\"toml\":\"~3.0.0\",\"ts-loader\":\"~8.0.14\",\"tv4\":\"~1.3.0\",\"typescript\":\"~4.1.2\",\"webpack\":\"~5.11.1\",\"webpack-cli\":\"~4.3.1\"},\"keywords\":[\"markdown\",\"lint\",\"md\",\"CommonMark\",\"markdownlint\"]}");
/***/ }), /***/ }),

View file

@ -35,8 +35,11 @@ function assertLintResults(results: markdownlint.LintResults) {
assert.equal(results["string"][0].errorContext, null); assert.equal(results["string"][0].errorContext, null);
assert.deepEqual(results["string"][0].errorRange, [ 9, 1 ]); assert.deepEqual(results["string"][0].errorRange, [ 9, 1 ]);
assert(!!results["string"][0].fixInfo); assert(!!results["string"][0].fixInfo);
// @ts-ignore
assert.equal(results["string"][0].fixInfo.editColumn, 10); assert.equal(results["string"][0].fixInfo.editColumn, 10);
// @ts-ignore
assert(!results["string"][0].fixInfo.deleteCount); assert(!results["string"][0].fixInfo.deleteCount);
// @ts-ignore
assert.equal(results["string"][0].fixInfo.insertText, "\n"); assert.equal(results["string"][0].fixInfo.insertText, "\n");
assert.equal(results["../bad.md"].length, 2); assert.equal(results["../bad.md"].length, 2);
// Deliberate assignment to unused variable validates types // Deliberate assignment to unused variable validates types

View file

@ -310,7 +310,7 @@ type LintError = {
/** /**
* Fix information. * Fix information.
*/ */
fixInfo: FixInfo; fixInfo?: FixInfo;
}; };
/** /**
* Fix information. * Fix information.

View file

@ -1178,7 +1178,7 @@ module.exports = markdownlint;
* @property {string} errorDetail Detail about the error. * @property {string} errorDetail Detail about the error.
* @property {string} errorContext Context for the error. * @property {string} errorContext Context for the error.
* @property {number[]} errorRange Column number (1-based) and length. * @property {number[]} errorRange Column number (1-based) and length.
* @property {FixInfo} fixInfo Fix information. * @property {FixInfo} [fixInfo] Fix information.
*/ */
/** /**

View file

@ -24,11 +24,11 @@
"declaration": "npm run build-declaration && npm run test-declaration", "declaration": "npm run build-declaration && npm run test-declaration",
"example": "cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint", "example": "cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint",
"lint": "eslint --max-warnings 0 .", "lint": "eslint --max-warnings 0 .",
"lint-test-repos": "node test/markdownlint-test-repos.js", "lint-test-repos": "ava test/markdownlint-test-repos.js",
"test": "tape test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js", "test": "ava test/markdownlint-test.js test/markdownlint-test-custom-rules.js test/markdownlint-test-helpers.js test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js",
"test-cover": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test", "test-cover": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test",
"test-declaration": "cd example/typescript && tsc && node type-check.js", "test-declaration": "cd example/typescript && tsc && node type-check.js",
"test-extra": "node test/markdownlint-test-extra.js" "test-extra": "ava --timeout=3m test/markdownlint-test-extra.js"
}, },
"engines": { "engines": {
"node": ">=10" "node": ">=10"
@ -38,6 +38,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "~14.14.9", "@types/node": "~14.14.9",
"ava": "~3.15.0",
"c8": "~7.3.5", "c8": "~7.3.5",
"cpy-cli": "~3.1.1", "cpy-cli": "~3.1.1",
"eslint": "~7.14.0", "eslint": "~7.14.0",
@ -54,8 +55,6 @@
"npm-run-all": "~4.1.5", "npm-run-all": "~4.1.5",
"rimraf": "~3.0.2", "rimraf": "~3.0.2",
"strip-json-comments": "~3.1.1", "strip-json-comments": "~3.1.1",
"tape": "~5.0.1",
"tape-player": "~0.1.1",
"toml": "~3.0.0", "toml": "~3.0.0",
"ts-loader": "~8.0.14", "ts-loader": "~8.0.14",
"tv4": "~1.3.0", "tv4": "~1.3.0",

View file

@ -2,16 +2,15 @@
"use strict"; "use strict";
const tape = require("tape"); const test = require("ava").default;
require("tape-player");
const packageJson = require("../package.json"); const packageJson = require("../package.json");
const markdownlint = require("../lib/markdownlint"); const markdownlint = require("../lib/markdownlint");
const customRules = require("./rules/rules.js"); const customRules = require("./rules/rules.js");
const homepage = packageJson.homepage; const homepage = packageJson.homepage;
const version = packageJson.version; const version = packageJson.version;
tape("customRulesV0", (test) => { test.cb("customRulesV0", (t) => {
test.plan(4); t.plan(4);
const customRulesMd = "./test/custom-rules.md"; const customRulesMd = "./test/custom-rules.md";
const options = { const options = {
"customRules": customRules.all, "customRules": customRules.all,
@ -19,7 +18,7 @@ tape("customRulesV0", (test) => {
"resultVersion": 0 "resultVersion": 0
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = {}; const expectedResult = {};
expectedResult[customRulesMd] = { expectedResult[customRulesMd] = {
"any-blockquote": [ 12 ], "any-blockquote": [ 12 ],
@ -27,7 +26,7 @@ tape("customRulesV0", (test) => {
"first-line": [ 1 ], "first-line": [ 1 ],
"letters-E-X": [ 3, 7 ] "letters-E-X": [ 3, 7 ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
let actualMessage = actualResult.toString(); let actualMessage = actualResult.toString();
let expectedMessage = let expectedMessage =
"./test/custom-rules.md: 12: any-blockquote" + "./test/custom-rules.md: 12: any-blockquote" +
@ -48,7 +47,7 @@ tape("customRulesV0", (test) => {
" Rule that reports an error for lines with the letters 'EX'\n" + " Rule that reports an error for lines with the letters 'EX'\n" +
"./test/custom-rules.md: 7: letters-E-X" + "./test/custom-rules.md: 7: letters-E-X" +
" Rule that reports an error for lines with the letters 'EX'"; " Rule that reports an error for lines with the letters 'EX'";
test.equal(actualMessage, expectedMessage, "Incorrect message (name)."); t.is(actualMessage, expectedMessage, "Incorrect message (name).");
// @ts-ignore // @ts-ignore
actualMessage = actualResult.toString(true); actualMessage = actualResult.toString(true);
expectedMessage = expectedMessage =
@ -70,13 +69,13 @@ tape("customRulesV0", (test) => {
" Rule that reports an error for lines with the letters 'EX'\n" + " Rule that reports an error for lines with the letters 'EX'\n" +
"./test/custom-rules.md: 7: letter-E-letter-X" + "./test/custom-rules.md: 7: letter-E-letter-X" +
" Rule that reports an error for lines with the letters 'EX'"; " Rule that reports an error for lines with the letters 'EX'";
test.equal(actualMessage, expectedMessage, "Incorrect message (alias)."); t.is(actualMessage, expectedMessage, "Incorrect message (alias).");
test.end(); t.end();
}); });
}); });
tape("customRulesV1", (test) => { test.cb("customRulesV1", (t) => {
test.plan(3); t.plan(3);
const customRulesMd = "./test/custom-rules.md"; const customRulesMd = "./test/custom-rules.md";
const options = { const options = {
"customRules": customRules.all, "customRules": customRules.all,
@ -84,7 +83,7 @@ tape("customRulesV1", (test) => {
"resultVersion": 1 "resultVersion": 1
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = {}; const expectedResult = {};
expectedResult[customRulesMd] = [ expectedResult[customRulesMd] = [
{ "lineNumber": 12, { "lineNumber": 12,
@ -163,7 +162,7 @@ tape("customRulesV1", (test) => {
"errorContext": "text", "errorContext": "text",
"errorRange": null } "errorRange": null }
]; ];
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
const actualMessage = actualResult.toString(); const actualMessage = actualResult.toString();
const expectedMessage = const expectedMessage =
"./test/custom-rules.md: 12: any-blockquote/any-blockquote" + "./test/custom-rules.md: 12: any-blockquote/any-blockquote" +
@ -187,13 +186,13 @@ tape("customRulesV1", (test) => {
"./test/custom-rules.md: 7: letters-E-X/letter-E-letter-X" + "./test/custom-rules.md: 7: letters-E-X/letter-E-letter-X" +
" Rule that reports an error for lines with the letters 'EX'" + " Rule that reports an error for lines with the letters 'EX'" +
" [Context: \"text\"]"; " [Context: \"text\"]";
test.equal(actualMessage, expectedMessage, "Incorrect message."); t.is(actualMessage, expectedMessage, "Incorrect message.");
test.end(); t.end();
}); });
}); });
tape("customRulesV2", (test) => { test.cb("customRulesV2", (t) => {
test.plan(3); t.plan(3);
const customRulesMd = "./test/custom-rules.md"; const customRulesMd = "./test/custom-rules.md";
const options = { const options = {
"customRules": customRules.all, "customRules": customRules.all,
@ -201,7 +200,7 @@ tape("customRulesV2", (test) => {
"resultVersion": 2 "resultVersion": 2
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = {}; const expectedResult = {};
expectedResult[customRulesMd] = [ expectedResult[customRulesMd] = [
{ "lineNumber": 12, { "lineNumber": 12,
@ -271,7 +270,7 @@ tape("customRulesV2", (test) => {
"errorContext": "text", "errorContext": "text",
"errorRange": null } "errorRange": null }
]; ];
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
const actualMessage = actualResult.toString(); const actualMessage = actualResult.toString();
const expectedMessage = const expectedMessage =
"./test/custom-rules.md: 12: any-blockquote" + "./test/custom-rules.md: 12: any-blockquote" +
@ -295,13 +294,13 @@ tape("customRulesV2", (test) => {
"./test/custom-rules.md: 7: letters-E-X/letter-E-letter-X/contains-ex" + "./test/custom-rules.md: 7: letters-E-X/letter-E-letter-X/contains-ex" +
" Rule that reports an error for lines with the letters 'EX'" + " Rule that reports an error for lines with the letters 'EX'" +
" [Context: \"text\"]"; " [Context: \"text\"]";
test.equal(actualMessage, expectedMessage, "Incorrect message."); t.is(actualMessage, expectedMessage, "Incorrect message.");
test.end(); t.end();
}); });
}); });
tape("customRulesConfig", (test) => { test.cb("customRulesConfig", (t) => {
test.plan(2); t.plan(2);
const customRulesMd = "./test/custom-rules.md"; const customRulesMd = "./test/custom-rules.md";
const options = { const options = {
"customRules": customRules.all, "customRules": customRules.all,
@ -316,7 +315,7 @@ tape("customRulesConfig", (test) => {
"resultVersion": 0 "resultVersion": 0
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = {}; const expectedResult = {};
expectedResult[customRulesMd] = { expectedResult[customRulesMd] = {
"any-blockquote": [ 12 ], "any-blockquote": [ 12 ],
@ -324,13 +323,13 @@ tape("customRulesConfig", (test) => {
"first-line": [ 1 ], "first-line": [ 1 ],
"letters-E-X": [ 7 ] "letters-E-X": [ 7 ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.end(); t.end();
}); });
}); });
tape("customRulesNpmPackage", (test) => { test("customRulesNpmPackage", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"customRules": [ require("./rules/npm") ], "customRules": [ require("./rules/npm") ],
"strings": { "strings": {
@ -339,18 +338,18 @@ tape("customRulesNpmPackage", (test) => {
"resultVersion": 0 "resultVersion": 0
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = {}; const expectedResult = {};
expectedResult.string = { expectedResult.string = {
"sample-rule": [ 3 ] "sample-rule": [ 3 ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); // @ts-ignore
test.end(); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
}); });
}); });
tape("customRulesBadProperty", (test) => { test("customRulesBadProperty", (t) => {
test.plan(23); t.plan(23);
[ [
{ {
"propertyName": "names", "propertyName": "names",
@ -382,22 +381,22 @@ tape("customRulesBadProperty", (test) => {
const options = { const options = {
"customRules": [ badRule ] "customRules": [ badRule ]
}; };
test.throws( t.throws(
function badRuleCall() { function badRuleCall() {
markdownlint.sync(options); markdownlint.sync(options);
}, },
new RegExp( {
`Property '${propertyName}' of custom rule at index 0 is incorrect.` "message":
), `Property '${propertyName}' of custom rule at index 0 is incorrect.`
},
"Did not get correct exception for missing property." "Did not get correct exception for missing property."
); );
}); });
}); });
test.end();
}); });
tape("customRulesUsedNameName", (test) => { test("customRulesUsedNameName", (t) => {
test.plan(4); t.plan(4);
markdownlint({ markdownlint({
"customRules": [ "customRules": [
{ {
@ -408,19 +407,18 @@ tape("customRulesUsedNameName", (test) => {
} }
] ]
}, function callback(err, result) { }, function callback(err, result) {
test.ok(err, "Did not get an error for duplicate name."); t.truthy(err, "Did not get an error for duplicate name.");
test.ok(err instanceof Error, "Error not instance of Error."); t.true(err instanceof Error, "Error not instance of Error.");
test.equal(err.message, t.is(err.message,
"Name 'NO-missing-SPACE-atx' of custom rule at index 0 is " + "Name 'NO-missing-SPACE-atx' of custom rule at index 0 is " +
"already used as a name or tag.", "already used as a name or tag.",
"Incorrect message for duplicate name."); "Incorrect message for duplicate name.");
test.ok(!result, "Got result for duplicate name."); t.true(!result, "Got result for duplicate name.");
test.end();
}); });
}); });
tape("customRulesUsedNameTag", (test) => { test("customRulesUsedNameTag", (t) => {
test.plan(4); t.plan(4);
markdownlint({ markdownlint({
"customRules": [ "customRules": [
{ {
@ -431,18 +429,17 @@ tape("customRulesUsedNameTag", (test) => {
} }
] ]
}, function callback(err, result) { }, function callback(err, result) {
test.ok(err, "Did not get an error for duplicate name."); t.truthy(err, "Did not get an error for duplicate name.");
test.ok(err instanceof Error, "Error not instance of Error."); t.true(err instanceof Error, "Error not instance of Error.");
test.equal(err.message, t.is(err.message,
"Name 'HtMl' of custom rule at index 0 is already used as a name or tag.", "Name 'HtMl' of custom rule at index 0 is already used as a name or tag.",
"Incorrect message for duplicate name."); "Incorrect message for duplicate name.");
test.ok(!result, "Got result for duplicate name."); t.true(!result, "Got result for duplicate name.");
test.end();
}); });
}); });
tape("customRulesUsedTagName", (test) => { test("customRulesUsedTagName", (t) => {
test.plan(4); t.plan(4);
markdownlint({ markdownlint({
"customRules": [ "customRules": [
{ {
@ -459,19 +456,18 @@ tape("customRulesUsedTagName", (test) => {
} }
] ]
}, function callback(err, result) { }, function callback(err, result) {
test.ok(err, "Did not get an error for duplicate tag."); t.truthy(err, "Did not get an error for duplicate tag.");
test.ok(err instanceof Error, "Error not instance of Error."); t.true(err instanceof Error, "Error not instance of Error.");
test.equal(err.message, t.is(err.message,
"Tag 'NO-missing-SPACE-atx' of custom rule at index 1 is " + "Tag 'NO-missing-SPACE-atx' of custom rule at index 1 is " +
"already used as a name.", "already used as a name.",
"Incorrect message for duplicate name."); "Incorrect message for duplicate name.");
test.ok(!result, "Got result for duplicate tag."); t.true(!result, "Got result for duplicate tag.");
test.end();
}); });
}); });
tape("customRulesThrowForFile", (test) => { test.cb("customRulesThrowForFile", (t) => {
test.plan(4); t.plan(4);
const exceptionMessage = "Test exception message"; const exceptionMessage = "Test exception message";
markdownlint({ markdownlint({
"customRules": [ "customRules": [
@ -486,19 +482,19 @@ tape("customRulesThrowForFile", (test) => {
], ],
"files": [ "./test/custom-rules.md" ] "files": [ "./test/custom-rules.md" ]
}, function callback(err, result) { }, function callback(err, result) {
test.ok(err, "Did not get an error for function thrown."); t.truthy(err, "Did not get an error for function thrown.");
test.ok(err instanceof Error, "Error not instance of Error."); t.true(err instanceof Error, "Error not instance of Error.");
test.equal(err.message, exceptionMessage, t.is(err.message, exceptionMessage,
"Incorrect message for function thrown."); "Incorrect message for function thrown.");
test.ok(!result, "Got result for function thrown."); t.true(!result, "Got result for function thrown.");
test.end(); t.end();
}); });
}); });
tape("customRulesThrowForFileSync", (test) => { test("customRulesThrowForFileSync", (t) => {
test.plan(1); t.plan(1);
const exceptionMessage = "Test exception message"; const exceptionMessage = "Test exception message";
test.throws( t.throws(
function customRuleThrowsCall() { function customRuleThrowsCall() {
markdownlint.sync({ markdownlint.sync({
"customRules": [ "customRules": [
@ -514,14 +510,15 @@ tape("customRulesThrowForFileSync", (test) => {
"files": [ "./test/custom-rules.md" ] "files": [ "./test/custom-rules.md" ]
}); });
}, },
new RegExp(exceptionMessage), {
"message": exceptionMessage
},
"Did not get correct exception for function thrown." "Did not get correct exception for function thrown."
); );
test.end();
}); });
tape("customRulesThrowForString", (test) => { test("customRulesThrowForString", (t) => {
test.plan(4); t.plan(4);
const exceptionMessage = "Test exception message"; const exceptionMessage = "Test exception message";
markdownlint({ markdownlint({
"customRules": [ "customRules": [
@ -538,17 +535,16 @@ tape("customRulesThrowForString", (test) => {
"string": "String" "string": "String"
} }
}, function callback(err, result) { }, function callback(err, result) {
test.ok(err, "Did not get an error for function thrown."); t.truthy(err, "Did not get an error for function thrown.");
test.ok(err instanceof Error, "Error not instance of Error."); t.true(err instanceof Error, "Error not instance of Error.");
test.equal(err.message, exceptionMessage, t.is(err.message, exceptionMessage,
"Incorrect message for function thrown."); "Incorrect message for function thrown.");
test.ok(!result, "Got result for function thrown."); t.true(!result, "Got result for function thrown.");
test.end();
}); });
}); });
tape("customRulesOnErrorNull", (test) => { test("customRulesOnErrorNull", (t) => {
test.plan(1); t.plan(1);
const options = { const options = {
"customRules": [ "customRules": [
{ {
@ -564,18 +560,19 @@ tape("customRulesOnErrorNull", (test) => {
"string": "String" "string": "String"
} }
}; };
test.throws( t.throws(
function nullErrorCall() { function nullErrorCall() {
markdownlint.sync(options); markdownlint.sync(options);
}, },
/Property 'lineNumber' of onError parameter is incorrect./, {
"message": "Property 'lineNumber' of onError parameter is incorrect."
},
"Did not get correct exception for null object." "Did not get correct exception for null object."
); );
test.end();
}); });
tape("customRulesOnErrorBad", (test) => { test("customRulesOnErrorBad", (t) => {
test.plan(21); t.plan(21);
[ [
{ {
"propertyName": "lineNumber", "propertyName": "lineNumber",
@ -652,22 +649,22 @@ tape("customRulesOnErrorBad", (test) => {
"string": "String" "string": "String"
} }
}; };
test.throws( t.throws(
function badErrorCall() { function badErrorCall() {
markdownlint.sync(options); markdownlint.sync(options);
}, },
new RegExp( {
`Property '${propertyNames}' of onError parameter is incorrect.` "message":
), `Property '${propertyNames}' of onError parameter is incorrect.`
},
"Did not get correct exception for bad object." "Did not get correct exception for bad object."
); );
}); });
}); });
test.end();
}); });
tape("customRulesOnErrorInvalid", (test) => { test("customRulesOnErrorInvalid", (t) => {
test.plan(17); t.plan(17);
[ [
{ {
"propertyName": "lineNumber", "propertyName": "lineNumber",
@ -724,22 +721,22 @@ tape("customRulesOnErrorInvalid", (test) => {
"string": "Text\ntext" "string": "Text\ntext"
} }
}; };
test.throws( t.throws(
function invalidErrorCall() { function invalidErrorCall() {
markdownlint.sync(options); markdownlint.sync(options);
}, },
new RegExp( {
`Property '${propertyNames}' of onError parameter is incorrect.` "message":
), `Property '${propertyNames}' of onError parameter is incorrect.`
},
"Did not get correct exception for invalid object." "Did not get correct exception for invalid object."
); );
}); });
}); });
test.end();
}); });
tape("customRulesOnErrorValid", (test) => { test("customRulesOnErrorValid", (t) => {
test.plan(24); t.plan(24);
[ [
{ {
"propertyName": "lineNumber", "propertyName": "lineNumber",
@ -800,14 +797,13 @@ tape("customRulesOnErrorValid", (test) => {
} }
}; };
markdownlint.sync(options); markdownlint.sync(options);
test.ok(true); t.truthy(true);
}); });
}); });
test.end();
}); });
tape("customRulesOnErrorLazy", (test) => { test("customRulesOnErrorLazy", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"customRules": [ "customRules": [
{ {
@ -829,7 +825,7 @@ tape("customRulesOnErrorLazy", (test) => {
} }
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"string": [ "string": [
{ {
@ -843,13 +839,12 @@ tape("customRulesOnErrorLazy", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.end();
}); });
}); });
tape("customRulesOnErrorModified", (test) => { test("customRulesOnErrorModified", (t) => {
test.plan(2); t.plan(2);
const errorObject = { const errorObject = {
"lineNumber": 1, "lineNumber": 1,
"detail": "detail", "detail": "detail",
@ -885,7 +880,7 @@ tape("customRulesOnErrorModified", (test) => {
"resultVersion": 3 "resultVersion": 3
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"string": [ "string": [
{ {
@ -904,13 +899,12 @@ tape("customRulesOnErrorModified", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.end();
}); });
}); });
tape("customRulesThrowForFileHandled", (test) => { test.cb("customRulesThrowForFileHandled", (t) => {
test.plan(2); t.plan(2);
const exceptionMessage = "Test exception message"; const exceptionMessage = "Test exception message";
markdownlint({ markdownlint({
"customRules": [ "customRules": [
@ -926,7 +920,7 @@ tape("customRulesThrowForFileHandled", (test) => {
"files": [ "./test/custom-rules.md" ], "files": [ "./test/custom-rules.md" ],
"handleRuleFailures": true "handleRuleFailures": true
}, function callback(err, actualResult) { }, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"./test/custom-rules.md": [ "./test/custom-rules.md": [
{ {
@ -941,13 +935,13 @@ tape("customRulesThrowForFileHandled", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.end(); t.end();
}); });
}); });
tape("customRulesThrowForStringHandled", (test) => { test("customRulesThrowForStringHandled", (t) => {
test.plan(2); t.plan(2);
const exceptionMessage = "Test exception message"; const exceptionMessage = "Test exception message";
const informationUrl = "https://example.com/rule"; const informationUrl = "https://example.com/rule";
markdownlint({ markdownlint({
@ -967,7 +961,7 @@ tape("customRulesThrowForStringHandled", (test) => {
}, },
"handleRuleFailures": true "handleRuleFailures": true
}, function callback(err, actualResult) { }, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"string": [ "string": [
{ {
@ -993,13 +987,12 @@ tape("customRulesThrowForStringHandled", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.end();
}); });
}); });
tape("customRulesOnErrorInvalidHandled", (test) => { test("customRulesOnErrorInvalidHandled", (t) => {
test.plan(2); t.plan(2);
markdownlint({ markdownlint({
"customRules": [ "customRules": [
{ {
@ -1019,7 +1012,7 @@ tape("customRulesOnErrorInvalidHandled", (test) => {
}, },
"handleRuleFailures": true "handleRuleFailures": true
}, function callback(err, actualResult) { }, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"string": [ "string": [
{ {
@ -1034,13 +1027,12 @@ tape("customRulesOnErrorInvalidHandled", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.end();
}); });
}); });
tape("customRulesFileName", (test) => { test.cb("customRulesFileName", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"customRules": [ "customRules": [
{ {
@ -1048,20 +1040,20 @@ tape("customRulesFileName", (test) => {
"description": "description", "description": "description",
"tags": [ "tag" ], "tags": [ "tag" ],
"function": function stringName(params) { "function": function stringName(params) {
test.equal(params.name, "doc/CustomRules.md", "Incorrect file name"); t.is(params.name, "doc/CustomRules.md", "Incorrect file name");
} }
} }
], ],
"files": "doc/CustomRules.md" "files": "doc/CustomRules.md"
}; };
markdownlint(options, function callback(err) { markdownlint(options, function callback(err) {
test.ifError(err); t.falsy(err);
test.end(); t.end();
}); });
}); });
tape("customRulesStringName", (test) => { test("customRulesStringName", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"customRules": [ "customRules": [
{ {
@ -1069,7 +1061,7 @@ tape("customRulesStringName", (test) => {
"description": "description", "description": "description",
"tags": [ "tag" ], "tags": [ "tag" ],
"function": function stringName(params) { "function": function stringName(params) {
test.equal(params.name, "string", "Incorrect string name"); t.is(params.name, "string", "Incorrect string name");
} }
} }
], ],
@ -1078,34 +1070,33 @@ tape("customRulesStringName", (test) => {
} }
}; };
markdownlint(options, function callback(err) { markdownlint(options, function callback(err) {
test.ifError(err); t.falsy(err);
test.end();
}); });
}); });
tape("customRulesDoc", (test) => { test.cb("customRulesDoc", (t) => {
test.plan(2); t.plan(2);
markdownlint({ markdownlint({
"files": "doc/CustomRules.md", "files": "./doc/CustomRules.md",
"config": { "config": {
"MD013": { "line_length": 200 } "MD013": { "line_length": 200 }
} }
}, function callback(err, actual) { }, function callback(err, actual) {
test.ifError(err); t.falsy(err);
const expected = { "doc/CustomRules.md": [] }; const expected = { "./doc/CustomRules.md": [] };
test.deepEqual(actual, expected, "Unexpected issues."); t.deepEqual(actual, expected, "Unexpected issues.");
test.end(); t.end();
}); });
}); });
tape("customRulesLintJavaScript", (test) => { test.cb("customRulesLintJavaScript", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"customRules": customRules.lintJavaScript, "customRules": customRules.lintJavaScript,
"files": "test/lint-javascript.md" "files": "test/lint-javascript.md"
}; };
markdownlint(options, (err, actual) => { markdownlint(options, (err, actual) => {
test.ifError(err); t.falsy(err);
const expected = { const expected = {
"test/lint-javascript.md": [ "test/lint-javascript.md": [
{ {
@ -1128,7 +1119,7 @@ tape("customRulesLintJavaScript", (test) => {
} }
] ]
}; };
test.deepEqual(actual, expected, "Unexpected issues."); t.deepEqual(actual, expected, "Unexpected issues.");
test.end(); t.end();
}); });
}); });

View file

@ -5,40 +5,37 @@
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const globby = require("globby"); const globby = require("globby");
const tape = require("tape"); const test = require("ava").default;
require("tape-player");
const markdownlint = require("../lib/markdownlint"); const markdownlint = require("../lib/markdownlint");
const { utf8Encoding } = require("../helpers");
// Simulates typing each test file to validate handling of partial input // Simulates typing each test file to validate handling of partial input
const files = fs.readdirSync("./test"); const files = fs.readdirSync("./test");
files.filter((file) => /\.md$/.test(file)).forEach((file) => { files.filter((file) => /\.md$/.test(file)).forEach((file) => {
const strings = {}; const strings = {};
let content = fs.readFileSync(path.join("./test", file), utf8Encoding); let content = fs.readFileSync(path.join("./test", file), "utf8");
while (content) { while (content) {
strings[content.length.toString()] = content; strings[content.length.toString()] = content;
content = content.slice(0, -1); content = content.slice(0, -1);
} }
tape(`type ${file}`, (test) => { test(`type ${file}`, (t) => {
test.plan(1); t.plan(1);
markdownlint.sync({ markdownlint.sync({
// @ts-ignore // @ts-ignore
strings, strings,
"resultVersion": 0 "resultVersion": 0
}); });
test.pass(); t.pass();
test.end();
}); });
}); });
// Parses all Markdown files in all package dependencies // Parses all Markdown files in all package dependencies
tape("parseAllFiles", (test) => { test.cb("parseAllFiles", (t) => {
test.plan(1); t.plan(1);
const options = { const options = {
"files": globby.sync("**/*.{md,markdown}") "files": globby.sync("**/*.{md,markdown}")
}; };
markdownlint(options, (err) => { markdownlint(options, (err) => {
test.ifError(err); t.falsy(err);
test.end(); t.end();
}); });
}); });

View file

@ -3,12 +3,11 @@
"use strict"; "use strict";
const os = require("os"); const os = require("os");
const tape = require("tape"); const test = require("ava").default;
require("tape-player");
const helpers = require("../helpers"); const helpers = require("../helpers");
tape("clearHtmlCommentTextValid", (test) => { test("clearHtmlCommentTextValid", (t) => {
test.plan(1); t.plan(1);
const validComments = [ const validComments = [
"<!-- text -->", "<!-- text -->",
"<!--text-->", "<!--text-->",
@ -85,12 +84,11 @@ tape("clearHtmlCommentTextValid", (test) => {
]; ];
const actual = helpers.clearHtmlCommentText(validComments.join("\n")); const actual = helpers.clearHtmlCommentText(validComments.join("\n"));
const expected = validResult.join("\n"); const expected = validResult.join("\n");
test.equal(actual, expected); t.is(actual, expected);
test.end();
}); });
tape("clearHtmlCommentTextInvalid", (test) => { test("clearHtmlCommentTextInvalid", (t) => {
test.plan(1); t.plan(1);
const invalidComments = [ const invalidComments = [
"<!>", "<!>",
"<!->", "<!->",
@ -111,12 +109,11 @@ tape("clearHtmlCommentTextInvalid", (test) => {
]; ];
const actual = helpers.clearHtmlCommentText(invalidComments.join("\n")); const actual = helpers.clearHtmlCommentText(invalidComments.join("\n"));
const expected = invalidComments.join("\n"); const expected = invalidComments.join("\n");
test.equal(actual, expected); t.is(actual, expected);
test.end();
}); });
tape("clearHtmlCommentTextNonGreedy", (test) => { test("clearHtmlCommentTextNonGreedy", (t) => {
test.plan(1); t.plan(1);
const nonGreedyComments = [ const nonGreedyComments = [
"<!-- text --> -->", "<!-- text --> -->",
"<!---text --> -->", "<!---text --> -->",
@ -131,12 +128,11 @@ tape("clearHtmlCommentTextNonGreedy", (test) => {
]; ];
const actual = helpers.clearHtmlCommentText(nonGreedyComments.join("\n")); const actual = helpers.clearHtmlCommentText(nonGreedyComments.join("\n"));
const expected = nonGreedyResult.join("\n"); const expected = nonGreedyResult.join("\n");
test.equal(actual, expected); t.is(actual, expected);
test.end();
}); });
tape("clearHtmlCommentTextEmbedded", (test) => { test("clearHtmlCommentTextEmbedded", (t) => {
test.plan(1); t.plan(1);
const embeddedComments = [ const embeddedComments = [
"text<!--text-->text", "text<!--text-->text",
"<!-- markdownlint-disable MD010 -->", "<!-- markdownlint-disable MD010 -->",
@ -153,12 +149,11 @@ tape("clearHtmlCommentTextEmbedded", (test) => {
]; ];
const actual = helpers.clearHtmlCommentText(embeddedComments.join("\n")); const actual = helpers.clearHtmlCommentText(embeddedComments.join("\n"));
const expected = embeddedResult.join("\n"); const expected = embeddedResult.join("\n");
test.equal(actual, expected); t.is(actual, expected);
test.end();
}); });
tape("unescapeMarkdown", (test) => { test("unescapeMarkdown", (t) => {
test.plan(7); t.plan(7);
// Test cases from https://spec.commonmark.org/0.29/#backslash-escapes // Test cases from https://spec.commonmark.org/0.29/#backslash-escapes
const testCases = [ const testCases = [
[ [
@ -214,13 +209,12 @@ bar`
testCases.forEach(function forTestCase(testCase) { testCases.forEach(function forTestCase(testCase) {
const [ markdown, expected, replacement ] = testCase; const [ markdown, expected, replacement ] = testCase;
const actual = helpers.unescapeMarkdown(markdown, replacement); const actual = helpers.unescapeMarkdown(markdown, replacement);
test.equal(actual, expected); t.is(actual, expected);
}); });
test.end();
}); });
tape("isBlankLine", (test) => { test("isBlankLine", (t) => {
test.plan(25); t.plan(25);
const blankLines = [ const blankLines = [
null, null,
"", "",
@ -240,7 +234,7 @@ tape("isBlankLine", (test) => {
"> <!--text-->", "> <!--text-->",
">><!--text-->" ">><!--text-->"
]; ];
blankLines.forEach((line) => test.ok(helpers.isBlankLine(line), line)); blankLines.forEach((line) => t.true(helpers.isBlankLine(line), line || ""));
const nonBlankLines = [ const nonBlankLines = [
"text", "text",
" text ", " text ",
@ -251,12 +245,11 @@ tape("isBlankLine", (test) => {
"<!--", "<!--",
"-->" "-->"
]; ];
nonBlankLines.forEach((line) => test.ok(!helpers.isBlankLine(line), line)); nonBlankLines.forEach((line) => t.true(!helpers.isBlankLine(line), line));
test.end();
}); });
tape("includesSorted", (test) => { test("includesSorted", (t) => {
test.plan(154); t.plan(154);
const inputs = [ const inputs = [
[ ], [ ],
[ 8 ], [ 8 ],
@ -268,14 +261,13 @@ tape("includesSorted", (test) => {
]; ];
inputs.forEach((input) => { inputs.forEach((input) => {
for (let i = 0; i <= 21; i++) { for (let i = 0; i <= 21; i++) {
test.equal(helpers.includesSorted(input, i), input.includes(i)); t.is(helpers.includesSorted(input, i), input.includes(i));
} }
}); });
test.end();
}); });
tape("forEachInlineCodeSpan", (test) => { test("forEachInlineCodeSpan", (t) => {
test.plan(99); t.plan(99);
const testCases = const testCases =
[ [
{ {
@ -369,18 +361,17 @@ tape("forEachInlineCodeSpan", (test) => {
helpers.forEachInlineCodeSpan(input, (code, line, column, ticks) => { helpers.forEachInlineCodeSpan(input, (code, line, column, ticks) => {
const [ expectedCode, expectedLine, expectedColumn, expectedTicks ] = const [ expectedCode, expectedLine, expectedColumn, expectedTicks ] =
expecteds.shift(); expecteds.shift();
test.equal(code, expectedCode, input); t.is(code, expectedCode, input);
test.equal(line, expectedLine, input); t.is(line, expectedLine, input);
test.equal(column, expectedColumn, input); t.is(column, expectedColumn, input);
test.equal(ticks, expectedTicks, input); t.is(ticks, expectedTicks, input);
}); });
test.equal(expecteds.length, 0, "length"); t.is(expecteds.length, 0, "length");
}); });
test.end();
}); });
tape("getPreferredLineEnding", (test) => { test("getPreferredLineEnding", (t) => {
test.plan(17); t.plan(17);
const testCases = [ const testCases = [
[ "", os.EOL ], [ "", os.EOL ],
[ "\r", "\r" ], [ "\r", "\r" ],
@ -403,13 +394,12 @@ tape("getPreferredLineEnding", (test) => {
testCases.forEach((testCase) => { testCases.forEach((testCase) => {
const [ input, expected ] = testCase; const [ input, expected ] = testCase;
const actual = helpers.getPreferredLineEnding(input); const actual = helpers.getPreferredLineEnding(input);
test.equal(actual, expected, "Incorrect line ending returned."); t.is(actual, expected, "Incorrect line ending returned.");
}); });
test.end();
}); });
tape("applyFix", (test) => { test("applyFix", (t) => {
test.plan(4); t.plan(4);
const testCases = [ const testCases = [
[ [
"Hello world.", "Hello world.",
@ -452,13 +442,12 @@ tape("applyFix", (test) => {
const [ line, fixInfo, lineEnding, expected ] = testCase; const [ line, fixInfo, lineEnding, expected ] = testCase;
// @ts-ignore // @ts-ignore
const actual = helpers.applyFix(line, fixInfo, lineEnding); const actual = helpers.applyFix(line, fixInfo, lineEnding);
test.equal(actual, expected, "Incorrect fix applied."); t.is(actual, expected, "Incorrect fix applied.");
}); });
test.end();
}); });
tape("applyFixes", (test) => { test("applyFixes", (t) => {
test.plan(29); t.plan(29);
const testCases = [ const testCases = [
[ [
"Hello world.", "Hello world.",
@ -909,7 +898,6 @@ tape("applyFixes", (test) => {
testCases.forEach((testCase) => { testCases.forEach((testCase) => {
const [ input, errors, expected ] = testCase; const [ input, errors, expected ] = testCase;
const actual = helpers.applyFixes(input, errors); const actual = helpers.applyFixes(input, errors);
test.equal(actual, expected, "Incorrect fix applied."); t.is(actual, expected, "Incorrect fix applied.");
}); });
test.end();
}); });

View file

@ -9,8 +9,7 @@ const { promisify } = require("util");
const globby = require("globby"); const globby = require("globby");
const jsYaml = require("js-yaml"); const jsYaml = require("js-yaml");
const stripJsonComments = require("strip-json-comments"); const stripJsonComments = require("strip-json-comments");
const tape = require("tape"); const test = require("ava").default;
require("tape-player");
const markdownlint = require("../lib/markdownlint"); const markdownlint = require("../lib/markdownlint");
const markdownlintPromise = promisify(markdownlint); const markdownlintPromise = promisify(markdownlint);
const readConfigPromise = promisify(markdownlint.readConfig); const readConfigPromise = promisify(markdownlint.readConfig);
@ -38,13 +37,14 @@ function yamlParse(yaml) {
/** /**
* Lints a test repository. * Lints a test repository.
* *
* @param {Object} test Test instance. * @param {Object} t Test instance.
* @param {string[]} globPatterns Array of files to in/exclude. * @param {string[]} globPatterns Array of files to in/exclude.
* @param {string} configPath Path to config file. * @param {string} configPath Path to config file.
* @returns {Promise} Test result.
*/ */
function lintTestRepo(test, globPatterns, configPath) { function lintTestRepo(t, globPatterns, configPath) {
test.plan(1); t.plan(1);
Promise.all([ return Promise.all([
globby(globPatterns), globby(globPatterns),
// @ts-ignore // @ts-ignore
readConfigPromise(configPath, [ jsoncParse, yamlParse ]) readConfigPromise(configPath, [ jsoncParse, yamlParse ])
@ -60,22 +60,21 @@ function lintTestRepo(test, globPatterns, configPath) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(resultsString); console.log(resultsString);
} }
test.ok(!resultsString.length, "Unexpected linting violations"); t.true(!resultsString.length, "Unexpected linting violations");
test.end();
}); });
}); });
} }
// Run markdownlint the same way the corresponding repositories do // Run markdownlint the same way the corresponding repositories do
tape("https://github.com/eslint/eslint", (test) => { test("https://github.com/eslint/eslint", (t) => {
const rootDir = "./test-repos/eslint-eslint"; const rootDir = "./test-repos/eslint-eslint";
const globPatterns = [ join(rootDir, "docs/**/*.md") ]; const globPatterns = [ join(rootDir, "docs/**/*.md") ];
const configPath = join(rootDir, ".markdownlint.yml"); const configPath = join(rootDir, ".markdownlint.yml");
lintTestRepo(test, globPatterns, configPath); return lintTestRepo(t, globPatterns, configPath);
}); });
tape("https://github.com/mkdocs/mkdocs", (test) => { test("https://github.com/mkdocs/mkdocs", (t) => {
const rootDir = "./test-repos/mkdocs-mkdocs"; const rootDir = "./test-repos/mkdocs-mkdocs";
const globPatterns = [ const globPatterns = [
join(rootDir, "README.md"), join(rootDir, "README.md"),
@ -84,21 +83,21 @@ tape("https://github.com/mkdocs/mkdocs", (test) => {
"!" + join(rootDir, "docs/CNAME") "!" + join(rootDir, "docs/CNAME")
]; ];
const configPath = join(rootDir, ".markdownlintrc"); const configPath = join(rootDir, ".markdownlintrc");
lintTestRepo(test, globPatterns, configPath); return lintTestRepo(t, globPatterns, configPath);
}); });
tape("https://github.com/pi-hole/docs", (test) => { test("https://github.com/pi-hole/docs", (t) => {
const rootDir = "./test-repos/pi-hole-docs"; const rootDir = "./test-repos/pi-hole-docs";
const globPatterns = [ join(rootDir, "**/*.md") ]; const globPatterns = [ join(rootDir, "**/*.md") ];
const configPath = join(rootDir, ".markdownlint.json"); const configPath = join(rootDir, ".markdownlint.json");
lintTestRepo(test, globPatterns, configPath); return lintTestRepo(t, globPatterns, configPath);
}); });
// Optional repositories (very large) // Optional repositories (very large)
const dotnetDocsDir = "./test-repos/dotnet-docs"; const dotnetDocsDir = "./test-repos/dotnet-docs";
if (existsSync(dotnetDocsDir)) { if (existsSync(dotnetDocsDir)) {
tape("https://github.com/dotnet/docs", (test) => { test("https://github.com/dotnet/docs", (t) => {
const rootDir = dotnetDocsDir; const rootDir = dotnetDocsDir;
const globPatterns = [ const globPatterns = [
join(rootDir, "**/*.md"), join(rootDir, "**/*.md"),
@ -111,6 +110,6 @@ if (existsSync(dotnetDocsDir)) {
) )
]; ];
const configPath = join(rootDir, ".markdownlint.json"); const configPath = join(rootDir, ".markdownlint.json");
lintTestRepo(test, globPatterns, configPath); return lintTestRepo(t, globPatterns, configPath);
}); });
} }

View file

@ -2,32 +2,31 @@
"use strict"; "use strict";
const tape = require("tape"); const test = require("ava").default;
require("tape-player");
const packageJson = require("../package.json"); const packageJson = require("../package.json");
const markdownlint = require("../lib/markdownlint"); const markdownlint = require("../lib/markdownlint");
const homepage = packageJson.homepage; const homepage = packageJson.homepage;
const version = packageJson.version; const version = packageJson.version;
tape("resultObjectToStringNotEnumerable", (test) => { test.cb("resultObjectToStringNotEnumerable", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"strings": { "strings": {
"string": "# Heading" "string": "# Heading"
} }
}; };
markdownlint(options, function callback(err, result) { markdownlint(options, function callback(err, result) {
test.ifError(err); t.falsy(err);
// eslint-disable-next-line guard-for-in // eslint-disable-next-line guard-for-in
for (const property in result) { for (const property in result) {
test.notEqual(property, "toString", "Function should not enumerate."); t.not(property, "toString", "Function should not enumerate.");
} }
test.end(); t.end();
}); });
}); });
tape("resultFormattingV0", (test) => { test.cb("resultFormattingV0", (t) => {
test.plan(4); t.plan(4);
const options = { const options = {
"files": [ "files": [
"./test/atx_heading_spacing.md", "./test/atx_heading_spacing.md",
@ -40,7 +39,7 @@ tape("resultFormattingV0", (test) => {
"resultVersion": 0 "resultVersion": 0
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"./test/atx_heading_spacing.md": { "./test/atx_heading_spacing.md": {
"MD002": [ 3 ], "MD002": [ 3 ],
@ -51,7 +50,8 @@ tape("resultFormattingV0", (test) => {
"MD002": [ 1 ] "MD002": [ 1 ]
} }
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); // @ts-ignore
t.deepEqual(actualResult, expectedResult, "Undetected issues.");
let actualMessage = actualResult.toString(); let actualMessage = actualResult.toString();
let expectedMessage = let expectedMessage =
"./test/atx_heading_spacing.md: 3: MD002" + "./test/atx_heading_spacing.md: 3: MD002" +
@ -64,7 +64,7 @@ tape("resultFormattingV0", (test) => {
" Multiple spaces after hash on atx style heading\n" + " Multiple spaces after hash on atx style heading\n" +
"./test/first_heading_bad_atx.md: 1: MD002" + "./test/first_heading_bad_atx.md: 1: MD002" +
" First heading should be a top-level heading"; " First heading should be a top-level heading";
test.equal(actualMessage, expectedMessage, "Incorrect message (name)."); t.is(actualMessage, expectedMessage, "Incorrect message (name).");
// @ts-ignore // @ts-ignore
actualMessage = actualResult.toString(true); actualMessage = actualResult.toString(true);
expectedMessage = expectedMessage =
@ -78,13 +78,13 @@ tape("resultFormattingV0", (test) => {
" Multiple spaces after hash on atx style heading\n" + " Multiple spaces after hash on atx style heading\n" +
"./test/first_heading_bad_atx.md: 1: first-heading-h1" + "./test/first_heading_bad_atx.md: 1: first-heading-h1" +
" First heading should be a top-level heading"; " First heading should be a top-level heading";
test.equal(actualMessage, expectedMessage, "Incorrect message (alias)."); t.is(actualMessage, expectedMessage, "Incorrect message (alias).");
test.end(); t.end();
}); });
}); });
tape("resultFormattingSyncV0", (test) => { test("resultFormattingSyncV0", (t) => {
test.plan(3); t.plan(3);
const options = { const options = {
"files": [ "files": [
"./test/atx_heading_spacing.md", "./test/atx_heading_spacing.md",
@ -107,7 +107,8 @@ tape("resultFormattingSyncV0", (test) => {
"MD002": [ 1 ] "MD002": [ 1 ]
} }
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); // @ts-ignore
t.deepEqual(actualResult, expectedResult, "Undetected issues.");
let actualMessage = actualResult.toString(); let actualMessage = actualResult.toString();
let expectedMessage = let expectedMessage =
"./test/atx_heading_spacing.md: 3: MD002" + "./test/atx_heading_spacing.md: 3: MD002" +
@ -120,7 +121,7 @@ tape("resultFormattingSyncV0", (test) => {
" Multiple spaces after hash on atx style heading\n" + " Multiple spaces after hash on atx style heading\n" +
"./test/first_heading_bad_atx.md: 1: MD002" + "./test/first_heading_bad_atx.md: 1: MD002" +
" First heading should be a top-level heading"; " First heading should be a top-level heading";
test.equal(actualMessage, expectedMessage, "Incorrect message (name)."); t.is(actualMessage, expectedMessage, "Incorrect message (name).");
// @ts-ignore // @ts-ignore
actualMessage = actualResult.toString(true); actualMessage = actualResult.toString(true);
expectedMessage = expectedMessage =
@ -134,12 +135,11 @@ tape("resultFormattingSyncV0", (test) => {
" Multiple spaces after hash on atx style heading\n" + " Multiple spaces after hash on atx style heading\n" +
"./test/first_heading_bad_atx.md: 1: first-heading-h1" + "./test/first_heading_bad_atx.md: 1: first-heading-h1" +
" First heading should be a top-level heading"; " First heading should be a top-level heading";
test.equal(actualMessage, expectedMessage, "Incorrect message (alias)."); t.is(actualMessage, expectedMessage, "Incorrect message (alias).");
test.end();
}); });
tape("resultFormattingV1", (test) => { test.cb("resultFormattingV1", (t) => {
test.plan(3); t.plan(3);
const options = { const options = {
"strings": { "strings": {
"truncate": "truncate":
@ -156,7 +156,7 @@ tape("resultFormattingV1", (test) => {
"resultVersion": 1 "resultVersion": 1
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"truncate": [ "truncate": [
{ "lineNumber": 1, { "lineNumber": 1,
@ -214,7 +214,8 @@ tape("resultFormattingV1", (test) => {
"errorRange": null } "errorRange": null }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); // @ts-ignore
t.deepEqual(actualResult, expectedResult, "Undetected issues.");
const actualMessage = actualResult.toString(); const actualMessage = actualResult.toString();
const expectedMessage = const expectedMessage =
"./test/atx_heading_spacing.md: 3: MD002/first-heading-h1" + "./test/atx_heading_spacing.md: 3: MD002/first-heading-h1" +
@ -235,13 +236,13 @@ tape("resultFormattingV1", (test) => {
"truncate: 1: MD021/no-multiple-space-closed-atx" + "truncate: 1: MD021/no-multiple-space-closed-atx" +
" Multiple spaces inside hashes on closed atx style heading" + " Multiple spaces inside hashes on closed atx style heading" +
" [Context: \"# Multiple spa...tyle heading #\"]"; " [Context: \"# Multiple spa...tyle heading #\"]";
test.equal(actualMessage, expectedMessage, "Incorrect message."); t.is(actualMessage, expectedMessage, "Incorrect message.");
test.end(); t.end();
}); });
}); });
tape("resultFormattingV2", (test) => { test.cb("resultFormattingV2", (t) => {
test.plan(3); t.plan(3);
const options = { const options = {
"strings": { "strings": {
"truncate": "truncate":
@ -257,7 +258,7 @@ tape("resultFormattingV2", (test) => {
} }
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"truncate": [ "truncate": [
{ "lineNumber": 1, { "lineNumber": 1,
@ -309,7 +310,7 @@ tape("resultFormattingV2", (test) => {
"errorRange": null } "errorRange": null }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
const actualMessage = actualResult.toString(); const actualMessage = actualResult.toString();
const expectedMessage = const expectedMessage =
"./test/atx_heading_spacing.md: 3:" + "./test/atx_heading_spacing.md: 3:" +
@ -332,13 +333,13 @@ tape("resultFormattingV2", (test) => {
"truncate: 1: MD021/no-multiple-space-closed-atx" + "truncate: 1: MD021/no-multiple-space-closed-atx" +
" Multiple spaces inside hashes on closed atx style heading" + " Multiple spaces inside hashes on closed atx style heading" +
" [Context: \"# Multiple spa...tyle heading #\"]"; " [Context: \"# Multiple spa...tyle heading #\"]";
test.equal(actualMessage, expectedMessage, "Incorrect message."); t.is(actualMessage, expectedMessage, "Incorrect message.");
test.end(); t.end();
}); });
}); });
tape("resultFormattingV3", (test) => { test.cb("resultFormattingV3", (t) => {
test.plan(3); t.plan(3);
const options = { const options = {
"strings": { "strings": {
"input": "input":
@ -350,7 +351,7 @@ tape("resultFormattingV3", (test) => {
"resultVersion": 3 "resultVersion": 3
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"input": [ "input": [
{ {
@ -423,7 +424,7 @@ tape("resultFormattingV3", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
const actualMessage = actualResult.toString(); const actualMessage = actualResult.toString();
const expectedMessage = const expectedMessage =
"input: 1: MD009/no-trailing-spaces" + "input: 1: MD009/no-trailing-spaces" +
@ -436,13 +437,13 @@ tape("resultFormattingV3", (test) => {
" Spaces inside emphasis markers [Context: \"* emphasis *\"]\n" + " Spaces inside emphasis markers [Context: \"* emphasis *\"]\n" +
"input: 4: MD047/single-trailing-newline" + "input: 4: MD047/single-trailing-newline" +
" Files should end with a single newline character"; " Files should end with a single newline character";
test.equal(actualMessage, expectedMessage, "Incorrect message."); t.is(actualMessage, expectedMessage, "Incorrect message.");
test.end(); t.end();
}); });
}); });
tape("onePerLineResultVersion0", (test) => { test.cb("onePerLineResultVersion0", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"strings": { "strings": {
"input": "# Heading\theading\t\theading\n" "input": "# Heading\theading\t\theading\n"
@ -450,19 +451,20 @@ tape("onePerLineResultVersion0", (test) => {
"resultVersion": 0 "resultVersion": 0
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"input": { "input": {
"MD010": [ 1 ] "MD010": [ 1 ]
} }
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); // @ts-ignore
test.end(); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
t.end();
}); });
}); });
tape("onePerLineResultVersion1", (test) => { test.cb("onePerLineResultVersion1", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"strings": { "strings": {
"input": "# Heading\theading\t\theading\n" "input": "# Heading\theading\t\theading\n"
@ -470,7 +472,7 @@ tape("onePerLineResultVersion1", (test) => {
"resultVersion": 1 "resultVersion": 1
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"input": [ "input": [
{ {
@ -486,13 +488,14 @@ tape("onePerLineResultVersion1", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); // @ts-ignore
test.end(); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
t.end();
}); });
}); });
tape("onePerLineResultVersion2", (test) => { test.cb("onePerLineResultVersion2", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"strings": { "strings": {
"input": "# Heading\theading\t\theading\n" "input": "# Heading\theading\t\theading\n"
@ -500,7 +503,7 @@ tape("onePerLineResultVersion2", (test) => {
"resultVersion": 2 "resultVersion": 2
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"input": [ "input": [
{ {
@ -515,13 +518,13 @@ tape("onePerLineResultVersion2", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.end(); t.end();
}); });
}); });
tape("manyPerLineResultVersion3", (test) => { test.cb("manyPerLineResultVersion3", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"strings": { "strings": {
"input": "# Heading\theading\t\theading\n" "input": "# Heading\theading\t\theading\n"
@ -529,7 +532,7 @@ tape("manyPerLineResultVersion3", (test) => {
"resultVersion": 3 "resultVersion": 3
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"input": [ "input": [
{ {
@ -564,13 +567,13 @@ tape("manyPerLineResultVersion3", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.end(); t.end();
}); });
}); });
tape("frontMatterResultVersion3", (test) => { test.cb("frontMatterResultVersion3", (t) => {
test.plan(2); t.plan(2);
const options = { const options = {
"strings": { "strings": {
"input": "---\n---\n# Heading\nText\n" "input": "---\n---\n# Heading\nText\n"
@ -578,7 +581,7 @@ tape("frontMatterResultVersion3", (test) => {
"resultVersion": 3 "resultVersion": 3
}; };
markdownlint(options, function callback(err, actualResult) { markdownlint(options, function callback(err, actualResult) {
test.ifError(err); t.falsy(err);
const expectedResult = { const expectedResult = {
"input": [ "input": [
{ {
@ -598,7 +601,7 @@ tape("frontMatterResultVersion3", (test) => {
} }
] ]
}; };
test.deepEqual(actualResult, expectedResult, "Undetected issues."); t.deepEqual(actualResult, expectedResult, "Undetected issues.");
test.end(); t.end();
}); });
}); });

View file

@ -5,8 +5,7 @@
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const { promisify } = require("util"); const { promisify } = require("util");
const tape = require("tape"); const test = require("ava").default;
require("tape-player");
const { version } = require("../package.json"); const { version } = require("../package.json");
const markdownlint = require("../lib/markdownlint"); const markdownlint = require("../lib/markdownlint");
const helpers = require("../helpers"); const helpers = require("../helpers");
@ -19,9 +18,9 @@ const helpers = require("../helpers");
*/ */
function createTestForFile(file) { function createTestForFile(file) {
const markdownlintPromise = promisify(markdownlint); const markdownlintPromise = promisify(markdownlint);
return function testForFile(test) { return function testForFile(t) {
const detailedResults = /[/\\]detailed-results-/.test(file); const detailedResults = /[/\\]detailed-results-/.test(file);
test.plan(detailedResults ? 3 : 2); t.plan(detailedResults ? 3 : 2);
const resultsFile = file.replace(/\.md$/, ".results.json"); const resultsFile = file.replace(/\.md$/, ".results.json");
const fixedFile = file.replace(/\.md$/, ".md.fixed"); const fixedFile = file.replace(/\.md$/, ".md.fixed");
const configFile = file.replace(/\.md$/, ".json"); const configFile = file.replace(/\.md$/, ".json");
@ -66,8 +65,7 @@ function createTestForFile(file) {
const actual = helpers.applyFixes(content, errors); const actual = helpers.applyFixes(content, errors);
// Uncomment the following line to update *.md.fixed files // Uncomment the following line to update *.md.fixed files
// fs.writeFileSync(fixedFile, actual, "utf8"); // fs.writeFileSync(fixedFile, actual, "utf8");
test.equal(actual, expected, t.is(actual, expected, "Unexpected output from applyFixes.");
"Unexpected output from applyFixes.");
return resultVersion2or3; return resultVersion2or3;
}) : }) :
resultVersion2or3; resultVersion2or3;
@ -128,18 +126,18 @@ function createTestForFile(file) {
}); });
return sortedResults; return sortedResults;
}); });
Promise.all([ actualPromise, expectedPromise ]) return Promise.all([ actualPromise, expectedPromise ])
.then( .then(
function compareResults(fulfillments) { function compareResults(fulfillments) {
const [ [ actual0, actual2or3 ], expected ] = fulfillments; const [ [ actual0, actual2or3 ], expected ] = fulfillments;
const actual = detailedResults ? actual2or3 : actual0; const actual = detailedResults ? actual2or3 : actual0;
test.deepEqual(actual, expected, "Line numbers are not correct."); t.deepEqual(actual, expected, "Line numbers are not correct.");
return actual2or3; return actual2or3;
}) })
.then( .then(
function verifyFixes(errors) { function verifyFixes(errors) {
if (detailedResults) { if (detailedResults) {
return test.ok(true); return t.true(true);
} }
return fs.promises.readFile(file, "utf8") return fs.promises.readFile(file, "utf8")
.then( .then(
@ -157,16 +155,16 @@ function createTestForFile(file) {
function checkFixes(newErrors) { function checkFixes(newErrors) {
const unfixed = newErrors.input const unfixed = newErrors.input
.filter((error) => !!error.fixInfo); .filter((error) => !!error.fixInfo);
test.deepEqual(unfixed, [], "Fixable error was not fixed."); t.deepEqual(unfixed, [], "Fixable error was not fixed.");
} }
); );
}) })
.catch() .catch()
.then(test.done); .then(t.done);
}; };
} }
fs.readdirSync("./test") fs.readdirSync("./test")
.filter((file) => /\.md$/.test(file)) .filter((file) => /\.md$/.test(file))
// @ts-ignore // @ts-ignore
.forEach((file) => tape(file, createTestForFile(path.join("./test", file)))); .forEach((file) => test(file, createTestForFile(path.join("./test", file))));

File diff suppressed because it is too large Load diff