Skip to content

Commit 7f52b8e

Browse files
committed
Add tests for the PdfGenerator
1 parent a7e54ca commit 7f52b8e

6 files changed

Lines changed: 206 additions & 2 deletions

File tree

‎.github/workflows/build.yml‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ jobs:
5151
- name: Build
5252
run: dotnet build Source/HtmlRenderer.sln --configuration Release --no-restore
5353

54+
- name: Run Tests
55+
run: dotnet test Source/HtmlRenderer.sln --configuration Release --no-build --logger trx --results-directory ${{ github.workspace }}/TestResults
56+
env:
57+
PDF_OUTPUT_DIRECTORY: ${{ github.workspace }}/pdf-artifacts/${{ matrix.platform.name }}-${{ matrix.dotnet.name }}
58+
5459
- name: Create HtmlRenderer.Core NuGet package
5560
run: dotnet pack Source/HtmlRenderer/HtmlRenderer.csproj --configuration Release --include-symbols -p:SymbolPackageFormat=snupkg --no-build --verbosity normal --output ${{ env.NuGetDirectory }}
5661

@@ -69,6 +74,14 @@ jobs:
6974
name: "HTML Renderer (${{ matrix.platform.name }} ${{ matrix.dotnet.name }})"
7075
path: ${{ env.NuGetDirectory }}/*.*nupkg
7176

77+
- name: Upload PDF artifacts
78+
if: always()
79+
uses: actions/upload-artifact@v7
80+
with:
81+
name: "PDF artifacts (${{ matrix.platform.name }} ${{ matrix.dotnet.name }})"
82+
path: ${{ github.workspace }}/pdf-artifacts/**/*.pdf
83+
if-no-files-found: ignore
84+
7285
- name: NuGet Login
7386
if: startsWith(github.ref, 'refs/tags/') && matrix.dotnet.name == '.NET 8' && runner.os == 'Windows'
7487
uses: NuGet/login@v1

‎Source/Directory.Build.props‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<Authors>Arthur Teplitzki</Authors>
55
<Owners>Arthur Teplitzki</Owners>
66
<Company>Open source hosted on GitHub</Company>
7-
<Copyright>Copyright © 2008-2025</Copyright>
7+
<Copyright>Copyright © 2008-2026</Copyright>
88
<Version>1.6.0-dev</Version>
99
<AssemblyVersion>1.6.0.0</AssemblyVersion>
1010
<FileVersion>1.6.0.0</FileVersion>
@@ -16,7 +16,7 @@
1616
<PackageReleaseNotes>See https://github.com/ArthurHub/HTML-Renderer/releases.</PackageReleaseNotes>
1717
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
1818
</PropertyGroup>
19-
<ItemGroup>
19+
<ItemGroup Condition="'$(IsTestProject)' != 'true'">
2020
<None Include="../../html.png" Pack="true" PackagePath="\"/>
2121
</ItemGroup>
2222
</Project>

