|
| 1 | +package main_test |
| 2 | + |
| 3 | +import ( |
| 4 | + "os" |
| 5 | + "path/filepath" |
| 6 | + "testing" |
| 7 | + |
| 8 | + "github.com/stretchr/testify/assert" |
| 9 | + "github.com/stretchr/testify/require" |
| 10 | +) |
| 11 | + |
| 12 | +// gitattributesFixture is a .gitattributes body whose `#` comment lines |
| 13 | +// would be parsed as ATX headings if linted as Markdown: they sit with |
| 14 | +// no surrounding blank lines (blank-line-around-headings would insert |
| 15 | +// them) and end in punctuation (MDS017). If the explicit-path guard |
| 16 | +// regresses, `fix` rewrites this content and the byte-equality |
| 17 | +// assertion fails. |
| 18 | +const gitattributesFixture = `# BEGIN mdsmith merge-driver |
| 19 | +*.md merge=mdsmith |
| 20 | +*.markdown merge=mdsmith |
| 21 | +# END mdsmith merge-driver |
| 22 | +# Re-enable git 3-way merge for code under the trees mdsmith marks -merge. |
| 23 | +# mdsmith derives those -merge lines from the config ignore patterns. |
| 24 | +` |
| 25 | + |
| 26 | +// TestFix_ExplicitNonMarkdownFileUnchanged is the regression test for |
| 27 | +// issue #759: passing a non-Markdown file explicitly to `mdsmith fix` |
| 28 | +// must not rewrite it. The directory walk already skips such files; an |
| 29 | +// explicit path must behave the same. |
| 30 | +func TestFix_ExplicitNonMarkdownFileUnchanged(t *testing.T) { |
| 31 | + dir := t.TempDir() |
| 32 | + isolateDir(t, dir) |
| 33 | + attrPath := filepath.Join(dir, ".gitattributes") |
| 34 | + require.NoError(t, os.WriteFile(attrPath, []byte(gitattributesFixture), 0o644)) |
| 35 | + |
| 36 | + _, stderr, exitCode := runBinaryInDir(t, dir, "", "fix", ".gitattributes") |
| 37 | + assert.Equal(t, 0, exitCode, "fix on a non-Markdown file should succeed with nothing to do") |
| 38 | + assert.Contains(t, stderr, `skipping ".gitattributes"`, |
| 39 | + "fix should warn that the explicitly named non-Markdown file was skipped, not do nothing silently") |
| 40 | + |
| 41 | + got, err := os.ReadFile(attrPath) |
| 42 | + require.NoError(t, err) |
| 43 | + assert.Equal(t, gitattributesFixture, string(got), |
| 44 | + "fix must leave a non-Markdown file byte-for-byte unchanged") |
| 45 | +} |
| 46 | + |
| 47 | +// TestCheck_ExplicitNonMarkdownFileClean is the check-side counterpart: |
| 48 | +// a non-Markdown file named explicitly is skipped (no Markdown content |
| 49 | +// diagnostics, clean exit) but reported with a warning rather than a |
| 50 | +// silent no-op. |
| 51 | +func TestCheck_ExplicitNonMarkdownFileClean(t *testing.T) { |
| 52 | + dir := t.TempDir() |
| 53 | + isolateDir(t, dir) |
| 54 | + attrPath := filepath.Join(dir, ".gitattributes") |
| 55 | + require.NoError(t, os.WriteFile(attrPath, []byte(gitattributesFixture), 0o644)) |
| 56 | + |
| 57 | + stdout, stderr, exitCode := runBinaryInDir(t, dir, "", "check", ".gitattributes") |
| 58 | + assert.Equal(t, 0, exitCode, |
| 59 | + "check on a non-Markdown file should exit clean; stdout=%q stderr=%q", stdout, stderr) |
| 60 | + assert.NotContains(t, stderr, "MDS", "no Markdown diagnostics should be reported") |
| 61 | + assert.Contains(t, stderr, `skipping ".gitattributes"`, |
| 62 | + "check should warn that the explicitly named non-Markdown file was skipped") |
| 63 | +} |
| 64 | + |
| 65 | +// TestCheck_NonMarkdownWarningSuppressed verifies the skip warning is a |
| 66 | +// text-format, non-quiet affordance only: it must not appear under |
| 67 | +// --quiet (non-error output) or --format json (the JSON document shares |
| 68 | +// the stderr stream and a prose line would corrupt it). |
| 69 | +func TestCheck_NonMarkdownWarningSuppressed(t *testing.T) { |
| 70 | + dir := t.TempDir() |
| 71 | + isolateDir(t, dir) |
| 72 | + attrPath := filepath.Join(dir, ".gitattributes") |
| 73 | + require.NoError(t, os.WriteFile(attrPath, []byte(gitattributesFixture), 0o644)) |
| 74 | + |
| 75 | + for _, tc := range []struct { |
| 76 | + name string |
| 77 | + args []string |
| 78 | + }{ |
| 79 | + {"quiet", []string{"check", "--quiet", ".gitattributes"}}, |
| 80 | + {"json", []string{"check", "-f", "json", ".gitattributes"}}, |
| 81 | + } { |
| 82 | + t.Run(tc.name, func(t *testing.T) { |
| 83 | + stdout, stderr, exitCode := runBinaryInDir(t, dir, "", tc.args...) |
| 84 | + assert.Equal(t, 0, exitCode, "should still exit clean; stdout=%q stderr=%q", stdout, stderr) |
| 85 | + assert.NotContains(t, stderr, "skipping", |
| 86 | + "the human skip warning must be suppressed in %s mode", tc.name) |
| 87 | + }) |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +// TestCheck_MixedExplicitPathsLintsOnlyMarkdown pins that when both a |
| 92 | +// Markdown file and a non-Markdown file are named explicitly, only the |
| 93 | +// Markdown one is linted: the non-Markdown file is dropped, but the |
| 94 | +// Markdown file's genuine diagnostic still surfaces. |
| 95 | +func TestCheck_MixedExplicitPathsLintsOnlyMarkdown(t *testing.T) { |
| 96 | + dir := t.TempDir() |
| 97 | + isolateDir(t, dir) |
| 98 | + attrPath := filepath.Join(dir, ".gitattributes") |
| 99 | + mdPath := filepath.Join(dir, "bad.md") |
| 100 | + require.NoError(t, os.WriteFile(attrPath, []byte(gitattributesFixture), 0o644)) |
| 101 | + // A heading ending in a period is MDS017, a default-enabled rule |
| 102 | + // (the issue confirms it fires); used only to prove the Markdown |
| 103 | + // file was actually linted. |
| 104 | + require.NoError(t, os.WriteFile(mdPath, []byte("# Heading.\n"), 0o644)) |
| 105 | + |
| 106 | + stdout, stderr, exitCode := runBinaryInDir(t, dir, "", "check", ".gitattributes", "bad.md") |
| 107 | + assert.Equal(t, 1, exitCode, |
| 108 | + "the Markdown file's diagnostic should still fail the run; stdout=%q stderr=%q", stdout, stderr) |
| 109 | + assert.Contains(t, stderr, "bad.md", "the Markdown file should be the one reported") |
| 110 | + // The non-Markdown file may appear in the skip warning |
| 111 | + // (`skipping ".gitattributes"`), but must never appear as a linted |
| 112 | + // diagnostic — those are anchored as `<path>:<line>:<col>`. |
| 113 | + assert.NotContains(t, stderr, ".gitattributes:", |
| 114 | + "the non-Markdown file must not be linted (no diagnostic anchored to it)") |
| 115 | +} |
0 commit comments