I have the below function to print receipts:
const generateOnePDF = async (ticket, orderData) =>
  new Promise(async (resolve, reject) => {
    let finalString = '';
    if (!ticket) {
      const err = new Error('missing ticket data');
      reject(err);
    }
    if (!orderData) {
      const err = new Error('missing order data');
      reject(err);
    }
    const { payload, sequence, title } = ticket;
    if (!payload) {
      const err = new Error('missing payload data');
      reject(err);
    }
    if (!sequence) {
      const err = new Error('missing ticket sequence');
      reject(err);
    }
    if (!title) {
      const err = new Error('missing ticket book title');
      reject(err);
    }
    const doc = new PDFDocument();
    PDFDocument.prototype.addSVG = function (svg, x, y, options) {
      return SVGtoPDF(this, svg, x, y, options);
    };
    const stream = doc.pipe(new Base64Encode());
    // logo
    const logo = await fetchImage(
      `${url}/static/media/logo_157.c15ac239.svg`
    );
    doc.addSVG(logo.toString(), 32, 40, {});
    doc.moveUp();
    doc.moveUp();
    doc.text(`Order: O${orderData.orderId}`, { align: 'right' });
    const rectXOffset = 25;
    const rectPosition = 32;
    doc
      .rect(rectXOffset, rectPosition, doc.page.width - rectXOffset * 2, 32)
      .stroke();
    doc.moveDown();
    doc.moveDown();
    doc.moveDown();
    doc.rect(rectXOffset, 80, doc.page.width - rectXOffset * 2, 680).stroke();
    doc.text(orderData.title, { align: 'left' });
    doc.moveDown();
    doc.text(orderData.venue, { align: 'left' });
    doc.text(orderData.address, { align: 'left' });
    doc.text(`${orderData.city}, ${orderData.province} ${orderData.zip}`, {
      align: 'left'
    });
    if (orderData.custom) {
      doc.moveDown();
      doc.text(orderData.customCopy, { align: 'left' });
    }
    doc.moveDown();
    doc.text(`${orderData.date} at ${orderData.show}`, { align: 'left' });
    doc.moveDown();
    const image = await fetchImage(orderData['image']);
    doc.image(image, {
      fit: [100, 100],
      align: 'right',
      valign: 'top'
    });
    doc.moveDown();
    doc.text(
      `Order: O${orderData.orderId}. Placed by ${orderData.firstName} ${orderData.lastName} on ${orderData.created}`
    );
    // right column
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.moveUp();
    doc.text(`Ticket: ${sequence} ${title}`, { align: 'right' });
    const qrcode = new QRCode({
      content: payload,
      width: 200,
      height: 200,
      xmlDeclaration: false,
      join: true
    }).svg();
    const options = { align: 'right' };
    doc.addSVG(qrcode, 400, 150, options);
    // finalize/close the PDF file
    doc.end();
    stream.on('data', (chunk) => {
      finalString += chunk;
    });
    stream.on('end', () => {
      // the stream is at its end, so push the resulting base64 string to the response
      resolve(finalString);
    });
    stream.on('error', (err) => {
      reject(err);
    });
  });
It is not the cleanest piece of code in the world, but it works for me, in the meantime.
I added a simple unit test for this code, below:
  it('should throw an error if the ticket or order data are invalid', async () => {
    await expect(generateOnePDF(null, {})).rejects.toThrowError();
    await expect(generateOnePDF({}, null)).rejects.toThrowError();
  });
The tests passes, but it writes "garbage" to the console. There are unhandled rejects in the code.
(node:53703) UnhandledPromiseRejectionWarning: TypeError: Cannot destructure property 'payload' of '((cov_2gbfm4phuo(...).s[25]++) , ticket)' as it is null.
(Use `node --trace-warnings ...` to show where the warning was created)
is one such error and another is:
(node:53703) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'orderId' of null
What I don't understand why if (!ticket) throw() and if (!orderData) throw would not prevent the errors from occurring. Where is the "broken promise?"
I am doing reject inside the promise handler function, so where I am not doing it?
 
     
    