GitRoot

craft your forge, build your project, grow your community freely
  1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
  2//
  3// SPDX-License-Identifier: EUPL-1.2
  4
  5package main
  6
  7import (
  8	"strings"
  9	"testing"
 10	"time"
 11
 12	"gitroot.dev/libs/golang/plugin/model"
 13	"gitroot.dev/libs/golang/plugin/test"
 14)
 15
 16type finalizeCall struct {
 17	fp                 string
 18	htmlContent        string
 19	htmlShouldContains []string
 20}
 21
 22func TestRender(t *testing.T) {
 23	w := worktree{lines: []gitWorktreeLine{{
 24		FullPath:       "file",
 25		LastEdited:     time.Now(),
 26		Message:        "Mon joli file",
 27		hasBeenUpdated: true,
 28	}, {
 29		FullPath:       "dir/file2",
 30		LastEdited:     time.Now(),
 31		Message:        "Mon joli file2",
 32		hasBeenUpdated: true,
 33	}, {
 34		FullPath:       "dir/dir2/dir3/file3",
 35		LastEdited:     time.Now(),
 36		Message:        "Mon joli file3",
 37		hasBeenUpdated: true,
 38	}, {
 39		FullPath:       "dir4/file4",
 40		LastEdited:     time.Now(),
 41		Message:        "Mon joli file4",
 42		hasBeenUpdated: true,
 43	}}}
 44	expected := []finalizeCall{{
 45		fp: "worktree/file.html",
 46		htmlShouldContains: []string{
 47			"<pre>Binary</pre>",
 48		},
 49	}, {
 50		fp: "worktree/dir/file2.html",
 51		htmlShouldContains: []string{
 52			"<pre>Binary</pre>",
 53		},
 54	}, {
 55		fp: "worktree/dir/dir2/dir3/file3.html",
 56		htmlShouldContains: []string{
 57			"<pre>Binary</pre>",
 58		},
 59	}, {
 60		fp: "worktree/dir/dir2/dir3/index.html",
 61		htmlShouldContains: []string{
 62			"<a href=\"worktree\">worktree</a>", "<a href=\"worktree/dir\">dir</a>", "<a href=\"worktree/dir/dir2\">dir2</a>", "dir3",
 63			"<a href=\"worktree/dir/dir2/dir3/file3.html\">file3</a>",
 64		},
 65	}, {
 66		fp: "worktree/dir/dir2/index.html",
 67		htmlShouldContains: []string{
 68			"<a href=\"worktree\">worktree</a>", "<a href=\"worktree/dir\">dir</a>", "dir2",
 69			"<a href=\"worktree/dir/dir2/dir3/index.html\">dir3</a>",
 70		},
 71	}, {
 72		fp: "worktree/dir/index.html",
 73		htmlShouldContains: []string{
 74			"<a href=\"worktree\">worktree</a>", "dir",
 75			"<a href=\"worktree/dir/dir2/index.html\">dir2</a>", "<a href=\"worktree/dir/file2.html\">file2</a>",
 76		},
 77	}, {
 78		fp: "worktree/dir4/file4.html",
 79		htmlShouldContains: []string{
 80			"<pre>Binary</pre>",
 81		},
 82	}, {
 83		fp: "worktree/dir4/index.html",
 84		htmlShouldContains: []string{
 85			"<a href=\"worktree\">worktree</a>", "dir4",
 86			"<a href=\"worktree/dir4/file4.html\">file4</a>",
 87		},
 88	}, {
 89		fp: "worktree/index.html",
 90		htmlShouldContains: []string{
 91			"worktree",
 92			"<a href=\"worktree/dir/index.html\">dir</a>", "<a href=\"worktree/dir4/index.html\">dir4</a>", "<a href=\"worktree/file.html\">file</a>",
 93		},
 94	}}
 95	called := make([]finalizeCall, 0)
 96	w.renderHtml("", "worktree", func(fp, htmlContent string) {
 97		called = append(called, finalizeCall{fp: fp, htmlContent: htmlContent})
 98	})
 99	if len(called) != len(expected) {
100		t.Errorf("Should be called %d times but was %d\n%#v", len(expected), len(called), called)
101	}
102	for i, exp := range expected {
103		if called[i].fp != exp.fp {
104			t.Errorf("called[%d].fp should be %s but was %s", i, exp.fp, called[i].fp)
105		}
106		for _, shouldContains := range exp.htmlShouldContains {
107			if _, after, found := strings.Cut(called[i].htmlContent, shouldContains); found {
108				called[i].htmlContent = after
109			} else {
110				t.Errorf("%s should contains %s but was %s", exp.fp, shouldContains, called[i].htmlContent)
111			}
112		}
113	}
114}
115
116func TestRenderWithOnlyTopModified(t *testing.T) {
117	fakeServer := test.NewFakeServer(t, test.Override{})
118	fakeServer.ModifyContent("README.txt", "hello")
119	fakeServer.ModifyContent("dir/README.txt", "hello")
120	fakeServer.ModifyContent("dir/README2.txt", "hello")
121
122	p := &Plugin{
123		server: fakeServer,
124	}
125	p.Init("repo", false, `{"generateGitWorktree": true, "defaultBranch": "main"}`)
126	p.StartCommit(model.Commit{Branch: "main"})
127	p.AddFile(model.File{Path: "README.txt"})
128	p.AddFile(model.File{Path: "dir/README.txt"})
129	p.AddFile(model.File{Path: "dir/README2.txt"})
130	p.Finish()
131	if fakeServer.NbCall.ModifyWebContent != 11 {
132		t.Fatalf("not called %d", fakeServer.NbCall.ModifyWebContent)
133	}
134
135	p = &Plugin{
136		server: fakeServer,
137	}
138	p.Init("repo", false, `{"generateGitWorktree": true, "defaultBranch": "main"}`)
139	p.StartCommit(model.Commit{Branch: "main"})
140	p.ModFile(model.File{Path: "README.txt"})
141	p.Finish()
142	if fakeServer.NbCall.ModifyWebContent != 11+3 {
143		t.Fatalf("not called %d", fakeServer.NbCall.ModifyWebContent)
144	}
145
146	p = &Plugin{
147		server: fakeServer,
148	}
149	p.Init("repo", false, `{"generateGitWorktree": true, "defaultBranch": "main"}`)
150	p.StartCommit(model.Commit{Branch: "main"})
151	p.ModFile(model.File{Path: "dir/README.txt"})
152	p.Finish()
153	if fakeServer.NbCall.ModifyWebContent != 11+3+4 {
154		t.Fatalf("not called %d", fakeServer.NbCall.ModifyWebContent)
155	}
156}
157
158func TestIcon(t *testing.T) {
159	if ok := getIcon(".yml"); ok == "📄" {
160		t.Fatalf("icon markdown not found")
161	}
162}
163
164func TestEmoji(t *testing.T) {
165	loadEmojis()
166	if res := replaceEmoji(".yml"); res != ".yml" {
167		t.Fatalf("bad emoji for '.yml'")
168	}
169	if res := replaceEmoji(":fire:"); res != "🔥" {
170		t.Fatalf("bad emoji for ':fire:' %s", res)
171	}
172	if res := replaceEmoji("New release :rocket: :tada:"); res != "New release 🚀 🎉" {
173		t.Fatalf("bad emoji for 'New release :rocket: :tada:' %s", res)
174	}
175}