Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 128 additions & 42 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,6 @@ Other [compares](https://github.com/VerifyTests/Verify/blob/main/docs/comparer.m
* https://github.com/VerifyTests/Verify.ImageSharp.Compare


### Outputs

`Initialize` accepts an optional `QuestPdfOutputs` to control which outputs a document is split into:

* `Png`: render each page to a png. When omitted, pages are not rasterized at all.
* `None`: none of the above. Only the info and the source document are emitted.
* `All`: the default.

The pdf target is not controlled by this setting. Use `VerifierSettings.ExcludeTargets("pdf")` to exclude it.

<!-- snippet: InitializeOutputs -->
<a id='snippet-InitializeOutputs'></a>
```cs
[ModuleInitializer]
public static void Init()
{
QuestPDF.Settings.License = LicenseType.Community;
// Skip rendering pages to png
VerifyQuestPdf.Initialize(QuestPdfOutputs.None);
}
```
<sup><a href='/src/StaticSettingsTests/ModuleInitializer.cs#L3-L13' title='Snippet source file'>snippet source</a> | <a href='#snippet-InitializeOutputs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

### Code that generates a document

<!-- snippet: GenerateDocument -->
Expand Down Expand Up @@ -115,7 +91,7 @@ static void AddPage(PageDescriptor page)
});
}
```
<sup><a href='/src/Tests/Samples.cs#L95-L128' title='Snippet source file'>snippet source</a> | <a href='#snippet-GenerateDocument' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/Samples.cs#L107-L140' title='Snippet source file'>snippet source</a> | <a href='#snippet-GenerateDocument' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand All @@ -137,33 +113,87 @@ public Task VerifyDocument()

### Results

Verifying a document produces:

* The pdf itself as `.verified.pdf`. This can be omitted with [`ExcludeTargets`](#exclude-the-pdf).
* An info file as `.verified.txt`, with the metadata and settings of the document and its page count.
* A png of every page as `#page_0001.verified.png`, `#page_0002.verified.png`, etc. These can be omitted with [`ExcludeDerivedTargets`](#exclude-the-page-images).

The page files are named by Verify's [paged documents](https://github.com/VerifyTests/Verify/blob/main/docs/paged-documents.md) support, which every Verify plugin that splits a document into pages shares. So are the settings that [choose what is verified](#choosing-what-is-verified).


#### Metadata

<!-- snippet: Samples.VerifyDocument.verified.txt -->
<a id='snippet-Samples.VerifyDocument.verified.txt'></a>
```txt
{
Pages: 2,
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
Document: {
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
},
PageCount: 2
}
```
<sup><a href='/src/Tests/Samples.VerifyDocument.verified.txt#L1-L10' title='Snippet source file'>snippet source</a> | <a href='#snippet-Samples.VerifyDocument.verified.txt' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/Samples.VerifyDocument.verified.txt#L1-L12' title='Snippet source file'>snippet source</a> | <a href='#snippet-Samples.VerifyDocument.verified.txt' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


#### Pdf as image

<img src="src/Tests/Samples.VerifyDocument%2300.verified.png" width="300px">
<img src="src/Tests/Samples.VerifyDocument%23page_0001.verified.png" width="300px">


## Choosing what is verified

What a document is split into is controlled by Verify's settings for [paged documents](https://github.com/VerifyTests/Verify/blob/main/docs/paged-documents.md). Each can be set on a verification, or for every test on `VerifierSettings` at initialization.

No text is read from a document, so `PageText` has no effect.


## Exclude the pdf
### Exclude the page images

`ExcludeDerivedTargets("png")` leaves out the png of every page, keeping the pdf and the info file. Rasterizing pages is expensive, and it is then skipped altogether:

<!-- snippet: ExcludePng -->
<a id='snippet-ExcludePng'></a>
```cs
[Test]
public Task ExcludePng()
{
var document = GenerateDocument();
return Verify(document)
.ExcludeDerivedTargets("png");
}
```
<sup><a href='/src/Tests/Samples.cs#L71-L81' title='Snippet source file'>snippet source</a> | <a href='#snippet-ExcludePng' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

To leave out the page images for every test:

<!-- snippet: InitializeOutputs -->
<a id='snippet-InitializeOutputs'></a>
```cs
[ModuleInitializer]
public static void Init()
{
QuestPDF.Settings.License = LicenseType.Community;
VerifyQuestPdf.Initialize();

// For every test: no page images, so pages are not rendered to png
VerifierSettings.ExcludeDerivedTargets("png");
}
```
<sup><a href='/src/StaticSettingsTests/ModuleInitializer.cs#L3-L15' title='Snippet source file'>snippet source</a> | <a href='#snippet-InitializeOutputs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


