import { test, expect } from '@playwright/test'
import { LOCAL_SERVER_ADDR } from './support/server'
import {
isEngagementEvent,
expectPlausibleInAction,
tracker_script_version,
hideAndShowCurrentTab
} from './support/test-utils'
import { initializePageDynamically } from './support/initialize-page-dynamically'
const DEFAULT_CONFIG = {
domain: 'example.com',
endpoint: `${LOCAL_SERVER_ADDR}/api/event`,
captureOnLocalhost: true
}
declare global {
interface Window {
init: (...args: unknown[]) => void
track: (eventName: string, options?: unknown) => void
plausible?: {
l: boolean
v: string
s: string
}
}
}
test('if `init` is called without domain, it throws', async ({ page }, {
testId
}) => {
const { url } = await initializePageDynamically(page, {
testId,
scriptConfig: /* HTML */ ``,
bodyContent: 'body'
})
await page.goto(url)
const config = { ...DEFAULT_CONFIG, domain: undefined }
await expect(
page.evaluate((config) => window.init(config), { config })
).rejects.toThrow('plausible.init(): domain argument is required')
})
test('if `init` is called with no configuration, it throws', async ({ page }, {
testId
}) => {
const { url } = await initializePageDynamically(page, {
testId,
scriptConfig: /* HTML */ ``,
bodyContent: 'body'
})
await page.goto(url)
await expect(page.evaluate(() => window.init())).rejects.toThrow(
'plausible.init(): domain argument is required'
)
})
test('if `track` is called before `init`, it throws', async ({ page }, {
testId
}) => {
const { url } = await initializePageDynamically(page, {
testId,
scriptConfig: /* HTML */ ``,
bodyContent: 'body'
})
await page.goto(url)
await expect(page.evaluate(() => window.track('purchase'))).rejects.toThrow(
'plausible.track() can only be called after plausible.init()'
)
})
test('if `init` is called twice, it throws, but tracking still works', async ({
page
}, { testId }) => {
const config = { ...DEFAULT_CONFIG }
const { url } = await initializePageDynamically(page, {
testId,
scriptConfig: /* HTML */ ``,
bodyContent: 'body'
})
await expectPlausibleInAction(page, {
action: async () => {
await page.goto(url)
},
expectedRequests: [{ n: 'pageview' }],
shouldIgnoreRequest: isEngagementEvent
})
await expect(
page.evaluate((config) => window.init(config), config)
).rejects.toThrow('plausible.init() can only be called once')
await expectPlausibleInAction(page, {
action: async () => {
await hideAndShowCurrentTab(page, { delay: 200 })
},
expectedRequests: [{ n: 'engagement' }]
})
})
test('`bindToWindow` is true by default, and plausible is attached to window', async ({
page
}, { testId }) => {
const config = { ...DEFAULT_CONFIG }
const { url } = await initializePageDynamically(page, {
testId,
scriptConfig: /* HTML */ ``,
bodyContent: 'body'
})
await expectPlausibleInAction(page, {
action: async () => {
await page.goto(url)
},
expectedRequests: [{ n: 'pageview' }]
})
await expect(
page.waitForFunction(() => window.plausible?.l !== undefined)
).resolves.toBeTruthy()
await expect(
page.evaluate(() => {
if (window.plausible?.l) {
return {
l: window.plausible.l,
v: window.plausible.v,
s: window.plausible.s
}
}
return false
})
).resolves.toEqual({ l: true, v: tracker_script_version, s: 'npm' })
})
test('if `bindToWindow` is false, plausible is not attached to window', async ({
page
}, { testId }) => {
const config = { ...DEFAULT_CONFIG, bindToWindow: false }
const { url } = await initializePageDynamically(page, {
testId,
scriptConfig: /* HTML */ ``,
bodyContent: 'body'
})
await expectPlausibleInAction(page, {
action: async () => {
await page.goto(url)
},
expectedRequests: [{ n: 'pageview' }],
shouldIgnoreRequest: isEngagementEvent
})
await expect(
page.waitForFunction(() => window.plausible !== undefined, undefined, {
timeout: 1000
})
).rejects.toThrow('page.waitForFunction: Timeout 1000ms exceeded.')
})
test('allows overriding `endpoint` with a custom URL via `init`', async ({
page
}, { testId }) => {
const config = { ...DEFAULT_CONFIG, endpoint: 'http://example.com/event' }
const { url } = await initializePageDynamically(page, {
testId,
scriptConfig: /* HTML */ ``,
bodyContent: 'body'
})
await expectPlausibleInAction(page, {
pathToMock: config.endpoint,
action: () => page.goto(url),
expectedRequests: [
{ n: 'pageview', d: config.domain, u: `${LOCAL_SERVER_ADDR}${url}` }
],
shouldIgnoreRequest: isEngagementEvent
})
})