mirror of
https://github.com/hanzoai/insights-js.git
synced 2026-11-03 00:53:53 +00:00
insights-web serves surveys, early access features, web experiments, product tours and the conversations widget at /v1/ and answers /api/ with 404, so every one of these calls failed. Claude-Session: https://claude.ai/code/session_011i2AG9nwpiKUCVxAdDzYuU
144 lines
4.5 KiB
TypeScript
144 lines
4.5 KiB
TypeScript
import { BrowserContext, Page } from '@playwright/test'
|
|
import { ProductTour, ProductTourStep } from '@/insights-product-tours-types'
|
|
import { FeatureFlagDetail } from '@/types'
|
|
import { start, StartOptions } from '../utils/setup'
|
|
import {
|
|
TOUR_SHOWN_KEY_PREFIX,
|
|
TOUR_COMPLETED_KEY_PREFIX,
|
|
TOUR_DISMISSED_KEY_PREFIX,
|
|
ACTIVE_TOUR_SESSION_KEY,
|
|
LAST_SEEN_TOUR_DATE_KEY_PREFIX,
|
|
} from '@/extensions/product-tours/constants'
|
|
|
|
export { ACTIVE_TOUR_SESSION_KEY, LAST_SEEN_TOUR_DATE_KEY_PREFIX }
|
|
|
|
export const tourShownKey = (tourId: string) => `${TOUR_SHOWN_KEY_PREFIX}${tourId}`
|
|
export const tourCompletedKey = (tourId: string) => `${TOUR_COMPLETED_KEY_PREFIX}${tourId}`
|
|
export const tourDismissedKey = (tourId: string) => `${TOUR_DISMISSED_KEY_PREFIX}${tourId}`
|
|
|
|
export const startOptionsWithProductTours: StartOptions = {
|
|
options: {
|
|
disable_product_tours: false,
|
|
},
|
|
flagsResponseOverrides: {
|
|
productTours: true,
|
|
},
|
|
url: './playground/cypress/index.html',
|
|
}
|
|
|
|
const defaultStep: ProductTourStep = {
|
|
id: 'step-1',
|
|
type: 'modal',
|
|
progressionTrigger: 'button',
|
|
content: null,
|
|
contentHtml: '<p>This is a test tour step</p>',
|
|
}
|
|
|
|
export function createStep(overrides: Partial<ProductTourStep> = {}): ProductTourStep {
|
|
return { ...defaultStep, ...overrides }
|
|
}
|
|
|
|
export function createTour(overrides: Partial<ProductTour> = {}): ProductTour {
|
|
const id = overrides.id || 'test-tour'
|
|
return {
|
|
id,
|
|
name: `Test Tour ${id}`,
|
|
tour_type: 'tour',
|
|
auto_launch: true,
|
|
start_date: '2021-01-01T00:00:00Z',
|
|
end_date: null,
|
|
steps: [createStep()],
|
|
display_frequency: 'until_interacted',
|
|
...overrides,
|
|
}
|
|
}
|
|
|
|
export function createElementStep(
|
|
selector: string,
|
|
overrides: Partial<ProductTourStep> = {},
|
|
asModal?: boolean
|
|
): ProductTourStep {
|
|
return createStep({
|
|
type: asModal ? 'modal' : 'element',
|
|
selector,
|
|
useManualSelector: true,
|
|
...overrides,
|
|
})
|
|
}
|
|
|
|
export function createBannerStep(overrides: Partial<ProductTourStep> = {}): ProductTourStep {
|
|
return createStep({
|
|
type: 'banner',
|
|
contentHtml: '<p>Banner content</p>',
|
|
bannerConfig: { behavior: 'static' },
|
|
...overrides,
|
|
})
|
|
}
|
|
|
|
export function mockProductToursApi(page: Page, tours: ProductTour[]) {
|
|
return page.route('**/v1/product_tours/**', async (route) => {
|
|
await route.fulfill({
|
|
json: { product_tours: tours },
|
|
})
|
|
})
|
|
}
|
|
|
|
export function tourContainer(page: Page, tourId: string) {
|
|
return page.locator(`.ph-product-tour-container-${tourId}`)
|
|
}
|
|
|
|
export function tourTooltip(page: Page, tourId: string) {
|
|
return tourContainer(page, tourId).locator('.ph-tour-tooltip')
|
|
}
|
|
|
|
export function createFlagsOverride(
|
|
flags: Record<string, { enabled: boolean; variant?: string }>
|
|
): Record<string, FeatureFlagDetail> {
|
|
return Object.fromEntries(
|
|
Object.entries(flags).map(([key, { enabled, variant }]) => [
|
|
key,
|
|
{
|
|
key,
|
|
enabled,
|
|
variant,
|
|
reason: { code: 'condition_match', condition_index: 0, description: 'Matched' },
|
|
metadata: { id: 1, version: 1, description: undefined, payload: undefined },
|
|
} as FeatureFlagDetail,
|
|
])
|
|
)
|
|
}
|
|
|
|
export async function startWithTours(
|
|
page: Page,
|
|
context: BrowserContext,
|
|
tours: ProductTour[],
|
|
options: { waitForApiResponse?: boolean; startOptions?: StartOptions } = {}
|
|
): Promise<void> {
|
|
const { waitForApiResponse = false, startOptions = startOptionsWithProductTours } = options
|
|
|
|
const toursApiRoute = mockProductToursApi(page, tours)
|
|
|
|
if (waitForApiResponse) {
|
|
const toursResponse = page.waitForResponse('**/v1/product_tours/**')
|
|
await start(startOptions, page, context)
|
|
await toursApiRoute
|
|
await toursResponse
|
|
} else {
|
|
await start(startOptions, page, context)
|
|
await toursApiRoute
|
|
}
|
|
}
|
|
|
|
export function getSessionState(page: Page): Promise<{ tourId?: string; stepIndex?: number }> {
|
|
return page.evaluate((key) => JSON.parse(sessionStorage.getItem(key) || '{}'), ACTIVE_TOUR_SESSION_KEY)
|
|
}
|
|
|
|
export function captureEvent(page: Page, eventName: string, properties?: Record<string, unknown>): Promise<void> {
|
|
return page.evaluate(
|
|
({ name, props }) => {
|
|
;(window as any).insights.capture(name, props)
|
|
},
|
|
{ name: eventName, props: properties }
|
|
)
|
|
}
|