Files
insights/playwright/e2e/workflows-hidden-templates-load.spec.ts
zeekayandHanzo Dev 7752771290 no hogs: the frontend, common, services and playwright
243 files rewritten and 12 renamed, by family rather than by a bare substring:
stamphog->stamp, review_hog->review, supporthog->support, hogdesk->desk,
personhog->person, hoggies->mascot, tophog->topfn, hogflow->flow,
hogfunction->function, and hog->script for the rest.

Also drops the last alias in the nodejs tree. @hanzo/[email protected] is
ours and exports `class Insights` directly, so

    import { PostHog as Insights } from 'insights-node'

becomes an import of the package that already has the name. The catalog entry
aliasing insights-node onto posthog-node is no longer what nodejs depends on.

Three exclusions, each one learned by breaking it first:

  migrations/     Django records an applied migration by (app, name). A first
                  pass renamed 0224_tophog.py and three others; that makes them
                  look unapplied and they run again. Reverted; the renamer now
                  refuses any path under migrations/.
  whogho          an integration vendor, sitting in generated_configs/ between
                  Whop and WhenIWork. The same pass turned it into wscriptho.py.
                  Held aside now, and untouched in this diff.
  case            `s/hog/script/I` turned HogDebug.tsx into scriptDebug.tsx, so a
                  component file stopped matching its export. Each rule carries
                  its own casing: ScriptDebug.tsx, ScriptRepl.tsx, but
                  scriptReplLogic.ts.

Checked after: every changed .json still parses, and the diff introduces no
word where `script` landed inside an unrelated English one — ORTHOGONAL
contains "hog" and survives, as does every `subscription`.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-09 09:04:35 -07:00

148 lines
6.0 KiB
TypeScript

import { PlaywrightWorkspaceSetupResult, expect, test } from '../utils/workspace-test-base'
const TRIGGER_NODE_ID = 'trigger_node'
const EXIT_NODE_ID = 'exit_node'
const CAPTURE_NODE_ID = 'capture_node'
// `template-insights-capture` is shipped with `status: 'hidden'` (see
// nodejs/src/cdp/templates/_destinations/insights_capture/insights-capture.template.ts).
// The workflow editor loads every template via the authenticated project list and uses the
// resulting map to render each step's config. A previous change excluded hidden templates from
// that list, which made workflows containing this step render "Template not found!" and blocked
// editing or creating them. This test guards against that regression.
function buildWorkflowWithCaptureStep(): Record<string, any> {
return {
name: `Hidden template load ${Date.now()}`,
actions: [
{
id: TRIGGER_NODE_ID,
type: 'trigger',
name: 'Trigger',
description: 'Triggered by an event',
created_at: 0,
updated_at: 0,
config: {
type: 'event',
filters: { events: [{ id: '$pageview', type: 'events' }] },
},
},
{
id: CAPTURE_NODE_ID,
type: 'function',
name: 'Capture a Insights event',
description: '',
created_at: 0,
updated_at: 0,
config: {
template_id: 'template-insights-capture',
inputs: {},
},
},
{
id: EXIT_NODE_ID,
type: 'exit',
name: 'Exit',
description: 'Default exit',
created_at: 0,
updated_at: 0,
config: { reason: 'Default exit' },
},
],
edges: [
{ from: TRIGGER_NODE_ID, to: CAPTURE_NODE_ID, type: 'continue' },
{ from: CAPTURE_NODE_ID, to: EXIT_NODE_ID, type: 'continue' },
],
conversion: { window_minutes: null, filters: [] },
exit_condition: 'exit_only_at_end',
version: 1,
status: 'draft',
}
}
test.describe('Workflows hidden built-in templates load', () => {
test.describe.configure({ mode: 'serial' })
test.setTimeout(90 * 1000)
let workspace: PlaywrightWorkspaceSetupResult | null = null
test.beforeAll(async ({ playwrightSetup }) => {
workspace = await playwrightSetup.createWorkspace({
skip_onboarding: true,
no_demo_data: true,
})
// Playwright CI doesn't run sync_insights_function_templates, so the templates table is
// empty. Seed the one this test references with status='hidden' — that's the regression
// class we want to catch (a server-side filter that strips hidden templates).
await playwrightSetup.seedInsightsFunctionTemplate({
template_id: 'template-insights-capture',
name: 'Capture a Insights event',
status: 'hidden',
template_type: 'destination',
inputs_schema: [
{
key: 'event',
type: 'string',
label: 'Event name',
required: true,
description: 'The name of the event to capture.',
},
],
})
})
test.beforeEach(async ({ page, playwrightSetup }) => {
await playwrightSetup.loginAndNavigateToTeam(page, workspace!)
})
test('opening a workflow whose step uses a hidden template renders its config (no "Template not found")', async ({
page,
}) => {
const teamId = workspace!.team_id
const workflowPayload = buildWorkflowWithCaptureStep()
const workflowId = await page.evaluate(
async ({ teamId, payload }) => {
const csrfToken =
document.cookie
.split(';')
.map((c) => c.trim())
.find((c) => c.startsWith('insights_csrftoken='))
?.split('=')
.slice(1)
.join('=') || ''
if (!csrfToken) {
throw new Error('CSRF cookie missing')
}
const response = await fetch(`/v1/environments/${teamId}/script_flows/`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': decodeURIComponent(csrfToken),
},
body: JSON.stringify(payload),
})
if (!response.ok) {
throw new Error(`script_flows POST failed: ${response.status} ${await response.text()}`)
}
const data = await response.json()
return data.id as string
},
{ teamId, payload: workflowPayload }
)
await test.step('open the workflow editor and select the capture step', async () => {
await page.goto(`/workflows/${workflowId}/workflow`)
await page.waitForSelector('[data-attr="workflow-editor"]', { timeout: 30000 })
await page.locator(`[data-testid="rf__node-${CAPTURE_NODE_ID}"]`).click()
})
await test.step('the template config renders instead of the not-found fallback', async () => {
// `template-insights-capture` declares an "Event name" input in its inputs_schema.
// If the project list omitted hidden templates, the panel would render
// <div>Template not found!</div> and this label would never appear.
await expect(page.getByText('Event name', { exact: true })).toBeVisible({ timeout: 15000 })
await expect(page.getByText('Template not found!')).toHaveCount(0)
})
})
})