jsdom#JSDOM TypeScript Examples

The following examples show how to use jsdom#JSDOM. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From vite-plugin-vue-i18n with MIT License 7 votes vote down vote up
export async function bundleAndRun(
  fixture: string,
  options: Record<string, unknown> = {}
) {
  const { code } = await bundle(fixture, options)

  let dom: JSDOM | null = null
  let jsdomError
  try {
    dom = new JSDOM(`<!DOCTYPE html><html><head></head><body></body></html>`, {
      runScripts: 'outside-only',
      virtualConsole: new VirtualConsole()
    })
    dom.window.eval(code)
  } catch (e) {
    console.error(`JSDOM error:\n${e.stack}`)
    jsdomError = e
  }

  if (!dom) {
    return Promise.reject(new Error('Cannot assigned JSDOM instance'))
  }

  const { window } = dom
  const { module, exports } = window

  return Promise.resolve({
    window,
    module,
    exports,
    jsdomError
  })
}
Example #2
Source File: cheatsheet.ts    From vscode-openscad with GNU General Public License v3.0 6 votes vote down vote up
// Returns cheatsheet html for webview
    private getWebviewContent(styleKey: string): string {
        // Read HTML from file
        const htmlContent = fs
            .readFileSync(
                path.join(this._extensionPath, 'media', 'cheatsheet.html')
            )
            .toString();

        // Create html document using jsdom to assign new stylesheet
        const htmlDocument = new JSDOM(htmlContent).window.document;
        const head = htmlDocument.getElementsByTagName('head')[0];
        const styles = htmlDocument.getElementsByTagName('link');

        // Remove existing styles
        Array.from(styles).forEach((element) => {
            head.removeChild(element);
        });

        // Get uri of stylesheet
        const styleUri = this.getStyleSheet(styleKey);

        // Create new style element
        const newStyle = htmlDocument.createElement('link');
        newStyle.type = 'text/css';
        newStyle.rel = 'stylesheet';
        newStyle.href = styleUri.toString();
        newStyle.media = 'all';

        // Append style element
        head.appendChild(newStyle);

        // Return document as html string
        return htmlDocument.documentElement.outerHTML;
    }
