11import GitHub from './github' ;
22import { getRemoteUrls } from '../util/create-git-meta' ;
3- import { repositoriesQuery } from '../graphql' ;
3+ import { repositoriesQuery , userConnectionsQuery } from '../graphql' ;
44import BaseClass from './base-class' ;
5+ import { existsSync } from 'fs' ;
56
67jest . mock ( '../util/create-git-meta' ) ;
8+ jest . mock ( 'fs' , ( ) => ( {
9+ ...jest . requireActual ( 'fs' ) ,
10+ existsSync : jest . fn ( ) ,
11+ } ) ) ;
712
13+ const userConnections = [
14+ {
15+ __typename : 'UserConnection' ,
16+ userUid : 'testuser1' ,
17+ provider : 'GitHub' ,
18+ } ,
19+ ] ;
820const repositories = [
921 {
1022 __typename : 'GitRepository' ,
@@ -33,24 +45,70 @@ const repositories = [
3345] ;
3446
3547describe ( 'GitHub Adapter' , ( ) => {
36- describe ( 'checkGitRemoteAvailableAndValid' , ( ) => {
37- const repositoriesResponse = { data : { repositories } } ;
38- let logMock : jest . Mock ;
39- let exitMock : jest . Mock ;
48+ let logMock : jest . Mock ;
49+ let exitMock : jest . Mock ;
4050
41- beforeEach ( ( ) => {
42- logMock = jest . fn ( ) ;
43- exitMock = jest . fn ( ) . mockImplementationOnce ( ( ) => {
44- throw new Error ( '1' ) ;
45- } ) ;
51+ beforeEach ( ( ) => {
52+ logMock = jest . fn ( ) ;
53+ exitMock = jest . fn ( ) . mockImplementationOnce ( ( ) => {
54+ throw new Error ( '1' ) ;
4655 } ) ;
56+ } ) ;
57+
58+ afterEach ( ( ) => {
59+ jest . resetAllMocks ( ) ;
60+ } ) ;
61+
62+ describe ( 'checkGitHubConnected' , ( ) => {
63+ it ( 'should return true if GitHub is connected' , async ( ) => {
64+ const userConnectionResponse = { data : { userConnections } } ;
65+ const apolloClient = {
66+ query : jest . fn ( ) . mockResolvedValueOnce ( userConnectionResponse ) ,
67+ } as any ;
68+ const githubAdapterInstance = new GitHub ( {
69+ config : { projectBasePath : '/home/project1' , provider : 'GitHub' } ,
70+ apolloClient : apolloClient ,
71+ log : logMock ,
72+ } as any ) ;
73+ const connectToAdapterOnUiMock = jest
74+ . spyOn ( BaseClass . prototype , 'connectToAdapterOnUi' )
75+ . mockResolvedValueOnce ( undefined ) ;
76+
77+ await githubAdapterInstance . checkGitHubConnected ( ) ;
78+
79+ expect ( apolloClient . query ) . toHaveBeenCalledWith ( { query : userConnectionsQuery } ) ;
80+ expect ( logMock ) . toHaveBeenCalledWith ( 'GitHub connection identified!' , 'info' ) ;
81+ expect ( githubAdapterInstance . config . userConnection ) . toEqual ( userConnections [ 0 ] ) ;
82+ expect ( connectToAdapterOnUiMock ) . not . toHaveBeenCalled ( ) ;
83+ } ) ;
84+
85+ it ( 'should log an error and exit if GitHub is not connected' , async ( ) => {
86+ const userConnectionResponse = { data : { userConnections : [ ] } } ;
87+ const connectToAdapterOnUiMock = jest . spyOn ( BaseClass . prototype , 'connectToAdapterOnUi' ) . mockResolvedValueOnce ( ) ;
88+ const apolloClient = {
89+ query : jest . fn ( ) . mockResolvedValueOnce ( userConnectionResponse ) ,
90+ } as any ;
91+ const githubAdapterInstance = new GitHub ( {
92+ config : { projectBasePath : '/home/project1' } ,
93+ apolloClient : apolloClient ,
94+ log : logMock ,
95+ } as any ) ;
96+
97+ await githubAdapterInstance . checkGitHubConnected ( ) ;
4798
48- afterEach ( ( ) => {
49- jest . resetAllMocks ( ) ;
99+ expect ( apolloClient . query ) . toHaveBeenCalledWith ( { query : userConnectionsQuery } ) ;
100+ expect ( logMock ) . toHaveBeenCalledWith ( 'GitHub connection not found!' , 'error' ) ;
101+ expect ( connectToAdapterOnUiMock ) . toHaveBeenCalled ( ) ;
102+ expect ( githubAdapterInstance . config . userConnection ) . toEqual ( undefined ) ;
50103 } ) ;
104+ } ) ;
105+
106+ describe ( 'checkGitRemoteAvailableAndValid' , ( ) => {
107+ const repositoriesResponse = { data : { repositories } } ;
51108
52109 it ( `should successfully check if the git remote is available and valid
53110 when the github remote URL is HTTPS based` , async ( ) => {
111+ ( existsSync as jest . Mock ) . mockReturnValueOnce ( true ) ;
54112 ( getRemoteUrls as jest . Mock ) . mockResolvedValueOnce ( {
55113 origin : 'https://github.com/test-user/eleventy-sample.git' ,
56114 } ) ;
@@ -64,6 +122,7 @@ describe('GitHub Adapter', () => {
64122
65123 const result = await githubAdapterInstance . checkGitRemoteAvailableAndValid ( ) ;
66124
125+ expect ( existsSync ) . toHaveBeenCalledWith ( '/home/project1/.git' ) ;
67126 expect ( getRemoteUrls as jest . Mock ) . toHaveBeenCalledWith ( '/home/project1/.git/config' ) ;
68127 expect ( apolloClient . query ) . toHaveBeenCalledWith ( { query : repositoriesQuery } ) ;
69128 expect ( githubAdapterInstance . config . repository ) . toEqual ( {
@@ -79,6 +138,7 @@ describe('GitHub Adapter', () => {
79138
80139 it ( `should successfully check if the git remote is available and valid
81140 when the github remote URL is SSH based` , async ( ) => {
141+ ( existsSync as jest . Mock ) . mockReturnValueOnce ( true ) ;
82142 ( getRemoteUrls as jest . Mock ) . mockResolvedValueOnce ( {
83143 origin : 'git@github.com:test-user/eleventy-sample.git' ,
84144 } ) ;
@@ -92,6 +152,7 @@ describe('GitHub Adapter', () => {
92152
93153 const result = await githubAdapterInstance . checkGitRemoteAvailableAndValid ( ) ;
94154
155+ expect ( existsSync ) . toHaveBeenCalledWith ( '/home/project1/.git' ) ;
95156 expect ( getRemoteUrls as jest . Mock ) . toHaveBeenCalledWith ( '/home/project1/.git/config' ) ;
96157 expect ( apolloClient . query ) . toHaveBeenCalledWith ( { query : repositoriesQuery } ) ;
97158 expect ( githubAdapterInstance . config . repository ) . toEqual ( {
@@ -105,15 +166,39 @@ describe('GitHub Adapter', () => {
105166 expect ( result ) . toBe ( true ) ;
106167 } ) ;
107168
108- it ( `should log an error and proceed to connection via UI
109- if git repo remote url is unavailable and exit` , async ( ) => {
169+ it ( 'should log an error and exit if git config file does not exists' , async ( ) => {
170+ ( existsSync as jest . Mock ) . mockReturnValueOnce ( false ) ;
171+ const githubAdapterInstance = new GitHub ( {
172+ config : { projectBasePath : '/home/project1' } ,
173+ log : logMock ,
174+ exit : exitMock ,
175+ } as any ) ;
176+ let err ;
177+
178+ try {
179+ await githubAdapterInstance . checkGitRemoteAvailableAndValid ( ) ;
180+ } catch ( error : any ) {
181+ err = error ;
182+ }
183+
184+ expect ( getRemoteUrls as jest . Mock ) . not . toHaveBeenCalled ( ) ;
185+ expect ( logMock ) . toHaveBeenCalledWith ( 'No Git repository configuration found at /home/project1.' , 'error' ) ;
186+ expect ( logMock ) . toHaveBeenCalledWith (
187+ 'Please initialize a Git repository and try again, or use the File Upload option.' ,
188+ 'error' ,
189+ ) ;
190+ expect ( exitMock ) . toHaveBeenCalledWith ( 1 ) ;
191+ expect ( err ) . toEqual ( new Error ( '1' ) ) ;
192+ } ) ;
193+
194+ it ( `should log an error if git repo remote url
195+ is unavailable and exit` , async ( ) => {
196+ ( existsSync as jest . Mock ) . mockReturnValueOnce ( true ) ;
110197 ( getRemoteUrls as jest . Mock ) . mockResolvedValueOnce ( undefined ) ;
111- const connectToAdapterOnUiMock
112- = jest . spyOn ( BaseClass . prototype , 'connectToAdapterOnUi' ) . mockResolvedValueOnce ( undefined ) ;
113- const githubAdapterInstance = new GitHub ( {
114- config : { projectBasePath : '/home/project1' } ,
115- log : logMock ,
116- exit : exitMock
198+ const githubAdapterInstance = new GitHub ( {
199+ config : { projectBasePath : '/home/project1' } ,
200+ log : logMock ,
201+ exit : exitMock ,
117202 } as any ) ;
118203 let err ;
119204
@@ -123,25 +208,61 @@ describe('GitHub Adapter', () => {
123208 err = error ;
124209 }
125210
211+ expect ( existsSync ) . toHaveBeenCalledWith ( '/home/project1/.git' ) ;
212+ expect ( getRemoteUrls as jest . Mock ) . toHaveBeenCalledWith ( '/home/project1/.git/config' ) ;
213+ expect ( logMock ) . toHaveBeenCalledWith (
214+ `No Git remote origin URL found for the repository at /home/project1.
215+ Please add a git remote origin url and try again` ,
216+ 'error' ,
217+ ) ;
218+ expect ( exitMock ) . toHaveBeenCalledWith ( 1 ) ;
219+ expect ( err ) . toEqual ( new Error ( '1' ) ) ;
220+ expect ( githubAdapterInstance . config . repository ) . toBeUndefined ( ) ;
221+ } ) ;
222+
223+ it ( 'should log an error and exit if GitHub app is uninstalled' , async ( ) => {
224+ ( existsSync as jest . Mock ) . mockReturnValueOnce ( true ) ;
225+ ( getRemoteUrls as jest . Mock ) . mockResolvedValueOnce ( {
226+ origin : 'https://github.com/test-user/eleventy-sample.git' ,
227+ } ) ;
228+ const apolloClient = {
229+ query : jest . fn ( ) . mockRejectedValue ( new Error ( 'GitHub app error' ) ) ,
230+ } as any ;
231+ const connectToAdapterOnUiMock = jest . spyOn ( BaseClass . prototype , 'connectToAdapterOnUi' ) . mockResolvedValueOnce ( ) ;
232+ const githubAdapterInstance = new GitHub ( {
233+ config : { projectBasePath : '/home/project1' } ,
234+ apolloClient : apolloClient ,
235+ log : logMock ,
236+ exit : exitMock ,
237+ } as any ) ;
238+ let err ;
239+
240+ try {
241+ await githubAdapterInstance . checkGitRemoteAvailableAndValid ( ) ;
242+ } catch ( error : any ) {
243+ err = error ;
244+ }
126245
246+ expect ( existsSync ) . toHaveBeenCalledWith ( '/home/project1/.git' ) ;
127247 expect ( getRemoteUrls as jest . Mock ) . toHaveBeenCalledWith ( '/home/project1/.git/config' ) ;
128- expect ( logMock ) . toHaveBeenCalledWith ( 'GitHub project not identified!' , 'error' ) ;
248+ expect ( apolloClient . query ) . toHaveBeenCalled ( ) ;
129249 expect ( connectToAdapterOnUiMock ) . toHaveBeenCalled ( ) ;
250+ expect ( logMock ) . toHaveBeenCalledWith ( 'GitHub app uninstalled. Please reconnect the app and try again' , 'error' ) ;
130251 expect ( exitMock ) . toHaveBeenCalledWith ( 1 ) ;
131252 expect ( err ) . toEqual ( new Error ( '1' ) ) ;
132- expect ( githubAdapterInstance . config . repository ) . toBeUndefined ( ) ;
133253 } ) ;
134254
135255 it ( 'should log an error and exit if repository is not found in the list of available repositories' , async ( ) => {
256+ ( existsSync as jest . Mock ) . mockReturnValueOnce ( true ) ;
136257 ( getRemoteUrls as jest . Mock ) . mockResolvedValueOnce ( {
137258 origin : 'https://github.com/test-user/test-repo-2.git' ,
138259 } ) ;
139260 const apolloClient = {
140261 query : jest . fn ( ) . mockResolvedValueOnce ( repositoriesResponse ) ,
141262 } as any ;
142- const githubAdapterInstance = new GitHub ( {
143- config : { projectBasePath : '/home/project1' } ,
144- log : logMock ,
263+ const githubAdapterInstance = new GitHub ( {
264+ config : { projectBasePath : '/home/project1' } ,
265+ log : logMock ,
145266 exit : exitMock ,
146267 apolloClient : apolloClient ,
147268 } as any ) ;
@@ -153,9 +274,13 @@ describe('GitHub Adapter', () => {
153274 err = error ;
154275 }
155276
277+ expect ( existsSync ) . toHaveBeenCalledWith ( '/home/project1/.git' ) ;
156278 expect ( getRemoteUrls as jest . Mock ) . toHaveBeenCalledWith ( '/home/project1/.git/config' ) ;
157279 expect ( apolloClient . query ) . toHaveBeenCalledWith ( { query : repositoriesQuery } ) ;
158- expect ( logMock ) . toHaveBeenCalledWith ( 'Repository not found in the list!' , 'error' ) ;
280+ expect ( logMock ) . toHaveBeenCalledWith (
281+ 'Repository not added to the GitHub app. Please add it to the app’s repository access list and try again.' ,
282+ 'error' ,
283+ ) ;
159284 expect ( exitMock ) . toHaveBeenCalledWith ( 1 ) ;
160285 expect ( err ) . toEqual ( new Error ( '1' ) ) ;
161286 expect ( githubAdapterInstance . config . repository ) . toBeUndefined ( ) ;
0 commit comments