@@ -3,9 +3,11 @@ const fs = require("fs");
33const pdfjsLib = require ( "pdfjs-dist/legacy/build/pdf.js" ) ;
44const { PNG } = require ( "pngjs" ) ;
55const sharp = require ( "sharp" ) ;
6- const pdfParse = require ( "pdf-parse" ) ;
76
8- const pdfParseFn = typeof pdfParse === "function" ? pdfParse : pdfParse . default ;
7+ // Define missing DOMMatrix in Node context (for pdfjs)
8+ if ( typeof global . DOMMatrix === "undefined" ) {
9+ global . DOMMatrix = class DOMMatrix { } ;
10+ }
911
1012module . exports = defineConfig ( {
1113 e2e : {
@@ -20,117 +22,98 @@ module.exports = defineConfig({
2022 watchForFileChanges : true ,
2123 video : true ,
2224 setupNodeEvents ( on , config ) {
23- //Task: checks if the PDF contains embedded images and verifies logo existence and text content
25+ // ✅ Task: verify PDF images and logo
2426 on ( "task" , {
25- // --- Check if PDF contains any image ---
2627 async verifyPdf ( { filePath, options = { } } ) {
27- // options: { referenceLogoPath: string, checkText: true/false }
28- try {
29- if ( typeof global . DOMMatrix === "undefined" ) {
30- global . DOMMatrix = class DOMMatrix { } ;
31- }
28+ // options: { referenceLogoPath: string }
29+
30+ // Load PDF
31+ const data = new Uint8Array ( fs . readFileSync ( filePath ) ) ;
32+ const pdfDoc = await pdfjsLib . getDocument ( { data } ) . promise ;
33+
34+ // Import pixelmatch only if logo check is needed
35+ let pixelmatch ;
36+ const doLogoCheck = ! ! options . referenceLogoPath ;
37+ if ( doLogoCheck ) {
38+ const pm = await import ( "pixelmatch" ) ;
39+ pixelmatch = pm . default ;
40+ }
3241
33- // PDF loading
34- const data = new Uint8Array ( fs . readFileSync ( filePath ) ) ;
35- const pdfDoc = await pdfjsLib . getDocument ( { data } ) . promise ;
42+ let hasImage = false ;
43+ let logoFound = false ;
44+
45+ for ( let p = 1 ; p <= pdfDoc . numPages ; p ++ ) {
46+ const page = await pdfDoc . getPage ( p ) ;
47+ const ops = await page . getOperatorList ( ) ;
48+
49+ for ( let i = 0 ; i < ops . fnArray . length ; i ++ ) {
50+ const fn = ops . fnArray [ i ] ;
51+ const args = ops . argsArray [ i ] ;
52+
53+ // --- Image check ---
54+ if (
55+ fn === pdfjsLib . OPS . paintImageXObject ||
56+ fn === pdfjsLib . OPS . paintJpegXObject ||
57+ fn === pdfjsLib . OPS . paintInlineImageXObject
58+ ) {
59+ hasImage = true ;
60+
61+ if ( doLogoCheck && args [ 0 ] ) {
62+ const objName = args [ 0 ] ;
63+ const imgData = await page . objs . get ( objName ) ;
64+ if ( ! imgData ) {
65+ continue ;
66+ }
3667
37- // Dynamic import pixelmatch if logo check is needed
38- let pixelmatch ;
39- const doLogoCheck = ! ! options . referenceLogoPath ;
40- if ( doLogoCheck ) {
41- const pm = await import ( "pixelmatch" ) ;
42- pixelmatch = pm . default ;
43- }
68+ const pdfImg = new PNG ( { width : imgData . width , height : imgData . height } ) ;
69+ pdfImg . data = imgData . data ;
4470
45- let hasImage = false ;
46- let logoFound = false ;
47- let extractedText = "" ;
48-
49- for ( let p = 1 ; p <= pdfDoc . numPages ; p ++ ) {
50- const page = await pdfDoc . getPage ( p ) ;
51-
52- // --- Text extraction ---
53- if ( options . checkText ) {
54- extractedText += await new Promise ( ( resolve , reject ) => {
55- extract ( filePath , ( err , pages ) => {
56- if ( err ) return reject ( err ) ;
57- resolve ( pages . join ( "\n" ) ) ;
58- } ) ;
59- } ) ;
60- }
71+ const pdfBuffer = PNG . sync . write ( pdfImg ) ;
72+ const refLogo = PNG . sync . read ( fs . readFileSync ( options . referenceLogoPath ) ) ;
73+
74+ const resizedPdfBuffer = await sharp ( pdfBuffer )
75+ . resize ( refLogo . width , refLogo . height )
76+ . png ( )
77+ . toBuffer ( ) ;
78+
79+ const resizedPdfImg = PNG . sync . read ( resizedPdfBuffer ) ;
6180
62- const ops = await page . getOperatorList ( ) ;
63-
64- for ( let i = 0 ; i < ops . fnArray . length ; i ++ ) {
65- const fn = ops . fnArray [ i ] ;
66- const args = ops . argsArray [ i ] ;
67-
68- // --- Image check ---
69- if (
70- fn === pdfjsLib . OPS . paintImageXObject ||
71- fn === pdfjsLib . OPS . paintJpegXObject ||
72- fn === pdfjsLib . OPS . paintInlineImageXObject
73- ) {
74- hasImage = true ;
75-
76- if ( doLogoCheck && args [ 0 ] ) {
77- const objName = args [ 0 ] ;
78- const imgData = await page . objs . get ( objName ) ;
79- if ( ! imgData ) continue ;
80-
81- const pdfImg = new PNG ( { width : imgData . width , height : imgData . height } ) ;
82- pdfImg . data = imgData . data ;
83-
84- // resize PDF image to reference logo size
85- const pdfBuffer = PNG . sync . write ( pdfImg ) ;
86- const refLogo = PNG . sync . read ( fs . readFileSync ( options . referenceLogoPath ) ) ;
87- const resizedPdfBuffer = await sharp ( pdfBuffer )
88- . resize ( refLogo . width , refLogo . height )
89- . png ( )
90- . toBuffer ( ) ;
91-
92- const resizedPdfImg = PNG . sync . read ( resizedPdfBuffer ) ;
93-
94- // pixelmatch
95- const diff = new PNG ( { width : refLogo . width , height : refLogo . height } ) ;
96- const mismatched = pixelmatch (
97- refLogo . data ,
98- resizedPdfImg . data ,
99- diff . data ,
100- refLogo . width ,
101- refLogo . height ,
102- { threshold : 0.1 }
103- ) ;
104-
105- if ( mismatched === 0 ) {
106- logoFound = true ;
107- break ;
108- }
81+ const diff = new PNG ( { width : refLogo . width , height : refLogo . height } ) ;
82+ const mismatched = pixelmatch (
83+ refLogo . data ,
84+ resizedPdfImg . data ,
85+ diff . data ,
86+ refLogo . width ,
87+ refLogo . height ,
88+ { threshold : 0.1 }
89+ ) ;
90+
91+ if ( mismatched === 0 ) {
92+ logoFound = true ;
93+ break ;
10994 }
11095 }
11196 }
112-
113- if ( ( doLogoCheck && logoFound ) || ( ! doLogoCheck && hasImage ) ) {
114- break ;
115- }
11697 }
11798
118- if ( doLogoCheck && ! logoFound ) {
119- throw new Error ( "Logo in PDF does not match reference image" ) ;
99+ if ( ( doLogoCheck && logoFound ) || ( ! doLogoCheck && hasImage ) ) {
100+ break ;
120101 }
102+ }
121103
122- return {
123- hasImage,
124- logoFound,
125- text : extractedText ,
126- numPages : pdfDoc . numPages
127- } ;
128- } catch ( err ) {
129- throw err ;
104+ if ( doLogoCheck && ! logoFound ) {
105+ throw new Error ( "Logo in PDF does not match reference image" ) ;
130106 }
131- }
107+
108+ return {
109+ hasImage,
110+ logoFound,
111+ numPages : pdfDoc . numPages
112+ } ;
113+ } ,
132114 } ) ;
133115
116+
134117 on ( "after:spec" , ( spec , results ) => {
135118 if ( results ?. video ) {
136119 const hasFailures = results . tests . some ( ( t ) => t . attempts . some ( ( a ) => a . state === "failed" ) ) ;
0 commit comments