turbo-editors/turbo-pythonpublic Fork 0
8d00593827066877caa1ea4cc66e88773514627b
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-python.git
git clone ssh://git@rickub.com/turbo-editors/turbo-python.git

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

main_test.go · 197 lines · 6.5 KBGo Blame HistoryRaw
📦 Turbo Python 6fc62ea k33g yesterday1package main
2
3import (
📦 Turbo Python 8d00593 k33g 7h ago4 "errors"
📦 Turbo Python 6fc62ea k33g yesterday5 "os"
6 "path/filepath"
📦 Turbo Python 8d00593 k33g 7h ago7 "strings"
📦 Turbo Python 6fc62ea k33g yesterday8 "testing"
9
10 "rickub.com/turbo-editors/turbo-core/app"
📦 Turbo Python 8d00593 k33g 7h ago11 "rickub.com/turbo-editors/turbo-core/configrepo"
📦 Turbo Python 6fc62ea k33g yesterday12 "rickub.com/turbo-editors/turbo-core/settings"
13 "rickub.com/turbo-editors/turbo-core/theme"
14
15 "rickub.com/turbo-editors/turbo-python/internal/pythonlang"
16)
17
18// Each of the three markers finds the root on its own, and the walk stops at
19// the nearest directory holding any of them. pylsp is started there, and it is
20// what decides the code the server loads.
21func TestTheProjectRootIsFoundByAnyOfTheThreeMarkers(t *testing.T) {
22 markers := map[string]string{
23 "pyproject.toml": "[project]\nname = \"x\"\n",
24 "setup.py": "from setuptools import setup\n\nsetup()\n",
25 "setup.cfg": "[metadata]\nname = x\n",
26 }
27
28 for marker, contents := range markers {
29 t.Run(marker, func(t *testing.T) {
30 root := t.TempDir()
31 writeFile(t, filepath.Join(root, marker), contents)
32 file := filepath.Join(root, "src", "package", "deep.py")
33 writeFile(t, file, "def f() -> None:\n pass\n")
34
35 if got := app.ProjectRoot(pythonlang.Profile(), []string{file}); got != root {
36 t.Errorf("ProjectRoot() = %q, want the project root %q", got, root)
37 }
38 })
39 }
40}
41
42// A directory with none of the three is its own root: the walk must not climb
43// past a project into whatever is above it.
44func TestAFileInNoProjectIsItsOwnRoot(t *testing.T) {
45 root := t.TempDir()
46 file := filepath.Join(root, "script.py")
47 writeFile(t, file, "print(1)\n")
48
49 if got := app.ProjectRoot(pythonlang.Profile(), []string{file}); got != root {
50 t.Errorf("ProjectRoot() = %q, want the file's own directory %q", got, root)
51 }
52}
53
54// writeFile creates a file, making its directory first.
55func writeFile(t *testing.T, path, contents string) {
56 t.Helper()
57 if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
58 t.Fatalf("creating %s: %v", filepath.Dir(path), err)
59 }
60 if err := os.WriteFile(path, []byte(contents), 0o644); err != nil {
61 t.Fatalf("writing %s: %v", path, err)
62 }
63}
64
65func TestThemeNamePrefersTheFlagOverTheProject(t *testing.T) {
66 got := themeName(options{theme: "borland-light"}, settings.Settings{Theme: "turbo-dark"})
67
68 if got != "borland-light" {
69 t.Errorf("themeName() = %q; an explicit -theme must win over the project's", got)
70 }
71}
72
73func TestThemeNameUsesTheProjectWhenNoFlagWasGiven(t *testing.T) {
74 got := themeName(options{}, settings.Settings{Theme: "turbo-dark"})
75
76 if got != "turbo-dark" {
77 t.Errorf("themeName() = %q, want the project's theme", got)
78 }
79}
80
81func TestThemeNameFallsBackToTheDefault(t *testing.T) {
82 got := themeName(options{}, settings.Settings{})
83
84 if got != theme.DefaultName {
85 t.Errorf("themeName() = %q, want %q", got, theme.DefaultName)
86 }
87}
88
89func TestLoadProjectSettingsReadsTheWorkingDirectory(t *testing.T) {
90 project := t.TempDir()
91 t.Chdir(project)
92 if err := os.MkdirAll(settings.Dir(pythonlang.Profile(), project), 0o755); err != nil {
93 t.Fatalf("creating the settings directory: %v", err)
94 }
95 contents := "[editor]\ntheme = \"turbo-dark\"\nautosave = true\n"
96 if err := os.WriteFile(settings.Path(pythonlang.Profile(), project), []byte(contents), 0o644); err != nil {
97 t.Fatalf("writing the settings file: %v", err)
98 }
99
100 _, loaded := loadProjectSettings(pythonlang.Profile())
101
102 if loaded.Theme != "turbo-dark" {
103 t.Errorf("Theme = %q, want turbo-dark", loaded.Theme)
104 }
105 if !loaded.Autosave {
106 t.Error("Autosave = false, want the file's true")
107 }
108}
109
110func TestLoadProjectSettingsDoesNotWalkUpToAParent(t *testing.T) {
111 // "The project is where you started the editor" is the rule; a settings
112 // file one directory up belongs to a different project.
113 parent := t.TempDir()
114 if err := os.MkdirAll(settings.Dir(pythonlang.Profile(), parent), 0o755); err != nil {
115 t.Fatalf("creating the settings directory: %v", err)
116 }
117 if err := os.WriteFile(settings.Path(pythonlang.Profile(), parent), []byte("[editor]\ntheme = \"turbo-dark\"\n"), 0o644); err != nil {
118 t.Fatalf("writing the settings file: %v", err)
119 }
120 child := filepath.Join(parent, "src")
121 if err := os.Mkdir(child, 0o755); err != nil {
122 t.Fatalf("creating the child directory: %v", err)
123 }
124 t.Chdir(child)
125
126 _, loaded := loadProjectSettings(pythonlang.Profile())
127
128 if loaded.Theme != "" {
129 t.Errorf("Theme = %q; settings were read from a parent directory", loaded.Theme)
130 }
131}
132
133func TestLoadProjectSettingsCarriesOnWithoutAFile(t *testing.T) {
134 t.Chdir(t.TempDir())
135
136 _, loaded := loadProjectSettings(pythonlang.Profile())
137
138 if loaded != settings.Default() {
139 t.Errorf("loadProjectSettings(pythonlang.Profile()) = %+v, want the defaults", loaded)
140 }
141}
142
143func TestABrokenSettingsFileDoesNotStopTheEditor(t *testing.T) {
144 // The editor is how you would fix the file, so it has to open.
145 project := t.TempDir()
146 t.Chdir(project)
147 if err := os.MkdirAll(settings.Dir(pythonlang.Profile(), project), 0o755); err != nil {
148 t.Fatalf("creating the settings directory: %v", err)
149 }
150 if err := os.WriteFile(settings.Path(pythonlang.Profile(), project), []byte("[editor\nnot toml"), 0o644); err != nil {
151 t.Fatalf("writing the settings file: %v", err)
152 }
153
154 _, loaded := loadProjectSettings(pythonlang.Profile())
155
156 if loaded != settings.Default() {
157 t.Errorf("loadProjectSettings(pythonlang.Profile()) = %+v, want the defaults", loaded)
158 }
159}
📦 Turbo Python 8d00593 k33g 7h ago160
161func TestDescribeLoadNamesTheSourceAndEveryFile(t *testing.T) {
162 got := describeLoad(configrepo.Result{
163 Remote: "https://git.rickub.com/turbo-editors/configs.git",
164 Ref: "main",
165 Dir: "/work/.turbo-python",
166 Files: []string{"settings.toml", "tools.toml"},
167 })
168
169 want := "Copied /work/.turbo-python from https://git.rickub.com/turbo-editors/configs.git (main):\n settings.toml\n tools.toml\n"
170 if got != want {
171 t.Errorf("describeLoad() =\n%q\nwant\n%q", got, want)
172 }
173}
174
175func TestDescribeLoadOmitsTheRefWhenTheDefaultBranchWasUsed(t *testing.T) {
176 got := describeLoad(configrepo.Result{Remote: "r", Dir: "d"})
177
178 if strings.Contains(got, "(") {
179 t.Errorf("describeLoad() = %q, want no parenthesised ref", got)
180 }
181}
182
183func TestLoadConfigLeavesAProjectThatHasAConfigurationAlone(t *testing.T) {
184 // Checked before anything is fetched, so this needs neither git nor a
185 // network: the project's own .turbo-python is a decision, not a default.
186 project := t.TempDir()
187 if err := os.MkdirAll(filepath.Join(project, ".turbo-python"), 0o755); err != nil {
188 t.Fatal(err)
189 }
190 t.Chdir(project)
191
192 err := loadConfig(pythonlang.Profile(), "https://rickub.com/turbo-editors/configs/tree/main/golang-init")
193
194 if !errors.Is(err, configrepo.ErrExists) {
195 t.Errorf("loadConfig() error = %v, want ErrExists", err)
196 }
197}