mirror of
https://github.com/hanzoai/insights-js.git
synced 2026-11-03 00:53:53 +00:00
# Conflicts: # .github/workflows/check-insights-major-version.yml # .github/workflows/check-posthog-major-version.yml # .github/workflows/ci-security.yaml # .github/workflows/validate-versioning.yml # AGENTS.md # AGENTS.md~upstream_main # packages/ai/src/otel/capture.ts # packages/ai/src/otel/mappers/aiSdk.ts # packages/ai/src/otel/mappers/index.ts # packages/ai/src/otel/types.ts # packages/core/src/__tests__/posthog.init.spec.ts # packages/react-native/src/PostHogProvider.tsx # packages/react/src/context/PostHogContext.ts # packages/react/src/context/PostHogProvider.tsx # tooling/eslint-plugin-insights/no-unsafe-web-global.js
189 lines
6.9 KiB
TypeScript
189 lines
6.9 KiB
TypeScript
import { expect, test } from './utils/insights-playwright-test-base'
|
|
import { start } from './utils/setup'
|
|
import { pollUntilEventCaptured } from './utils/event-capture-utils'
|
|
|
|
const startOptions = {
|
|
options: {
|
|
capture_dead_clicks: true,
|
|
},
|
|
url: '/playground/cypress/index.html',
|
|
}
|
|
|
|
test.describe('Dead clicks', () => {
|
|
test('capture dead clicks when configured to', async ({ page, context }) => {
|
|
await start(startOptions, page, context)
|
|
|
|
await page.locator('[data-cy-not-an-order-button]').click()
|
|
|
|
await pollUntilEventCaptured(page, '$dead_click')
|
|
|
|
const deadClicks = (await page.capturedEvents()).filter((event) => event.event === '$dead_click')
|
|
expect(deadClicks.length).toBe(1)
|
|
const deadClick = deadClicks[0]
|
|
|
|
// this assertion flakes, sometimes there is no $dead_click_last_mutation_timestamp
|
|
//expect(deadClick.properties.$dead_click_last_mutation_timestamp).toBeGreaterThan(0)
|
|
expect(deadClick.properties.$dead_click_event_timestamp).toBeGreaterThan(0)
|
|
expect(deadClick.properties.$dead_click_absolute_delay_ms).toBeGreaterThan(0)
|
|
expect(deadClick.properties.$dead_click_scroll_timeout).toBe(false)
|
|
expect(deadClick.properties.$dead_click_mutation_timeout).toBe(false)
|
|
expect(deadClick.properties.$dead_click_absolute_timeout).toBe(true)
|
|
})
|
|
|
|
test('does not capture dead click when ctrl key is held', async ({ page, context }) => {
|
|
await start(startOptions, page, context)
|
|
|
|
await page.resetCapturedEvents()
|
|
|
|
await page.locator('[data-cy-not-an-order-button]').click({ modifiers: ['Control'] })
|
|
|
|
// wait long enough for a dead click to be detected if it was going to be
|
|
await page.waitForTimeout(3500)
|
|
|
|
const deadClicks = (await page.capturedEvents()).filter((event) => event.event === '$dead_click')
|
|
expect(deadClicks.length).toBe(0)
|
|
})
|
|
|
|
test('does not capture dead click when meta/cmd key is held', async ({ page, context }) => {
|
|
await start(startOptions, page, context)
|
|
|
|
await page.resetCapturedEvents()
|
|
|
|
await page.locator('[data-cy-not-an-order-button]').click({ modifiers: ['Meta'] })
|
|
|
|
await page.waitForTimeout(3500)
|
|
|
|
const deadClicks = (await page.capturedEvents()).filter((event) => event.event === '$dead_click')
|
|
expect(deadClicks.length).toBe(0)
|
|
})
|
|
|
|
test('does not capture dead click when shift key is held', async ({ page, context }) => {
|
|
await start(startOptions, page, context)
|
|
|
|
await page.resetCapturedEvents()
|
|
|
|
await page.locator('[data-cy-not-an-order-button]').click({ modifiers: ['Shift'] })
|
|
|
|
await page.waitForTimeout(3500)
|
|
|
|
const deadClicks = (await page.capturedEvents()).filter((event) => event.event === '$dead_click')
|
|
expect(deadClicks.length).toBe(0)
|
|
})
|
|
|
|
test('does not capture dead click when alt key is held', async ({ page, context }) => {
|
|
await start(startOptions, page, context)
|
|
|
|
await page.resetCapturedEvents()
|
|
|
|
await page.locator('[data-cy-not-an-order-button]').click({ modifiers: ['Alt'] })
|
|
|
|
await page.waitForTimeout(3500)
|
|
|
|
const deadClicks = (await page.capturedEvents()).filter((event) => event.event === '$dead_click')
|
|
expect(deadClicks.length).toBe(0)
|
|
})
|
|
|
|
test('captures dead click with modifier key when capture_clicks_with_modifier_keys is true', async ({
|
|
page,
|
|
context,
|
|
}) => {
|
|
await start(
|
|
{
|
|
options: {
|
|
capture_dead_clicks: {
|
|
capture_clicks_with_modifier_keys: true,
|
|
},
|
|
},
|
|
url: '/playground/cypress/index.html',
|
|
},
|
|
page,
|
|
context
|
|
)
|
|
|
|
// Wait for dead clicks extension to be fully loaded
|
|
await page.waitForFunction(
|
|
() => {
|
|
const win = window as any
|
|
return !!win.insights?.deadClicksAutocapture?.lazyLoadedDeadClicksAutocapture
|
|
},
|
|
{ timeout: 10000 }
|
|
)
|
|
|
|
await page.resetCapturedEvents()
|
|
|
|
// Use Shift modifier since Ctrl+Click triggers contextmenu instead of click in some browsers
|
|
await page.locator('[data-cy-not-an-order-button]').click({ modifiers: ['Shift'] })
|
|
|
|
await pollUntilEventCaptured(page, '$dead_click')
|
|
|
|
const deadClicks = (await page.capturedEvents()).filter((event) => event.event === '$dead_click')
|
|
expect(deadClicks.length).toBe(1)
|
|
})
|
|
|
|
test('does not capture dead click when visibility changes to visible after click', async ({ page, context }) => {
|
|
await start(startOptions, page, context)
|
|
|
|
await page.resetCapturedEvents()
|
|
|
|
await page.locator('[data-cy-not-an-order-button]').click()
|
|
|
|
await page.evaluate(() => {
|
|
Object.defineProperty(document, 'visibilityState', { value: 'visible', writable: true })
|
|
document.dispatchEvent(new Event('visibilitychange'))
|
|
})
|
|
|
|
await page.waitForTimeout(3500)
|
|
|
|
const deadClicks = (await page.capturedEvents()).filter((event) => event.event === '$dead_click')
|
|
expect(deadClicks.length).toBe(0)
|
|
})
|
|
|
|
test('does not capture dead click when visibility changes to visible just before click', async ({
|
|
page,
|
|
context,
|
|
}) => {
|
|
await start(startOptions, page, context)
|
|
|
|
await page.resetCapturedEvents()
|
|
|
|
await page.evaluate(() => {
|
|
Object.defineProperty(document, 'visibilityState', { value: 'visible', writable: true })
|
|
document.dispatchEvent(new Event('visibilitychange'))
|
|
})
|
|
|
|
await page.locator('[data-cy-not-an-order-button]').click()
|
|
|
|
await page.waitForTimeout(3500)
|
|
|
|
const deadClicks = (await page.capturedEvents()).filter((event) => event.event === '$dead_click')
|
|
expect(deadClicks.length).toBe(0)
|
|
})
|
|
|
|
test('does not capture dead click for selected text', async ({ page, context }) => {
|
|
await start(startOptions, page, context)
|
|
|
|
await page.resetCapturedEvents()
|
|
|
|
const locator = page.locator('[data-cy-dead-click-text]')
|
|
const boundingBox = await locator.boundingBox()
|
|
if (!boundingBox) {
|
|
throw new Error('must get a bounding box')
|
|
}
|
|
const position = boundingBox.x + boundingBox.width / 2
|
|
const wordToSelectLength = 50
|
|
|
|
await page.mouse.move(position, boundingBox.y)
|
|
|
|
await page.mouse.down()
|
|
await page.mouse.move(position + wordToSelectLength, boundingBox.y)
|
|
await page.mouse.up()
|
|
await page.mouse.dblclick(position, boundingBox.y)
|
|
|
|
const selection = await page.evaluate(() => window.getSelection()?.toString())
|
|
expect(selection?.trim().length).toBeGreaterThan(0)
|
|
|
|
await page.waitForTimeout(1000)
|
|
await page.expectCapturedEventsToBe([])
|
|
})
|
|
})
|