Example #3
Source File: misc.test.ts    From remotely-save with Apache License 2.0 6 votes vote down vote up
describe("Misc: extract svg", () => {
  beforeEach(function () {
    const fakeBrowser = new JSDOM("");
    global.window = fakeBrowser.window as any;
  });

  it("should extract rect from svg correctly", () => {
    const x = "<svg><rect/><g/></svg>";
    const y = misc.extractSvgSub(x);
    // console.log(x)
    expect(y).to.equal("<rect/><g/>");
  });
});
Example #4
Source File: pdf.ts    From pdf-generator-service with MIT License 6 votes vote down vote up
extractPDFToc = async (pdfBuffer: Buffer, options: PdfOptions): Promise<void> => {
  const data = await parsePdf(pdfBuffer, { pagerender: pageRender })
  data.text.split(PAGE_BREAK_MARKER).forEach((content: string, pageIndex: number) => {
    options.tocContext._toc.map((entry) => {
      if (content.includes(entry.id)) {
        entry.page = pageIndex + 1
      }
      return entry
    })
  })

  const document = new JSDOM(options.content).window.document
  const tocElement: HTMLElement | null = document.querySelector('.print-toc')
  document.querySelectorAll('.removeAfterTocExtraction').forEach((el) => el.parentNode?.removeChild(el))
  if (tocElement) {
    tocElement.innerHTML = handlebars.compile(options.tocTemplate || '')({
      ...options.context,
      ...options.tocContext,
    })
    options.tocTemplate = tocElement.outerHTML
  }
  options.content = document.documentElement.outerHTML
}
Example #5
Source File: index.ts    From pdf-generator-service with MIT License 6 votes vote down vote up
export function prepareToc(options: PdfOptions): void {
  const tocIgnoreClass = 'toc-ignore'
  const headingSelectors = 'h1, h2, h3, h4, h5, h6'
  const document = new JSDOM(options.content).window.document
  const tocElement: HTMLElement | null = document.querySelector('.print-toc')

  if (tocElement) {
    tocElement.style.pageBreakAfter = 'always'
    // Extract TOC template and include the default html head tag
    const tocDocument = new JSDOM(options.content).window.document
    const bodyEl = tocDocument.querySelector('body') as HTMLElement

    // Exclude headings inside toc template from the toc itself
    tocElement.querySelectorAll(headingSelectors).forEach((h) => h.classList.add(tocIgnoreClass))

    bodyEl.innerHTML = tocElement.outerHTML
    options.tocTemplate = tocDocument.documentElement.outerHTML

    document.querySelectorAll(headingSelectors).forEach((h) => {
      if (h.classList.contains(tocIgnoreClass)) return
      const title = h.textContent || ''
      if (title && title.trim().length) {
        const id = h.id || UID.sync(16)
        const level = Number.parseInt(h.tagName.substr(1))
        h.id = id
        h.innerHTML = `${title}<span class="removeAfterTocExtraction">${id}</span>`
        options.tocContext._toc.push({ id, title, level, href: `#${id}` })
      }
    })
  }
  options.content = document.documentElement.outerHTML
}
Example #6
Source File: fetch-idl.ts    From webidl2ts with MIT License 6 votes vote down vote up
export async function fetchIDL(uri: string): Promise<string> {
  let result: string
  if (fs.existsSync(uri)) {
    result = fs.readFileSync(uri).toString()
  } else {
    result = await getUrl(uri)
  }
  if (uri.match(/\.w?idl$/)) {
    return result
  }
  return extractIDL(JSDOM.fragment(result))
}
Example #7
Source File: parse-cdn.test.ts    From analytics-next with MIT License 6 votes vote down vote up
function withTag(tag: string) {
  const html = `
    <!DOCTYPE html>
      <head>
        ${tag}
      </head>
      <body>
      </body>
    </html>
    `.trim()

  const virtualConsole = new VirtualConsole()
  const jsd = new JSDOM(html, {
    runScripts: 'dangerously',
    resources: 'usable',
    url: 'https://segment.com',
    virtualConsole,
  })

  const windowSpy = jest.spyOn(global, 'window', 'get')

  const documentSpy = jest.spyOn(global, 'document', 'get')

  jest.spyOn(console, 'warn').mockImplementationOnce(() => {})

  windowSpy.mockImplementation(() => {
    return jsd.window as unknown as Window & typeof globalThis
  })

  documentSpy.mockImplementation(
    () => jsd.window.document as unknown as Document
  )
}
Example #8
Source File: simple-wappalyzer.ts    From crossfeed with Creative Commons Zero v1.0 Universal 6 votes vote down vote up
wappalyzer = ({ data = '', url = '', headers = {} }) => {
  const dom = new JSDOM(data, { url, virtualConsole: new VirtualConsole() });
  return analyze({
    url: url,
    meta: getMeta(dom.window.document),
    headers: getHeaders(headers),
    scripts: getScripts(dom.window.document.scripts),
    cookies: getCookies(headers['set-cookie']),
    html: dom.serialize()
  });
}
Example #9
Source File: index.test.ts    From analytics-next with MIT License 6 votes vote down vote up
beforeEach(async () => {
  jest.restoreAllMocks()
  jest.resetAllMocks()

  const html = `
    <!DOCTYPE html>
      <head>
        <script>
          'hi'
        </script>
      </head>
      <body>
      </body>
    </html>
    `.trim()

  const jsd = new JSDOM(html, {
    runScripts: 'dangerously',
    resources: 'usable',
  })

  const windowSpy = jest.spyOn(global, 'window', 'get')
  windowSpy.mockImplementation(() => {
    return jsd.window as unknown as Window & typeof globalThis
  })
})
Example #10
Source File: standalone.test.ts    From analytics-next with MIT License 5 votes vote down vote up
describe('standalone bundle', () => {
  const segmentDotCom = `foo`

  let jsd: JSDOM
  let windowSpy: jest.SpyInstance
  let documentSpy: jest.SpyInstance

  beforeEach(() => {
    jest.restoreAllMocks()
    jest.resetAllMocks()

    jest.spyOn(console, 'warn').mockImplementationOnce(() => {})

    // @ts-ignore ignore Response required fields
    mocked(unfetch).mockImplementation((): Promise<Response> => fetchSettings)

    const html = `
    <!DOCTYPE html>
      <head>
        <script>
          ${snippet(segmentDotCom, true)}
        </script>
      </head>
      <body>
      </body>
    </html>
    `.trim()

    const virtualConsole = new jsdom.VirtualConsole()
    jsd = new JSDOM(html, {
      runScripts: 'dangerously',
      resources: 'usable',
      url: 'https://segment.com',
      virtualConsole,
    })

    windowSpy = jest.spyOn(global, 'window', 'get')
    documentSpy = jest.spyOn(global, 'document', 'get')

    jest.spyOn(console, 'warn').mockImplementationOnce(() => {})

    windowSpy.mockImplementation(() => {
      return jsd.window as unknown as Window & typeof globalThis
    })

    documentSpy.mockImplementation(
      () => jsd.window.document as unknown as Document
    )
  })

  it('loads AJS on execution', async () => {
    await import('../standalone')

    await pWhile(
      () => window.analytics?.initialized !== true,
      () => {}
    )

    expect(window.analytics).not.toBeUndefined()
    expect(window.analytics.initialized).toBe(true)
  })
})
Example #11
Source File: integration.test.ts    From analytics-next with MIT License 5 votes vote down vote up
describe('deregister', () => {
  beforeEach(async () => {
    jest.restoreAllMocks()
    jest.resetAllMocks()

    const html = `
    <!DOCTYPE html>
      <head>
        <script>'hi'</script>
      </head>
      <body>
      </body>
    </html>
    `.trim()

    const jsd = new JSDOM(html, {
      runScripts: 'dangerously',
      resources: 'usable',
      url: 'https://localhost',
    })

    const windowSpy = jest.spyOn(global, 'window', 'get')
    windowSpy.mockImplementation(
      () => jsd.window as unknown as Window & typeof globalThis
    )
  })

  it('deregisters a plugin given its name', async () => {
    const unload = jest.fn((): Promise<unknown> => {
      return Promise.resolve()
    })
    xt.unload = unload

    const [analytics] = await AnalyticsBrowser.load({
      writeKey,
      plugins: [xt],
    })

    await analytics.deregister('Test Plugin')
    expect(xt.unload).toHaveBeenCalled()
  })

  it('cleans up the DOM when deregistering a legacy integration', async () => {
    const amplitude = new LegacyDestination(
      'amplitude',
      'latest',
      {
        apiKey: AMPLITUDE_WRITEKEY,
      },
      {}
    )

    const [analytics] = await AnalyticsBrowser.load({
      writeKey,
      plugins: [amplitude],
    })

    await analytics.ready()

    const scriptsLength = window.document.scripts.length
    expect(scriptsLength).toBeGreaterThan(1)

    await analytics.deregister('amplitude')
    expect(window.document.scripts.length).toBe(scriptsLength - 1)
  })
})
Example #12
Source File: integration.test.ts    From analytics-next with MIT License 5 votes vote down vote up
describe('addDestinationMiddleware', () => {
  beforeEach(async () => {
    jest.restoreAllMocks()
    jest.resetAllMocks()

    const html = `
    <!DOCTYPE html>
      <head>
        <script>'hi'</script>
      </head>
      <body>
      </body>
    </html>
    `.trim()

    const jsd = new JSDOM(html, {
      runScripts: 'dangerously',
      resources: 'usable',
      url: 'https://localhost',
    })

    const windowSpy = jest.spyOn(global, 'window', 'get')
    windowSpy.mockImplementation(
      () => jsd.window as unknown as Window & typeof globalThis
    )
  })

  it('supports registering destination middlewares', async () => {
    const [analytics] = await AnalyticsBrowser.load({
      writeKey,
    })

    const amplitude = new LegacyDestination(
      'amplitude',
      'latest',
      {
        apiKey: AMPLITUDE_WRITEKEY,
      },
      {}
    )

    await analytics.register(amplitude)
    await amplitude.ready()

    analytics
      .addDestinationMiddleware('amplitude', ({ next, payload }) => {
        payload.obj.properties!.hello = 'from the other side'
        next(payload)
      })
      .catch((err) => {
        throw err
      })

    const integrationMock = jest.spyOn(amplitude.integration!, 'track')
    const ctx = await analytics.track('Hello!')

    // does not modify the event
    expect(ctx.event.properties).not.toEqual({
      hello: 'from the other side',
    })

    const calledWith = integrationMock.mock.calls[0][0].properties()

    // only impacted this destination
    expect(calledWith).toEqual({
      ...ctx.event.properties,
      hello: 'from the other side',
    })
  })
})
Example #13
Source File: readRosterFile.ts    From PrettyScribe with ISC License 5 votes vote down vote up
export async function readZippedRosterFile(filename: string): Promise<Document> {
  const contents: string = fs.readFileSync(filename, 'binary');
  const xmldata = await unzip(contents);
  return new JSDOM(xmldata, { contentType: "text/xml" }).window.document;
}
Example #14
Source File: readRosterFile.ts    From PrettyScribe with ISC License 5 votes vote down vote up
export function readRosterFile(filename: string): Document {
  const xmldata: string = fs.readFileSync(filename, 'binary');
  return new JSDOM(xmldata, { contentType: "text/xml" }).window.document;
}
Example #15
Source File: integration.test.ts    From analytics-next with MIT License 5 votes vote down vote up
describe.skip('Remote Plugin Integration', () => {
  const window = global.window as any

  beforeEach(async () => {
    jest.restoreAllMocks()
    jest.resetAllMocks()

    const html = `
    <!DOCTYPE html>
      <head>
        <script>'hi'</script>
      </head>
      <body>
      </body>
    </html>
    `.trim()

    const jsd = new JSDOM(html, {
      runScripts: 'dangerously',
      resources: 'usable',
      url: 'https://localhost',
    })

    const windowSpy = jest.spyOn(global, 'window', 'get')
    windowSpy.mockImplementation(
      () => jsd.window as unknown as Window & typeof globalThis
    )

    const cdnResponse: LegacySettings = {
      integrations: {},
      remotePlugins: [
        // This may be a bit flaky
        // we should mock this file in case it becomes a problem
        // but I'd like to have a full integration test if possible
        {
          name: 'amplitude',
          url: 'https://ajs-next-integrations.s3-us-west-2.amazonaws.com/fab-5/amplitude-plugins.js',
          libraryName: 'amplitude-pluginsDestination',
          settings: {
            subscriptions: `[{"partnerAction":"sessionId","name":"SessionId","enabled":true,"subscribe":"type = \\"track\\"", "mapping":{}}]`,
          },
        },
      ],
    }

    // @ts-ignore mocking fetch is *hard*
    mocked(unfetch).mockImplementation(
      (): Promise<Response> =>
        // @ts-expect-error
        Promise.resolve({
          json: () => Promise.resolve(cdnResponse),
        })
    )
  })

  it('loads remote plugins', async () => {
    await AnalyticsBrowser.load({
      writeKey: 'test-write-key',
    })

    // loaded remote plugin
    expect(window['amplitude-pluginsDestination']).not.toBeUndefined()
  })
})
Example #16
Source File: ssr.test.tsx    From urx with MIT License 5 votes vote down vote up
describe('SSR component', () => {
  it('sets prop values', () => {
    const html = ReactDOMServer.renderToString(<Component id="root" prop={30} />)
    const { document } = new JSDOM(html).window
    expect(document.querySelector('#root')!.textContent).toEqual('30')
  })
})
Example #17
Source File: card.ts    From github-profile-summary-cards with MIT License 5 votes vote down vote up
constructor(title = 'Title', width = 1280, height = 1024, theme: Theme, xPadding = 30, yPadding = 40) {
        this.title = title;
        this.width = width;
        this.height = height;
        this.xPadding = xPadding;
        this.yPadding = yPadding;
        // use fake dom let us can get html element
        const fakeDom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
        this.body = d3.select(fakeDom.window.document).select('body');
        this.svg = this.body
            .append('div')
            .attr('class', 'container')
            .append('svg')
            .attr('xmlns', 'http://www.w3.org/2000/svg')
            .attr('width', width)
            .attr('height', height)
            .attr('viewBox', `0 0 ${this.width} ${this.height}`);
        this.svg.append('style').html(
            `* {
          font-family: 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif
        }`
        );
        this.svg
            .append('rect')
            .attr('x', 1.5)
            .attr('y', 1.5)
            .attr('rx', 5)
            .attr('ry', 5)
            .attr('height', '98%')
            .attr('width', '98%')
            .attr('stroke', `${theme.stroke}`)
            .attr('stroke-width', '1')
            .attr('fill', `${theme.background}`)
            .attr('stroke-opacity', 1);

        const isEmptyTitle = this.title == '';
        if (!isEmptyTitle) {
            this.svg
                .append('text')
                .attr('x', this.xPadding)
                .attr('y', this.yPadding)
                .style('font-size', `22px`)
                .style('fill', `${theme.title}`)
                .text(this.title);
        }
        this.svg = this.svg.append<SVGSVGElement>('g').attr('transform', 'translate(0,40)');
    }