### Exclude the pdf

QuestPDF renders the source pdf, and it is included in the snapshot as a `.verified.pdf`. Generating it is expensive, and committing it is not always wanted. [`ExcludeTargets`](https://github.com/VerifyTests/Verify/blob/main/docs/converter.md#excluding-targets) drops it from a verification and skips the generation, while the rendered pages and info still verify:

Expand All @@ -184,9 +214,9 @@ public Task ExcludePdf()
To exclude the pdf for every test, call `VerifierSettings.ExcludeTargets("pdf")` at initialization.


## PagesToInclude
### PagesToInclude

To render only a defined number of pages at the start of a document:
To verify only a defined number of pages at the start of a document:

<!-- snippet: PagesToInclude -->
<a id='snippet-PagesToInclude'></a>
Expand All @@ -199,13 +229,15 @@ public Task PagesToInclude()
.PagesToInclude(1);
}
```
<sup><a href='/src/Tests/Samples.cs#L71-L81' title='Snippet source file'>snippet source</a> | <a href='#snippet-PagesToInclude' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/Samples.cs#L83-L93' title='Snippet source file'>snippet source</a> | <a href='#snippet-PagesToInclude' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

The pdf is still verified whole, and `PageCount` in the info file is still the number of pages the document has.


### Dynamic
#### Dynamic

To dynamically control what pages are rendered:
To dynamically control what pages are verified, pass a delegate that takes the 1 based number of a page:

<!-- snippet: PagesToIncludeDynamic -->
<a id='snippet-PagesToIncludeDynamic'></a>
Expand All @@ -218,5 +250,59 @@ public Task PagesToIncludeDynamic()
.PagesToInclude(pageNumber => pageNumber == 2);
}
```
<sup><a href='/src/Tests/Samples.cs#L83-L93' title='Snippet source file'>snippet source</a> | <a href='#snippet-PagesToIncludeDynamic' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/Samples.cs#L95-L105' title='Snippet source file'>snippet source</a> | <a href='#snippet-PagesToIncludeDynamic' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

A page keeps its number when other pages are left out. The above verifies the second page as `#page_0002.verified.png`.

QuestPDF draws all the pages of a document in one pass, so the pages that are left out are still rendered. `PagesToInclude` limits what is verified, not the work done.


## Reviewing changes

