@@ -194,6 +194,114 @@ func TestRepoSlug(t *testing.T) {
194194 }
195195}
196196
197+ func testSpecWithSkip () * Spec {
198+ s := testSpec ()
199+ s .Spec .Skip = "check-skip"
200+ return s
201+ }
202+
203+ func TestResolveWorkspaceSkippedRepoExcluded (t * testing.T ) {
204+ // repo-a is in-progress (feature branch), repo-b is open (main, skipped).
205+ // Without skip, workspace would be open. With skip, repo-b excluded → in-progress.
206+ perRepoMock := & perRepoRunner {
207+ results : map [string ]map [string ]bool {
208+ "github.com/org/repo-a" : {"check-progress" : true },
209+ "github.com/org/repo-b" : {"check-skip" : true },
210+ },
211+ }
212+ resolver := & Resolver {Runner : perRepoMock }
213+
214+ repos := []RepoInfo {
215+ {URL : "github.com/org/repo-a" , Branch : "feat/x" , Path : "./repo-a" },
216+ {URL : "github.com/org/repo-b" , Branch : "main" , Path : "./repo-b" },
217+ }
218+ result := resolver .ResolveWorkspace (context .Background (), testSpecWithSkip (), repos , "ws-1" , "my-ws" )
219+
220+ if result .Status != "in-progress" {
221+ t .Errorf ("workspace status = %q, want in-progress (skipped repo excluded)" , result .Status )
222+ }
223+ }
224+
225+ func TestResolveWorkspaceDefaultStatusPassive (t * testing.T ) {
226+ // Two feature repos: one closed, one at default (open).
227+ // Default status is passive — should not drag workspace to open.
228+ perRepoMock := & perRepoRunner {
229+ results : map [string ]map [string ]bool {
230+ "github.com/org/repo-a" : {"check-closed" : true },
231+ "github.com/org/repo-b" : {},
232+ },
233+ }
234+ resolver := & Resolver {Runner : perRepoMock }
235+
236+ repos := []RepoInfo {
237+ {URL : "github.com/org/repo-a" , Branch : "feat/x" , Path : "./repo-a" },
238+ {URL : "github.com/org/repo-b" , Branch : "feat/y" , Path : "./repo-b" },
239+ }
240+ result := resolver .ResolveWorkspace (context .Background (), testSpec (), repos , "ws-1" , "my-ws" )
241+
242+ if result .Status != "closed" {
243+ t .Errorf ("workspace status = %q, want closed (default status passive)" , result .Status )
244+ }
245+ }
246+
247+ func TestResolveWorkspaceAllSkippedFallback (t * testing.T ) {
248+ // All repos skipped → fall back to default status.
249+ mock := & mockRunner {results : map [string ]bool {
250+ "check-skip" : true ,
251+ }}
252+ resolver := & Resolver {Runner : mock }
253+
254+ repos := []RepoInfo {
255+ {URL : "github.com/org/repo-a" , Branch : "main" , Path : "./repo-a" },
256+ {URL : "github.com/org/repo-b" , Branch : "main" , Path : "./repo-b" },
257+ }
258+ result := resolver .ResolveWorkspace (context .Background (), testSpecWithSkip (), repos , "ws-1" , "my-ws" )
259+
260+ if result .Status != "open" {
261+ t .Errorf ("workspace status = %q, want open (all skipped fallback)" , result .Status )
262+ }
263+ }
264+
265+ func TestResolveWorkspaceMixedSkipAndDefault (t * testing.T ) {
266+ // repo-a: closed (feat), repo-b: in-review (feat), repo-c: open (main, skipped).
267+ // Skip excludes repo-c, default excludes nothing extra. Least advanced = in-review.
268+ perRepoMock := & perRepoRunner {
269+ results : map [string ]map [string ]bool {
270+ "github.com/org/repo-a" : {"check-closed" : true },
271+ "github.com/org/repo-b" : {"check-review" : true },
272+ "github.com/org/repo-c" : {"check-skip" : true },
273+ },
274+ }
275+ resolver := & Resolver {Runner : perRepoMock }
276+
277+ repos := []RepoInfo {
278+ {URL : "github.com/org/repo-a" , Branch : "feat/x" , Path : "./repo-a" },
279+ {URL : "github.com/org/repo-b" , Branch : "feat/y" , Path : "./repo-b" },
280+ {URL : "github.com/org/repo-c" , Branch : "main" , Path : "./repo-c" },
281+ }
282+ result := resolver .ResolveWorkspace (context .Background (), testSpecWithSkip (), repos , "ws-1" , "my-ws" )
283+
284+ if result .Status != "in-review" {
285+ t .Errorf ("workspace status = %q, want in-review (mixed skip and default)" , result .Status )
286+ }
287+ }
288+
289+ func TestResolveWorkspaceAllFeatureAtDefault (t * testing.T ) {
290+ // All feature-branch repos at default status → default (no active signal).
291+ mock := & mockRunner {results : map [string ]bool {}}
292+ resolver := & Resolver {Runner : mock }
293+
294+ repos := []RepoInfo {
295+ {URL : "github.com/org/repo-a" , Branch : "feat/x" , Path : "./repo-a" },
296+ {URL : "github.com/org/repo-b" , Branch : "feat/y" , Path : "./repo-b" },
297+ }
298+ result := resolver .ResolveWorkspace (context .Background (), testSpec (), repos , "ws-1" , "my-ws" )
299+
300+ if result .Status != "open" {
301+ t .Errorf ("workspace status = %q, want open (all at default)" , result .Status )
302+ }
303+ }
304+
197305// perRepoRunner distinguishes check results by repo URL (extracted from env).
198306type perRepoRunner struct {
199307 results map [string ]map [string ]bool // repoURL -> command -> result
0 commit comments