@@ -11,7 +11,7 @@ See the License for the specific language governing permissions and
1111limitations under the License.
1212*/
1313
14- import { Mock , beforeEach , describe , expect , it , mock } from 'bun:test' ;
14+ import { Mock , beforeEach , afterEach , describe , expect , it , mock , spyOn } from 'bun:test' ;
1515import { setupMocks } from '../setup' ;
1616
1717setupMocks ( ) ;
@@ -25,23 +25,10 @@ const ownerMap: { [key: string]: { data: { login: string }[] } } = {
2525 team6 : { data : [ { login : 'user8' } , { login : 'user9' } ] }
2626} ;
2727
28- // Mock paginateMembersInOrg
29- mock . module ( '../../src/utils/paginate-members-in-org' , ( ) => ( {
30- paginateMembersInOrg : mock ( async ( team : string ) => {
31- const teamSlug = team . replace ( '@ExpediaGroup/' , '' ) . replace ( 'ExpediaGroup/' , '' ) . replace ( 'owner/' , '' ) ;
32- return ownerMap [ teamSlug ] ?. data || [ ] ;
33- } )
34- } ) ) ;
35-
36- // Mock getRequiredCodeOwnersEntries
37- mock . module ( '../../src/utils/get-core-member-logins' , ( ) => ( {
38- getRequiredCodeOwnersEntries : mock ( ( ) => Promise . resolve ( [ ] ) ) ,
39- getCoreMemberLogins : mock ( ( ) => Promise . resolve ( [ ] ) )
40- } ) ) ;
41-
4228const { approvalsSatisfied } = await import ( '../../src/helpers/approvals-satisfied' ) ;
4329const { octokit } = await import ( '../../src/octokit' ) ;
44- const { getRequiredCodeOwnersEntries } = await import ( '../../src/utils/get-core-member-logins' ) ;
30+ const getCoreMemberLoginsModule = await import ( '../../src/utils/get-core-member-logins' ) ;
31+ const paginateMembersInOrgModule = await import ( '../../src/utils/paginate-members-in-org' ) ;
4532const core = await import ( '@actions/core' ) ;
4633
4734const mockPagination = ( result : unknown ) => {
@@ -51,8 +38,24 @@ const mockPagination = (result: unknown) => {
5138} ;
5239
5340describe ( 'approvalsSatisfied' , ( ) => {
41+ let paginateMembersInOrgSpy : ReturnType < typeof spyOn > ;
42+ let getRequiredCodeOwnersEntriesSpy : ReturnType < typeof spyOn > ;
43+ let getCoreMemberLoginsSpy : ReturnType < typeof spyOn > ;
44+
5445 beforeEach ( ( ) => {
5546 mock . clearAllMocks ( ) ;
47+ paginateMembersInOrgSpy = spyOn ( paginateMembersInOrgModule , 'paginateMembersInOrg' ) . mockImplementation ( async ( team : string ) => {
48+ const teamSlug = team . replace ( '@ExpediaGroup/' , '' ) . replace ( 'ExpediaGroup/' , '' ) . replace ( 'owner/' , '' ) ;
49+ return ( ownerMap [ teamSlug ] ?. data || [ ] ) as any ;
50+ } ) ;
51+ getRequiredCodeOwnersEntriesSpy = spyOn ( getCoreMemberLoginsModule , 'getRequiredCodeOwnersEntries' ) . mockResolvedValue ( [ ] ) ;
52+ getCoreMemberLoginsSpy = spyOn ( getCoreMemberLoginsModule , 'getCoreMemberLogins' ) . mockResolvedValue ( [ ] ) ;
53+ } ) ;
54+
55+ afterEach ( ( ) => {
56+ paginateMembersInOrgSpy . mockRestore ( ) ;
57+ getRequiredCodeOwnersEntriesSpy . mockRestore ( ) ;
58+ getCoreMemberLoginsSpy . mockRestore ( ) ;
5659 } ) ;
5760
5861 it ( 'should return false when passing teams override and required approvals are not met' , async ( ) => {
@@ -67,7 +70,7 @@ describe('approvalsSatisfied', () => {
6770
6871 const result = await approvalsSatisfied ( { teams : 'team1' , pull_number : '12345' } ) ;
6972 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
70- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
73+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
7174 expect ( result ) . toBe ( false ) ;
7275 } ) ;
7376
@@ -82,13 +85,13 @@ describe('approvalsSatisfied', () => {
8285 } ) ;
8386 const result = await approvalsSatisfied ( { teams : 'team1' , pull_number : '12345' } ) ;
8487 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
85- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
88+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
8689 expect ( result ) . toBe ( true ) ;
8790 } ) ;
8891
8992 it ( 'should throw an error when passing teams override with full name and org is different than repo org' , async ( ) => {
9093 const result = await approvalsSatisfied ( { teams : 'owner/team2\nsomeOtherOrg/team1' , pull_number : '12345' } ) ;
91- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
94+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
9295 expect ( core . setFailed ) . toHaveBeenCalled ( ) ;
9396 expect ( result ) . toBe ( false ) ;
9497 } ) ;
@@ -108,7 +111,7 @@ describe('approvalsSatisfied', () => {
108111 } ) ;
109112 const result = await approvalsSatisfied ( { teams : 'team1\nteam2' , pull_number : '12345' , number_of_reviewers : '2' } ) ;
110113 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
111- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
114+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
112115 expect ( result ) . toBe ( true ) ;
113116 } ) ;
114117
@@ -124,7 +127,7 @@ describe('approvalsSatisfied', () => {
124127
125128 const result = await approvalsSatisfied ( { users : 'user1' , pull_number : '12345' } ) ;
126129 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
127- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
130+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
128131 expect ( result ) . toBe ( false ) ;
129132 } ) ;
130133
@@ -139,7 +142,7 @@ describe('approvalsSatisfied', () => {
139142 } ) ;
140143 const result = await approvalsSatisfied ( { users : 'user1' , pull_number : '12345' } ) ;
141144 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
142- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
145+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
143146 expect ( result ) . toBe ( true ) ;
144147 } ) ;
145148
@@ -162,7 +165,7 @@ describe('approvalsSatisfied', () => {
162165 } ) ;
163166 const result = await approvalsSatisfied ( { users : 'user1\nuser2\nuser3' , pull_number : '12345' , number_of_reviewers : '2' } ) ;
164167 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
165- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
168+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
166169 expect ( result ) . toBe ( true ) ;
167170 } ) ;
168171
@@ -190,12 +193,12 @@ describe('approvalsSatisfied', () => {
190193 number_of_reviewers : '2'
191194 } ) ;
192195 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
193- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
196+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
194197 expect ( result ) . toBe ( true ) ;
195198 } ) ;
196199
197200 it ( 'should return false when a core member has not approved' , async ( ) => {
198- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team1' ] } ] ) ;
201+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team1' ] } ] ) ;
199202 mockPagination ( {
200203 data : [
201204 {
@@ -206,12 +209,12 @@ describe('approvalsSatisfied', () => {
206209 } ) ;
207210 const result = await approvalsSatisfied ( { pull_number : '12345' } ) ;
208211 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
209- expect ( getRequiredCodeOwnersEntries ) . toHaveBeenCalledWith ( 12345 , undefined ) ;
212+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . toHaveBeenCalledWith ( 12345 , undefined ) ;
210213 expect ( result ) . toBe ( false ) ;
211214 } ) ;
212215
213216 it ( 'should return true when a member from the team specified in codeowners_overrides has approved' , async ( ) => {
214- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team6' ] } ] ) ;
217+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team6' ] } ] ) ;
215218 mockPagination ( {
216219 data : [
217220 {
@@ -223,12 +226,12 @@ describe('approvalsSatisfied', () => {
223226 const codeOwnersOverrides = '* @ExpediaGroup/team6' ;
224227 const result = await approvalsSatisfied ( { pull_number : '12345' , codeowners_overrides : codeOwnersOverrides } ) ;
225228 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
226- expect ( getRequiredCodeOwnersEntries ) . toHaveBeenCalledWith ( 12345 , codeOwnersOverrides ) ;
229+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . toHaveBeenCalledWith ( 12345 , codeOwnersOverrides ) ;
227230 expect ( result ) . toBe ( true ) ;
228231 } ) ;
229232
230233 it ( 'should return true when a core member has approved' , async ( ) => {
231- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team1' ] } ] ) ;
234+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team1' ] } ] ) ;
232235 mockPagination ( {
233236 data : [
234237 {
@@ -246,7 +249,7 @@ describe('approvalsSatisfied', () => {
246249 } ) ;
247250
248251 it ( 'should return false when not all core teams have approved' , async ( ) => {
249- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
252+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [
250253 { owners : [ '@ExpediaGroup/team1' ] } ,
251254 { owners : [ '@ExpediaGroup/team2' ] } ,
252255 { owners : [ '@ExpediaGroup/team3' ] }
@@ -268,7 +271,7 @@ describe('approvalsSatisfied', () => {
268271 } ) ;
269272
270273 it ( 'should return true when a member from each core team has approved' , async ( ) => {
271- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
274+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [
272275 { owners : [ '@ExpediaGroup/team1' ] } ,
273276 { owners : [ '@ExpediaGroup/team2' ] } ,
274277 { owners : [ '@ExpediaGroup/team3' ] }
@@ -294,7 +297,7 @@ describe('approvalsSatisfied', () => {
294297 } ) ;
295298
296299 it ( 'should return true when a member from each owner group (teams and users) has approved' , async ( ) => {
297- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
300+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [
298301 { owners : [ '@ExpediaGroup/team1' ] } ,
299302 { owners : [ '@ExpediaGroup/team2' ] } ,
300303 { owners : [ '@ExpediaGroup/team4' , 'user10' ] }
@@ -324,10 +327,7 @@ describe('approvalsSatisfied', () => {
324327 } ) ;
325328
326329 it ( 'should return false when not enough members from core teams have approved' , async ( ) => {
327- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
328- { owners : [ '@ExpediaGroup/team2' ] } ,
329- { owners : [ '@ExpediaGroup/team4' ] }
330- ] ) ;
330+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team2' ] } , { owners : [ '@ExpediaGroup/team4' ] } ] ) ;
331331 mockPagination ( {
332332 data : [
333333 {
@@ -349,10 +349,7 @@ describe('approvalsSatisfied', () => {
349349 } ) ;
350350
351351 it ( 'should return true when enough members from core teams have approved' , async ( ) => {
352- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
353- { owners : [ '@ExpediaGroup/team2' ] } ,
354- { owners : [ '@ExpediaGroup/team4' ] }
355- ] ) ;
352+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team2' ] } , { owners : [ '@ExpediaGroup/team4' ] } ] ) ;
356353 mockPagination ( {
357354 data : [
358355 {
@@ -378,7 +375,7 @@ describe('approvalsSatisfied', () => {
378375 } ) ;
379376
380377 it ( 'should return false when not enough collective approvals from shared owners are met' , async ( ) => {
381- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team4' , '@ExpediaGroup/team5' ] } ] ) ;
378+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team4' , '@ExpediaGroup/team5' ] } ] ) ;
382379 mockPagination ( {
383380 data : [
384381 {
@@ -392,7 +389,7 @@ describe('approvalsSatisfied', () => {
392389 } ) ;
393390
394391 it ( 'should return false when not enough collective approvals from shared owners are met even if user is in both groups' , async ( ) => {
395- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team4' , '@ExpediaGroup/team5' ] } ] ) ;
392+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team4' , '@ExpediaGroup/team5' ] } ] ) ;
396393 mockPagination ( {
397394 data : [
398395 {
@@ -406,7 +403,7 @@ describe('approvalsSatisfied', () => {
406403 } ) ;
407404
408405 it ( 'should return true when enough collective approvals from shared owners are met' , async ( ) => {
409- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team4' , '@ExpediaGroup/team5' ] } ] ) ;
406+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ '@ExpediaGroup/team4' , '@ExpediaGroup/team5' ] } ] ) ;
410407 mockPagination ( {
411408 data : [
412409 {
@@ -424,7 +421,7 @@ describe('approvalsSatisfied', () => {
424421 } ) ;
425422
426423 it ( 'should return false when collective approvals are met but not standalone approvals' , async ( ) => {
427- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
424+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [
428425 { owners : [ '@ExpediaGroup/team4' ] } ,
429426 { owners : [ '@ExpediaGroup/team5' , '@ExpediaGroup/team6' ] }
430427 ] ) ;
@@ -445,7 +442,7 @@ describe('approvalsSatisfied', () => {
445442 } ) ;
446443
447444 it ( 'should return true when both collective and standalone approvals are met' , async ( ) => {
448- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
445+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [
449446 { owners : [ '@ExpediaGroup/team4' ] } ,
450447 { owners : [ '@ExpediaGroup/team5' , '@ExpediaGroup/team6' ] }
451448 ] ) ;
@@ -470,10 +467,7 @@ describe('approvalsSatisfied', () => {
470467 } ) ;
471468
472469 it ( 'should return true when there are no code owners for one file and the other file is satisfied' , async ( ) => {
473- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
474- { owners : [ ] } ,
475- { owners : [ '@ExpediaGroup/team5' , '@ExpediaGroup/team6' ] }
476- ] ) ;
470+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ ] } , { owners : [ '@ExpediaGroup/team5' , '@ExpediaGroup/team6' ] } ] ) ;
477471 mockPagination ( {
478472 data : [
479473 {
@@ -495,10 +489,7 @@ describe('approvalsSatisfied', () => {
495489 } ) ;
496490
497491 it ( 'should return false when there are no code owners for one file and the other file is not satisfied' , async ( ) => {
498- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
499- { owners : [ ] } ,
500- { owners : [ '@ExpediaGroup/team5' , '@ExpediaGroup/team6' ] }
501- ] ) ;
492+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ ] } , { owners : [ '@ExpediaGroup/team5' , '@ExpediaGroup/team6' ] } ] ) ;
502493 mockPagination ( {
503494 data : [
504495 {
@@ -512,7 +503,7 @@ describe('approvalsSatisfied', () => {
512503 } ) ;
513504
514505 it ( 'should return true when the overridden team config is satisfied' , async ( ) => {
515- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [
506+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [
516507 { owners : [ '@ExpediaGroup/team1' ] } ,
517508 { owners : [ '@ExpediaGroup/team2' ] } ,
518509 { owners : [ '@ExpediaGroup/team3' ] }
@@ -554,7 +545,7 @@ describe('approvalsSatisfied', () => {
554545 pull_number : '12345'
555546 } ) ;
556547 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
557- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
548+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
558549 expect ( result ) . toBe ( true ) ;
559550 } ) ;
560551
@@ -572,12 +563,12 @@ describe('approvalsSatisfied', () => {
572563 pull_number : '12345'
573564 } ) ;
574565 expect ( octokit . pulls . listReviews ) . toHaveBeenCalledWith ( { pull_number : 12345 , repo : 'repo' , owner : 'owner' , page : 1 , per_page : 100 } ) ;
575- expect ( getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
566+ expect ( getCoreMemberLoginsModule . getRequiredCodeOwnersEntries ) . not . toHaveBeenCalled ( ) ;
576567 expect ( result ) . toBe ( false ) ;
577568 } ) ;
578569
579570 it ( 'should return true when approvals are satisfied and users are explicitly defined in CODEOWNERS' , async ( ) => {
580- ( getRequiredCodeOwnersEntries as Mock < any > ) . mockResolvedValue ( [ { owners : [ '@user1' , '@user2' ] } ] ) ;
571+ getRequiredCodeOwnersEntriesSpy . mockResolvedValue ( [ { owners : [ '@user1' , '@user2' ] } ] ) ;
581572 mockPagination ( {
582573 data : [
583574 {
0 commit comments