Repository navigation
Expand file tree
/
Copy pathmark_dryrun_orphans_test.go
More file actions
128 lines (107 loc) · 4.64 KB
/
Copy pathmark_dryrun_orphans_test.go
File metadata and controls
128 lines (107 loc) · 4.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package mark
import (
"encoding/json"
"net/http"
"os"
"path/filepath"
"testing"
"github.com/kovetskiy/mark/v16/confluence/confluencetest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// writesTo lists the requests that could have changed something on the server:
// anything that is not a read. A dry run must send none of them.
func writesTo(server *confluencetest.Server) []string {
var writes []string
for _, r := range server.Requests() {
if r.Method != http.MethodGet && r.Method != http.MethodHead {
writes = append(writes, r.Method+" "+r.Path)
}
}
return writes
}
// publishTracked publishes every *.md in dir with tracking on and
// --on-orphan delete, returning the config so a dry run can repeat it.
func publishTracked(t *testing.T, server *confluencetest.Server, dir string) Config {
t.Helper()
config := trackingConfig(server, filepath.Join(dir, "*.md"))
config.OnOrphan = "delete"
require.NoError(t, Run(config))
return config
}
// TestDryRunDoesNotReportPublishedPagesAsOrphans: a dry run over documents that
// are all still present, after a tracked publish, must not read them as gone.
// The dry run found each page by title and returned before recording it, so
// every tracked path looked unseen: it reported the whole set as orphans, and
// with --on-orphan delete only the "nothing was published" guard in mark.go
// stopped it from listing each one as to be deleted.
func TestDryRunDoesNotReportPublishedPagesAsOrphans(t *testing.T) {
server, api := docsSpace(t)
dir := t.TempDir()
a := writeFile(t, dir, "a.md", markdownWithTitle("A"))
b := writeFile(t, dir, "b.md", markdownWithTitle("B"))
config := publishTracked(t, server, dir)
pageA, err := api.FindPage("DOCS", "A", "page")
require.NoError(t, err)
require.NotNil(t, pageA)
pageB, err := api.FindPage("DOCS", "B", "page")
require.NoError(t, err)
require.NotNil(t, pageB)
server.ResetRequests()
dry := config
dry.DryRun = true
logged := captureLog(t, func() { require.NoError(t, Run(dry)) })
// The capture works, at the level the orphan report is written at: without
// this, a quieter logger would make the assertions below pass vacuously.
assert.Contains(t, logged, "processing "+inLog(a))
assert.Contains(t, logged, "processing "+inLog(b))
// What the dry run used to log: every page reported as an orphan, then the
// "nothing was published" guard holding the deletion back.
assert.NotContains(t, logged, "had no matching source file",
"every document is still there")
assert.NotContains(t, logged, "nothing was published in this run")
// The guard above stopped the original bug short of this line; this
// assertion guards against a regression that gets past it. The text comes
// from the "page %q would be %sd" format in page/orphan.go.
assert.NotContains(t, logged, "would be deleted")
assert.Empty(t, writesTo(server), "a dry run must not change anything")
assert.False(t, server.Page(pageA.ID).Trashed)
assert.False(t, server.Page(pageB.ID).Trashed)
}
// TestDryRunStillReportsRealOrphans is the other half: recording the pages a dry
// run finds must not hide the one that is really gone. It is reported, and
// would be deleted, but the dry run leaves it where it is.
func TestDryRunStillReportsRealOrphans(t *testing.T) {
server, api := docsSpace(t)
dir := t.TempDir()
a := writeFile(t, dir, "a.md", markdownWithTitle("A"))
b := writeFile(t, dir, "b.md", markdownWithTitle("B"))
config := publishTracked(t, server, dir)
pageA, err := api.FindPage("DOCS", "A", "page")
require.NoError(t, err)
require.NotNil(t, pageA)
pageB, err := api.FindPage("DOCS", "B", "page")
require.NoError(t, err)
require.NotNil(t, pageB)
require.NoError(t, os.Remove(b))
server.ResetRequests()
dry := config
dry.DryRun = true
logged := captureLog(t, func() { require.NoError(t, Run(dry)) })
assert.Contains(t, logged, "processing "+inLog(a))
assert.Contains(t, logged, "1 tracked page(s) had no matching source file in this run: "+filepath.ToSlash(b),
"b.md is gone, and only b.md")
// "page %q would be %sd" in page/orphan.go; the quotes are escaped because
// zerolog writes the message as JSON.
assert.Contains(t, logged, `page \"B\" would be deleted`)
assert.NotContains(t, logged, `page \"A\" would be deleted`)
assert.Empty(t, writesTo(server), "a dry run must not change anything")
assert.False(t, server.Page(pageA.ID).Trashed)
assert.False(t, server.Page(pageB.ID).Trashed, "a dry run only says what it would delete")
}
// inLog is s as it reads in the captured log, which zerolog writes as JSON: a
// Windows path has its backslashes doubled.
func inLog(s string) string {
b, _ := json.Marshal(s)
return string(b[1 : len(b)-1])
}