|
4 | 4 | * Unit tests for utils.js helpers used by custom rules (e.g. isRuleSuppressedByComment). |
5 | 5 | */ |
6 | 6 |
|
| 7 | +const path = require("node:path"); |
7 | 8 | const { describe, it } = require("node:test"); |
8 | 9 | const assert = require("node:assert"); |
9 | | -const { isRuleSuppressedByComment } = require("../../markdownlint-rules/utils.js"); |
| 10 | +const { isRuleSuppressedByComment, matchGlob, pathMatchesAny } = require("../../markdownlint-rules/utils.js"); |
10 | 11 |
|
11 | 12 | describe("utils", () => { |
| 13 | + describe("matchGlob", () => { |
| 14 | + it("matches bare filename only at path root (single segment)", () => { |
| 15 | + assert.strictEqual(matchGlob("README.md", "README.md"), true); |
| 16 | + assert.strictEqual(matchGlob("docs/README.md", "README.md"), false); |
| 17 | + assert.strictEqual(matchGlob("docs/README.md", "**/README.md"), true); |
| 18 | + }); |
| 19 | + |
| 20 | + it("matches *.md only at root segment", () => { |
| 21 | + assert.strictEqual(matchGlob("doc.md", "*.md"), true); |
| 22 | + assert.strictEqual(matchGlob("sub/doc.md", "*.md"), false); |
| 23 | + assert.strictEqual(matchGlob("sub/doc.md", "**/*.md"), true); |
| 24 | + }); |
| 25 | + |
| 26 | + it("matches root basename when path is absolute (markdownlint passes full path)", () => { |
| 27 | + const rootReadme = path.join(process.cwd(), "README.md"); |
| 28 | + const nestedReadme = path.join(process.cwd(), "docs", "README.md"); |
| 29 | + assert.strictEqual(matchGlob(rootReadme, "README.md"), true); |
| 30 | + assert.strictEqual(matchGlob(nestedReadme, "README.md"), false); |
| 31 | + }); |
| 32 | + |
| 33 | + it("normalizes relative paths with .. before matching (docs/../README.md)", () => { |
| 34 | + assert.strictEqual(matchGlob("docs/../README.md", "README.md"), true); |
| 35 | + assert.strictEqual(matchGlob("docs/../other/README.md", "README.md"), false); |
| 36 | + }); |
| 37 | + |
| 38 | + it("matches one .. segment relative to cwd (../README.md from a subdir)", () => { |
| 39 | + const parentReadme = path.resolve(process.cwd(), "..", "README.md"); |
| 40 | + assert.strictEqual(matchGlob(parentReadme, "README.md"), true); |
| 41 | + assert.strictEqual(matchGlob(path.resolve(process.cwd(), "..", "other", "README.md"), "README.md"), false); |
| 42 | + }); |
| 43 | + }); |
| 44 | + |
| 45 | + describe("pathMatchesAny", () => { |
| 46 | + it("returns false when no pattern matches", () => { |
| 47 | + assert.strictEqual(pathMatchesAny("a/b.md", ["x.md"]), false); |
| 48 | + }); |
| 49 | + |
| 50 | + it("returns true when any pattern matches", () => { |
| 51 | + assert.strictEqual(pathMatchesAny("README.md", ["other.md", "README.md"]), true); |
| 52 | + }); |
| 53 | + }); |
| 54 | + |
12 | 55 | describe("isRuleSuppressedByComment", () => { |
13 | 56 | it("returns true when previous line is solely the suppress comment", () => { |
14 | 57 | const lines = ["<!-- no-empty-heading allow -->", "## Empty", "## Next"]; |
15 | 58 | assert.strictEqual(isRuleSuppressedByComment(lines, 2, "no-empty-heading"), true); |
16 | 59 | }); |
17 | 60 |
|
| 61 | + it("returns true when suppress comment is separated by blank lines from the line", () => { |
| 62 | + const lines = ["<!-- no-h1-content allow -->", "", "", "Intro paragraph.", "## Next"]; |
| 63 | + assert.strictEqual(isRuleSuppressedByComment(lines, 4, "no-h1-content"), true); |
| 64 | + }); |
| 65 | + |
| 66 | + it("returns false when a non-blank line between target and suppress is not the comment", () => { |
| 67 | + const lines = ["<!-- no-h1-content allow -->", "- [TOC](#toc)", "", "Prose.", "## Next"]; |
| 68 | + assert.strictEqual(isRuleSuppressedByComment(lines, 4, "no-h1-content"), false); |
| 69 | + }); |
| 70 | + |
18 | 71 | it("returns true when current line ends with the suppress comment", () => { |
19 | 72 | const lines = ["## Empty section <!-- no-empty-heading allow -->", "## Next"]; |
20 | 73 | assert.strictEqual(isRuleSuppressedByComment(lines, 1, "no-empty-heading"), true); |
|
0 commit comments