turbo-editors/turbo-golopublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-golo.git
git clone ssh://git@rickub.com/turbo-editors/turbo-golo.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

main_test.go · 159 lines · 5.1 KBGo Blame HistoryRaw
📦 Turbo Golo d710c1b k33g 12h ago1package main
2
3import (
4 "flag"
5 "os"
6 "path/filepath"
7 "slices"
8 "testing"
9
10 "rickub.com/turbo-editors/turbo-core/app"
11 "rickub.com/turbo-editors/turbo-core/settings"
12
13 "rickub.com/turbo-editors/turbo-golo/internal/gololang"
14)
15
16// withArgs runs the command line parser against a fixed argument list, and
17// restores the real one afterwards so tests do not affect each other.
18func withArgs(t *testing.T, args ...string) options {
19 t.Helper()
20
21 realArgs, realFlags := os.Args, flag.CommandLine
22 t.Cleanup(func() { os.Args, flag.CommandLine = realArgs, realFlags })
23
24 os.Args = append([]string{"turbo-golo"}, args...)
25 flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
26 return parseFlags()
27}
28
29func TestFilesAreWhatIsLeftAfterTheFlags(t *testing.T) {
30 opts := withArgs(t, "-no-lsp", "main.golo", "lib/x.golo")
31
32 if !opts.noLSP {
33 t.Error("-no-lsp was not read")
34 }
35 if want := []string{"main.golo", "lib/x.golo"}; !slices.Equal(opts.files, want) {
36 t.Errorf("files = %v, want %v", opts.files, want)
37 }
38}
39
40func TestTheThemeFlagDefaultsToEmptyRatherThanToAName(t *testing.T) {
41 // Empty is what lets "was -theme given?" still be answered afterwards, and
42 // that is what lets the project's settings fill it in without overriding an
43 // explicit choice.
44 if opts := withArgs(t); opts.theme != "" {
45 t.Errorf("theme = %q with no flag, want the empty string", opts.theme)
46 }
47}
48
49func TestTheThemeFlagBeatsTheProjectSettings(t *testing.T) {
50 project := settings.Default()
51 project.Theme = "cobalt"
52
53 if got := themeName(options{theme: "monochrome"}, project); got != "monochrome" {
54 t.Errorf("themeName() = %q, want the flag's %q", got, "monochrome")
55 }
56}
57
58func TestTheProjectSettingsBeatTheBuiltInDefault(t *testing.T) {
59 project := settings.Default()
60 project.Theme = "cobalt"
61
62 if got := themeName(options{}, project); got != "cobalt" {
63 t.Errorf("themeName() = %q, want the project's %q", got, "cobalt")
64 }
65}
66
67func TestTheBuiltInDefaultIsUsedWhenNobodySaysOtherwise(t *testing.T) {
68 if got := themeName(options{}, settings.Default()); got == "" {
69 t.Error("themeName() = \"\" with nothing set, want the library's default")
70 }
71}
72
73func TestTheProjectRootIsTheDirectoryOfTheFile(t *testing.T) {
74 // app.ProjectRoot walks up looking for the profile's RootMarkers, and Golo
75 // has none: a script is a file, and there is no manifest above it to find.
76 // So the server is started in the file's own directory, however deep.
77 root := t.TempDir()
78 nested := filepath.Join(root, "scripts", "tools")
79 if err := os.MkdirAll(nested, 0o755); err != nil {
80 t.Fatal(err)
81 }
82
83 file := filepath.Join(nested, "main.golo")
84 if got := app.ProjectRoot(gololang.Profile(), []string{file}); got != nested {
85 t.Errorf("ProjectRoot(%q) = %q, want the file's own directory %q", file, got, nested)
86 }
87}
88
89func TestNothingAboveTheFileChangesTheRoot(t *testing.T) {
90 // A .git directory and a main.golo higher up are the two things somebody
91 // might expect to count as a project. Neither is a marker here, so neither
92 // moves the root: the rule is "no walk", and this pins it.
93 root := t.TempDir()
94 nested := filepath.Join(root, "lib")
95 if err := os.MkdirAll(filepath.Join(root, ".git"), 0o755); err != nil {
96 t.Fatal(err)
97 }
98 if err := os.MkdirAll(nested, 0o755); err != nil {
99 t.Fatal(err)
100 }
101 if err := os.WriteFile(filepath.Join(root, "main.golo"), []byte("module m\n"), 0o644); err != nil {
102 t.Fatal(err)
103 }
104
105 file := filepath.Join(nested, "helpers.golo")
106 if got := app.ProjectRoot(gololang.Profile(), []string{file}); got != nested {
107 t.Errorf("ProjectRoot(%q) = %q, want %q; something above the file was taken for a marker", file, got, nested)
108 }
109}
110
111func TestWithNoFileTheRootIsTheWorkingDirectory(t *testing.T) {
112 // `turbo-golo` with no file opens an empty window, and the server has to
113 // be started somewhere. Where the editor was started is the only answer.
114 dir := t.TempDir()
115 t.Chdir(dir)
116
117 got := app.ProjectRoot(gololang.Profile(), nil)
118 want, err := os.Getwd()
119 if err != nil {
120 t.Fatal(err)
121 }
122 if got != want {
123 t.Errorf("ProjectRoot() with no file = %q, want the working directory %q", got, want)
124 }
125}
126
127func TestLoadingSettingsFromADirectoryWithNoneGivesTheDefaults(t *testing.T) {
128 // A directory somebody merely started the editor in has said nothing, and
129 // the editor must not write to it. The starter file turns autosave on; the
130 // default leaves it off.
131 dir := t.TempDir()
132 t.Chdir(dir)
133
134 project, loaded := loadProjectSettings(gololang.Profile())
135 if project == "" {
136 t.Error("loadProjectSettings returned no project directory")
137 }
138 if loaded.Autosave {
139 t.Error("autosave is on with no settings file, want it off")
140 }
141}
142
143func TestABrokenSettingsFileDoesNotStopTheEditorOpening(t *testing.T) {
144 // A broken settings file must not stop the editor opening, because the
145 // editor is how you would fix it.
146 dir := t.TempDir()
147 p := gololang.Profile()
148 if err := os.MkdirAll(filepath.Join(dir, p.ProjectDir()), 0o755); err != nil {
149 t.Fatal(err)
150 }
151 if err := os.WriteFile(settings.Path(p, dir), []byte("this is not ["), 0o644); err != nil {
152 t.Fatal(err)
153 }
154 t.Chdir(dir)
155
156 if _, loaded := loadProjectSettings(p); loaded != settings.Default() {
157 t.Errorf("loadProjectSettings() = %+v with a broken file, want the defaults", loaded)
158 }
159}