-
Notifications
You must be signed in to change notification settings - Fork 21
Description
Background
I started encountering this issue recently - I'm using PlayWright and Mailpit to perform a PDF diff against PDF files sent as email attachments.
Will link relevant parts of the code here for now, can't provide a minimal reproduction base right now as I'm pressed for time but I will edit the issue description to link to a public repo that reproduces the issue in a bit.
Describing the issue now just in case it's easy to spot and fix on your end ⚡
Bug
When performing two diffs of the same PDF file from within a single PlayWright spec the PDF comparison fails for the 2nd diff due to the masks not being applied in the correct location.
// spec
...
// if I skip this test the 2nd comparison passes
test.skip('signer sees confirmation email with holiday letting agreement attached', async ({}, testInfo) => {
await signer.seesEmail({
subject: `Holiday Letting agreement - ${address}`,
specFile: testInfo.file,
pdfs: [pdfs.document],
masks: masks.document,
markAsRead: false
});
});
// if I skip this test and don't skip the above test, the 1st one passes
test('agent sees confirmation email with holiday letting agreement attached', async ({}, testInfo) => {
await agent.seesEmail({
subject: `Holiday Letting agreement - ${address}`,
specFile: testInfo.file,
pdfs: [pdfs.document],
masks: masks.document
});
});Here's the relevant part of the class method:
// Actor class
...
// do a PDF diff for each PDF attachment
if (pdfs.length > 0) {
const messageSummary = await getMail(message.ID);
const messageAttachments = messageSummary.Attachments;
for (const attachment of messageAttachments) {
const pdf = pdfs.find(pdf => this.#safeStringCompare(pdf, attachment.FileName));
// assert that we found a matching pdf based on the filename
expect(pdf).toBeDefined();
// assert that the attachment is indeed a PDF file
expect(attachment.ContentType).toBe('application/pdf');
// convert the pdf file name to a normalized string for the snapshot path
const pdfSafeName = this.#safeguardString(pdf);
// get the PDF buffer and perform a visual diff against our local snapshot
const buffer = await getMailAttachment(message.ID, attachment.PartID);
const result = await comparePdfs({ buffer, path: specPath, name: pdfSafeName, masks });
// expect the comparison to return true
expect(result).toBe(true);
}
}I know there's a lot of hidden logic here, what I can say with 100% certainty is that the PDF being used in each comparison is pulled from the exact same email - what happens is we send an email with that PDF to two recipients. The spec file simply does two comparisons because sometimes we send slightly different PDFs based on the recipient (which would be two different emails). In this case the agent and signer get the exact same copy.
I get these results:
Skipping either of those two comparisons causes the other to pass:

Misc
I didn't go to deep into the pdf-diff code. I get the feeling there is something about how the PDF canvas is cleaning up that causes the masks to be applied in the wrong location on the 2nd comparison, I inserted a hard coded 30 second wait before doing the 2nd comparison and got the same result, so it doesn't seem like it's a race condition.
The error might actually be coming from a dependency and not this module itself, will move this report there if that's the case.
Expected Behaviour
Doing multiple PDF comparisons in a single spec file should apply the masks consistently.


