@@ -23,6 +23,7 @@ import type { Mocked, MockedObject } from 'vitest';
2323import { vi } from 'vitest' ;
2424import { mockDeep } from 'vitest-mock-extended' ;
2525import { partial } from '~test/util.ts' ;
26+ import { GlobalConfig } from '../../../config/global.ts' ;
2627import {
2728 REPOSITORY_ARCHIVED ,
2829 REPOSITORY_NOT_FOUND ,
@@ -33,6 +34,9 @@ import type * as _hostRules from '../../../util/host-rules.ts';
3334import type { Platform , RepoParams } from '../types.ts' ;
3435import { AzurePrVote } from './types.ts' ;
3536
37+ vi . mock ( '../../../config/global.ts' , async ( importOriginal ) =>
38+ importOriginal < typeof import ( '../../../config/global.ts' ) > ( ) ,
39+ ) ;
3640vi . mock ( './azure-got-wrapper.ts' , ( ) => mockDeep ( ) ) ;
3741vi . mock ( './azure-helper.ts' , ( ) => mockDeep ( ) ) ;
3842vi . mock ( '../../../util/sanitize.ts' , ( ) =>
@@ -51,6 +55,7 @@ describe('modules/platform/azure/index', () => {
5155 beforeEach ( async ( ) => {
5256 // reset module
5357 vi . resetModules ( ) ;
58+ GlobalConfig . reset ( ) ;
5459 hostRules = await vi . importActual ( '../../../util/host-rules.ts' ) ;
5560 azure = await vi . importActual ( './index.ts' ) ;
5661 azureApi = await vi . importMock ( './azure-got-wrapper.ts' ) ;
@@ -66,6 +71,7 @@ describe('modules/platform/azure/index', () => {
6671 hostRules . clear ( ) ;
6772 hostRules . add ( { token : 'token' } ) ;
6873 azureHelper . getPolicyEvaluations . mockResolvedValue ( [ ] ) ;
74+ azureApi . getAuthenticatedUserId . mockResolvedValue ( 'renovate-user-id' ) ;
6975 // Default to the hosted (cloud) endpoint used across these tests.
7076 azureApi . isHosted . mockResolvedValue ( true ) ;
7177 await azure . initPlatform ( {
@@ -156,6 +162,22 @@ describe('modules/platform/azure/index', () => {
156162 token : 'token' ,
157163 } ) ,
158164 ) . toMatchSnapshot ( ) ;
165+ expect ( azureApi . getAuthenticatedUserId ) . toHaveBeenLastCalledWith ( {
166+ token : 'token' ,
167+ } ) ;
168+ } ) ;
169+
170+ it ( 'should discover the authenticated user with basic credentials' , async ( ) => {
171+ await azure . initPlatform ( {
172+ endpoint : 'https://dev.azure.com/renovate12345' ,
173+ username : 'user' ,
174+ password : 'pass' ,
175+ } ) ;
176+
177+ expect ( azureApi . getAuthenticatedUserId ) . toHaveBeenLastCalledWith ( {
178+ username : 'user' ,
179+ password : 'pass' ,
180+ } ) ;
159181 } ) ;
160182 } ) ;
161183
@@ -499,6 +521,81 @@ describe('modules/platform/azure/index', () => {
499521 } ) ;
500522 } ) ;
501523
524+ it ( 'queries the exact branch when including other authors' , async ( ) => {
525+ await initRepo ( ) ;
526+ const getPullRequests = vi . fn ( ) . mockResolvedValue ( [
527+ {
528+ pullRequestId : 1 ,
529+ sourceRefName : 'refs/heads/branch-a' ,
530+ targetRefName : 'refs/heads/branch-b' ,
531+ title : 'branch a pr' ,
532+ status : 1 ,
533+ } ,
534+ ] ) ;
535+ azureApi . gitApi . mockResolvedValueOnce (
536+ partial < IGitApi > ( {
537+ getPullRequests,
538+ } ) ,
539+ ) ;
540+
541+ const res = await azure . findPr ( {
542+ branchName : 'branch-a' ,
543+ state : 'open' ,
544+ targetBranch : 'branch-b' ,
545+ includeOtherAuthors : true ,
546+ } ) ;
547+
548+ expect ( res ) . toMatchObject ( {
549+ number : 1 ,
550+ sourceBranch : 'branch-a' ,
551+ state : 'open' ,
552+ targetBranch : 'branch-b' ,
553+ } ) ;
554+ expect ( getPullRequests ) . toHaveBeenCalledExactlyOnceWith (
555+ '1' ,
556+ {
557+ sourceRefName : 'refs/heads/branch-a' ,
558+ sourceRepositoryId : '1' ,
559+ status : 1 ,
560+ targetRefName : 'refs/heads/branch-b' ,
561+ } ,
562+ 'some' ,
563+ 0 ,
564+ 0 ,
565+ 1 ,
566+ ) ;
567+ } ) ;
568+
569+ it ( 'returns null when no PR from another author matches' , async ( ) => {
570+ await initRepo ( ) ;
571+ const getPullRequests = vi . fn ( ) . mockResolvedValue ( [ ] ) ;
572+ azureApi . gitApi . mockResolvedValueOnce (
573+ partial < IGitApi > ( {
574+ getPullRequests,
575+ } ) ,
576+ ) ;
577+
578+ const res = await azure . findPr ( {
579+ branchName : 'branch-a' ,
580+ state : 'open' ,
581+ includeOtherAuthors : true ,
582+ } ) ;
583+
584+ expect ( res ) . toBeNull ( ) ;
585+ expect ( getPullRequests ) . toHaveBeenCalledExactlyOnceWith (
586+ '1' ,
587+ {
588+ sourceRefName : 'refs/heads/branch-a' ,
589+ sourceRepositoryId : '1' ,
590+ status : 1 ,
591+ } ,
592+ 'some' ,
593+ 0 ,
594+ 0 ,
595+ 1 ,
596+ ) ;
597+ } ) ;
598+
502599 it ( 'catches errors' , async ( ) => {
503600 azureApi . gitApi . mockResolvedValueOnce (
504601 partial < IGitApi > ( {
@@ -514,13 +611,96 @@ describe('modules/platform/azure/index', () => {
514611 } ) ;
515612
516613 describe ( 'getPrList()' , ( ) => {
517- it ( 'returns empty array' , async ( ) => {
614+ it ( 'filters PRs by repository and authenticated user' , async ( ) => {
615+ await initRepo ( ) ;
616+ const getPullRequests = vi . fn ( ) . mockResolvedValue ( [ ] ) ;
518617 azureApi . gitApi . mockResolvedValueOnce (
519618 partial < IGitApi > ( {
520- getPullRequests : vi . fn ( ) . mockResolvedValue ( [ ] ) ,
619+ getPullRequests,
620+ } ) ,
621+ ) ;
622+ expect ( await azure . getPrList ( ) ) . toEqual ( [ ] ) ;
623+ expect ( azureApi . getAuthenticatedUserId ) . toHaveBeenCalledExactlyOnceWith ( {
624+ token : 'token' ,
625+ } ) ;
626+ expect ( azureApi . gitApi ) . toHaveBeenLastCalledWith ( ) ;
627+ expect ( getPullRequests ) . toHaveBeenCalledExactlyOnceWith (
628+ '1' ,
629+ {
630+ creatorId : 'renovate-user-id' ,
631+ sourceRepositoryId : '1' ,
632+ status : 4 ,
633+ } ,
634+ 'some' ,
635+ 0 ,
636+ 0 ,
637+ 100 ,
638+ ) ;
639+ } ) ;
640+
641+ it ( 'does not filter by authenticated user when ignorePrAuthor is enabled' , async ( ) => {
642+ GlobalConfig . set ( { ignorePrAuthor : true } ) ;
643+ await initRepo ( ) ;
644+ const getPullRequests = vi . fn ( ) . mockResolvedValue ( [ ] ) ;
645+ azureApi . gitApi . mockResolvedValueOnce (
646+ partial < IGitApi > ( {
647+ getPullRequests,
648+ } ) ,
649+ ) ;
650+
651+ expect ( await azure . getPrList ( ) ) . toEqual ( [ ] ) ;
652+ expect ( getPullRequests ) . toHaveBeenCalledExactlyOnceWith (
653+ '1' ,
654+ {
655+ sourceRepositoryId : '1' ,
656+ status : 4 ,
657+ } ,
658+ 'some' ,
659+ 0 ,
660+ 0 ,
661+ 100 ,
662+ ) ;
663+ } ) ;
664+
665+ it ( 'does not filter by authenticated user when the ID is unavailable' , async ( ) => {
666+ azureApi . getAuthenticatedUserId . mockResolvedValueOnce ( undefined ) ;
667+ await azure . initPlatform ( {
668+ endpoint : 'https://dev.azure.com/renovate12345' ,
669+ token : 'token' ,
670+ } ) ;
671+ await initRepo ( ) ;
672+ const getPullRequests = vi . fn ( ) . mockResolvedValue ( [ ] ) ;
673+ azureApi . gitApi . mockResolvedValueOnce (
674+ partial < IGitApi > ( {
675+ getPullRequests,
521676 } ) ,
522677 ) ;
678+
523679 expect ( await azure . getPrList ( ) ) . toEqual ( [ ] ) ;
680+ expect ( getPullRequests ) . toHaveBeenCalledExactlyOnceWith (
681+ '1' ,
682+ {
683+ sourceRepositoryId : '1' ,
684+ status : 4 ,
685+ } ,
686+ 'some' ,
687+ 0 ,
688+ 0 ,
689+ 100 ,
690+ ) ;
691+ } ) ;
692+
693+ it ( 'reuses the cached PR list' , async ( ) => {
694+ await initRepo ( ) ;
695+ const getPullRequests = vi . fn ( ) . mockResolvedValue ( [ ] ) ;
696+ azureApi . gitApi . mockResolvedValueOnce (
697+ partial < IGitApi > ( { getPullRequests } ) ,
698+ ) ;
699+
700+ await azure . getPrList ( ) ;
701+ await azure . getPrList ( ) ;
702+
703+ expect ( getPullRequests ) . toHaveBeenCalledOnce ( ) ;
524704 } ) ;
525705 } ) ;
526706
0 commit comments