Add tests to verify detailed result format and basic content.

This commit is contained in:
David Anson 2016-10-16 21:46:02 -07:00
parent 23404f95ac
commit 5627bc27eb
13 changed files with 434 additions and 27 deletions

View file

@ -898,7 +898,8 @@ module.exports = [
var left = linkText.trimLeft().length !== linkText.length; var left = linkText.trimLeft().length !== linkText.length;
var right = linkText.trimRight().length !== linkText.length; var right = linkText.trimRight().length !== linkText.length;
if (left || right) { if (left || right) {
errors.addContext(token.lineNumber, linkText, left, right); errors.addContext(
token.lineNumber, "[" + linkText + "]", left, right);
} }
} else if (inLink) { } else if (inLink) {
linkText += child.content; linkText += child.content;

View file

@ -0,0 +1,17 @@
## One
#### Two
### Three ###
* Alpha
* Bravo
- Charlie
* Delta
* Echo
Text
Text text

View file

@ -0,0 +1,74 @@
[
{
"lineNumber": 3,
"ruleName": "MD001",
"ruleAlias": "header-increment",
"ruleDescription": "Header levels should only increment by one level at a time",
"errorDetail": "Expected: h3; Actual: h4",
"errorContext": null
},
{
"lineNumber": 1,
"ruleName": "MD002",
"ruleAlias": "first-header-h1",
"ruleDescription": "First header should be a top level header",
"errorDetail": "Expected: h1; Actual: h2",
"errorContext": null
},
{
"lineNumber": 5,
"ruleName": "MD003",
"ruleAlias": "header-style",
"ruleDescription": "Header style",
"errorDetail": "Expected: atx; Actual: atx_closed",
"errorContext": null
},
{
"lineNumber": 10,
"ruleName": "MD004",
"ruleAlias": "ul-style",
"ruleDescription": "Unordered list style",
"errorDetail": "Expected: asterisk; Actual: dash",
"errorContext": null
},
{
"lineNumber": 8,
"ruleName": "MD005",
"ruleAlias": "list-indent",
"ruleDescription": "Inconsistent indentation for list items at the same level",
"errorDetail": "Expected: 0; Actual: 1",
"errorContext": null
},
{
"lineNumber": 12,
"ruleName": "MD006",
"ruleAlias": "ul-start-left",
"ruleDescription": "Consider starting bulleted lists at the beginning of the line",
"errorDetail": "Expected: 0; Actual: 1",
"errorContext": null
},
{
"lineNumber": 12,
"ruleName": "MD007",
"ruleAlias": "ul-indent",
"ruleDescription": "Unordered list indentation",
"errorDetail": "Expected: 2; Actual: 1",
"errorContext": null
},
{
"lineNumber": 15,
"ruleName": "MD009",
"ruleAlias": "no-trailing-spaces",
"ruleDescription": "Trailing spaces",
"errorDetail": "Expected: 0; Actual: 1",
"errorContext": null
},
{
"lineNumber": 17,
"ruleName": "MD010",
"ruleAlias": "no-hard-tabs",
"ruleDescription": "Hard tabs",
"errorDetail": "Column: 5",
"errorContext": null
}
]

View file

@ -0,0 +1,16 @@
<!-- markdownlint-disable MD003 -->
A (reversed)[link] example.
123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
$ command with no output
#No space A
# Multiple spaces A
#No space B#
# Multiple spaces B #

View file

@ -0,0 +1,66 @@
[
{
"lineNumber": 3,
"ruleName": "MD011",
"ruleAlias": "no-reversed-links",
"ruleDescription": "Reversed link syntax",
"errorDetail": "(reversed)[link]",
"errorContext": null
},
{
"lineNumber": 5,
"ruleName": "MD012",
"ruleAlias": "no-multiple-blanks",
"ruleDescription": "Multiple consecutive blank lines",
"errorDetail": "Expected: 1; Actual: 2",
"errorContext": null
},
{
"lineNumber": 6,
"ruleName": "MD013",
"ruleAlias": "line-length",
"ruleDescription": "Line length",
"errorDetail": "Expected: 80; Actual: 99",
"errorContext": null
},
{
"lineNumber": 8,
"ruleName": "MD014",
"ruleAlias": "commands-show-output",
"ruleDescription": "Dollar signs used before commands without showing output",
"errorDetail": null,
"errorContext": "$ command with no output"
},
{
"lineNumber": 10,
"ruleName": "MD018",
"ruleAlias": "no-missing-space-atx",
"ruleDescription": "No space after hash on atx style header",
"errorDetail": null,
"errorContext": "#No space A"
},
{
"lineNumber": 12,
"ruleName": "MD019",
"ruleAlias": "no-multiple-space-atx",
"ruleDescription": "Multiple spaces after hash on atx style header",
"errorDetail": null,
"errorContext": "# Multiple spaces A"
},
{
"lineNumber": 14,
"ruleName": "MD020",
"ruleAlias": "no-missing-space-closed-atx",
"ruleDescription": "No space inside hashes on closed atx style header",
"errorDetail": null,
"errorContext": "#No space B#"
},
{
"lineNumber": 16,
"ruleName": "MD021",
"ruleAlias": "no-multiple-space-closed-atx",
"ruleDescription": "Multiple spaces inside hashes on closed atx style header",
"errorDetail": null,
"errorContext": "# Multiple spaces B #"
}
]

View file

@ -0,0 +1,13 @@
# Heading
Text
# Heading
## Another heading.
> Multiple spaces
> Blank line above
1. Alpha
2. Beta

View file

@ -0,0 +1,74 @@
[
{
"lineNumber": 1,
"ruleName": "MD022",
"ruleAlias": "blanks-around-headers",
"ruleDescription": "Headers should be surrounded by blank lines",
"errorDetail": null,
"errorContext": "# Heading"
},
{
"lineNumber": 1,
"ruleName": "MD023",
"ruleAlias": "header-start-left",
"ruleDescription": "Headers must start at the beginning of the line",
"errorDetail": null,
"errorContext": " # Heading"
},
{
"lineNumber": 4,
"ruleName": "MD024",
"ruleAlias": "no-duplicate-header",
"ruleDescription": "Multiple headers with the same content",
"errorDetail": null,
"errorContext": "# Heading"
},
{
"lineNumber": 4,
"ruleName": "MD025",
"ruleAlias": "single-h1",
"ruleDescription": "Multiple top level headers in the same document",
"errorDetail": null,
"errorContext": "# Heading"
},
{
"lineNumber": 6,
"ruleName": "MD026",
"ruleAlias": "no-trailing-punctuation",
"ruleDescription": "Trailing punctuation in header",
"errorDetail": "Punctuation: '.'",
"errorContext": null
},
{
"lineNumber": 8,
"ruleName": "MD027",
"ruleAlias": "no-multiple-space-blockquote",
"ruleDescription": "Multiple spaces after blockquote symbol",
"errorDetail": null,
"errorContext": "> Multiple spaces"
},
{
"lineNumber": 9,
"ruleName": "MD028",
"ruleAlias": "no-blanks-blockquote",
"ruleDescription": "Blank line inside blockquote",
"errorDetail": null,
"errorContext": null
},
{
"lineNumber": 13,
"ruleName": "MD029",
"ruleAlias": "ol-prefix",
"ruleDescription": "Ordered list item prefix",
"errorDetail": "Expected: 1; Actual: 2",
"errorContext": null
},
{
"lineNumber": 13,
"ruleName": "MD030",
"ruleAlias": "list-marker-space",
"ruleDescription": "Spaces after list markers",
"errorDetail": "Expected: 1; Actual: 2",
"errorContext": null
}
]

View file

@ -0,0 +1,22 @@
```js
debugger;
```
* List
Inline<hr/>HTML
Bare http://example.com link
---
***
*Emphasis*
Space * inside * emphasis
Space ` inside ` code span
Space [ inside ](link) text
```
```

View file

@ -0,0 +1,82 @@
[
{
"lineNumber": 3,
"ruleName": "MD031",
"ruleAlias": "blanks-around-fences",
"ruleDescription": "Fenced code blocks should be surrounded by blank lines",
"errorDetail": null,
"errorContext": "```"
},
{
"lineNumber": 4,
"ruleName": "MD032",
"ruleAlias": "blanks-around-lists",
"ruleDescription": "Lists should be surrounded by blank lines",
"errorDetail": null,
"errorContext": "* List"
},
{
"lineNumber": 6,
"ruleName": "MD033",
"ruleAlias": "no-inline-html",
"ruleDescription": "Inline HTML",
"errorDetail": "Element: hr",
"errorContext": null
},
{
"lineNumber": 8,
"ruleName": "MD034",
"ruleAlias": "no-bare-urls",
"ruleDescription": "Bare URL used",
"errorDetail": null,
"errorContext": "http://example.com"
},
{
"lineNumber": 11,
"ruleName": "MD035",
"ruleAlias": "hr-style",
"ruleDescription": "Horizontal rule style",
"errorDetail": "Expected: ---; Actual: ***",
"errorContext": null
},
{
"lineNumber": 13,
"ruleName": "MD036",
"ruleAlias": "no-emphasis-as-header",
"ruleDescription": "Emphasis used instead of a header",
"errorDetail": null,
"errorContext": "Emphasis"
},
{
"lineNumber": 15,
"ruleName": "MD037",
"ruleAlias": "no-space-in-emphasis",
"ruleDescription": "Spaces inside emphasis markers",
"errorDetail": null,
"errorContext": "* inside *"
},
{
"lineNumber": 17,
"ruleName": "MD038",
"ruleAlias": "no-space-in-code",
"ruleDescription": "Spaces inside code span elements",
"errorDetail": null,
"errorContext": "` inside `"
},
{
"lineNumber": 19,
"ruleName": "MD039",
"ruleAlias": "no-space-in-links",
"ruleDescription": "Spaces inside link text",
"errorDetail": null,
"errorContext": "[ inside ]"
},
{
"lineNumber": 21,
"ruleName": "MD040",
"ruleAlias": "fenced-code-language",
"ruleDescription": "Fenced code blocks should have a language specified",
"errorDetail": null,
"errorContext": "```"
}
]

View file

@ -0,0 +1,9 @@
{
"default": true,
"MD041": true,
"MD043": {
"headers": [
"# Header"
]
}
}

View file

@ -0,0 +1,3 @@
Not a header
An [empty]() link

View file

@ -0,0 +1,26 @@
[
{
"lineNumber": 1,
"ruleName": "MD041",
"ruleAlias": "first-line-h1",
"ruleDescription": "First line in file should be a top level header",
"errorDetail": null,
"errorContext": "Not a header"
},
{
"lineNumber": 3,
"ruleName": "MD042",
"ruleAlias": "no-empty-links",
"ruleDescription": "No empty links",
"errorDetail": null,
"errorContext": "[empty]"
},
{
"lineNumber": 4,
"ruleName": "MD043",
"ruleAlias": "required-headers",
"ruleDescription": "Required header structure",
"errorDetail": null,
"errorContext": "# Header"
}
]

View file

@ -15,15 +15,14 @@ var configSchema = require("../schema/markdownlint-config-schema.json");
function createTestForFile(file) { function createTestForFile(file) {
return function testForFile(test) { return function testForFile(test) {
test.expect(1); test.expect(1);
var detailedResults = /[\/\\]detailed-results-/.test(file);
var resultsFile = file.replace(/\.md$/, ".results.json");
var configFile = file.replace(/\.md$/, ".json"); var configFile = file.replace(/\.md$/, ".json");
var actualPromise = Q.nfcall(fs.stat, configFile) var actualPromise = Q.nfcall(fs.stat, configFile)
.then( .then(
function configFileExists() { function configFileExists() {
return Q.nfcall(fs.readFile, configFile, shared.utf8Encoding) return Q.nfcall(fs.readFile, configFile, shared.utf8Encoding)
.then( .then(JSON.parse);
function configFileContents(contents) {
return JSON.parse(contents);
});
}, },
function noConfigFile() { function noConfigFile() {
return {}; return {};
@ -33,30 +32,34 @@ function createTestForFile(file) {
var mergedConfig = shared.assign(shared.clone(defaultConfig), config); var mergedConfig = shared.assign(shared.clone(defaultConfig), config);
return Q.nfcall(markdownlint, { return Q.nfcall(markdownlint, {
"files": [ file ], "files": [ file ],
"config": mergedConfig "config": mergedConfig,
"resultVersion": detailedResults ? 1 : 0
}); });
}); });
var expectedPromise = Q.nfcall(fs.readFile, file, shared.utf8Encoding) var expectedPromise = detailedResults ?
.then( Q.nfcall(fs.readFile, resultsFile, shared.utf8Encoding)
function fileContents(contents) { .then(JSON.parse) :
var lines = contents.split(shared.newLineRe); Q.nfcall(fs.readFile, file, shared.utf8Encoding)
var results = {}; .then(
lines.forEach(function forLine(line, lineNum) { function fileContents(contents) {
var regex = /\{(MD\d+)(?::(\d+))?\}/g; var lines = contents.split(shared.newLineRe);
var match = null; var results = {};
while ((match = regex.exec(line))) { lines.forEach(function forLine(line, lineNum) {
var rule = match[1]; var regex = /\{(MD\d+)(?::(\d+))?\}/g;
var errors = results[rule] || []; var match = null;
errors.push(match[2] ? parseInt(match[2], 10) : lineNum + 1); while ((match = regex.exec(line))) {
results[rule] = errors; var rule = match[1];
} var errors = results[rule] || [];
errors.push(match[2] ? parseInt(match[2], 10) : lineNum + 1);
results[rule] = errors;
}
});
var sortedResults = {};
Object.keys(results).sort().forEach(function forKey(key) {
sortedResults[key] = results[key];
});
return sortedResults;
}); });
var sortedResults = {};
Object.keys(results).sort().forEach(function forKey(key) {
sortedResults[key] = results[key];
});
return sortedResults;
});
Q.all([ actualPromise, expectedPromise ]) Q.all([ actualPromise, expectedPromise ])
.then( .then(
function compareResults(fulfillments) { function compareResults(fulfillments) {
@ -1026,10 +1029,11 @@ module.exports.doc = function doc(test) {
module.exports.validateConfigSchema = function validateConfigSchema(test) { module.exports.validateConfigSchema = function validateConfigSchema(test) {
var jsonFileRe = /\.json$/i; var jsonFileRe = /\.json$/i;
var resultsFileRe = /\.results\.json$/i;
var testDirectory = __dirname; var testDirectory = __dirname;
var testFiles = fs.readdirSync(testDirectory); var testFiles = fs.readdirSync(testDirectory);
testFiles.filter(function filterFile(file) { testFiles.filter(function filterFile(file) {
return jsonFileRe.test(file); return jsonFileRe.test(file) && !resultsFileRe.test(file);
}).forEach(function forFile(file) { }).forEach(function forFile(file) {
var data = fs.readFileSync(path.join(testDirectory, file)); var data = fs.readFileSync(path.join(testDirectory, file));
test.ok( test.ok(