1
+ namespace AngleSharp . Io . Tests . Network
2
+ {
3
+ using System ;
4
+ using System . Collections . Generic ;
5
+ using System . IO ;
6
+ using System . Linq ;
7
+ using System . Net ;
8
+ using System . Net . Http ;
9
+ using System . Text ;
10
+ using System . Threading ;
11
+ using System . Threading . Tasks ;
12
+ using AngleSharp . Io . Network ;
13
+ using AngleSharp . Network ;
14
+ using AngleSharp . Services . Default ;
15
+ using FluentAssertions ;
16
+ using NUnit . Framework ;
17
+ using NetHttpMethod = System . Net . Http . HttpMethod ;
18
+ using AngleSharpHttpMethod = AngleSharp . Network . HttpMethod ;
19
+
20
+
21
+ [ TestFixture ]
22
+ public class HttpClientRequesterTests
23
+ {
24
+ [ Test ]
25
+ public async Task RequestWithContent ( )
26
+ {
27
+ // ARRANGE
28
+ var ts = new TestState ( ) ;
29
+
30
+ // ACT
31
+ await ts . Target . RequestAsync ( ts . Request , CancellationToken . None ) ;
32
+
33
+ // ASSERT
34
+ ts . HttpRequestMessage . Version . Should ( ) . Be ( new Version ( 1 , 1 ) ) ;
35
+ ts . HttpRequestMessage . Method . Should ( ) . Be ( NetHttpMethod . Post ) ;
36
+ ts . HttpRequestMessage . RequestUri . Should ( ) . Be ( new Uri ( "http://example/path?query=value" ) ) ;
37
+ Encoding . UTF8 . GetString ( ts . HttpRequestMessageContent ) . Should ( ) . Be ( "\" request\" " ) ;
38
+ ts . HttpRequestMessage . Content . Headers . Select ( p => p . Key ) . ShouldBeEquivalentTo ( new [ ] { "Content-Type" , "Content-Length" } ) ;
39
+ ts . HttpRequestMessage . Content . Headers . ContentType . ToString ( ) . Should ( ) . Be ( "application/json" ) ;
40
+ ts . HttpRequestMessage . Content . Headers . ContentLength . Should ( ) . Be ( 9 ) ;
41
+ ts . HttpRequestMessage . Properties . Should ( ) . BeEmpty ( ) ;
42
+ ts . HttpRequestMessage . Headers . Select ( p => p . Key ) . ShouldBeEquivalentTo ( new [ ] { "User-Agent" , "Cookie" } ) ;
43
+ ts . HttpRequestMessage . Headers . UserAgent . ToString ( ) . Should ( ) . Be ( "Foo/2.0" ) ;
44
+ ts . HttpRequestMessage . Headers . Single ( p => p . Key == "Cookie" ) . Value . ShouldBeEquivalentTo ( new [ ] { "foo=bar" } ) ;
45
+ }
46
+
47
+ [ Test ]
48
+ public async Task RequestWithoutContent ( )
49
+ {
50
+ // ARRANGE
51
+ var ts = new TestState { Request = { Content = null , Method = AngleSharpHttpMethod . Get } } ;
52
+
53
+ // ACT
54
+ await ts . Target . RequestAsync ( ts . Request , CancellationToken . None ) ;
55
+
56
+ // ASSERT
57
+ ts . HttpRequestMessage . Version . Should ( ) . Be ( new Version ( 1 , 1 ) ) ;
58
+ ts . HttpRequestMessage . Method . Should ( ) . Be ( NetHttpMethod . Get ) ;
59
+ ts . HttpRequestMessage . RequestUri . Should ( ) . Be ( new Uri ( "http://example/path?query=value" ) ) ;
60
+ ts . HttpRequestMessage . Content . Should ( ) . BeNull ( ) ;
61
+ ts . HttpRequestMessage . Properties . Should ( ) . BeEmpty ( ) ;
62
+ ts . HttpRequestMessage . Headers . Select ( p => p . Key ) . ShouldBeEquivalentTo ( new [ ] { "User-Agent" , "Cookie" } ) ;
63
+ ts . HttpRequestMessage . Headers . UserAgent . ToString ( ) . Should ( ) . Be ( "Foo/2.0" ) ;
64
+ ts . HttpRequestMessage . Headers . Single ( p => p . Key == "Cookie" ) . Value . ShouldBeEquivalentTo ( new [ ] { "foo=bar" } ) ;
65
+ }
66
+
67
+ [ Test ]
68
+ public async Task ResponseWithContent ( )
69
+ {
70
+ // ARRANGE
71
+ var ts = new TestState ( ) ;
72
+
73
+ // ACT
74
+ var response = await ts . Target . RequestAsync ( ts . Request , CancellationToken . None ) ;
75
+
76
+ // ASSERT
77
+ response . Address . ShouldBeEquivalentTo ( ts . Request . Address ) ;
78
+ response . StatusCode . Should ( ) . Be ( ts . HttpResponseMessage . StatusCode ) ;
79
+ response . Headers . Keys . ShouldBeEquivalentTo ( new [ ] { "Server" , "X-Powered-By" , "X-CSV" , "Content-Type" , "Content-Length" } ) ;
80
+ response . Headers [ "Server" ] . Should ( ) . Be ( "Fake" ) ;
81
+ response . Headers [ "X-Powered-By" ] . Should ( ) . Be ( "Magic" ) ;
82
+ response . Headers [ "X-CSV" ] . Should ( ) . Be ( "foo, bar" ) ;
83
+ response . Headers [ "Content-Type" ] . Should ( ) . Be ( "application/json; charset=utf-8" ) ;
84
+ response . Headers [ "Content-Length" ] . Should ( ) . Be ( "10" ) ;
85
+ new StreamReader ( response . Content , Encoding . UTF8 ) . ReadToEnd ( ) . Should ( ) . Be ( "\" response\" " ) ;
86
+ }
87
+
88
+ [ Test ]
89
+ public async Task ResponseWithoutContent ( )
90
+ {
91
+ // ARRANGE
92
+ var ts = new TestState { HttpResponseMessage = { Content = null } } ;
93
+
94
+ // ACT
95
+ var response = await ts . Target . RequestAsync ( ts . Request , CancellationToken . None ) ;
96
+
97
+ // ASSERT
98
+ response . Address . ShouldBeEquivalentTo ( ts . Request . Address ) ;
99
+ response . StatusCode . Should ( ) . Be ( ts . HttpResponseMessage . StatusCode ) ;
100
+ response . Headers . Keys . ShouldBeEquivalentTo ( new [ ] { "Server" , "X-Powered-By" , "X-CSV" } ) ;
101
+ response . Headers [ "Server" ] . Should ( ) . Be ( "Fake" ) ;
102
+ response . Headers [ "X-Powered-By" ] . Should ( ) . Be ( "Magic" ) ;
103
+ response . Headers [ "X-CSV" ] . Should ( ) . Be ( "foo, bar" ) ;
104
+ response . Content . Should ( ) . BeNull ( ) ;
105
+ }
106
+
107
+ [ Test ]
108
+ public void SupportsHttp ( )
109
+ {
110
+ // ARRANGE, ACT, ASSERT
111
+ new TestState ( ) . Target . SupportsProtocol ( "HTTP" ) . Should ( ) . BeTrue ( ) ;
112
+ }
113
+
114
+ [ Test ]
115
+ public void SupportsHttps ( )
116
+ {
117
+ // ARRANGE, ACT, ASSERT
118
+ new TestState ( ) . Target . SupportsProtocol ( "HTTPS" ) . Should ( ) . BeTrue ( ) ;
119
+ }
120
+
121
+ [ Test ]
122
+ public async Task EndToEnd ( )
123
+ {
124
+ if ( Helper . IsNetworkAvailable ( ) )
125
+ {
126
+ // ARRANGE
127
+ var httpClient = new HttpClient ( ) ;
128
+ var requester = new HttpClientRequester ( httpClient ) ;
129
+ var configuration = new Configuration ( new [ ] { new LoaderService ( new [ ] { requester } ) } ) ;
130
+ var context = BrowsingContext . New ( configuration ) ;
131
+ var request = DocumentRequest . Get ( Url . Create ( "http://httpbin.org/html" ) ) ;
132
+
133
+ // ACT
134
+ var response = await context . Loader . LoadAsync ( request , CancellationToken . None ) ;
135
+ var document = await context . OpenAsync ( response , CancellationToken . None ) ;
136
+
137
+ // ASSERT
138
+ document . QuerySelector ( "h1" ) . ToHtml ( ) . Should ( ) . Be ( "<h1>Herman Melville - Moby-Dick</h1>" ) ;
139
+ }
140
+ }
141
+
142
+ class TestState
143
+ {
144
+ public TestState ( )
145
+ {
146
+ // dependencies
147
+
148
+ TestHandler = new TestHandler ( this ) ;
149
+ HttpClient = new HttpClient ( TestHandler ) ;
150
+
151
+ // data
152
+ Request = new Request
153
+ {
154
+ Method = AngleSharpHttpMethod . Post ,
155
+ Address = new Url ( "http://example/path?query=value" ) ,
156
+ Headers = new Dictionary < String , String >
157
+ {
158
+ { "User-Agent" , "Foo/2.0" } ,
159
+ { "Cookie" , "foo=bar" } ,
160
+ { "Content-Type" , "application/json" } ,
161
+ { "Content-Length" , "9" }
162
+ } ,
163
+ Content = new MemoryStream ( Encoding . UTF8 . GetBytes ( "\" request\" " ) )
164
+ } ;
165
+ HttpResponseMessage = new HttpResponseMessage ( HttpStatusCode . OK )
166
+ {
167
+ Content = new StringContent ( "\" response\" " , Encoding . UTF8 , "application/json" ) ,
168
+ Headers =
169
+ {
170
+ { "Server" , "Fake" } ,
171
+ { "X-Powered-By" , "Magic" } ,
172
+ { "X-CSV" , new [ ] { "foo" , "bar" } }
173
+ }
174
+ } ;
175
+
176
+ // setup
177
+ Target = new HttpClientRequester ( HttpClient ) ;
178
+ }
179
+
180
+ public Request Request
181
+ {
182
+ get ;
183
+ }
184
+
185
+ public HttpClientRequester Target
186
+ {
187
+ get ;
188
+ }
189
+
190
+ public HttpClient HttpClient
191
+ {
192
+ get ;
193
+ }
194
+
195
+ public TestHandler TestHandler
196
+ {
197
+ get ;
198
+ }
199
+
200
+ public HttpResponseMessage HttpResponseMessage
201
+ {
202
+ get ;
203
+ }
204
+
205
+ public HttpRequestMessage HttpRequestMessage
206
+ {
207
+ get ;
208
+ set ;
209
+ }
210
+
211
+ public Byte [ ] HttpRequestMessageContent
212
+ {
213
+ get ;
214
+ set ;
215
+ }
216
+ }
217
+
218
+ class TestHandler : DelegatingHandler
219
+ {
220
+ readonly TestState _testState ;
221
+
222
+ public TestHandler ( TestState testState )
223
+ {
224
+ _testState = testState ;
225
+ }
226
+
227
+ protected override async Task < HttpResponseMessage > SendAsync ( HttpRequestMessage request , CancellationToken cancellationToken )
228
+ {
229
+ _testState . HttpRequestMessage = request ;
230
+ if ( request . Content != null )
231
+ _testState . HttpRequestMessageContent = await request . Content . ReadAsByteArrayAsync ( ) ;
232
+
233
+ _testState . HttpResponseMessage . RequestMessage = request ;
234
+ return _testState . HttpResponseMessage ;
235
+ }
236
+ }
237
+
238
+ class Request : IRequest
239
+ {
240
+ public AngleSharpHttpMethod Method
241
+ {
242
+ get ;
243
+ set ;
244
+ }
245
+
246
+ public Url Address
247
+ {
248
+ get ;
249
+ set ;
250
+ }
251
+
252
+ public Dictionary < String , String > Headers
253
+ {
254
+ get ;
255
+ set ;
256
+ }
257
+
258
+ public Stream Content
259
+ {
260
+ get ;
261
+ set ;
262
+ }
263
+ }
264
+ }
265
+ }
0 commit comments