forked from
tangled.org/core
Monorepo for Tangled
1package pages
2
3import (
4 "bytes"
5 "io"
6 "log/slog"
7 "strings"
8 "testing"
9
10 "tangled.org/core/appview/config"
11 "tangled.org/core/appview/models"
12 "tangled.org/core/appview/pages/repoinfo"
13 "tangled.org/core/patchutil"
14 "tangled.org/core/types"
15)
16
17func TestPullComposeTemplatesParse(t *testing.T) {
18 cfg := &config.Config{}
19 p := NewPages(cfg, nil, nil, nil, slog.New(slog.NewTextHandler(io.Discard, nil)))
20
21 cases := []struct {
22 name string
23 stack []string
24 }{
25 {"new.html via repo base", []string{"layouts/base", "layouts/repobase", "repo/pulls/new"}},
26 {"pullComposeHost", []string{"repo/pulls/fragments/pullComposeHost"}},
27 {"pullStepSource", []string{"repo/pulls/fragments/pullStepSource"}},
28 {"pullStepReview", []string{"repo/pulls/fragments/pullStepReview"}},
29 {"pullStepDetails", []string{"repo/pulls/fragments/pullStepDetails"}},
30 {"pullCompareForks", []string{"repo/pulls/fragments/pullCompareForks"}},
31 {"pullCompareBranches", []string{"repo/pulls/fragments/pullCompareBranches"}},
32 {"pullCompareForksBranches", []string{"repo/pulls/fragments/pullCompareForksBranches"}},
33 {"pull.html via repo base", []string{"layouts/base", "layouts/repobase", "repo/pulls/pull"}},
34 {"pullNewComment", []string{"repo/pulls/fragments/pullNewComment"}},
35 {"pullComment", []string{"fragments/comment/pullComment"}},
36 }
37
38 for _, c := range cases {
39 t.Run(c.name, func(t *testing.T) {
40 if _, err := p.rawParse(c.stack...); err != nil {
41 t.Fatalf("parse %v: %v", c.stack, err)
42 }
43 })
44 }
45}
46
47func TestPullComposeHostRender(t *testing.T) {
48 cfg := &config.Config{}
49 p := NewPages(cfg, nil, nil, nil, slog.New(slog.NewTextHandler(io.Discard, nil)))
50
51 base := RepoNewPullParams{
52 RepoInfo: repoinfo.RepoInfo{
53 OwnerDid: "did:plc:test",
54 Name: "test-repo",
55 },
56 }
57
58 for _, source := range []Source{"", SourceBranch, SourceFork, SourcePatch} {
59 for _, stacked := range []bool{false, true} {
60 if source == SourcePatch && stacked {
61 continue
62 }
63 params := base
64 params.Source = source
65 params.IsStacked = stacked
66 name := string(source)
67 if name == "" {
68 name = "default"
69 }
70 if stacked {
71 name += "-stacked"
72 }
73 t.Run(name, func(t *testing.T) {
74 if err := p.PullComposeHostFragment(io.Discard, params); err != nil {
75 t.Fatalf("render source=%q stacked=%v: %v", source, stacked, err)
76 }
77 })
78 }
79 }
80}
81
82func TestPullComposeHostRenderWithData(t *testing.T) {
83 cfg := &config.Config{}
84 p := NewPages(cfg, nil, nil, nil, slog.New(slog.NewTextHandler(io.Discard, nil)))
85
86 sampleBranches := []types.Branch{
87 {Reference: types.Reference{Name: "feature"}},
88 {Reference: types.Reference{Name: "main"}, IsDefault: true},
89 }
90
91 formatPatch := `From 1111111111111111111111111111111111111111 Mon Sep 11 00:00:00 2001
92From: Test <test@best.fest>
93Date: Tue, 1 Jan 2020 00:00:00 +0000
94Subject: [PATCH] example commit
95
96---
97 a.txt | 1 +
98 1 file changed, 1 insertion(+)
99
100diff --git a/a.txt b/a.txt
101index 0000000..1111111 100644
102--- a/a.txt
103+++ b/a.txt
104@@ -0,0 +1 @@
105+hello
106`
107 patches, err := patchutil.ExtractPatches(formatPatch)
108 if err != nil {
109 t.Fatalf("extract patches: %v", err)
110 }
111 comparison := &types.RepoFormatPatchResponse{
112 FormatPatchRaw: formatPatch,
113 FormatPatch: patches,
114 }
115 diff := patchutil.AsNiceDiff(formatPatch, "main")
116
117 params := RepoNewPullParams{
118 RepoInfo: repoinfo.RepoInfo{
119 OwnerDid: "did:plc:test",
120 Name: "test-repo",
121 },
122 Branches: sampleBranches,
123 SourceBranches: []types.Branch{sampleBranches[0]},
124 ForkBranches: []types.Branch{sampleBranches[0]},
125 Source: SourceBranch,
126 SourceBranch: "feature",
127 TargetBranch: "main",
128 Comparison: comparison,
129 Diff: &diff,
130 }
131
132 if err := p.PullComposeHostFragment(io.Discard, params); err != nil {
133 t.Fatalf("render with data: %v", err)
134 }
135
136 params.IsStacked = true
137 if err := p.PullComposeHostFragment(io.Discard, params); err != nil {
138 t.Fatalf("render stacked: %v", err)
139 }
140
141 params.PrefillError = "branch not found"
142 params.Comparison = nil
143 params.Diff = nil
144 if err := p.PullComposeHostFragment(io.Discard, params); err != nil {
145 t.Fatalf("render with prefill error: %v", err)
146 }
147
148 bugDef := &models.LabelDefinition{
149 Did: "did:plc:test",
150 Rkey: "bug",
151 Name: "bug",
152 ValueType: models.ValueType{Type: models.ConcreteTypeNull},
153 Scope: []string{"sh.tangled.repo.pull"},
154 }
155 priorityDef := &models.LabelDefinition{
156 Did: "did:plc:test",
157 Rkey: "priority",
158 Name: "priority",
159 ValueType: models.ValueType{Type: models.ConcreteTypeString, Enum: []string{"low", "med", "high"}},
160 Scope: []string{"sh.tangled.repo.pull"},
161 }
162 assigneeDef := &models.LabelDefinition{
163 Did: "did:plc:test",
164 Rkey: "assignee",
165 Name: "assignee",
166 ValueType: models.ValueType{Type: models.ConcreteTypeString, Format: models.ValueTypeFormatDid},
167 Scope: []string{"sh.tangled.repo.pull"},
168 Multiple: true,
169 }
170 labelDefs := map[string]*models.LabelDefinition{
171 bugDef.AtUri().String(): bugDef,
172 priorityDef.AtUri().String(): priorityDef,
173 assigneeDef.AtUri().String(): assigneeDef,
174 }
175
176 pushRepoInfo := repoinfo.RepoInfo{
177 OwnerDid: "did:plc:test",
178 Name: "test-repo",
179 Roles: repoinfo.RolesInRepo{Roles: []string{"repo:push"}},
180 }
181 params = RepoNewPullParams{
182 RepoInfo: pushRepoInfo,
183 Branches: sampleBranches,
184 SourceBranches: []types.Branch{sampleBranches[0]},
185 Source: SourceBranch,
186 SourceBranch: "feature",
187 TargetBranch: "main",
188 Comparison: comparison,
189 Diff: &diff,
190 LabelDefs: labelDefs,
191 LabelState: models.NewLabelState(),
192 }
193 if err := p.PullComposeHostFragment(io.Discard, params); err != nil {
194 t.Fatalf("render with labels: %v", err)
195 }
196
197 params.IsStacked = true
198 if err := p.PullComposeHostFragment(io.Discard, params); err != nil {
199 t.Fatalf("render stacked with labels: %v", err)
200 }
201
202 params.StackedDiffs = []StackedDiff{{
203 Diff: &diff,
204 Opts: types.DiffOpts{Split: true, RefreshUrl: "/r", Target: "#stack-diff-x", Field: "stackSplit[x]"},
205 }}
206 if err := p.PullComposeHostFragment(io.Discard, params); err != nil {
207 t.Fatalf("render stacked with per-commit diffs: %v", err)
208 }
209}
210
211func TestPullComposeLabelStateRoundTrip(t *testing.T) {
212 cfg := &config.Config{}
213 p := NewPages(cfg, nil, nil, nil, slog.New(slog.NewTextHandler(io.Discard, nil)))
214
215 sampleBranches := []types.Branch{
216 {Reference: types.Reference{Name: "feature"}},
217 {Reference: types.Reference{Name: "main"}, IsDefault: true},
218 }
219
220 bugDef := &models.LabelDefinition{
221 Did: "did:plc:test", Rkey: "bug", Name: "bug",
222 ValueType: models.ValueType{Type: models.ConcreteTypeNull},
223 Scope: []string{"sh.tangled.repo.pull"},
224 }
225 priorityDef := &models.LabelDefinition{
226 Did: "did:plc:test", Rkey: "priority", Name: "priority",
227 ValueType: models.ValueType{Type: models.ConcreteTypeString, Enum: []string{"low", "med", "high"}},
228 Scope: []string{"sh.tangled.repo.pull"},
229 }
230 bugKey := bugDef.AtUri().String()
231 priorityKey := priorityDef.AtUri().String()
232 labelDefs := map[string]*models.LabelDefinition{
233 bugKey: bugDef,
234 priorityKey: priorityDef,
235 }
236
237 state := models.NewLabelState()
238 actx := &models.LabelApplicationCtx{Defs: labelDefs}
239 for _, op := range []models.LabelOp{
240 {OperandKey: bugKey, OperandValue: "null", Operation: models.LabelOperationAdd},
241 {OperandKey: priorityKey, OperandValue: "high", Operation: models.LabelOperationAdd},
242 } {
243 if err := actx.ApplyLabelOp(state, op); err != nil {
244 t.Fatalf("seed state: %v", err)
245 }
246 }
247
248 formatPatch := `From 1111111111111111111111111111111111111111 Mon Sep 11 00:00:00 2001
249From: Test <test@best.fest>
250Date: Tue, 1 Jan 2020 00:00:00 +0000
251Subject: [PATCH] example commit
252
253---
254 a.txt | 1 +
255 1 file changed, 1 insertion(+)
256
257diff --git a/a.txt b/a.txt
258index 0000000..1111111 100644
259--- a/a.txt
260+++ b/a.txt
261@@ -0,0 +1 @@
262+hello
263`
264 patches, err := patchutil.ExtractPatches(formatPatch)
265 if err != nil {
266 t.Fatalf("extract patches: %v", err)
267 }
268 comparison := &types.RepoFormatPatchResponse{
269 FormatPatchRaw: formatPatch,
270 FormatPatch: patches,
271 }
272
273 params := RepoNewPullParams{
274 RepoInfo: repoinfo.RepoInfo{
275 OwnerDid: "did:plc:test",
276 Name: "test-repo",
277 Roles: repoinfo.RolesInRepo{Roles: []string{"repo:push"}},
278 },
279 Branches: sampleBranches,
280 SourceBranches: []types.Branch{sampleBranches[0]},
281 Source: SourceBranch,
282 SourceBranch: "feature",
283 TargetBranch: "main",
284 Comparison: comparison,
285 LabelDefs: labelDefs,
286 LabelState: state,
287 }
288
289 var buf bytes.Buffer
290 if err := p.PullComposeHostFragment(&buf, params); err != nil {
291 t.Fatalf("render: %v", err)
292 }
293 out := buf.String()
294 for _, want := range []string{
295 `value="null" checked`,
296 `value="high" checked`,
297 } {
298 if !strings.Contains(out, want) {
299 t.Errorf("missing pre-selection %q", want)
300 }
301 }
302}
303
304func TestParseSource(t *testing.T) {
305 cases := []struct {
306 in string
307 want Source
308 wantOk bool
309 }{
310 {"branch", SourceBranch, true},
311 {"BRANCH", SourceBranch, true},
312 {"fork", SourceFork, true},
313 {"patch", SourcePatch, true},
314 {"", "", false},
315 {"method", "", false},
316 {"strategy", "", false},
317 {"unknown", "", false},
318 }
319 for _, c := range cases {
320 got, ok := ParseSource(c.in)
321 if got != c.want || ok != c.wantOk {
322 t.Errorf("ParseSource(%q) = %q, %v; want %q, %v", c.in, got, ok, c.want, c.wantOk)
323 }
324 }
325}