<|start_filename|>src/shared/utils.spec.js<|end_filename|>
import {
  isDataURI,
  dataURItoByteString,
} from './utils';

describe('isDataURI()', () => {
  it.each`
    input                                            | expectedResult
    ${'potato'}                                      | ${false}
    ${'data:,Hello%2C%20world%21'}                   | ${true}
    ${'data:text/plain;base64,SGVsbG8sIHdvcmxkIQ=='} | ${true}
  `('returns $expectedResult given $input', ({ input, expectedResult }) => {
    const result = isDataURI(input);

    expect(result).toBe(expectedResult);
  });
});

describe('dataURItoByteString()', () => {
  it('throws given invalid data URI', () => {
    expect(() => dataURItoByteString('potato')).toThrow();
  });

  it('returns a byte string given plain text data URI', () => {
    const result = dataURItoByteString('data:,Hello%2C%20world%21');

    expect(result).toBe('Hello, world!');
  });

  it('returns a byte string given base64 data URI', () => {
    const result = dataURItoByteString('data:text/plain;base64,SGVsbG8sIHdvcmxkIQ==');

    expect(result).toBe('Hello, world!');
  });

  it('returns a byte string given base64 PDF data URI', () => {
    const result = dataURItoByteString('data:application/pdf;base64,JVBERi0xLg10cmFpbGVyPDwvUm9vdDw8L1BhZ2VzPDwvS2lkc1s8PC9NZWRpYUJveFswIDAgMyAzXT4+XT4+Pj4+Pg==');

    expect(result).toBe('%PDF-1.\rtrailer<</Root<</Pages<</Kids[<</MediaBox[0 0 3 3]>>]>>>>>>');
  });

  it('returns a byte string given base64 PDF data URI with filename', () => {
    const result = dataURItoByteString('data:application/pdf;filename=generated.pdf;base64,JVBERi0xLg10cmFpbGVyPDwvUm9vdDw8L1BhZ2VzPDwvS2lkc1s8PC9NZWRpYUJveFswIDAgMyAzXT4+XT4+Pj4+Pg==');

    expect(result).toBe('%PDF-1.\rtrailer<</Root<</Pages<</Kids[<</MediaBox[0 0 3 3]>>]>>>>>>');
  });
});


<|start_filename|>src/shared/utils.js<|end_filename|>
/**
 * Checks if we're running in a browser environment.
 */
export const isBrowser = typeof window !== 'undefined';

/**
 * Checks whether we're running from a local file system.
 */
export const isLocalFileSystem = isBrowser && window.location.protocol === 'file:';

/**
 * Checks whether we're running on a production build or not.
 */
export const isProduction = process.env.NODE_ENV === 'production';

/**
 * Checks whether a variable is defined.
 *
 * @param {*} variable Variable to check
 */
export function isDefined(variable) {
  return typeof variable !== 'undefined';
}

/**
 * Checks whether a variable is defined and not null.
 *
 * @param {*} variable Variable to check
 */
export function isProvided(variable) {
  return isDefined(variable) && variable !== null;
}

/**
 * Checkes whether a variable provided is a string.
 *
 * @param {*} variable Variable to check
 */
export function isString(variable) {
  return typeof variable === 'string';
}

/**
 * Checks whether a variable provided is an ArrayBuffer.
 *
 * @param {*} variable Variable to check
 */
export function isArrayBuffer(variable) {
  return variable instanceof ArrayBuffer;
}

/**
 * Checkes whether a variable provided is a Blob.
 *
 * @param {*} variable Variable to check
 */
export function isBlob(variable) {
  if (!isBrowser) {
    throw new Error('Attempted to check if a variable is a Blob on a non-browser environment.');
  }

  return variable instanceof Blob;
}

/**
 * Checkes whether a variable provided is a File.
 *
 * @param {*} variable Variable to check
 */
export function isFile(variable) {
  if (!isBrowser) {
    throw new Error('Attempted to check if a variable is a File on a non-browser environment.');
  }

  return variable instanceof File;
}

/**
 * Checks whether a string provided is a data URI.
 *
 * @param {string} str String to check
 */
export function isDataURI(str) {
  return isString(str) && /^data:/.test(str);
}

export function dataURItoByteString(dataURI) {
  if (!isDataURI(dataURI)) {
    throw new Error('Invalid data URI.');
  }

  const [headersString, dataString] = dataURI.split(',');
  const headers = headersString.split(';');

  if (headers.indexOf('base64') !== -1) {
    return atob(dataString);
  }

  return unescape(dataString);
}

export function getPixelRatio() {
  return (isBrowser && window.devicePixelRatio) || 1;
}

