diff --git a/tests/unit/acroform.spec.js b/tests/unit/acroform.spec.js index f6f120c..8b4e50a 100644 --- a/tests/unit/acroform.spec.js +++ b/tests/unit/acroform.spec.js @@ -4,26 +4,20 @@ import { logData } from './helpers'; import PDFFontFactory from '../../lib/font_factory'; import fs from 'fs' -const ESC = [ - [/\//g, '\\\/'], - [/\(/g, '\\\('], - [/\)/g, '\\\)'] -]; - // manual mock for PDFSecurity to ensure stored id will be the same accross different systems PDFSecurity.generateFileID = () => { return new Buffer('mocked-pdf-id'); }; -function joinTokens (arr) { - if (Array.isArray(arr)) { - let a = arr.map(i => { - return i.replace(ESC[0][0], ESC[0][1]).replace(ESC[1][0], ESC[1][1]).replace(ESC[2][0], ESC[2][1]); - }) - let b = [].concat(['^'], a, ['$']); - return new RegExp(b.join('\\s*')); - } - return arr; +function escapeRegExp (string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +function joinTokens (...args) { + let a = args.map(i => escapeRegExp(i)); + let r = new RegExp('^' + a.join('\\s*') + '$'); + console.log(r) + return r; } describe('AcroForm', () => { @@ -38,9 +32,8 @@ describe('AcroForm', () => { test('named JavaScript', () => { const expected = [ '2 0 obj', - /.*/, // '<<\n/Dests <<\n/Names []\n>>\n/JavaScript <<\n/Names [\n(name1) <<\n/JS (my javascript goes here)\n/S /JavaScript\n>>\n]\n>>\n>>', - // joinTokens(['<<', '/Dests', '<<', '/Names', '[', ']', '>>', '/JavaScript', '<<', '/Names', '[', '(name1)', '<<', '/JS', '(my javascript goes here)', '/S', '/JavaScript', '>>', ']', '>>', '>>']), + joinTokens('<<', '/Dests', '<<', '/Names', '[', ']', '>>', '/JavaScript', '<<', '/Names', '[', '(name1)', '<<', '/JS', '(my javascript goes here)', '/S', '/JavaScript', '>>', ']', '>>', '>>'), 'endobj' ]; const docData = logData(doc); @@ -50,123 +43,116 @@ describe('AcroForm', () => { expect(docData).toContainChunk(expected); }) - describe('init', () => { - test('no fonts', () => { - doc.addPage(); - const docData = logData(doc); - const font = PDFFontFactory.open( - doc, - 'tests/fonts/Roboto-Regular.ttf' - ); - doc.initAcroForm(); - expect(docData.length).toBe(0); - }); + test('init no fonts', () => { + doc.addPage(); + const docData = logData(doc); + const font = PDFFontFactory.open( + doc, + 'tests/fonts/Roboto-Regular.ttf' + ); + doc.initAcroForm(); + expect(docData.length).toBe(0); + }); - test('push button', () => { - const expected = [ - '10 0 obj', - '<<\n/FT /Btn\n/Ff 65536\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/MK <<\n/CA (Test Button)\n/BG [1 1 0]\n>>\n/T (btn1)\n/Subtype /Widget\n/F 4\n/Type /Annot\n/Rect [20 742 120 772]\n>>', - 'endobj' - ]; + test('init standard fonts', () => { + const expected = [ + '12 0 obj', + joinTokens('<<', '/FT', '/Tx', '/Ff', '4096', '/DR', '<<', '/Font', '<<', '/F3', '10 0 R', '>>', '>>', '/T', '(file0)', '/Subtype', '/Widget', '/F', '4', '/Type', '/Annot', '/Rect', '[10 292 602 692]', '>>'), + 'endobj' + ]; - doc.initAcroForm(); - const docData = logData(doc); - let opts = { - backgroundColor: 'yellow', - label: 'Test Button', - }; - doc.formPushButton('btn1', 20, 20, 100, 30, opts); - expect(docData.length).toBe(3); - expect(docData[0]).toBe(expected[0]); - expect(docData[1]).toBe(expected[1]); - expect(docData[2]).toBe(expected[2]); - }); + const docData = logData(doc); + doc.registerFont('myfont1', 'tests/fonts/Roboto-Regular.ttf') - test('standard fonts', () => { - const expected = [ - '12 0 obj', - /.*/, - // ['<<', '/FT', '/Tx', '/Ff', '4096', '/DR', '<<', '/Font', '<<', '/F3', '10 0 R', '>>', '>>', '/T', '(file0)', '/Subtype', '/Widget', '/F4', '/Type', '/Annot', '/Rect', '[10 292 602 692]', '>>'], - 'endobj' - ]; + doc.font('Courier-Bold') // establishes the default font + doc.initAcroForm() - const docData = logData(doc); + doc.font('myfont1') + .fontSize(25) + .text('Test Doc', 0, 20, { width: 612, align: 'center' }); + doc.font('Courier') + .fontSize(16) + .text('Courier subheading', 0, 50, { width: 612, align: 'center' }); - doc.registerFont('myfont1', 'tests/fonts/Roboto-Regular.ttf') + doc.font('myfont1').formText('file0', 10, 100, 592, 400, { multiline: true }); - doc.font('Courier-Bold') // establishes the default font - doc.initAcroForm() + expect(docData.length).toBe(3); + expect(docData).toContainChunk(expected) + }); - doc.font('myfont1') - .fontSize(25) - .text('Test Doc', 0, 20, { width: 612, align: 'center' }); - doc.font('Courier') - .fontSize(16) - .text('Courier subheading', 0, 50, { width: 612, align: 'center' }); + test('push button', () => { + const expected = [ + '10 0 obj', + '<<\n/FT /Btn\n/Ff 65536\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/MK <<\n/CA (Test Button)\n/BG [1 1 0]\n>>\n/T (btn1)\n/Subtype /Widget\n/F 4\n/Type /Annot\n/Rect [20 742 120 772]\n>>', + 'endobj' + ]; + doc.initAcroForm(); + const docData = logData(doc); + let opts = { + backgroundColor: 'yellow', + label: 'Test Button', + }; + doc.formPushButton('btn1', 20, 20, 100, 30, opts); + expect(docData.length).toBe(3); + expect(docData[0]).toBe(expected[0]); + expect(docData[1]).toBe(expected[1]); + expect(docData[2]).toBe(expected[2]); + }); - doc.font('myfont1').formText('file0', 10, 100, 592, 400, { multiline: true }); + test('field heirarchy', () => { - expect(docData.length).toBe(3); - for (let idx = 0; idx < expected.length; ++idx) { - expect(docData[idx]).toMatch(joinTokens(expected[idx])) - } - }); + const expected = [ + "13 0 obj", + '<<\n/Parent 11 0 R\n/FT /Tx\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (leaf1)\n/Subtype /Widget\n/F 4\n/Type /Annot\n/Rect [10 742 210 782]\n>>', + "endobj", + '14 0 obj', + '<<\n/Parent 11 0 R\n/FT /Tx\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (leaf2)\n/Subtype /Widget\n/F 4\n/Type /Annot\n/Rect [10 692 210 732]\n>>', + 'endobj', + '15 0 obj', + '<<\n/Parent 12 0 R\n/FT /Tx\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (leaf3)\n/Subtype /Widget\n/F 4\n/Type /Annot\n/Rect [10 642 210 682]\n>>', + 'endobj' + ]; + const expected2 = [ + '11 0 obj', + '<<\n/Parent 10 0 R\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (child1Field)\n/Kids [13 0 R 14 0 R]\n>>', + 'endobj', + '12 0 obj', + '<<\n/Parent 10 0 R\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (child2Field)\n/Kids [15 0 R]\n>>', + 'endobj', + '10 0 obj', + '<<\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (rootField)\n/Kids [11 0 R 12 0 R]\n>>', + 'endobj', + '9 0 obj', + '<<\n/Fields [10 0 R]\n/NeedAppearances true\n/DA (/F1 0 Tf 0 g)\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n>>', + 'endobj', + ]; - test('field heirarchy', () => { + const docData = logData(doc); - const expected = [ - "13 0 obj", - '<<\n/Parent 11 0 R\n/FT /Tx\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (leaf1)\n/Subtype /Widget\n/F 4\n/Type /Annot\n/Rect [10 742 210 782]\n>>', - "endobj", - '14 0 obj', - '<<\n/Parent 11 0 R\n/FT /Tx\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (leaf2)\n/Subtype /Widget\n/F 4\n/Type /Annot\n/Rect [10 692 210 732]\n>>', - 'endobj', - '15 0 obj', - '<<\n/Parent 12 0 R\n/FT /Tx\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (leaf3)\n/Subtype /Widget\n/F 4\n/Type /Annot\n/Rect [10 642 210 682]\n>>', - 'endobj' - ]; - const expected2 = [ - '11 0 obj', - '<<\n/Parent 10 0 R\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (child1Field)\n/Kids [13 0 R 14 0 R]\n>>', - 'endobj', - '12 0 obj', - '<<\n/Parent 10 0 R\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (child2Field)\n/Kids [15 0 R]\n>>', - 'endobj', - '10 0 obj', - '<<\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n/T (rootField)\n/Kids [11 0 R 12 0 R]\n>>', - 'endobj', - '9 0 obj', - '<<\n/Fields [10 0 R]\n/NeedAppearances true\n/DA (/F1 0 Tf 0 g)\n/DR <<\n/Font <<\n/F1 8 0 R\n>>\n>>\n>>', - 'endobj', - ]; + doc.font('Helvetica') // establishes the default font + doc.initAcroForm() - const docData = logData(doc); + let rootField = doc.field('rootField'); + let child1Field = doc.field('child1Field', { Parent: rootField }); + let child2Field = doc.field('child2Field', { Parent: rootField }); + doc.formText('leaf1', 10, 10, 200, 40, { Parent: child1Field }) + doc.formText('leaf2', 10, 60, 200, 40, { Parent: child1Field }) + doc.formText('leaf3', 10, 110, 200, 40, { Parent: child2Field }) - doc.font('Helvetica') // establishes the default font - doc.initAcroForm() + expect(docData.length).toBe(expected.length); + for (let idx = 0; idx < expected.length; ++idx) { + expect(docData[idx]).toBe(expected[idx]) + } - let rootField = doc.field('rootField'); - let child1Field = doc.field('child1Field', { Parent: rootField }); - let child2Field = doc.field('child2Field', { Parent: rootField }); - doc.formText('leaf1', 10, 10, 200, 40, { Parent: child1Field }) - doc.formText('leaf2', 10, 60, 200, 40, { Parent: child1Field }) - doc.formText('leaf3', 10, 110, 200, 40, { Parent: child2Field }) + doc.end(); - expect(docData.length).toBe(expected.length); - for (let idx = 0; idx < expected.length; ++idx) { - expect(docData[idx]).toBe(expected[idx]) - } - - doc.end(); - - for (let idx = 0; idx < docData.length; ++idx) { - if (docData[idx] === expected2[0]) { - for (let jdx = 0; jdx < expected2.length; ++jdx) { - expect(docData[idx + jdx]).toBe(expected2[jdx]) - } + for (let idx = 0; idx < docData.length; ++idx) { + if (docData[idx] === expected2[0]) { + for (let jdx = 0; jdx < expected2.length; ++jdx) { + expect(docData[idx + jdx]).toBe(expected2[jdx]) } } - }); + } }); });