‎Source/HtmlRenderer.sln‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlRenderer", "HtmlRendere
1919
EndProject
2020
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlRenderer.PdfSharp", "HtmlRenderer.PdfSharp\HtmlRenderer.PdfSharp.csproj", "{CA249F5D-9285-40A6-B217-5889EF79FD7E}"
2121
EndProject
22+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{E508FA78-D57E-492F-9BF7-23640001848A}"
23+
EndProject
24+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HtmlRenderer.PdfSharp.Test", "Test\HtmlRenderer.PdfSharp.Test\HtmlRenderer.PdfSharp.Test.csproj", "{AF39851E-37B9-409E-A34D-CE091A098C86}"
25+
EndProject
2226
Global
2327
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2428
Debug|Any CPU = Debug|Any CPU
@@ -99,6 +103,18 @@ Global
99103
{CA249F5D-9285-40A6-B217-5889EF79FD7E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
100104
{CA249F5D-9285-40A6-B217-5889EF79FD7E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
101105
{CA249F5D-9285-40A6-B217-5889EF79FD7E}.Release|x86.ActiveCfg = Release|Any CPU
106+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
107+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Debug|Any CPU.Build.0 = Debug|Any CPU
108+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
109+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
110+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Debug|x86.ActiveCfg = Debug|Any CPU
111+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Debug|x86.Build.0 = Debug|Any CPU
112+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Release|Any CPU.ActiveCfg = Release|Any CPU
113+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Release|Any CPU.Build.0 = Release|Any CPU
114+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
115+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Release|Mixed Platforms.Build.0 = Release|Any CPU
116+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Release|x86.ActiveCfg = Release|Any CPU
117+
{AF39851E-37B9-409E-A34D-CE091A098C86}.Release|x86.Build.0 = Release|Any CPU
102118
EndGlobalSection
103119
GlobalSection(SolutionProperties) = preSolution
104120
HideSolutionNode = FALSE
@@ -107,6 +123,7 @@ Global
107123
{2390B71F-9400-47F4-B23A-7F2649C87D35} = {E263EA16-2E6A-4269-A319-AA2F97ADA8E1}
108124
{8AD34FE8-8382-4A8A-B3AA-A0392ED42423} = {E263EA16-2E6A-4269-A319-AA2F97ADA8E1}
109125
{F02E0216-4AE3-474F-9381-FCB93411CDB0} = {E263EA16-2E6A-4269-A319-AA2F97ADA8E1}
126+
{AF39851E-37B9-409E-A34D-CE091A098C86} = {E508FA78-D57E-492F-9BF7-23640001848A}
110127
EndGlobalSection
111128
GlobalSection(ExtensibilityGlobals) = postSolution
112129
SolutionGuid = {902788D6-3165-491D-B860-DF2F74E66C1D}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<LangVersion>latest</LangVersion>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="MSTest" Version="4.0.2"/>
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<ProjectReference Include="..\..\HtmlRenderer.PdfSharp\HtmlRenderer.PdfSharp.csproj" />
16+
<ProjectReference Include="..\..\Demo\Common\HtmlRenderer.Demo.Common.csproj" />
17+
</ItemGroup>
18+
19+
<ItemGroup>
20+
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting"/>
21+
</ItemGroup>
22+
23+
</Project>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[assembly: Parallelize(Scope = ExecutionScope.ClassLevel)]
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
using System.Runtime.InteropServices;
2+
using PdfSharp;
3+
using PdfSharp.Drawing;
4+
using TheArtOfDev.HtmlRenderer.Core.Entities;
5+
using TheArtOfDev.HtmlRenderer.Demo.Common;
6+
using TheArtOfDev.HtmlRenderer.PdfSharp;
7+
8+
namespace HtmlRenderer.PdfSharp.Test;
9+
10+
[TestClass]
11+
public sealed class PdfGeneratorTests
12+
{
13+
[TestMethod]
14+
public void GeneratePdf_FromHtml_CreatesPdfDocument()
15+
{
16+
// Arrange
17+
var config = new PdfGenerateConfig
18+
{
19+
PageSize = PageSize.A4
20+
};
21+
config.SetMargins(20);
22+
23+
const string html = """
24+
<html>
25+
<head>
26+
<link rel="Stylesheet" href="StyleSheet" />
27+
</head>
28+
<body>
29+
<h1>PdfSharp</h1>
30+
<p>This is html rendered text <img src="ImageIcon" /></p>
31+
</body>
32+
</html>
33+
""";
34+
35+
// Act
36+
using var document = PdfGenerator.GeneratePdf(html, config, null, DemoUtils.OnStylesheetLoad, OnImageLoadPdfSharp);
37+
38+
// Assert
39+
Assert.AreEqual(1, document.Pages.Count);
40+
41+
using var stream = new MemoryStream();
42+
document.Save(stream, false);
43+
44+
var pdf = stream.ToArray();
45+
Assert.IsGreaterThan(4, pdf.Length);
46+
Assert.AreEqual("%PDF", System.Text.Encoding.ASCII.GetString(pdf, 0, 4));
47+
48+
var pdfOutputDirectory = Environment.GetEnvironmentVariable("PDF_OUTPUT_DIRECTORY");
49+
if (string.IsNullOrWhiteSpace(pdfOutputDirectory))
50+
{
51+
pdfOutputDirectory = Path.Combine(Path.GetTempPath(), "html-renderer-pdf-artifacts");
52+
}
53+
54+
Directory.CreateDirectory(pdfOutputDirectory);
55+
56+
var pdfPath = Path.Combine(
57+
pdfOutputDirectory,
58+
$"{nameof(GeneratePdf_FromHtml_CreatesPdfDocument)}-{GetPlatformName()}.pdf");
59+
File.WriteAllBytes(pdfPath, pdf);
60+
}
61+
62+
[TestMethod]
63+
public void GeneratePdf_FromHtml_WithMultipleFonts_CreatesPdfDocument()
64+
{
65+
// Arrange
66+
var config = new PdfGenerateConfig
67+
{
68+
PageSize = PageSize.A4
69+
};
70+
config.SetMargins(20);
71+
72+
const string html = """
73+
<html>
74+
<head>
75+
<link rel="Stylesheet" href="StyleSheet" />
76+
<style>
77+
.helvetica { font-family: Helvetica; }
78+
.mono { font-family: monospace; }
79+
</style>
80+
</head>
81+
<body>
82+
<p class="helvetica">Helvetica text</p>
83+
<p class="mono">Monospace text</p>
84+
</body>
85+
</html>
86+
""";
87+
88+
// Act
89+
using var document = PdfGenerator.GeneratePdf(html, config, null, DemoUtils.OnStylesheetLoad, null);
90+
91+
// Assert
92+
Assert.AreEqual(1, document.Pages.Count);
93+
94+
using var stream = new MemoryStream();
95+
document.Save(stream, false);
96+
97+
var pdf = stream.ToArray();
98+
Assert.IsGreaterThan(4, pdf.Length);
99+
Assert.AreEqual("%PDF", System.Text.Encoding.ASCII.GetString(pdf, 0, 4));
100+
101+
var pdfOutputDirectory = Environment.GetEnvironmentVariable("PDF_OUTPUT_DIRECTORY");
102+
if (string.IsNullOrWhiteSpace(pdfOutputDirectory))
103+
{
104+
pdfOutputDirectory = Path.Combine(Path.GetTempPath(), "html-renderer-pdf-artifacts");
105+
}
106+
107+
Directory.CreateDirectory(pdfOutputDirectory);
108+
109+
var pdfPath = Path.Combine(
110+
pdfOutputDirectory,
111+
$"{nameof(GeneratePdf_FromHtml_WithMultipleFonts_CreatesPdfDocument)}-{GetPlatformName()}.pdf");
112+
File.WriteAllBytes(pdfPath, pdf);
113+
}
114+
115+
private static void OnImageLoadPdfSharp(object? sender, HtmlImageLoadEventArgs e)
116+
{
117+
if (!string.Equals(e.Src, "ImageIcon", StringComparison.OrdinalIgnoreCase))
118+
{
119+
return;
120+
}
121+
122+
using var imageStream = DemoUtils.GetImageStream(e.Src);
123+
if (imageStream == null)
124+
{
125+
throw new InvalidOperationException("Expected demo image resource was not found.");
126+
}
127+
128+
e.Callback(XImage.FromStream(imageStream));
129+
}
130+
131+
private static string GetPlatformName()
132+
{
133+
if (OperatingSystem.IsWindows())
134+
{
135+
return "windows";
136+
}
137+
138+
if (OperatingSystem.IsMacOS())
139+
{
140+
return "macos";
141+
}
142+
143+
if (OperatingSystem.IsLinux())
144+
{
145+
return "linux";
146+
}
147+
148+
return RuntimeInformation.RuntimeIdentifier;
149+
}
150+
}

0 commit comments

Comments
 (0)