function consoleOnDev(method, ...message) {
  if (!isProduction) {
    // eslint-disable-next-line no-console
    console[method](...message);
  }
}

export function warnOnDev(...message) {
  consoleOnDev('warn', ...message);
}

export function errorOnDev(...message) {
  consoleOnDev('error', ...message);
}

export function displayCORSWarning() {
  if (isLocalFileSystem) {
    warnOnDev('Loading PDF as base64 strings/URLs might not work on protocols other than HTTP/HTTPS. On Google Chrome, you can use --allow-file-access-from-files flag for debugging purposes.');
  }
}

export function cancelRunningTask(runningTask) {
  if (runningTask && runningTask.cancel) runningTask.cancel();
}

export function makePageCallback(page, scale) {
  Object.defineProperty(page, 'width', { get() { return this.view[2] * scale; }, configurable: true });
  Object.defineProperty(page, 'height', { get() { return this.view[3] * scale; }, configurable: true });
  Object.defineProperty(page, 'originalWidth', { get() { return this.view[2]; }, configurable: true });
  Object.defineProperty(page, 'originalHeight', { get() { return this.view[3]; }, configurable: true });
  return page;
}

export function isCancelException(error) {
  return error.name === 'RenderingCancelledException';
}

export function loadFromFile(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = () => resolve(new Uint8Array(reader.result));
    reader.onerror = (event) => {
      switch (event.target.error.code) {
        case event.target.error.NOT_FOUND_ERR:
          return reject(new Error('Error while reading a file: File not found.'));
        case event.target.error.NOT_READABLE_ERR:
          return reject(new Error('Error while reading a file: File not readable.'));
        case event.target.error.SECURITY_ERR:
          return reject(new Error('Error while reading a file: Security error.'));
        case event.target.error.ABORT_ERR:
          return reject(new Error('Error while reading a file: Aborted.'));
        default:
          return reject(new Error('Error while reading a file.'));
      }
    };
    reader.readAsArrayBuffer(file);

    return null;
  });
}


<|start_filename|>test/shared/propTypes.js<|end_filename|>
import PropTypes from 'prop-types';

/* eslint-disable react/forbid-prop-types */

const fileTypes = [
  PropTypes.string,
  PropTypes.instanceOf(ArrayBuffer),
  PropTypes.shape({
    data: PropTypes.object,
    httpHeaders: PropTypes.object,
    range: PropTypes.object,
    url: PropTypes.string,
    withCredentials: PropTypes.bool,
  }),
];
if (typeof File !== 'undefined') {
  fileTypes.push(PropTypes.instanceOf(File));
}
if (typeof Blob !== 'undefined') {
  fileTypes.push(PropTypes.instanceOf(Blob));
}

export const isFile = PropTypes.oneOfType(fileTypes);


<|start_filename|>__mocks__/_failing_pdf.js<|end_filename|>
export default {
  _pdfInfo: {
    fingerprint: 'a62067476e69734bb8eb60122615dfbf',
    numPages: 4,
  },
  fingerprint: 'a62067476e69734bb8eb60122615dfbf',
  getDestination: () => new Promise((resolve, reject) => reject(new Error())),
  getOutline: () => new Promise((resolve, reject) => reject(new Error())),
  getPage: () => new Promise((resolve, reject) => reject(new Error())),
  numPages: 4,
};


<|start_filename|>copy-styles.js<|end_filename|>
const fs = require('fs');

fs.copyFile('src/Page/AnnotationLayer.css', 'dist/esm/Page/AnnotationLayer.css', (error) => {
  if (error) {
    throw error;
  }
  // eslint-disable-next-line no-console
  console.log('AnnotationLayer.css copied successfully to ESM build.');
});

fs.copyFile('src/Page/AnnotationLayer.css', 'dist/umd/Page/AnnotationLayer.css', (error) => {
  if (error) {
    throw error;
  }
  // eslint-disable-next-line no-console
  console.log('AnnotationLayer.css copied successfully to UMD build.');
});


<|start_filename|>__mocks__/_failing_page.js<|end_filename|>
export default {
  _transport: {
    fontLoader: {},
  },
  commonObjs: {
    _objs: {},
    get: () => {},
  },
  getAnnotations: () => new Promise((resolve, reject) => reject(new Error())),
  getOperatorList: () => new Promise((resolve, reject) => reject(new Error())),
  getTextContent: () => new Promise((resolve, reject) => reject(new Error())),
  getViewport: () => ({
    width: 600,
    height: 800,
    rotation: 0,
  }),
  render: () => ({
    promise: new Promise((resolve, reject) => reject(new Error())),
  }),
};
