@@ -2,8 +2,9 @@ import { addStore, InMemoryStore, useSystemIdentityContext } from '@furystack/co
22import { Injector } from '@furystack/inject'
33import { useLogging , VerboseConsoleLogger } from '@furystack/logging'
44import { getRepository } from '@furystack/repository'
5+ import { usingAsync } from '@furystack/utils'
56import { GitHubRepository } from 'common'
6- import { afterEach , beforeEach , describe , expect , it , vi } from 'vitest'
7+ import { beforeEach , describe , expect , it , vi } from 'vitest'
78
89import { ValidateRepoAction } from './validate-repo-action.js'
910
@@ -28,82 +29,90 @@ const createMockActionContext = (options: { injector: Injector; urlParams?: Reco
2829 response : { } as never ,
2930} )
3031
31- describe ( 'ValidateRepoAction' , ( ) => {
32- let injector : Injector
33- let repoStore : InMemoryStore < GitHubRepository , 'id' >
32+ const createSetup = ( ) => {
33+ const injector = new Injector ( )
34+ useLogging ( injector , VerboseConsoleLogger )
35+ const repoStore = new InMemoryStore ( { model : GitHubRepository , primaryKey : 'id' } )
36+ addStore ( injector , repoStore )
37+ getRepository ( injector ) . createDataSet ( GitHubRepository , 'id' , { } )
38+ return { injector, repoStore }
39+ }
3440
41+ describe ( 'ValidateRepoAction' , ( ) => {
3542 beforeEach ( ( ) => {
36- injector = new Injector ( )
37- useLogging ( injector , VerboseConsoleLogger )
38-
39- repoStore = new InMemoryStore ( { model : GitHubRepository , primaryKey : 'id' } )
40- addStore ( injector , repoStore )
41- getRepository ( injector ) . createDataSet ( GitHubRepository , 'id' , { } )
42-
4343 vi . clearAllMocks ( )
4444 } )
4545
46- afterEach ( async ( ) => {
47- await injector [ Symbol . asyncDispose ] ( )
48- } )
49-
50- it ( 'should return accessible: true when git ls-remote succeeds' , async ( ) => {
51- const ts = new Date ( ) . toISOString ( )
52- await repoStore . add ( {
53- id : 'repo-1' ,
54- stackName : 'test-stack' ,
55- url : 'https://github.com/user/repo.git' ,
56- displayName : 'Test Repo' ,
57- description : '' ,
58- createdAt : ts ,
59- updatedAt : ts ,
60- } as GitHubRepository )
61-
62- execFileMock . mockResolvedValue ( { stdout : 'abc123\tHEAD\n' , stderr : '' } )
63-
64- const elevated = useSystemIdentityContext ( { injector } )
65- const result = await ValidateRepoAction (
66- createMockActionContext ( { injector : elevated , urlParams : { id : 'repo-1' } } ) ,
67- )
68- await elevated [ Symbol . asyncDispose ] ( )
69-
70- const body = result . chunk as { accessible : boolean }
71- expect ( body . accessible ) . toBe ( true )
72- expect ( execFileMock ) . toHaveBeenCalledWith ( 'git' , [ 'ls-remote' , '--exit-code' , 'https://github.com/user/repo.git' ] , {
73- timeout : 15000 ,
46+ it ( 'should return accessible: true when git ls-remote succeeds' , ( ) => {
47+ const { injector, repoStore } = createSetup ( )
48+ return usingAsync ( injector , async ( ) => {
49+ const ts = new Date ( ) . toISOString ( )
50+ await repoStore . add ( {
51+ id : 'repo-1' ,
52+ stackName : 'test-stack' ,
53+ url : 'https://github.com/user/repo.git' ,
54+ displayName : 'Test Repo' ,
55+ description : '' ,
56+ createdAt : ts ,
57+ updatedAt : ts ,
58+ } as GitHubRepository )
59+
60+ execFileMock . mockResolvedValue ( { stdout : 'abc123\tHEAD\n' , stderr : '' } )
61+
62+ const elevated = useSystemIdentityContext ( { injector } )
63+ const result = await ValidateRepoAction (
64+ createMockActionContext ( { injector : elevated , urlParams : { id : 'repo-1' } } ) ,
65+ )
66+ await elevated [ Symbol . asyncDispose ] ( )
67+
68+ const body = result . chunk as { accessible : boolean }
69+ expect ( body . accessible ) . toBe ( true )
70+ expect ( execFileMock ) . toHaveBeenCalledWith (
71+ 'git' ,
72+ [ 'ls-remote' , '--exit-code' , 'https://github.com/user/repo.git' ] ,
73+ {
74+ timeout : 15000 ,
75+ } ,
76+ )
7477 } )
7578 } )
7679
77- it ( 'should return accessible: false when git ls-remote fails' , async ( ) => {
78- const ts = new Date ( ) . toISOString ( )
79- await repoStore . add ( {
80- id : 'repo-2' ,
81- stackName : 'test-stack' ,
82- url : 'https://github.com/user/bad-repo.git' ,
83- displayName : 'Bad Repo' ,
84- description : '' ,
85- createdAt : ts ,
86- updatedAt : ts ,
87- } as GitHubRepository )
88-
89- execFileMock . mockRejectedValue ( new Error ( 'Repository not found' ) )
90-
91- const elevated = useSystemIdentityContext ( { injector } )
92- const result = await ValidateRepoAction (
93- createMockActionContext ( { injector : elevated , urlParams : { id : 'repo-2' } } ) ,
94- )
95- await elevated [ Symbol . asyncDispose ] ( )
96-
97- const body = result . chunk as { accessible : boolean ; message ?: string }
98- expect ( body . accessible ) . toBe ( false )
99- expect ( body . message ) . toContain ( 'Repository not found' )
80+ it ( 'should return accessible: false when git ls-remote fails' , ( ) => {
81+ const { injector, repoStore } = createSetup ( )
82+ return usingAsync ( injector , async ( ) => {
83+ const ts = new Date ( ) . toISOString ( )
84+ await repoStore . add ( {
85+ id : 'repo-2' ,
86+ stackName : 'test-stack' ,
87+ url : 'https://github.com/user/bad-repo.git' ,
88+ displayName : 'Bad Repo' ,
89+ description : '' ,
90+ createdAt : ts ,
91+ updatedAt : ts ,
92+ } as GitHubRepository )
93+
94+ execFileMock . mockRejectedValue ( new Error ( 'Repository not found' ) )
95+
96+ const elevated = useSystemIdentityContext ( { injector } )
97+ const result = await ValidateRepoAction (
98+ createMockActionContext ( { injector : elevated , urlParams : { id : 'repo-2' } } ) ,
99+ )
100+ await elevated [ Symbol . asyncDispose ] ( )
101+
102+ const body = result . chunk as { accessible : boolean ; message ?: string }
103+ expect ( body . accessible ) . toBe ( false )
104+ expect ( body . message ) . toContain ( 'Repository not found' )
105+ } )
100106 } )
101107
102- it ( 'should throw 404 when repository does not exist' , async ( ) => {
103- const elevated = useSystemIdentityContext ( { injector } )
104- await expect (
105- ValidateRepoAction ( createMockActionContext ( { injector : elevated , urlParams : { id : 'nonexistent' } } ) ) ,
106- ) . rejects . toThrow ( 'Repository not found' )
107- await elevated [ Symbol . asyncDispose ] ( )
108+ it ( 'should throw 404 when repository does not exist' , ( ) => {
109+ const { injector } = createSetup ( )
110+ return usingAsync ( injector , async ( ) => {
111+ const elevated = useSystemIdentityContext ( { injector } )
112+ await expect (
113+ ValidateRepoAction ( createMockActionContext ( { injector : elevated , urlParams : { id : 'nonexistent' } } ) ) ,
114+ ) . rejects . toThrow ( 'Repository not found' )
115+ await elevated [ Symbol . asyncDispose ] ( )
116+ } )
108117 } )
109118} )
0 commit comments