A change to a document is a change to several files: the pdf, its info file, and every page. Verify tells the diff tool that the pages and the info file were derived from the pdf, and [DiffEngineViewer](https://github.com/VerifyTests/DiffEngine/blob/main/docs/viewer.md#files-derived-from-a-document), which draws a pdf's pages itself, shows them as one row and accepts them together. Other diff tools are given each file, as before.

When the pdf has changed, its pages are compared exactly, skipping any [comparer](https://github.com/VerifyTests/Verify/blob/main/docs/comparer.md) registered for `png`. A comparer exists to tolerate rendering differences, and a pdf that has changed is the one case where its pages should not be given the benefit of the doubt.


## Migrating from 2.x

Version 3 moves to the paged document support in Verify 33.3. The settings for choosing what is verified are now those of Verify:

| 2.x | 3.x |
| --- | --- |
| `VerifyQuestPdf.Initialize(QuestPdfOutputs.None)` | `VerifyQuestPdf.Initialize()` and `VerifierSettings.ExcludeDerivedTargets("png")` |
| `VerifyQuestPdf.Initialize(QuestPdfOutputs.Png)` or `QuestPdfOutputs.All` | `VerifyQuestPdf.Initialize()` |
| `.PagesToInclude(2)` | Unchanged. It is now a member of `VerifySettings` and `SettingsTask`, and of `VerifierSettings` for every test |
| `.PagesToInclude(pageNumber => pageNumber == 2)` | Unchanged for a lambda. The delegate `VerifyQuestPDF.ShouldIncludePage` is replaced by `VerifyTests.IncludePage` |

The page images are renamed. The number of a page is now 1 based, is always present, and is the number the page has in the document:

| 2.x | 3.x |
| --- | --- |
| `Tests.Report#00.verified.png` | `Tests.Report#page_0001.verified.png` |
| `Tests.Report#01.verified.png` | `Tests.Report#page_0002.verified.png` |
| `Tests.Report.verified.png` for a document with one page | `Tests.Report#page_0001.verified.png` |
| `Tests.Report.verified.png` for `PagesToInclude(pageNumber => pageNumber == 2)` | `Tests.Report#page_0002.verified.png` |
| `Tests.Report.verified.pdf` | Unchanged |
| `Tests.Report.verified.txt` | The same name, with the content below |

In 2.x the pages `PagesToInclude` kept were numbered again from zero, so the name of a page file depended on which other pages were verified.

The info file has the shape every paged document has: the metadata and settings under `Document`, and `Pages` as `PageCount`.

```
{ {
Pages: 2, Document: {
Metadata: { Metadata: {
Title: The Title Title: The Title
}, },
Settings: { Settings: {
ContentDirection: LeftToRight ContentDirection: LeftToRight
} }
} },
PageCount: 2
}
```

Renamed snapshots show as a new file and a pending delete. Accepting both, or running once with [AutoVerify](https://github.com/VerifyTests/Verify/blob/main/docs/autoverify.md), moves a test over.
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project>
<PropertyGroup>
<NoWarn>CS1591;CS0649;NU1608;NU1109</NoWarn>
<Version>2.10.0</Version>
<Version>3.0.0</Version>
<AssemblyVersion>1.0.0</AssemblyVersion>
<LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down
6 changes: 3 additions & 3 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
<PackageVersion Include="DeterministicPdf" Version="2.1.0" />
<PackageVersion Include="QuestPDF" Version="2026.9.1" />
<PackageVersion Include="Sbom" Version="0.3.1" />
<PackageVersion Include="Verify" Version="33.2.0" />
<PackageVersion Include="Verify" Version="33.3.0" />
<PackageVersion Include="TUnit" Version="1.72.16" />
<PackageVersion Include="Verify.TUnit" Version="33.2.0" />
<PackageVersion Include="Verify.TUnit" Version="33.3.0" />
<PackageVersion Include="Argon" Version="0.37.0" />
<PackageVersion Include="DiffEngine" Version="20.6.0" />
<PackageVersion Include="DiffEngine" Version="20.7.0" />
<PackageVersion Include="EmptyFiles" Version="8.20.0" />
<PackageVersion Include="SimpleInfoName" Version="3.2.0" />
</ItemGroup>
Expand Down
6 changes: 4 additions & 2 deletions src/StaticSettingsTests/ModuleInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ public static class ModuleInitializer
public static void Init()
{
QuestPDF.Settings.License = LicenseType.Community;
// Skip rendering pages to png
VerifyQuestPdf.Initialize(QuestPdfOutputs.None);
VerifyQuestPdf.Initialize();

// For every test: no page images, so pages are not rendered to png
VerifierSettings.ExcludeDerivedTargets("png");
}

#endregion
Expand Down
18 changes: 10 additions & 8 deletions src/StaticSettingsTests/Tests.VerifyDocument.verified.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
Pages: 2,
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
Document: {
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
},
PageCount: 2
}
Binary file removed src/Tests/Samples.ExcludePdf#00.verified.png
Binary file not shown.
Binary file removed src/Tests/Samples.ExcludePdf#01.verified.png
Binary file not shown.
18 changes: 10 additions & 8 deletions src/Tests/Samples.ExcludePdf.verified.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
Pages: 2,
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
Document: {
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
},
PageCount: 2
}
Binary file added src/Tests/Samples.ExcludePng.verified.pdf
Binary file not shown.
12 changes: 12 additions & 0 deletions src/Tests/Samples.ExcludePng.verified.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
Document: {
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
},
PageCount: 2
}
18 changes: 10 additions & 8 deletions src/Tests/Samples.PagesToInclude.verified.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
Pages: 2,
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
Document: {
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
},
PageCount: 2
}
18 changes: 10 additions & 8 deletions src/Tests/Samples.PagesToIncludeDynamic.verified.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
Pages: 2,
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
Document: {
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
},
PageCount: 2
}
18 changes: 10 additions & 8 deletions src/Tests/Samples.SkipPdfNormalization.verified.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
Pages: 2,
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
Document: {
Settings: {
ContentDirection: LeftToRight,
PDFA_Conformance: None,
PDFUA_Conformance: None,
ImageCompressionQuality: High,
ImageRasterDpi: 288
}
},
PageCount: 2
}
Loading
Loading