1-- SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2--
3-- SPDX-License-Identifier: GPL-3.0-or-later
4
5-- Load main.lua as a module (it exports functions when required)
6package.path = package.path .. ";./?.lua"
7local wt = dofile("src/main.lua")
8
9describe("load_global_config", function()
10 local temp_dir
11
12 setup(function()
13 -- Create temp directory for test configs
14 local handle = io.popen("mktemp -d")
15 if handle then
16 temp_dir = handle:read("*l")
17 handle:close()
18 end
19 end)
20
21 teardown(function()
22 -- Restore HOME and clean up
23 if temp_dir then
24 os.execute("rm -rf " .. temp_dir)
25 end
26 end)
27
28 describe("with no config file", function()
29 it("returns empty table when config file missing", function()
30 local config = wt.load_global_config()
31 assert.is_table(config)
32 end)
33 end)
34
35 describe("config file format", function()
36 -- Note: These tests document expected behavior but can't easily
37 -- override HOME in the running process. They serve as specification.
38
39 it("accepts simple table config", function()
40 -- Expected: { branch_path_style = "flat" }
41 -- The loader prepends "return " so file should NOT have return
42 local config = wt.load_global_config()
43 assert.is_table(config)
44 end)
45 end)
46end)
47
48describe("load_project_config", function()
49 local temp_dir
50
51 setup(function()
52 local handle = io.popen("mktemp -d")
53 if handle then
54 temp_dir = handle:read("*l")
55 handle:close()
56 end
57 end)
58
59 teardown(function()
60 if temp_dir then
61 os.execute("rm -rf " .. temp_dir)
62 end
63 end)
64
65 describe("with no config file", function()
66 it("returns empty table for nonexistent path", function()
67 local config = wt.load_project_config("/nonexistent/path")
68 assert.are.same({}, config)
69 end)
70
71 it("returns empty table for directory without .wt.lua", function()
72 local config = wt.load_project_config(temp_dir)
73 assert.are.same({}, config)
74 end)
75 end)
76
77 describe("with valid config file", function()
78 it("loads hooks configuration", function()
79 if not temp_dir then
80 pending("temp_dir not available")
81 return
82 end
83 -- Write a test config
84 local config_path = temp_dir .. "/.wt.lua"
85 local f = io.open(config_path, "w")
86 if f then
87 f:write([[{
88 hooks = {
89 copy = { ".env.example" },
90 symlink = { "node_modules" },
91 run = { "npm install" },
92 }
93}]])
94 f:close()
95
96 local config = wt.load_project_config(temp_dir)
97 assert.is_table(config.hooks)
98 assert.are.same({ ".env.example" }, config.hooks.copy)
99 assert.are.same({ "node_modules" }, config.hooks.symlink)
100 assert.are.same({ "npm install" }, config.hooks.run)
101
102 os.remove(config_path)
103 else
104 pending("could not write test config")
105 end
106 end)
107
108 it("loads branch_path_style from project config", function()
109 if not temp_dir then
110 pending("temp_dir not available")
111 return
112 end
113 local config_path = temp_dir .. "/.wt.lua"
114 local f = io.open(config_path, "w")
115 if f then
116 f:write([[{ branch_path_style = "flat", flat_separator = "-" }]])
117 f:close()
118
119 local config = wt.load_project_config(temp_dir)
120 assert.are.equal("flat", config.branch_path_style)
121 assert.are.equal("-", config.flat_separator)
122
123 os.remove(config_path)
124 else
125 pending("could not write test config")
126 end
127 end)
128 end)
129
130 describe("error handling", function()
131 it("returns empty table for syntax error in config", function()
132 if not temp_dir then
133 pending("temp_dir not available")
134 return
135 end
136 local config_path = temp_dir .. "/.wt.lua"
137 local f = io.open(config_path, "w")
138 if f then
139 f:write([[{ invalid syntax here !!!]])
140 f:close()
141
142 local config = wt.load_project_config(temp_dir)
143 assert.are.same({}, config)
144
145 os.remove(config_path)
146 else
147 pending("could not write test config")
148 end
149 end)
150
151 it("returns empty table for runtime error in config", function()
152 if not temp_dir then
153 pending("temp_dir not available")
154 return
155 end
156 local config_path = temp_dir .. "/.wt.lua"
157 local f = io.open(config_path, "w")
158 if f then
159 f:write([[{ value = undefined_var + 1 }]])
160 f:close()
161
162 local config = wt.load_project_config(temp_dir)
163 assert.are.same({}, config)
164
165 os.remove(config_path)
166 else
167 pending("could not write test config")
168 end
169 end)
170
171 it("returns empty table when config returns non-table", function()
172 if not temp_dir then
173 pending("temp_dir not available")
174 return
175 end
176 local config_path = temp_dir .. "/.wt.lua"
177 local f = io.open(config_path, "w")
178 if f then
179 f:write([["just a string"]])
180 f:close()
181
182 local config = wt.load_project_config(temp_dir)
183 assert.are.same({}, config)
184
185 os.remove(config_path)
186 else
187 pending("could not write test config")
188 end
189 end)
190
191 it("loads config with leading comment", function()
192 if not temp_dir then
193 pending("temp_dir not available")
194 return
195 end
196 local config_path = temp_dir .. "/.wt.lua"
197 local f = io.open(config_path, "w")
198 if f then
199 f:write([[-- my config comment
200{ branch_path_style = "flat" }]])
201 f:close()
202
203 local config = wt.load_project_config(temp_dir)
204 assert.are.equal("flat", config.branch_path_style)
205
206 os.remove(config_path)
207 else
208 pending("could not write test config")
209 end
210 end)
211
212 it("loads config with explicit return", function()
213 if not temp_dir then
214 pending("temp_dir not available")
215 return
216 end
217 local config_path = temp_dir .. "/.wt.lua"
218 local f = io.open(config_path, "w")
219 if f then
220 f:write([[return { branch_path_style = "flat" }]])
221 f:close()
222
223 local config = wt.load_project_config(temp_dir)
224 assert.are.equal("flat", config.branch_path_style)
225
226 os.remove(config_path)
227 else
228 pending("could not write test config")
229 end
230 end)
231 end)
232
233 describe("sandboxed environment", function()
234 it("cannot access os module in config", function()
235 if not temp_dir then
236 pending("temp_dir not available")
237 return
238 end
239 local config_path = temp_dir .. "/.wt.lua"
240 local f = io.open(config_path, "w")
241 if f then
242 f:write([[{ home = os.getenv("HOME") }]])
243 f:close()
244
245 local config = wt.load_project_config(temp_dir)
246 -- Returns empty table due to runtime error (os is nil)
247 assert.are.same({}, config)
248
249 os.remove(config_path)
250 else
251 pending("could not write test config")
252 end
253 end)
254 end)
255end)