{
  "version": 3,
  "sources": ["../src/index.ts", "../src/make-spy.ts", "../src/browser-automation/browser-driver.ts", "../src/utils/process-utils.ts", "../src/browser-automation/browser-test-driver.ts", "../src/utils/diff-images.ts", "../src/utils/puppeteer-events.ts", "../src/utils/log-to-dom.ts"],
  "sourcesContent": ["export {makeSpy} from './make-spy';\n\nexport {default as BrowserDriver} from './browser-automation/browser-driver';\nexport {default as BrowserTestDriver} from './browser-automation/browser-test-driver';\n\n// EXPERIMENTAL TEST UTILS\n\n// Image tools\nexport {default as _diffImages} from './utils/diff-images';\n// DOM logging\nexport {enableDOMLogging as _enableDOMLogging} from './utils/log-to-dom';\n", "// probe.gl, MIT license\n// Inspired by https://github.com/popomore/spy\n\n// @ts-nocheck\ninterface Spy {\n  // (...args: any[]): any;\n  restore(): void;\n  reset(): void;\n  returns(returnValue: any): void;\n  callCount: number;\n  called: boolean;\n}\n\n/**\n * Attach a spy to the function. The spy has the following methods and fields\n * - `restore()` - remove spy completely\n * - `reset()` - reset call count\n * - `callCount` - number of calls\n * - `called` - whether spy was called\n */\nexport function makeSpy(obj, func): Spy {\n  let methodName;\n\n  if (!obj && !func) {\n    // eslint-disable-next-line @typescript-eslint/no-empty-function\n    func = function mock() {};\n    obj = {};\n    methodName = 'spy';\n  } else if (typeof obj === 'function' && !func) {\n    func = obj;\n    obj = {};\n    methodName = `${func.name}-spy`;\n  } else {\n    methodName = func;\n    func = obj[methodName];\n  }\n\n  return wrapFunction(obj, func, methodName);\n}\n\nfunction wrapFunction(obj, func, methodName) {\n  // will not wrap more than once\n  if (func.func !== undefined) {\n    return func;\n  }\n\n  // create a local function\n  function spy(...args) {\n    spy.callCount++;\n    spy.called = true;\n    /* eslint-disable no-invalid-this */\n    return 'returnValue' in spy ? spy.returnValue : func.apply(this, args);\n  }\n\n  // Add functions and members\n  Object.assign(spy, {\n    reset() {\n      spy.callCount = 0;\n      spy.called = false;\n    },\n\n    restore() {\n      obj[methodName] = func;\n    },\n\n    returns(returnValue) {\n      spy.returnValue = returnValue;\n    },\n\n    obj,\n    methodName,\n    func,\n    method: func\n  });\n\n  spy.reset();\n\n  // Overwrite the spy on the object\n  obj[methodName] = spy;\n  return spy;\n}\n", "// probe.gl, MIT license\n\n/* eslint-disable no-console */\n\nimport puppeteer, {Browser, Page, PuppeteerLaunchOptions, ConsoleMessage} from 'puppeteer';\nimport ChildProcess from 'child_process';\n\nimport {COLOR, Log} from '@probe.gl/log';\nimport {getAvailablePort} from '../utils/process-utils';\n\nexport type BrowserDriverProps = {\n  id?: string;\n};\n\ntype ServerInstance = {\n  url: string;\n  stop: () => void;\n};\n\nexport type ServerConfiguration = {\n  command?: string;\n  arguments?: string[];\n  port?: number | 'auto';\n  wait?: number;\n  options?: any;\n  /** Callback to start the server */\n  start?: (config: ServerConfiguration) => Promise<ServerInstance>;\n};\n\nconst AUTO_PORT_START = 5000;\n\nfunction noop() {} // eslint-disable-line @typescript-eslint/no-empty-function\n\nexport default class BrowserDriver {\n  readonly id: string;\n  logger: Log;\n  server: ServerInstance | null = null;\n  browser: Browser | null = null;\n  page: Page | null = null;\n\n  constructor(options?: BrowserDriverProps) {\n    const {id = 'browser-driver'} = options || {};\n    this.id = id;\n    this.logger = new Log({id});\n  }\n\n  async startBrowser(puppeteerOptions?: PuppeteerLaunchOptions): Promise<void> {\n    if (this.browser) {\n      return;\n    }\n    this.browser = await puppeteer.launch(puppeteerOptions);\n    const browserVersion = await this.browser.version();\n    this.logger.log(`Launched browser version ${browserVersion}`)();\n  }\n\n  async openPage(options?: {\n    url?: string;\n    exposeFunctions?: Record<string, Function>;\n    onLoad?: () => void;\n    onConsole?: (e: ConsoleMessage) => void;\n    onError?: (e: Error) => void;\n  }): Promise<Page> {\n    const {\n      url,\n      exposeFunctions = {},\n      onLoad = noop,\n      onConsole = noop,\n      onError = noop\n    } = options || {};\n\n    if (!this.browser) {\n      throw new Error('No browser instance is found. Forgot to call startBrowser()?');\n    }\n\n    this.page = await this.browser.newPage();\n\n    // https://ourcodeworld.com/articles/read/1106/how-to-solve-puppeteer-timeouterror-navigation-timeout-of-30000-ms-exceeded\n    this.page.setDefaultNavigationTimeout(0);\n\n    // attach events\n    const onRequestFail = (evt) => {\n      onError(new Error(`cannot load ${evt.url()}`));\n    };\n    this.page.on('console', onConsole);\n    // If the page crashes. consider the operation failed\n    this.page.on('error', onError);\n    // If any page resource fail to load, consider the operation failed\n    this.page.on('requestfailed', onRequestFail);\n    this.page.on('load', () => {\n      // Once the page loads, ignore script-initiated http requests\n      this.page?.off('requestfailed', onRequestFail);\n      onLoad();\n    });\n\n    const promises: Promise<void>[] = [];\n    for (const [name, functionToExpose] of Object.entries(exposeFunctions)) {\n      promises.push(this.page.exposeFunction(name, functionToExpose));\n    }\n    await Promise.all(promises);\n\n    if (url) {\n      await this.page.goto(url);\n    }\n\n    return this.page;\n  }\n\n  async stopBrowser(): Promise<void> {\n    if (!this.browser) {\n      return;\n    }\n    await this.browser.close();\n    this.browser = null;\n  }\n\n  /** Starts a web server with the provided configs.\n   * Resolves to the bound url if successful\n   */\n  async startServer(serverConfig: ServerConfiguration): Promise<string | null> {\n    const {port, start = startServerCLI} = serverConfig;\n    const config = {...serverConfig};\n\n    if (port === 'auto') {\n      config.port = await getAvailablePort(AUTO_PORT_START);\n    }\n    const server = await start(config);\n    if (server) {\n      this.server = server;\n\n      this.logger.log({\n        message: `Started server at ${server.url}`,\n        color: COLOR.BRIGHT_GREEN\n      })();\n\n      return server.url;\n    }\n    return null;\n  }\n\n  async stopServer(): Promise<void> {\n    if (this.server) {\n      this.server.stop();\n      this.server = null;\n    }\n  }\n\n  /* eslint-disable no-process-exit */\n  async exit(statusCode: number = 0): Promise<void> {\n    try {\n      await this.stopBrowser();\n      await this.stopServer();\n      process.exit(statusCode);\n    } catch (error) {\n      this.logger.error(error instanceof Error ? error.message : String(error))();\n      process.exit(1);\n    }\n  }\n}\n\n/** Default implementation of serverConfig.start */\nasync function startServerCLI(config: ServerConfiguration): Promise<ServerInstance> {\n  const {arguments: args = [], command = 'webpack-dev-server', port} = config;\n\n  if (port) {\n    args.push('--port', String(port));\n  }\n\n  const server = ChildProcess.spawn(command, args);\n\n  return await new Promise((resolve, reject) => {\n    server.stdout.on('data', (data) => {\n      console.log(data.toString());\n    });\n    server.stderr.on('data', (data) => {\n      console.error(data.toString());\n    });\n    server.on('close', onClose);\n\n    const successTimer = setTimeout(() => {\n      const url = port ? `http://localhost:${port}` : 'http://localhost';\n\n      resolve({\n        url,\n        stop: () => server.kill()\n      });\n    }, config.wait);\n\n    function onClose(code) {\n      if (!code) {\n        clearTimeout(successTimer);\n        reject();\n      }\n    }\n  });\n}\n", "import ChildProcess from 'child_process';\n\n// Get an available port\n// Works on Unix systems\nexport function getAvailablePort(defaultPort: number = 3000): Promise<number> {\n  return new Promise((resolve) => {\n    // Get a list of all ports in use\n    ChildProcess.exec('lsof -i -P -n | grep LISTEN', (error, stdout) => {\n      if (error) {\n        // likely no permission, e.g. CI\n        resolve(defaultPort);\n        return;\n      }\n\n      const portsInUse: number[] = [];\n      const regex = /:(\\d+) \\(LISTEN\\)/;\n      stdout.split('\\n').forEach((line) => {\n        const match = regex.exec(line);\n        if (match) {\n          portsInUse.push(Number(match[1]));\n        }\n      });\n      let port = defaultPort;\n      while (portsInUse.includes(port)) {\n        port++;\n      }\n      resolve(port);\n    });\n  });\n}\n", "// probe.gl, MIT license\n/* eslint-disable camelcase */\n\nimport {ScreenshotOptions, ConsoleMessage, Page} from 'puppeteer';\nimport fs from 'fs';\nimport {COLOR} from '@probe.gl/log';\nimport diffImages, {DiffImagesOptions} from '../utils/diff-images';\nimport * as eventDispatchers from '../utils/puppeteer-events';\nimport BrowserDriver, {ServerConfiguration} from './browser-driver';\n\ndeclare global {\n  function browserTestDriver_fail(): void;\n  function browserTestDriver_finish(): string;\n  function browserTestDriver_emulateInput(event: unknown): Promise<void>;\n  function browserTestDriver_captureAndDiffScreen(opts: DiffImagesOpts): Promise<DiffImageResult>;\n}\n\nconst MAX_CONSOLE_MESSAGE_LENGTH = 500;\n\ntype BrowserTestDriverProps = {\n  title?: string;\n  headless?: boolean;\n  maxConsoleMessageLength?: number;\n  server: ServerConfiguration;\n  browser?: object;\n  exposeFunctions?: any;\n  url?: string;\n  onStart?: (params: {page: Page}) => void | Promise<void>;\n  onFinish?: (params: {page: Page; isSuccessful: boolean}) => void | Promise<void>;\n};\n\nexport type DiffImagesOpts = DiffImagesOptions & {\n  goldenImage: string;\n  region?: any;\n  saveOnFail?: boolean;\n  saveAs?: string;\n};\n\n/** @todo this seems like just a light repackaging of the underlying result type. Reuse or better separation of types? */\nexport type DiffImageResult = {\n  headless: boolean;\n  match: string | number;\n  matchPercentage: string;\n  success: boolean;\n  error: Error | string | null;\n};\n\n/** A test driver that starts a browser instance and runs tests inside it */\nexport default class BrowserTestDriver extends BrowserDriver {\n  title: string = '';\n  headless: boolean = false;\n  time: number = Date.now();\n  failures: number = 0;\n  maxConsoleMessageLength = MAX_CONSOLE_MESSAGE_LENGTH;\n\n  async run(config: BrowserTestDriverProps): Promise<void> {\n    const {\n      title = 'Browser Test',\n      headless = false,\n      maxConsoleMessageLength = MAX_CONSOLE_MESSAGE_LENGTH\n    } = config;\n    this.title = title;\n    this.headless = headless;\n    this.maxConsoleMessageLength = maxConsoleMessageLength;\n\n    this.logger.log({\n      message: `${title}`,\n      color: COLOR.BRIGHT_YELLOW\n    })();\n\n    try {\n      const url = await this.startServer(config.server);\n      if (!url) {\n        return;\n      }\n\n      const result = await this._openPage(url, config);\n\n      await config.onFinish?.({\n        // @ts-ignore this.page is always populated after _openPage\n        page: this.page,\n        isSuccessful: this.failures === 0\n      });\n\n      this._onFinish(result);\n    } catch (error: unknown) {\n      this._fail((error as Error).message || 'puppeteer run failes');\n    }\n  }\n\n  _openPage(url: string, config: BrowserTestDriverProps): Promise<string> {\n    const browserConfig = Object.assign({}, config.browser, {headless: this.headless});\n\n    // eslint-disable-next-line @typescript-eslint/no-misused-promises\n    return new Promise<string>(async (resolve, reject) => {\n      await this.startBrowser(browserConfig);\n\n      const exposeFunctions = {\n        ...config.exposeFunctions,\n        browserTestDriver_fail: () => this.failures++,\n        browserTestDriver_finish: (message) => resolve(message),\n        browserTestDriver_emulateInput: (event) => this._emulateInput(event),\n        browserTestDriver_captureAndDiffScreen: (opts) => this._captureAndDiff(opts)\n      };\n\n      // Puppeteer can only inject functions, not values, into the global scope\n      // In headless mode, we inject the function so it's truthy\n      // In non-headless mode, we don't inject the function so it's undefined\n      if (this.headless) {\n        exposeFunctions.browserTestDriver_isHeadless = () => true;\n      }\n\n      this.logger.log({\n        message: 'Loading page in browser...',\n        color: COLOR.BRIGHT_YELLOW\n      })();\n\n      // resolve URL\n      const pageUrl: string = config.url\n        ? config.url.startsWith('http')\n          ? config.url\n          : `${url.replace(/\\/$/, '')}/${config.url.replace(/^\\//, '')}`\n        : url;\n\n      // eslint-disable-next-line @typescript-eslint/no-floating-promises\n      const page = await this.openPage({\n        exposeFunctions,\n        onConsole: (event) => this._onConsole(event),\n        onError: reject\n      });\n\n      await config.onStart?.({page});\n\n      await page.goto(pageUrl);\n    });\n  }\n\n  /* eslint-disable no-console */\n  _onConsole(event: ConsoleMessage) {\n    if (!this.headless) {\n      // Do not mirror console messages if the browser is open\n      return;\n    }\n\n    // Terminal console does not collapse big messages like Chrome does\n    // Crop very long text messages to avoid flooding\n    let text = event.text();\n    if (!text.startsWith('data:')) {\n      // Leave data URL intact so that we have a channel to get data out via console\n      text = text.slice(0, this.maxConsoleMessageLength);\n    }\n    switch (event.type()) {\n      case 'log':\n        console.log(text);\n        break;\n\n      case 'warn':\n        console.warn(text);\n        break;\n\n      case 'error':\n        const errorObject = event.args()[0]?.remoteObject();\n        console.error(errorObject?.description || text);\n        break;\n\n      default:\n      // ignore\n    }\n  }\n  /* eslint-enable no-console */\n\n  _onFinish(message: string): void {\n    const elapsed = ((Date.now() - this.time) / 1000).toFixed(1);\n    this.logger.log({\n      message: `${this.title} completed in ${elapsed}s.`,\n      color: COLOR.BRIGHT_YELLOW\n    })();\n\n    if (this.failures) {\n      this._fail(message || `${this.failures} test${this.failures > 1 ? 's' : ''} failed`);\n    } else {\n      this._pass(message || 'All tests passed');\n    }\n  }\n\n  _pass(message: string): void {\n    this.logger.log({\n      message: `${this.title} successful: ${message}`,\n      color: COLOR.BRIGHT_GREEN\n    })();\n\n    if (this.headless) {\n      this.exit(0); // eslint-disable-line @typescript-eslint/no-floating-promises\n    }\n  }\n\n  _fail(message: string): void {\n    this.logger.log({\n      message: `${this.title} failed: ${message}`,\n      color: COLOR.BRIGHT_RED\n    })();\n\n    if (this.headless) {\n      this.exit(1); // eslint-disable-line @typescript-eslint/no-floating-promises\n    }\n  }\n\n  _emulateInput(event) {\n    // eslint-disable-next-line import/namespace\n    if (eventDispatchers[event.type]) {\n      // eslint-disable-next-line import/namespace\n      return eventDispatchers[event.type](this.page, event);\n    }\n    throw new Error(`Unknown event: ${event.type}`);\n  }\n\n  async _captureAndDiff(opts: DiffImagesOpts): Promise<DiffImageResult> {\n    if (!opts.goldenImage) {\n      return Promise.reject(new Error('Must supply golden image for image diff'));\n    }\n\n    const screenshotOptions: ScreenshotOptions = {\n      type: 'png',\n      omitBackground: true,\n      encoding: 'binary'\n    };\n    if (opts.region) {\n      screenshotOptions.clip = opts.region;\n    } else {\n      screenshotOptions.fullPage = true;\n    }\n\n    try {\n      const image = await this.page?.screenshot(screenshotOptions);\n      if (!image) {\n        throw new Error('screenshot failed');\n      }\n      const result = await diffImages(image, opts.goldenImage, opts);\n      if (!result.success && opts.saveOnFail && result.source1) {\n        let filename = opts.saveAs || '[name]-failed.png';\n        filename = filename.replace('[name]', opts.goldenImage.replace(/\\.\\w+$/, ''));\n        this._saveScreenshot(filename, result.source1);\n      }\n      return {\n        headless: this.headless,\n        match: result.match || 0,\n        matchPercentage: result.matchPercentage || 'N/A',\n        success: result.success,\n        // @ts-expect-error\n        diffImage: result.diffImage || null,\n        error: result.error || null\n      };\n    } catch (error: unknown) {\n      return {\n        headless: this.headless,\n        match: 0,\n        matchPercentage: 'N/A',\n        success: false,\n        error: (error as Error).message\n      };\n    }\n  }\n\n  _saveScreenshot(filename, data) {\n    this.logger.log({\n      message: `Writing screenshot to ${filename}`,\n      color: COLOR.BRIGHT_YELLOW\n    })();\n    fs.writeFile(filename, data, (error) => {\n      if (error) {\n        this.logger.log({\n          message: `Save screenshot failed: ${error.message}`,\n          color: COLOR.BRIGHT_RED\n        })();\n      }\n    });\n  }\n}\n", "import fs from 'fs';\n// eslint-disable-next-line  import/no-extraneous-dependencies\nimport {PNG} from 'pngjs';\nimport pixelmatch from 'pixelmatch';\n\nexport type DiffImagesOptions = {\n  threshold?: number; // 0.99,\n  createDiffImage?: boolean; // false,\n  tolerance?: number; // 0.1,\n  includeAA?: boolean; // false,\n  includeEmpty?: boolean; // true\n};\n\nexport type DiffImagesResult = {\n  success: boolean;\n  error?: string;\n  match: number;\n  matchPercentage: string;\n  diffImage: any;\n  source1: string | Buffer;\n  source2: string;\n  options: unknown;\n};\n\nexport default async function diffImages(\n  source1: string | Buffer,\n  source2: string,\n  options: DiffImagesOptions = {}\n): Promise<DiffImagesResult> {\n  try {\n    const [image1, image2] = await Promise.all([parsePNG(source1), parsePNG(source2)]);\n    const result = diffPNGs(image1, image2, options);\n    return {\n      ...result,\n      source1,\n      source2,\n      options\n    };\n  } catch (error: unknown) {\n    // @ts-expect-error - partially populated result\n    return {\n      success: false,\n      error: (error as Error).message\n    };\n  }\n}\n\ntype DiffPngOptions = {\n  threshold?: number;\n  createDiffImage?: boolean;\n  tolerance?: number;\n  includeAA?: boolean;\n  includeEmpty?: boolean;\n};\n\nfunction diffPNGs(image1: PNG, image2: PNG, options: DiffPngOptions) {\n  const {width, height} = image1;\n  if (width !== image2.width || height !== image2.height) {\n    throw new Error('Image sizes do not match');\n  }\n\n  const {\n    threshold = 0.99,\n    createDiffImage = false,\n    tolerance = 0.1,\n    includeAA = false,\n    includeEmpty = true\n  } = options;\n\n  const diffImage = new PNG({width, height});\n\n  // pixelmatch returns the number of mismatched pixels\n  const mismatchedPixels = pixelmatch(\n    image1.data, // image 1\n    image2.data, // image 2\n    diffImage.data, // output\n    width, // width\n    height, // height\n    {threshold: tolerance, includeAA} // options\n  );\n\n  const pixelCount = includeEmpty ? width * height : countNonEmptyPixels(image1.data, image2.data);\n\n  const match = 1 - mismatchedPixels / pixelCount;\n  const success = match >= threshold;\n\n  return {\n    match,\n    matchPercentage: `${(match * 100).toFixed(2)}%`,\n    success,\n    diffImage: !success && createDiffImage ? encodePNG(diffImage) : null\n  };\n}\n\nfunction countNonEmptyPixels(data1: Buffer, data2: Buffer): number {\n  const pixels1 = new Uint8Array(data1.buffer);\n  const pixels2 = new Uint8Array(data2.buffer);\n  let count = 0;\n  for (let i = 3; i < pixels1.length; i += 4) {\n    // Exclude a pixel if it's empty in both images\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n    if ((pixels1[i] as number) > 0 || (pixels2[i] as number) > 0) {\n      count++;\n    }\n  }\n  return count;\n}\n\n/** @todo - replace pngjs with @loaders.gl/images */\nfunction parsePNG(source: string | Buffer): Promise<PNG> {\n  const image = new PNG();\n  if (typeof source === 'string') {\n    // url or local path\n    return new Promise((resolve, reject) => {\n      const readStream = fs.createReadStream(source).on('error', reject);\n      readStream.pipe(image).on('parsed', () => resolve(image));\n    });\n  }\n  if (source instanceof Buffer) {\n    // puppeteer.screenshot returns a Buffer object\n    return new Promise((resolve, reject) => {\n      image.parse(source, (error) => {\n        if (error) {\n          reject(error);\n        } else {\n          resolve(image);\n        }\n      });\n    });\n  }\n  return Promise.reject(new Error('Unknown image source'));\n}\n\nfunction encodePNG(image: PNG): string | null {\n  if (!image) {\n    return null;\n  }\n  const buffer = PNG.sync.write(image, {});\n  return `data:image/png;base64,${buffer.toString('base64')}`;\n}\n", "// probe.gl, MIT license\n\nimport type {Page} from 'puppeteer';\n\nasync function functionKeysDown(page: Page, {shiftKey, ctrlKey, metaKey}) {\n  if (shiftKey) {\n    await page.keyboard.down('Shift');\n  }\n  if (ctrlKey) {\n    await page.keyboard.down('Control');\n  }\n  if (metaKey) {\n    await page.keyboard.down('Meta');\n  }\n}\n\nasync function functionKeysUp(page: Page, {shiftKey, ctrlKey, metaKey}) {\n  if (shiftKey) {\n    await page.keyboard.up('Shift');\n  }\n  if (ctrlKey) {\n    await page.keyboard.up('Control');\n  }\n  if (metaKey) {\n    await page.keyboard.up('Meta');\n  }\n}\n\n/*\n * {\n     type: 'keypress',\n     key: <string>,\n     shiftKey: false,\n     ctrlKey: false,\n     metaKey: false,\n     delay: 0\n   }\n * keys:\n * https://github.com/GoogleChrome/puppeteer/blob/master/lib/USKeyboardLayout.js\n */\nexport async function keypress(page: Page, event) {\n  await functionKeysDown(page, event);\n  await page.keyboard.press(event.key, {delay: event.delay || 0});\n  await functionKeysUp(page, event);\n}\n\n/*\n * {\n     type: 'click',\n     x: <number>,\n     y: <number>,\n     button: 'left',\n     delay: 0,\n     shiftKey: false,\n     ctrlKey: false,\n     metaKey: false\n   }\n */\nexport async function click(page: Page, event) {\n  await functionKeysDown(page, event);\n  await page.mouse.click(event.x, event.y, {\n    button: event.button || 'left',\n    delay: event.delay || 0\n  });\n  await functionKeysUp(page, event);\n}\n\n/*\n * {\n     type: 'mousemove',\n     x: <number>,\n     y: <number>,\n     steps: 1\n   }\n */\nexport async function mousemove(page: Page, event) {\n  await page.mouse.move(event.x, event.y, {\n    steps: event.steps || 1\n  });\n}\n\n/*\n * {\n     type: 'drag',\n     startX: <number>,\n     startY: <number>,\n     endX: <number>,\n     endY: <number>,\n     button: 'left',\n     steps: 1,\n     shiftKey: false,\n     ctrlKey: false,\n     metaKey: false\n   }\n */\nexport async function drag(page: Page, event) {\n  await functionKeysDown(page, event);\n  await page.mouse.move(event.startX, event.startY);\n  await page.mouse.down(event.button || 'left');\n  await page.mouse.move(event.endX, event.endY, {steps: event.steps || 1});\n  await page.mouse.up(event.button || 'left');\n  await functionKeysUp(page, event);\n}\n", "/* eslint-disable no-console */\nconst {document, console} = globalThis;\n\nlet old: typeof console.log | null = null;\n\n// Can log a (not too long) number of messages to a div in the DOM\n// Set options to false to disable\nexport function enableDOMLogging(options = {}): void {\n  // First time, add a log div\n  if (options && !old) {\n    old = console.log.bind(console);\n    console.log = (...args) => {\n      // @ts-expect-error\n      logLineToDOM(options, ...args);\n      if (old) {\n        old(...args);\n      }\n    };\n  }\n  if (!options && old) {\n    console.log = old;\n    old = null;\n  }\n}\n\nlet logDiv: HTMLElement | null = null;\n\nfunction logLineToDOM(options, message: string): void {\n  logDiv = options.container || logDiv;\n\n  if (!logDiv) {\n    logDiv = document.createElement('pre');\n    document.body.append(logDiv);\n  }\n\n  // Add the line to the log element\n  if (typeof message === 'string') {\n    logDiv.innerHTML += `${message}\\n`;\n\n    if (options.getStyle) {\n      Object.assign(logDiv.style, options.getStyle(message));\n    }\n  }\n}\n\nexport default enableDOMLogging;\n"],
  "mappings": "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",
  "names": ["import_child_process", "ChildProcess", "puppeteer", "ChildProcess", "import_fs", "import_log", "pixelmatch", "fs", "fs", "console"]
}