Example #18
Source File: index.tsx    From shroom with GNU Lesser General Public License v3.0 5 votes vote down vote up
jsdom = new JSDOM()
Example #19
Source File: copyPasting.test.ts    From react-datasheet-grid with MIT License 5 votes vote down vote up
jest.mock('./domParser', () => ({
  parseDom: (html: string) => {
    const dom = new JSDOM(html)
    return dom.window.document
  },
}))
Example #20
Source File: index.d.ts    From amazon-kinesis-video-streams-webrtc-sdk-js-with-amazon-cognito with MIT No Attribution 5 votes vote down vote up
dom: JSDOM | null;
Example #21
Source File: index.d.ts    From amazon-kinesis-video-streams-webrtc-sdk-js-with-amazon-cognito with MIT No Attribution 5 votes vote down vote up
dom: JSDOM | null;
Example #22
Source File: setup.ts    From react-use-intercom with MIT License 5 votes vote down vote up
dom = new JSDOM()
Example #23
Source File: avatar.ts    From ens-metadata-service with MIT License 5 votes vote down vote up
window = new JSDOM('').window
Example #24
Source File: bundler.ts    From fect with MIT License 5 votes vote down vote up
build = async () => {
  const svgs = {}
  await clean()

  const getSource = async () => {
    const source = await getSVGSource()
    const { document } = new JSDOM(source).window
    const icons = document.querySelectorAll('.geist-container > .icon')
    try {
      if (!icons.length) throw new Error("\nCan't found svg elements. please check bundler.ts file.\n")
      const svgo = new Svgo(svgoConfig)
      await Promise.all(
        Array.from(icons).map(async (icon) => {
          const name = camelize(icon.querySelector('.geist-text').textContent)
          const svg = icon.querySelector('svg')
          const { data: optimizeString } = await svgo.optimize(svg.outerHTML)
          const style = svg.getAttribute('style')
          svgs[name] = svgParser(optimizeString, style)
        })
      )
    } catch (error) {
      console.log(error)
      process.exit(1)
    }
  }

  const generatorIconSource = async () => {
    await Promise.all(
      Object.keys(svgs).map(async (svg) => {
        const target = path.join(PACKAGE_PATH, `${svg}.tsx`)
        const name = svg.charAt(0).toUpperCase() + svg.slice(1)
        const component = singleDefine(name, replaceStyle(svgs[svg]))
        await fs.outputFile(target, component)
      })
    )
    await collect()
  }

  const cjsTask = async (input) => {
    const cjs = await bundle({ input, plugins: [transformScript({ babelEnv: 'commonjs' })] })
    await cjs.write({ dir: CJS_PATH })
  }

  const esmTask = async (input) => {
    const cjs = await bundle({ input, plugins: [transformScript({ babelEnv: 'esmodule' })] })
    await cjs.write({ dir: ESM_PATH })
  }

  await runTask('Icon Source', () => getSource())
  await generatorIconSource()
  await runTask('Declaration', () => declarationTask(PACKAGE_PATH))
  await runTask('CommonJs', () => cjsTask(PACKAGE_PATH))
  await runTask('EsModule', () => esmTask(PACKAGE_PATH))
  await clean()
}
Example #25
Source File: setup.ts    From gridjs with MIT License 5 votes vote down vote up
dom = new JSDOM('', {
  // Enable `requestAnimationFrame` which Preact uses internally.
  pretendToBeVisual: true,
})
Example #26
Source File: render.ts    From pintora with MIT License 5 votes vote down vote up
function renderPrepare(opts: CLIRenderOptions) {
  const { code, backgroundColor, pintoraConfig } = opts
  const devicePixelRatio = opts.devicePixelRatio || 2

  const dom = new JSDOM('<!DOCTYPE html><body></body>')
  const document = dom.window.document
  const container = document.createElement('div')
  container.id = 'pintora-container'

  // setup the env for renderer
  global.window = dom.window as any
  global.document = document
  ;(dom.window as any).devicePixelRatio = devicePixelRatio

  return {
    container,
    pintorRender(renderOpts: Pick<RenderOptions, 'renderer'>) {
      if (pintoraConfig) {
        pintoraStandalone.setConfig(pintoraConfig)
      }

      const containerSize = opts.width ? { width: opts.width } : undefined
      if (opts.width) {
        pintoraStandalone.setConfig({
          core: { useMaxWidth: true },
        })
      }

      return new Promise<IRenderer>((resolve, reject) => {
        pintoraStandalone.renderTo(code, {
          container,
          renderer: renderOpts.renderer || 'canvas',
          containerSize,
          enhanceGraphicIR(ir) {
            if (!ir.bgColor) {
              const themeVariables = pintoraStandalone.getConfig<PintoraConfig>().themeConfig.themeVariables
              const newBgColor =
                backgroundColor ||
                themeVariables.canvasBackground ||
                (themeVariables.isDark ? DEFAUT_BGS.dark : DEFAUT_BGS.light)
              ir.bgColor = newBgColor
            }
            return ir
          },
          onRender(renderer) {
            resolve(renderer)
          },
          onError(e) {
            console.error('onError', e)
            reject(e)
          },
        })
      })
    },
  }
}
Example #27
Source File: fakeDOM.ts    From vscode-riscv-venus with MIT License 5 votes vote down vote up
fakeDOM = new JSDOM(`<!DOCTYPE html>`)
Example #28
Source File: jsdom.ts    From mo360-ftk with MIT License 5 votes vote down vote up
setGlobalDomObjects = (url = 'http://localhost:8082/#!/') => {
  const dom: JSDOM = new JSDOM('<html><body></body></html>', { url });
  global.document = dom.window.document;
  global.window = dom.window;
  global.navigator = dom.window.navigator;
}
Example #29
Source File: integration.test.ts    From analytics-next with MIT License 4 votes vote down vote up
describe('.Integrations', () => {
  beforeEach(async () => {
    jest.restoreAllMocks()
    jest.resetAllMocks()

    const html = `
    <!DOCTYPE html>
      <head>
        <script>'hi'</script>
      </head>
      <body>
      </body>
    </html>
    `.trim()

    const jsd = new JSDOM(html, {
      runScripts: 'dangerously',
      resources: 'usable',
      url: 'https://localhost',
    })

    const windowSpy = jest.spyOn(global, 'window', 'get')
    windowSpy.mockImplementation(
      () => jsd.window as unknown as Window & typeof globalThis
    )
  })

  it('lists all legacy destinations', async () => {
    const amplitude = new LegacyDestination(
      'Amplitude',
      'latest',
      {
        apiKey: AMPLITUDE_WRITEKEY,
      },
      {}
    )

    const ga = new LegacyDestination('Google-Analytics', 'latest', {}, {})

    const [analytics] = await AnalyticsBrowser.load({
      writeKey,
      plugins: [amplitude, ga],
    })

    await analytics.ready()

    expect(analytics.Integrations).toMatchInlineSnapshot(`
      Object {
        "Amplitude": [Function],
        "Google-Analytics": [Function],
      }
    `)
  })

  it('catches destinations with dots in their names', async () => {
    const amplitude = new LegacyDestination(
      'Amplitude',
      'latest',
      {
        apiKey: AMPLITUDE_WRITEKEY,
      },
      {}
    )

    const ga = new LegacyDestination('Google-Analytics', 'latest', {}, {})
    const customerIO = new LegacyDestination('Customer.io', 'latest', {}, {})

    const [analytics] = await AnalyticsBrowser.load({
      writeKey,
      plugins: [amplitude, ga, customerIO],
    })

    await analytics.ready()

    expect(analytics.Integrations).toMatchInlineSnapshot(`
      Object {
        "Amplitude": [Function],
        "Customer.io": [Function],
        "Google-Analytics": [Function],
      }
    `)
  })
})