Skip to content

Commit 765d74d

Browse files
committed
Enforce ImgTest by asserting HttpClient call #216
1 parent 13ed3fa commit 765d74d

File tree

3 files changed

+72
-66
lines changed

3 files changed

+72
-66
lines changed

test/HtmlToOpenXml.Tests/ImgTests.cs

Lines changed: 31 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using DocumentFormat.OpenXml.Wordprocessing;
55
using Moq;
66
using System.Net.Http;
7-
using System.Net.Http.Headers;
87

98
namespace HtmlToOpenXml.Tests
109
{
@@ -21,7 +20,7 @@ public class ImgTests : HtmlConverterTestBase
2120
[TestCase("https://upload.wikimedia.org/wikipedia/commons/b/b0/Mozilla_dinosaur_head_logo.svg", "image/svg+xml")]
2221
public async Task AbsoluteUri_ReturnsDrawing_WithDownloadedData(string imageUri, string contentType)
2322
{
24-
var mockHttp = new MockHttpMessageHandler(uri => Task.FromResult(new HttpResponseMessage {
23+
var mockHttp = new ProxyHttpMessageHandler(uri => Task.FromResult(new HttpResponseMessage {
2524
StatusCode = System.Net.HttpStatusCode.OK,
2625
Content = new StreamContent(ResourceHelper.GetStream("Resources." + Path.GetFileName(imageUri))) {
2726
Headers = { { "Content-Type", contentType } }
@@ -293,28 +292,16 @@ await converter.ParseBody(@"
293292
[Test]
294293
public async Task ExternalLinkMode_RemoteImage_ShouldCreateExternalRelationship()
295294
{
296-
// Arrange
297-
var mockHttp = new MockHttpMessageHandler(uri => Task.FromResult(new HttpResponseMessage
298-
{
299-
StatusCode = System.Net.HttpStatusCode.OK,
300-
Content = new StreamContent(ResourceHelper.GetStream("Resources.smiley.gif"))
301-
{
302-
Headers = { { "Content-Type", "image/gif" } }
303-
}
304-
}));
305-
306-
var webRequest = new IO.DefaultWebRequest(new HttpClient(mockHttp));
307-
converter = new HtmlConverter(mainPart, webRequest)
308-
{
295+
var mockMessageHandler = new MockHttpMessageHandler();
296+
var webRequest = mockMessageHandler.GetWebRequest();
297+
converter = new HtmlConverter(mainPart, webRequest) {
309298
ImageProcessing = ImageProcessingMode.LinkExternal
310299
};
311300

312-
// Act
313301
await converter.ParseBody(
314302
@"<img src='https://www.example.com/image.gif' width='42' height='42'>",
315303
TestContext.CurrentContext.CancellationToken);
316304

317-
// Assert
318305
var paragraphs = mainPart.Document.Body!.Elements<Paragraph>();
319306
Assert.That(paragraphs.Count(), Is.EqualTo(1));
320307

@@ -323,12 +310,17 @@ await converter.ParseBody(
323310
var drawing = run.GetFirstChild<Drawing>();
324311
Assert.That(drawing, Is.Not.Null);
325312

313+
mockMessageHandler.AssertNeverCalled();
314+
326315
var pic = drawing.Inline?.Graphic?.GraphicData?.GetFirstChild<pic.Picture>();
327-
Assert.That(pic?.BlipFill?.Blip, Is.Not.Null);
316+
using (Assert.EnterMultipleScope())
317+
{
318+
Assert.That(pic?.BlipFill?.Blip, Is.Not.Null);
328319

329-
// Verify it's using Link instead of Embed
330-
Assert.That(pic.BlipFill.Blip.Link, Is.Not.Null);
331-
Assert.That(pic.BlipFill.Blip.Embed, Is.Null);
320+
// Verify it's using Link instead of Embed
321+
Assert.That(pic?.BlipFill?.Blip?.Link, Is.Not.Null);
322+
Assert.That(pic?.BlipFill?.Blip?.Embed, Is.Null);
323+
}
332324

333325
// Verify external relationship was created
334326
var externalRels = mainPart.ExternalRelationships
@@ -343,77 +335,62 @@ await converter.ParseBody(
343335
[Test]
344336
public async Task ExternalLinkMode_DataUri_ShouldStillEmbed()
345337
{
346-
// Arrange
347-
converter = new HtmlConverter(mainPart)
348-
{
338+
converter = new HtmlConverter(mainPart) {
349339
ImageProcessing = ImageProcessingMode.LinkExternal
350340
};
351341

352-
// Act
353342
await converter.ParseBody(
354343
@"<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==' width='42' height='42'>",
355344
TestContext.CurrentContext.CancellationToken);
356345

357-
// Assert
358346
var paragraphs = mainPart.Document.Body!.Elements<Paragraph>();
359347
Assert.That(paragraphs.Count(), Is.EqualTo(1));
360348

361349
var run = paragraphs.First().GetFirstChild<Run>();
362350
var drawing = run?.GetFirstChild<Drawing>();
363351
var pic = drawing?.Inline?.Graphic?.GraphicData?.GetFirstChild<pic.Picture>();
364352

365-
// Data URIs should still be embedded
366-
Assert.That(pic?.BlipFill?.Blip?.Embed, Is.Not.Null);
367-
Assert.That(pic?.BlipFill?.Blip?.Link, Is.Null);
368-
Assert.That(mainPart.ImageParts.Count(), Is.EqualTo(1));
353+
using (Assert.EnterMultipleScope())
354+
{
355+
// Data URIs should still be embedded
356+
Assert.That(pic?.BlipFill?.Blip?.Embed, Is.Not.Null);
357+
Assert.That(pic?.BlipFill?.Blip?.Link, Is.Null);
358+
Assert.That(mainPart.ImageParts.Count(), Is.EqualTo(1));
359+
}
369360
}
370361

371362
[Test]
372363
public async Task EmbedDataUriOnlyMode_RemoteImage_ShouldBeSkipped()
373364
{
374-
// Arrange
375-
var mockHttp = new MockHttpMessageHandler(uri => Task.FromResult(new HttpResponseMessage
376-
{
377-
StatusCode = System.Net.HttpStatusCode.OK,
378-
Content = new StreamContent(ResourceHelper.GetStream("Resources.smiley.gif"))
379-
{
380-
Headers = { { "Content-Type", "image/gif" } }
381-
}
382-
}));
383-
384-
var webRequest = new IO.DefaultWebRequest(new HttpClient(mockHttp));
385-
converter = new HtmlConverter(mainPart, webRequest)
386-
{
365+
var mockMessageHandler = new MockHttpMessageHandler();
366+
var webRequest = mockMessageHandler.GetWebRequest();
367+
converter = new HtmlConverter(mainPart, webRequest) {
387368
ImageProcessing = ImageProcessingMode.EmbedDataUriOnly
388369
};
389370

390-
// Act
391371
await converter.ParseBody(
392372
@"<img src='https://www.example.com/image.gif' width='42' height='42'>",
393373
TestContext.CurrentContext.CancellationToken);
394374

395-
// Assert
396375
var paragraphs = mainPart.Document.Body!.Elements<Paragraph>();
397376
// Image should be skipped, so paragraph should be empty or not contain drawing
398377
Assert.That(paragraphs.Count(), Is.EqualTo(0));
399378
Assert.That(mainPart.ImageParts.Count(), Is.EqualTo(0));
379+
380+
mockMessageHandler.AssertNeverCalled();
400381
}
401382

402383
[Test]
403384
public async Task EmbedDataUriOnlyMode_DataUri_ShouldEmbed()
404385
{
405-
// Arrange
406-
converter = new HtmlConverter(mainPart)
407-
{
386+
converter = new HtmlConverter(mainPart) {
408387
ImageProcessing = ImageProcessingMode.EmbedDataUriOnly
409388
};
410389

411-
// Act
412390
await converter.ParseBody(
413391
@"<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==' width='42' height='42'>",
414392
TestContext.CurrentContext.CancellationToken);
415393

416-
// Assert
417394
var paragraphs = mainPart.Document.Body!.Elements<Paragraph>();
418395
Assert.That(paragraphs.Count(), Is.EqualTo(1));
419396
AssertIsImg(mainPart, paragraphs.First());
@@ -423,28 +400,22 @@ await converter.ParseBody(
423400
[Test]
424401
public async Task EmbedMode_RemoteImage_ShouldDownloadAndEmbed()
425402
{
426-
// Arrange
427-
var mockHttp = new MockHttpMessageHandler(uri => Task.FromResult(new HttpResponseMessage
428-
{
403+
var mockHttp = new ProxyHttpMessageHandler(uri => Task.FromResult(new HttpResponseMessage {
429404
StatusCode = System.Net.HttpStatusCode.OK,
430-
Content = new StreamContent(ResourceHelper.GetStream("Resources.smiley.gif"))
431-
{
405+
Content = new StreamContent(ResourceHelper.GetStream("Resources.smiley.gif")) {
432406
Headers = { { "Content-Type", "image/gif" } }
433407
}
434408
}));
435409

436410
var webRequest = new IO.DefaultWebRequest(new HttpClient(mockHttp));
437-
converter = new HtmlConverter(mainPart, webRequest)
438-
{
411+
converter = new HtmlConverter(mainPart, webRequest) {
439412
ImageProcessing = ImageProcessingMode.Embed // Default behavior
440413
};
441414

442-
// Act
443415
await converter.ParseBody(
444416
@"<img src='https://www.example.com/image.gif' width='42' height='42'>",
445417
TestContext.CurrentContext.CancellationToken);
446418

447-
// Assert
448419
var paragraphs = mainPart.Document.Body!.Elements<Paragraph>();
449420
Assert.That(paragraphs.Count(), Is.EqualTo(1));
450421
AssertIsImg(mainPart, paragraphs.First());
@@ -465,7 +436,7 @@ private static (Drawing, ImagePart) AssertIsImg(OpenXmlPartContainer container,
465436
Assert.That(imagePartId, Is.Not.Null);
466437
var imagePart = container.GetPartById(imagePartId);
467438
Assert.That(imagePart, Is.TypeOf(typeof(ImagePart)));
468-
return (drawing, (ImagePart) imagePart);
439+
return (drawing, (ImagePart)imagePart);
469440
}
470441
}
471442
}
Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,35 @@
11
/*
22
* Copyright (c) 2017 Deal Stream sàrl. All rights reserved
33
*/
4+
using Moq;
5+
using Moq.Protected;
46
using System.Net.Http;
57

68
namespace HtmlToOpenXml.Tests
79
{
8-
public class MockHttpMessageHandler : HttpMessageHandler
10+
public class MockHttpMessageHandler
911
{
10-
private readonly Func<Uri, Task<HttpResponseMessage>> _getResponseFunc;
12+
private readonly Mock<HttpMessageHandler> mockMessageHandler;
1113

12-
public MockHttpMessageHandler(Func<Uri, Task<HttpResponseMessage>> getResponseFunc)
14+
15+
public MockHttpMessageHandler()
16+
{
17+
mockMessageHandler = new Mock<HttpMessageHandler>();
18+
mockMessageHandler.Protected()
19+
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
20+
.ReturnsAsync(new HttpResponseMessage());
21+
}
22+
23+
public IO.IWebRequest GetWebRequest()
1324
{
14-
_getResponseFunc = getResponseFunc;
25+
return new IO.DefaultWebRequest(new HttpClient(mockMessageHandler.Object));
1526
}
1627

17-
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
28+
public void AssertNeverCalled()
1829
{
19-
return await _getResponseFunc(request.RequestUri!);
30+
mockMessageHandler.Protected()
31+
.Verify("SendAsync", Times.Never(),
32+
ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>());
2033
}
2134
}
2235
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright (c) 2017 Deal Stream sàrl. All rights reserved
3+
*/
4+
using System.Net.Http;
5+
6+
namespace HtmlToOpenXml.Tests
7+
{
8+
public class ProxyHttpMessageHandler : HttpMessageHandler
9+
{
10+
private readonly Func<Uri, Task<HttpResponseMessage>> _getResponseFunc;
11+
12+
public ProxyHttpMessageHandler(Func<Uri, Task<HttpResponseMessage>> getResponseFunc)
13+
{
14+
_getResponseFunc = getResponseFunc;
15+
}
16+
17+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
18+
{
19+
return await _getResponseFunc(request.RequestUri!);
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)