-
-
Notifications
You must be signed in to change notification settings - Fork 184
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
170 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,26 @@ | ||
import {PDFDocument} from 'pdf-lib'; | ||
import { | ||
PDFArray, PDFDict, PDFDocument, PDFName, PDFString, | ||
} from 'pdf-lib'; | ||
import {readTestResource} from '@signpdf/internal-utils'; | ||
import {SUBFILTER_ETSI_CADES_DETACHED} from '@signpdf/utils'; | ||
import {DEFAULT_BYTE_RANGE_PLACEHOLDER, SUBFILTER_ETSI_CADES_DETACHED} from '@signpdf/utils'; | ||
import {pdflibAddPlaceholder} from './pdflibAddPlaceholder'; | ||
|
||
describe(pdflibAddPlaceholder, () => { | ||
const defaults = { | ||
reason: 'Because I can', | ||
contactInfo: '[email protected]', | ||
name: 'test name', | ||
location: 'test Location', | ||
}; | ||
|
||
it('adds placeholder to a prepared document', async () => { | ||
const input = readTestResource('w3dummy.pdf'); | ||
expect(input.indexOf('/ByteRange')).toBe(-1); | ||
const pdfDoc = await PDFDocument.load(input); | ||
|
||
pdflibAddPlaceholder({ | ||
pdfDoc, | ||
reason: 'Because I can', | ||
location: 'some place', | ||
name: 'example name', | ||
contactInfo: '[email protected]', | ||
...defaults, | ||
}); | ||
// Convert the PDFDocument to bytes | ||
const pdfBytes = await pdfDoc.save({useObjectStreams: false}); | ||
|
@@ -34,10 +40,7 @@ describe(pdflibAddPlaceholder, () => { | |
|
||
pdflibAddPlaceholder({ | ||
pdfDoc, | ||
reason: 'Because I can', | ||
location: 'some place', | ||
name: 'example name', | ||
contactInfo: '[email protected]', | ||
...defaults, | ||
subFilter: SUBFILTER_ETSI_CADES_DETACHED, | ||
}); | ||
// Convert the PDFDocument to bytes | ||
|
@@ -48,4 +51,161 @@ describe(pdflibAddPlaceholder, () => { | |
expect(buffer).toBeInstanceOf(Buffer); | ||
expect(buffer.indexOf(`/SubFilter /${SUBFILTER_ETSI_CADES_DETACHED}`)).not.toBe(-1); | ||
}); | ||
|
||
it('placeholder contains reason, contactInfo, name, location', async () => { | ||
const input = readTestResource('w3dummy.pdf'); | ||
expect(input.indexOf('/ByteRange')).toBe(-1); | ||
const pdfDoc = await PDFDocument.load(input); | ||
|
||
pdflibAddPlaceholder({ | ||
pdfDoc, | ||
...defaults, | ||
}); | ||
|
||
/** | ||
* @type {PDFArray} | ||
*/ | ||
const annots = pdfDoc.getPage(0).node.lookup(PDFName.of('Annots')); | ||
|
||
/** | ||
* @type {PDFDict} | ||
*/ | ||
const widget = annots.lookup(annots.size() - 1, PDFDict); | ||
|
||
/** | ||
* @type {PDFDict} | ||
*/ | ||
const widgetData = widget.lookup(PDFName.of('V')); | ||
|
||
expect(widget.get(PDFName.of('Subtype'))).toEqual(PDFName.of('Widget')); | ||
expect(widgetData.get(PDFName.of('Reason'))).toEqual(PDFString.of(defaults.reason)); | ||
expect(widgetData.get(PDFName.of('ContactInfo'))).toEqual(PDFString.of(defaults.contactInfo)); | ||
expect(widgetData.get(PDFName.of('Location'))).toEqual(PDFString.of(defaults.location)); | ||
expect(widgetData.get(PDFName.of('Name'))).toEqual(PDFString.of(defaults.name)); | ||
}); | ||
|
||
it('sets the widget rectange to invisible by default', async () => { | ||
const input = readTestResource('w3dummy.pdf'); | ||
expect(input.indexOf('/ByteRange')).toBe(-1); | ||
const pdfDoc = await PDFDocument.load(input); | ||
|
||
pdflibAddPlaceholder({ | ||
pdfDoc, | ||
...defaults, | ||
}); | ||
|
||
/** | ||
* @type {PDFArray} | ||
*/ | ||
const annots = pdfDoc.getPage(0).node.lookup(PDFName.of('Annots')); | ||
|
||
/** | ||
* @type {PDFDict} | ||
*/ | ||
const widget = annots.lookup(annots.size() - 1, PDFDict); | ||
|
||
/** | ||
* @type {PDFArray} | ||
*/ | ||
const rect = widget.get(PDFName.of('Rect')); | ||
expect(rect).toBeInstanceOf(PDFArray); | ||
expect(rect.toString()).toEqual('[ 0 0 0 0 ]'); | ||
}); | ||
|
||
it('allows defining widget rectange', async () => { | ||
const input = readTestResource('w3dummy.pdf'); | ||
expect(input.indexOf('/ByteRange')).toBe(-1); | ||
const pdfDoc = await PDFDocument.load(input); | ||
const widgetRect = [100, 100, 200, 200]; | ||
|
||
pdflibAddPlaceholder({ | ||
pdfDoc, | ||
...defaults, | ||
widgetRect, | ||
}); | ||
|
||
/** | ||
* @type {PDFArray} | ||
*/ | ||
const annots = pdfDoc.getPage(0).node.lookup(PDFName.of('Annots')); | ||
|
||
/** | ||
* @type {PDFDict} | ||
*/ | ||
const widget = annots.lookup(annots.size() - 1, PDFDict); | ||
|
||
/** | ||
* @type {PDFArray} | ||
*/ | ||
const rect = widget.get(PDFName.of('Rect')); | ||
expect(rect).toBeInstanceOf(PDFArray); | ||
expect(rect.toString()).toEqual('[ 100 100 200 200 ]'); | ||
}); | ||
|
||
it('does not overwrite the AcroForm when it was already there', async () => { | ||
const input = readTestResource('signed-once.pdf'); | ||
expect(input.indexOf('/ByteRange')).not.toBe(-1); | ||
const pdfDoc = await PDFDocument.load(input); | ||
const existingAcroFormTag = pdfDoc.catalog.get(PDFName.of('AcroForm')).tag; | ||
|
||
pdflibAddPlaceholder({ | ||
pdfDoc, | ||
...defaults, | ||
}); | ||
|
||
const newAcroFormRef = pdfDoc.catalog.get(PDFName.of('AcroForm')); | ||
expect(newAcroFormRef.tag).toBe(existingAcroFormTag); | ||
}); | ||
|
||
it('does not overwrite page annotations when there already were some', async () => { | ||
const input = readTestResource('signed-once.pdf'); | ||
expect(input.indexOf('/ByteRange')).not.toBe(-1); | ||
const pdfDoc = await PDFDocument.load(input); | ||
const existingAnnotations = pdfDoc | ||
.getPage(0).node | ||
.lookup(PDFName.of('Annots'), PDFArray) | ||
.asArray().map((v) => v.toString()); | ||
|
||
pdflibAddPlaceholder({ | ||
pdfDoc, | ||
...defaults, | ||
}); | ||
|
||
const newAnnotations = pdfDoc | ||
.getPage(0).node | ||
.lookup(PDFName.of('Annots'), PDFArray) | ||
.asArray().map((v) => v.toString()); | ||
expect(newAnnotations).toEqual(expect.arrayContaining(existingAnnotations)); | ||
expect(newAnnotations).toHaveLength(existingAnnotations.length + 1); | ||
}); | ||
|
||
it('adds placeholder to PDFDocument document when AcroForm is already there', async () => { | ||
const input = readTestResource('signed-once.pdf'); | ||
expect(input.indexOf('/ByteRange')).not.toBe(-1); | ||
const pdfDoc = await PDFDocument.load(input); | ||
|
||
pdflibAddPlaceholder({ | ||
pdfDoc, | ||
...defaults, | ||
}); | ||
|
||
const annotations = pdfDoc | ||
.getPage(0).node | ||
.lookup(PDFName.of('Annots'), PDFArray); | ||
const widgetDict = annotations.lookup(annotations.size() - 1, PDFDict); | ||
expect(widgetDict.get(PDFName.of('Subtype'))).toEqual(PDFName.of('Widget')); | ||
|
||
const byteRange = widgetDict | ||
.lookup(PDFName.of('V'), PDFDict) | ||
.lookup(PDFName.of('ByteRange'), PDFArray) | ||
.asArray() | ||
.map((v) => v.toString()); | ||
|
||
expect(byteRange).toEqual([ | ||
'0', | ||
PDFName.of(DEFAULT_BYTE_RANGE_PLACEHOLDER).asString(), | ||
PDFName.of(DEFAULT_BYTE_RANGE_PLACEHOLDER).asString(), | ||
PDFName.of(DEFAULT_BYTE_RANGE_PLACEHOLDER).asString(), | ||
]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,29 +36,6 @@ describe(pdfkitAddPlaceholder, () => { | |
it('placeholder contains reason, contactInfo, name, location', () => { | ||
const {pdf} = createPdfkitDocument(); | ||
|
||
const refs = pdfkitAddPlaceholder({ | ||
pdf, | ||
pdfBuffer: Buffer.from([pdf]), | ||
reason: 'test reason', | ||
...defaults, | ||
}); | ||
expect(Object.keys(refs)).toEqual(expect.arrayContaining([ | ||
'signature', | ||
'form', | ||
'widget', | ||
])); | ||
expect(pdf.page.dictionary.data.Annots).toHaveLength(1); | ||
expect(pdf.page.dictionary.data.Annots[0].data.Subtype).toEqual('Widget'); | ||
const widgetData = pdf.page.dictionary.data.Annots[0].data.V.data; | ||
expect(PDFObject.convert(widgetData.Reason)).toEqual('(test reason)'); | ||
expect(PDFObject.convert(widgetData.ContactInfo)).toEqual('([email protected])'); | ||
expect(PDFObject.convert(widgetData.Name)).toEqual('(test name)'); | ||
expect(PDFObject.convert(widgetData.Location)).toEqual('(test Location)'); | ||
}); | ||
|
||
it('placeholder contains default values for contactInfo, name, location', () => { | ||
const {pdf} = createPdfkitDocument(); | ||
|
||
const refs = pdfkitAddPlaceholder({ | ||
...defaults, | ||
pdf, | ||
|