1+ using GitHub . Actions . RunService . WebApi ;
2+ using GitHub . DistributedTask . WebApi ;
3+ using GitHub . Services . Launch . Client ;
4+ using GitHub . Services . Launch . Contracts ;
5+ using Moq ;
6+ using Moq . Protected ;
7+ using System ;
8+ using System . Collections . Generic ;
9+ using System . Linq ;
10+ using System . Net ;
11+ using System . Net . Http ;
12+ using System . Text ;
13+ using System . Threading ;
14+ using System . Threading . Tasks ;
15+ using Xunit ;
16+
17+ namespace GitHub . Actions . RunService . WebApi . Tests
18+ {
19+ public sealed class LaunchHttpClientL0
20+ {
21+ [ Fact ]
22+ public async Task GetResolveActionsDownloadInfoAsync_SuccessResponse ( )
23+ {
24+ var baseUrl = new Uri ( "https://api.github.com/" ) ;
25+ var planId = Guid . NewGuid ( ) ;
26+ var jobId = Guid . NewGuid ( ) ;
27+ var token = "fake-token" ;
28+
29+ var actionReferenceList = new ActionReferenceList
30+ {
31+ Actions = new List < ActionReference >
32+ {
33+ new ActionReference
34+ {
35+ NameWithOwner = "owner1/action1" ,
36+ Ref = "0123456789"
37+ }
38+ }
39+ } ;
40+
41+ var responseContent = @"{
42+ ""actions"": {
43+ ""owner1/action1@0123456789"": {
44+ ""name"": ""owner1/action1"",
45+ ""resolved_name"": ""owner1/action1"",
46+ ""resolved_sha"": ""0123456789"",
47+ ""version"": ""0123456789"",
48+ ""zip_url"": ""https://github.com/owner1/action1/zip"",
49+ ""tar_url"": ""https://github.com/owner1/action1/tar""
50+ }
51+ }
52+ }" ;
53+
54+ var httpResponse = new HttpResponseMessage ( HttpStatusCode . OK )
55+ {
56+ Content = new StringContent ( responseContent , Encoding . UTF8 , "application/json" ) ,
57+ RequestMessage = new HttpRequestMessage ( )
58+ {
59+ RequestUri = new Uri ( $ "{ baseUrl } actions/build/{ planId } /jobs/{ jobId } /runnerresolve/actions")
60+ }
61+ } ;
62+
63+ var mockHandler = new Mock < HttpMessageHandler > ( ) ;
64+ mockHandler . Protected ( ) . Setup < Task < HttpResponseMessage > > ( "SendAsync" , ItExpr . IsAny < HttpRequestMessage > ( ) , ItExpr . IsAny < CancellationToken > ( ) )
65+ . ReturnsAsync ( httpResponse ) ;
66+
67+ var client = new LaunchHttpClient ( baseUrl , mockHandler . Object , token , false ) ;
68+ var result = await client . GetResolveActionsDownloadInfoAsyncV2 ( planId , jobId , actionReferenceList , CancellationToken . None ) ;
69+
70+ // Assert
71+ Assert . NotNull ( result ) ;
72+ Assert . NotEmpty ( result . Actions ) ;
73+ Assert . Equal ( actionReferenceList . Actions . Count , result . Actions . Count ) ;
74+ Assert . True ( result . Actions . ContainsKey ( "owner1/action1@0123456789" ) ) ;
75+ }
76+
77+ [ Fact ]
78+ public async Task GetResolveActionsDownloadInfoAsync_UnprocessableEntityResponse ( )
79+ {
80+ var baseUrl = new Uri ( "https://api.github.com/" ) ;
81+ var planId = Guid . NewGuid ( ) ;
82+ var jobId = Guid . NewGuid ( ) ;
83+ var token = "fake-token" ;
84+
85+ var actionReferenceList = new ActionReferenceList
86+ {
87+ Actions = new List < ActionReference >
88+ {
89+ new ActionReference
90+ {
91+ NameWithOwner = "owner1/action1" ,
92+ Ref = "0123456789"
93+ }
94+ }
95+ } ;
96+
97+ var responseContent = @"{
98+ ""errors"": {
99+ ""owner1/invalid-action@0123456789"": {
100+ ""message"": ""Unable to resolve action 'owner1/invalid-action@0123456789', repository not found""
101+ }
102+ }
103+ }" ;
104+
105+ var httpResponse = new HttpResponseMessage ( HttpStatusCode . UnprocessableEntity )
106+ {
107+ Content = new StringContent ( responseContent , Encoding . UTF8 , "application/json" ) ,
108+ RequestMessage = new HttpRequestMessage ( )
109+ {
110+ RequestUri = new Uri ( $ "{ baseUrl } actions/build/{ planId } /jobs/{ jobId } /runnerresolve/actions")
111+ }
112+ } ;
113+
114+ var mockHandler = new Mock < HttpMessageHandler > ( ) ;
115+ mockHandler . Protected ( ) . Setup < Task < HttpResponseMessage > > ( "SendAsync" , ItExpr . IsAny < HttpRequestMessage > ( ) , ItExpr . IsAny < CancellationToken > ( ) )
116+ . ReturnsAsync ( httpResponse ) ;
117+
118+ var client = new LaunchHttpClient ( baseUrl , mockHandler . Object , token , false ) ;
119+
120+ var exception = await Assert . ThrowsAsync < UnresolvableActionDownloadInfoException > (
121+ ( ) => client . GetResolveActionsDownloadInfoAsyncV2 ( planId , jobId , actionReferenceList , CancellationToken . None ) ) ;
122+
123+ Assert . Contains ( "repository not found" , exception . Message ) ;
124+ }
125+ }
126+ }
0 commit comments