@noego/wood 0.4.8 → 0.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/axe.js +313 -98
- package/bin/wood.js +7 -1
- package/dist/automation/actions.cjs +17 -0
- package/dist/automation/actions.cjs.map +1 -0
- package/dist/automation/actions.d.cts +57 -0
- package/dist/automation/actions.d.ts +57 -0
- package/dist/automation/actions.js +1 -0
- package/dist/automation/actions.js.map +1 -0
- package/dist/automation/actions_executor.cjs +101 -0
- package/dist/automation/actions_executor.cjs.map +1 -0
- package/dist/automation/actions_executor.d.cts +16 -0
- package/dist/automation/actions_executor.d.ts +16 -0
- package/dist/automation/actions_executor.js +76 -0
- package/dist/automation/actions_executor.js.map +1 -0
- package/dist/automation/connection.cjs +86 -0
- package/dist/automation/connection.cjs.map +1 -0
- package/dist/automation/connection.d.cts +18 -0
- package/dist/automation/connection.d.ts +18 -0
- package/dist/automation/connection.js +51 -0
- package/dist/automation/connection.js.map +1 -0
- package/dist/automation/errors.cjs +50 -0
- package/dist/automation/errors.cjs.map +1 -0
- package/dist/automation/errors.d.cts +31 -0
- package/dist/automation/errors.d.ts +31 -0
- package/dist/automation/errors.js +24 -0
- package/dist/automation/errors.js.map +1 -0
- package/dist/automation/index.cjs +49 -0
- package/dist/automation/index.cjs.map +1 -0
- package/dist/automation/index.d.cts +16 -0
- package/dist/automation/index.d.ts +16 -0
- package/dist/automation/index.js +15 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/automation/introspection_reader.cjs +75 -0
- package/dist/automation/introspection_reader.cjs.map +1 -0
- package/dist/automation/introspection_reader.d.cts +20 -0
- package/dist/automation/introspection_reader.d.ts +20 -0
- package/dist/automation/introspection_reader.js +48 -0
- package/dist/automation/introspection_reader.js.map +1 -0
- package/dist/automation/locator.cjs +102 -0
- package/dist/automation/locator.cjs.map +1 -0
- package/dist/automation/locator.d.cts +51 -0
- package/dist/automation/locator.d.ts +51 -0
- package/dist/automation/locator.js +75 -0
- package/dist/automation/locator.js.map +1 -0
- package/dist/automation/observation.cjs +17 -0
- package/dist/automation/observation.cjs.map +1 -0
- package/dist/automation/observation.d.cts +44 -0
- package/dist/automation/observation.d.ts +44 -0
- package/dist/automation/observation.js +1 -0
- package/dist/automation/observation.js.map +1 -0
- package/dist/automation/receipts.cjs +17 -0
- package/dist/automation/receipts.cjs.map +1 -0
- package/dist/automation/receipts.d.cts +27 -0
- package/dist/automation/receipts.d.ts +27 -0
- package/dist/automation/receipts.js +1 -0
- package/dist/automation/receipts.js.map +1 -0
- package/dist/automation/scenario.cjs +696 -0
- package/dist/automation/scenario.cjs.map +1 -0
- package/dist/automation/scenario.d.cts +89 -0
- package/dist/automation/scenario.d.ts +89 -0
- package/dist/automation/scenario.js +660 -0
- package/dist/automation/scenario.js.map +1 -0
- package/dist/automation/scrolling.cjs +17 -0
- package/dist/automation/scrolling.cjs.map +1 -0
- package/dist/automation/scrolling.d.cts +51 -0
- package/dist/automation/scrolling.d.ts +51 -0
- package/dist/automation/scrolling.js +1 -0
- package/dist/automation/scrolling.js.map +1 -0
- package/dist/automation/scrolling_executor.cjs +109 -0
- package/dist/automation/scrolling_executor.cjs.map +1 -0
- package/dist/automation/scrolling_executor.d.cts +13 -0
- package/dist/automation/scrolling_executor.d.ts +13 -0
- package/dist/automation/scrolling_executor.js +84 -0
- package/dist/automation/scrolling_executor.js.map +1 -0
- package/dist/automation/target_identity.cjs +17 -0
- package/dist/automation/target_identity.cjs.map +1 -0
- package/dist/automation/target_identity.d.cts +28 -0
- package/dist/automation/target_identity.d.ts +28 -0
- package/dist/automation/target_identity.js +1 -0
- package/dist/automation/target_identity.js.map +1 -0
- package/dist/automation/target_registry.cjs +148 -0
- package/dist/automation/target_registry.cjs.map +1 -0
- package/dist/automation/target_registry.d.cts +32 -0
- package/dist/automation/target_registry.d.ts +32 -0
- package/dist/automation/target_registry.js +122 -0
- package/dist/automation/target_registry.js.map +1 -0
- package/dist/automation/waits.cjs +17 -0
- package/dist/automation/waits.cjs.map +1 -0
- package/dist/automation/waits.d.cts +44 -0
- package/dist/automation/waits.d.ts +44 -0
- package/dist/automation/waits.js +1 -0
- package/dist/automation/waits.js.map +1 -0
- package/dist/automation/waits_executor.cjs +104 -0
- package/dist/automation/waits_executor.cjs.map +1 -0
- package/dist/automation/waits_executor.d.cts +14 -0
- package/dist/automation/waits_executor.d.ts +14 -0
- package/dist/automation/waits_executor.js +79 -0
- package/dist/automation/waits_executor.js.map +1 -0
- package/dist/client/index.d.cts +1 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/codegen/renderer_app_generator.cjs +16 -1
- package/dist/codegen/renderer_app_generator.cjs.map +1 -1
- package/dist/codegen/renderer_app_generator.js +16 -1
- package/dist/codegen/renderer_app_generator.js.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/navigation/automation_introspection.cjs +110 -0
- package/dist/navigation/automation_introspection.cjs.map +1 -0
- package/dist/navigation/automation_introspection.d.cts +60 -0
- package/dist/navigation/automation_introspection.d.ts +60 -0
- package/dist/navigation/automation_introspection.js +85 -0
- package/dist/navigation/automation_introspection.js.map +1 -0
- package/dist/navigation/index.cjs +7 -2
- package/dist/navigation/index.cjs.map +1 -1
- package/dist/navigation/index.d.cts +2 -0
- package/dist/navigation/index.d.ts +2 -0
- package/dist/navigation/index.js +4 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/testing/automation_assertions.cjs +417 -0
- package/dist/testing/automation_assertions.cjs.map +1 -0
- package/dist/testing/automation_assertions.d.cts +44 -0
- package/dist/testing/automation_assertions.d.ts +44 -0
- package/dist/testing/automation_assertions.js +385 -0
- package/dist/testing/automation_assertions.js.map +1 -0
- package/dist/testing/browser.cjs +26 -34
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +2 -1
- package/dist/testing/browser.d.ts +2 -1
- package/dist/testing/browser.js +30 -31
- package/dist/testing/browser.js.map +1 -1
- package/dist/testing/create_controller_harness.d.cts +1 -0
- package/dist/testing/create_controller_harness.d.ts +1 -0
- package/dist/testing/geometry.cjs +109 -0
- package/dist/testing/geometry.cjs.map +1 -0
- package/dist/testing/geometry.d.cts +45 -0
- package/dist/testing/geometry.d.ts +45 -0
- package/dist/testing/geometry.js +79 -0
- package/dist/testing/geometry.js.map +1 -0
- package/dist/testing/index.cjs +31 -2
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +4 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.js +31 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/tracing/trace_hub.cjs +3 -0
- package/dist/tracing/trace_hub.cjs.map +1 -1
- package/dist/tracing/trace_hub.js +3 -0
- package/dist/tracing/trace_hub.js.map +1 -1
- package/package.json +7 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/automation/scenario.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Browser, ConsoleMessage, Page, Request } from 'playwright';\nimport type { WoodAutomationAction } from './actions.js';\nimport { executeAction } from './actions_executor.js';\nimport { automationError, automationOk, type WoodAutomationError, type WoodAutomationResult } from './errors.js';\nimport type { WoodConsoleEntry } from './observation.js';\nimport type { WoodActionReceipt } from './receipts.js';\nimport type { WoodScrollCommand, WoodScrollContainer } from './scrolling.js';\nimport { discoverTargets, selectTarget } from './target_registry.js';\nimport type { WoodWaitCondition } from './waits.js';\nimport { awaitCondition } from './waits_executor.js';\nimport type { WoodLocator } from './locator.js';\n\nconst EXPECT_TIMEOUT_MS = 2_000;\nconst ACTION_KINDS = [\n 'click',\n 'double_click',\n 'fill',\n 'type',\n 'press',\n 'select',\n 'toggle',\n 'scroll',\n 'back',\n 'forward',\n 'reload',\n 'wait',\n] as const;\nconst WAIT_KINDS = [\n 'route',\n 'url',\n 'target',\n 'visible',\n 'hidden',\n 'attached',\n 'detached',\n 'enabled',\n 'trace',\n 'scroll_edge',\n 'visual_stable',\n 'app_idle',\n] as const;\n\nexport interface WoodScenario {\n version: 1;\n target?: { windowId?: string };\n evidence?: {\n screenshot?: 'on-failure' | 'always' | 'off';\n console?: boolean;\n };\n steps: Array<{\n name?: string;\n action: WoodAutomationAction;\n wait?: WoodWaitCondition;\n expect?: WoodWaitCondition[];\n }>;\n}\n\nexport interface WoodScenarioStepReport {\n index: number;\n name?: string;\n startedAt: string;\n durationMs: number;\n receipt: WoodActionReceipt;\n evidence: string[];\n}\n\nexport interface WoodScenarioReport {\n startedAt: string;\n completedAt: string;\n durationMs: number;\n success: true;\n receipts: WoodActionReceipt[];\n steps: WoodScenarioStepReport[];\n evidence: string[];\n console: WoodConsoleEntry[];\n}\n\nexport type WoodScenarioEvent =\n | { kind: 'scenario_started'; startedAt: string; stepCount: number }\n | { kind: 'step_started'; stepIndex: number; stepName?: string; startedAt: string }\n | {\n kind: 'step_completed';\n stepIndex: number;\n stepName?: string;\n receipt: WoodActionReceipt;\n durationMs: number;\n evidence: string[];\n }\n | {\n kind: 'step_failed';\n stepIndex: number;\n stepName?: string;\n error: WoodAutomationError;\n durationMs: number;\n evidence: string[];\n }\n | {\n kind: 'scenario_completed';\n stepIndex?: number;\n stepName?: string;\n receipt?: WoodActionReceipt;\n error?: WoodAutomationError;\n startedAt: string;\n completedAt: string;\n durationMs: number;\n success: boolean;\n };\n\nexport interface WoodScenarioHooks {\n onEvent: (event: WoodScenarioEvent) => void;\n evidenceDir?: string;\n}\n\ntype Validation<T> = { ok: true; value: T } | { ok: false; message: string };\n\nfunction valid<T>(value: T): Validation<T> {\n return { ok: true, value };\n}\n\nfunction invalid<T = never>(message: string): Validation<T> {\n return { ok: false, message };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction requireRecord(value: unknown, at: string): Validation<Record<string, unknown>> {\n return isRecord(value) ? valid(value) : invalid(`${at} must be an object.`);\n}\n\nfunction requireString(value: unknown, at: string): Validation<string> {\n return typeof value === 'string' && value.length > 0\n ? valid(value)\n : invalid(`${at} must be a non-empty string.`);\n}\n\nfunction optionalBoolean(value: unknown, at: string): Validation<boolean | undefined> {\n return value === undefined || typeof value === 'boolean'\n ? valid(value)\n : invalid(`${at} must be a boolean when provided.`);\n}\n\nfunction optionalNumber(value: unknown, at: string): Validation<number | undefined> {\n return value === undefined || (typeof value === 'number' && Number.isFinite(value))\n ? valid(value)\n : invalid(`${at} must be a finite number when provided.`);\n}\n\nfunction stringRecord(value: unknown, at: string): Validation<Record<string, string> | undefined> {\n if (value === undefined) return valid(undefined);\n if (!isRecord(value)) return invalid(`${at} must be an object of string values.`);\n const result: Record<string, string> = {};\n for (const [key, item] of Object.entries(value)) {\n if (typeof item !== 'string') return invalid(`${at}.${key} must be a string.`);\n result[key] = item;\n }\n return valid(result);\n}\n\nfunction parseLocator(value: unknown, at: string): Validation<WoodLocator> {\n const object = requireRecord(value, at);\n if (!object.ok) return object;\n const kind = object.value.kind;\n if (kind === 'role') {\n const role = requireString(object.value.role, `${at}.role`);\n if (!role.ok) return role;\n if (object.value.name !== undefined && typeof object.value.name !== 'string') {\n return invalid(`${at}.name must be a string when provided.`);\n }\n const exact = optionalBoolean(object.value.exact, `${at}.exact`);\n if (!exact.ok) return exact;\n return valid({\n kind,\n role: role.value,\n ...(object.value.name !== undefined ? { name: object.value.name as string } : {}),\n ...(exact.value !== undefined ? { exact: exact.value } : {}),\n });\n }\n if (!['test_id', 'label', 'placeholder', 'text', 'css'].includes(String(kind))) {\n return invalid(`${at}.kind must be one of test_id, role, label, placeholder, text, css.`);\n }\n const text = requireString(object.value.value, `${at}.value`);\n if (!text.ok) return text;\n if (kind === 'css' || kind === 'test_id') return valid({ kind, value: text.value } as WoodLocator);\n const exact = optionalBoolean(object.value.exact, `${at}.exact`);\n if (!exact.ok) return exact;\n return valid({\n kind: kind as 'label' | 'placeholder' | 'text',\n value: text.value,\n ...(exact.value !== undefined ? { exact: exact.value } : {}),\n });\n}\n\nfunction parseContainer(value: unknown, at: string): Validation<WoodScrollContainer> {\n const object = requireRecord(value, at);\n if (!object.ok) return object;\n if (object.value.kind === 'viewport') return valid({ kind: 'viewport' });\n if (object.value.kind !== 'locator') {\n return invalid(`${at}.kind must be viewport or locator.`);\n }\n const target = parseLocator(object.value.target, `${at}.target`);\n return target.ok ? valid({ kind: 'locator', target: target.value }) : target;\n}\n\nfunction parseScroll(value: unknown, at: string): Validation<WoodScrollCommand> {\n const object = requireRecord(value, at);\n if (!object.ok) return object;\n const mode = object.value.mode;\n if (mode === 'into_view') {\n const target = parseLocator(object.value.target, `${at}.target`);\n if (!target.ok) return target;\n const block = object.value.block;\n if (block !== undefined && !['start', 'center', 'end', 'nearest'].includes(String(block))) {\n return invalid(`${at}.block must be start, center, end, or nearest.`);\n }\n return valid({\n mode,\n target: target.value,\n ...(block !== undefined ? { block: block as 'start' | 'center' | 'end' | 'nearest' } : {}),\n });\n }\n if (!['wheel', 'position', 'until'].includes(String(mode))) {\n return invalid(`${at}.mode must be wheel, position, into_view, or until.`);\n }\n const container = parseContainer(object.value.container, `${at}.container`);\n if (!container.ok) return container;\n if (mode === 'wheel') {\n const deltaX = optionalNumber(object.value.deltaX, `${at}.deltaX`);\n if (!deltaX.ok) return deltaX;\n const deltaY = optionalNumber(object.value.deltaY, `${at}.deltaY`);\n if (!deltaY.ok) return deltaY;\n return valid({\n mode,\n container: container.value,\n ...(deltaX.value !== undefined ? { deltaX: deltaX.value } : {}),\n ...(deltaY.value !== undefined ? { deltaY: deltaY.value } : {}),\n });\n }\n if (mode === 'position') {\n const x = optionalNumber(object.value.x, `${at}.x`);\n if (!x.ok) return x;\n const y = optionalNumber(object.value.y, `${at}.y`);\n if (!y.ok) return y;\n const edge = object.value.edge;\n if (edge !== undefined && !['top', 'bottom', 'left', 'right'].includes(String(edge))) {\n return invalid(`${at}.edge must be top, bottom, left, or right.`);\n }\n return valid({\n mode,\n container: container.value,\n ...(x.value !== undefined ? { x: x.value } : {}),\n ...(y.value !== undefined ? { y: y.value } : {}),\n ...(edge !== undefined ? { edge: edge as 'top' | 'bottom' | 'left' | 'right' } : {}),\n });\n }\n const target = parseLocator(object.value.target, `${at}.target`);\n if (!target.ok) return target;\n const direction = object.value.direction;\n if (!['up', 'down', 'left', 'right'].includes(String(direction))) {\n return invalid(`${at}.direction must be up, down, left, or right.`);\n }\n const stepPx = object.value.stepPx;\n if (typeof stepPx !== 'number' || !Number.isFinite(stepPx) || stepPx <= 0) {\n return invalid(`${at}.stepPx must be a positive number.`);\n }\n const maxSteps = object.value.maxSteps;\n if (!Number.isInteger(maxSteps) || (maxSteps as number) <= 0) {\n return invalid(`${at}.maxSteps must be a positive integer.`);\n }\n return valid({\n mode: 'until',\n container: container.value,\n target: target.value,\n direction: direction as 'up' | 'down' | 'left' | 'right',\n stepPx,\n maxSteps: maxSteps as number,\n });\n}\n\nfunction parseWait(value: unknown, at: string): Validation<WoodWaitCondition> {\n const object = requireRecord(value, at);\n if (!object.ok) return object;\n const kind = object.value.kind;\n if (!WAIT_KINDS.includes(kind as (typeof WAIT_KINDS)[number])) {\n return invalid(`${at}.kind must be one of ${WAIT_KINDS.join(', ')}.`);\n }\n if (kind === 'route') {\n const page = requireString(object.value.page, `${at}.page`);\n if (!page.ok) return page;\n const params = stringRecord(object.value.params, `${at}.params`);\n if (!params.ok) return params;\n const query = stringRecord(object.value.query, `${at}.query`);\n if (!query.ok) return query;\n return valid({\n kind,\n page: page.value,\n ...(params.value ? { params: params.value } : {}),\n ...(query.value ? { query: query.value } : {}),\n });\n }\n if (kind === 'url') {\n const text = requireString(object.value.value, `${at}.value`);\n if (!text.ok) return text;\n const match = object.value.match;\n if (match !== undefined && !['exact', 'glob', 'regex'].includes(String(match))) {\n return invalid(`${at}.match must be exact, glob, or regex.`);\n }\n return valid({\n kind,\n value: text.value,\n ...(match !== undefined ? { match: match as 'exact' | 'glob' | 'regex' } : {}),\n });\n }\n if (kind === 'target') {\n const windowId = requireString(object.value.windowId, `${at}.windowId`);\n if (!windowId.ok) return windowId;\n const state = object.value.state;\n if (!['present', 'active', 'closed'].includes(String(state))) {\n return invalid(`${at}.state must be present, active, or closed.`);\n }\n return valid({ kind, windowId: windowId.value, state: state as 'present' | 'active' | 'closed' });\n }\n if (['visible', 'hidden', 'attached', 'detached', 'enabled'].includes(String(kind))) {\n const target = parseLocator(object.value.target, `${at}.target`);\n return target.ok\n ? valid({ kind: kind as 'visible' | 'hidden' | 'attached' | 'detached' | 'enabled', target: target.value })\n : target;\n }\n if (kind === 'trace') {\n const type = requireString(object.value.type, `${at}.type`);\n if (!type.ok) return type;\n if (object.value.source !== undefined && typeof object.value.source !== 'string') {\n return invalid(`${at}.source must be a string when provided.`);\n }\n if (object.value.count !== undefined && (!Number.isInteger(object.value.count) || (object.value.count as number) < 1)) {\n return invalid(`${at}.count must be a positive integer when provided.`);\n }\n return valid({\n kind,\n type: type.value,\n ...(object.value.source !== undefined ? { source: object.value.source as string } : {}),\n ...(object.value.count !== undefined ? { count: object.value.count as number } : {}),\n });\n }\n if (kind === 'scroll_edge') {\n const container = parseContainer(object.value.container, `${at}.container`);\n if (!container.ok) return container;\n const edge = object.value.edge;\n if (!['top', 'bottom', 'left', 'right'].includes(String(edge))) {\n return invalid(`${at}.edge must be top, bottom, left, or right.`);\n }\n return valid({ kind, container: container.value, edge: edge as 'top' | 'bottom' | 'left' | 'right' });\n }\n if (kind === 'visual_stable') {\n const target = object.value.target === undefined\n ? valid<WoodLocator | undefined>(undefined)\n : parseLocator(object.value.target, `${at}.target`);\n if (!target.ok) return target;\n if (object.value.frames !== undefined && (!Number.isInteger(object.value.frames) || (object.value.frames as number) < 1)) {\n return invalid(`${at}.frames must be a positive integer when provided.`);\n }\n return valid({\n kind,\n ...(target.value ? { target: target.value } : {}),\n ...(object.value.frames !== undefined ? { frames: object.value.frames as number } : {}),\n });\n }\n return valid({ kind: 'app_idle' });\n}\n\nfunction parseAction(value: unknown, at: string): Validation<WoodAutomationAction> {\n const object = requireRecord(value, at);\n if (!object.ok) return object;\n const kind = object.value.kind;\n if (!ACTION_KINDS.includes(kind as (typeof ACTION_KINDS)[number])) {\n return invalid(`${at}.kind must be one of ${ACTION_KINDS.join(', ')}.`);\n }\n if (kind === 'back' || kind === 'forward' || kind === 'reload') return valid({ kind });\n if (kind === 'scroll') {\n const command = parseScroll(object.value.command, `${at}.command`);\n return command.ok ? valid({ kind, command: command.value }) : command;\n }\n if (kind === 'wait') {\n const condition = parseWait(object.value.condition, `${at}.condition`);\n return condition.ok ? valid({ kind, condition: condition.value }) : condition;\n }\n if (kind === 'press') {\n let target: Validation<WoodLocator | undefined> = valid(undefined);\n if (object.value.target !== undefined) target = parseLocator(object.value.target, `${at}.target`);\n if (!target.ok) return target;\n if (!Array.isArray(object.value.keys) || object.value.keys.length === 0) {\n return invalid(`${at}.keys must be a non-empty array of strings.`);\n }\n for (let index = 0; index < object.value.keys.length; index += 1) {\n if (typeof object.value.keys[index] !== 'string' || object.value.keys[index].length === 0) {\n return invalid(`${at}.keys[${index}] must be a non-empty string.`);\n }\n }\n return valid({\n kind,\n ...(target.value ? { target: target.value } : {}),\n keys: object.value.keys as string[],\n });\n }\n const target = parseLocator(object.value.target, `${at}.target`);\n if (!target.ok) return target;\n if (kind === 'click') {\n const button = object.value.button;\n if (button !== undefined && button !== 'left' && button !== 'middle') {\n return invalid(`${at}.button must be left or middle when provided.`);\n }\n return valid({ kind, target: target.value, ...(button ? { button } : {}) });\n }\n if (kind === 'double_click') return valid({ kind, target: target.value });\n if (kind === 'fill' || kind === 'type') {\n if (typeof object.value.value !== 'string') return invalid(`${at}.value must be a string.`);\n if (kind === 'type') {\n const delayMs = optionalNumber(object.value.delayMs, `${at}.delayMs`);\n if (!delayMs.ok) return delayMs;\n return valid({\n kind,\n target: target.value,\n value: object.value.value,\n ...(delayMs.value !== undefined ? { delayMs: delayMs.value } : {}),\n });\n }\n return valid({ kind, target: target.value, value: object.value.value });\n }\n if (kind === 'select') {\n if (typeof object.value.option !== 'string') return invalid(`${at}.option must be a string.`);\n return valid({ kind, target: target.value, option: object.value.option });\n }\n if (typeof object.value.checked !== 'boolean') return invalid(`${at}.checked must be a boolean.`);\n return valid({ kind: 'toggle', target: target.value, checked: object.value.checked });\n}\n\nexport function parseScenario(json: unknown): WoodAutomationResult<WoodScenario> {\n const root = requireRecord(json, '$');\n if (!root.ok) return automationError('ACTION_FAILED', root.message);\n if (root.value.version !== 1) {\n return automationError('UNSUPPORTED', '$.version must equal 1.');\n }\n if (!Array.isArray(root.value.steps)) {\n return automationError('ACTION_FAILED', '$.steps must be an array.');\n }\n if (root.value.steps.length === 0) {\n return automationError('ACTION_FAILED', '$.steps must contain at least one step.');\n }\n\n let target: WoodScenario['target'];\n if (root.value.target !== undefined) {\n const object = requireRecord(root.value.target, '$.target');\n if (!object.ok) return automationError('ACTION_FAILED', object.message);\n if (object.value.windowId !== undefined && (typeof object.value.windowId !== 'string' || object.value.windowId.length === 0)) {\n return automationError('ACTION_FAILED', '$.target.windowId must be a non-empty string when provided.');\n }\n target = object.value.windowId === undefined ? {} : { windowId: object.value.windowId as string };\n }\n\n let evidence: WoodScenario['evidence'];\n if (root.value.evidence !== undefined) {\n const object = requireRecord(root.value.evidence, '$.evidence');\n if (!object.ok) return automationError('ACTION_FAILED', object.message);\n const screenshot = object.value.screenshot;\n if (screenshot !== undefined && !['on-failure', 'always', 'off'].includes(String(screenshot))) {\n return automationError('ACTION_FAILED', '$.evidence.screenshot must be on-failure, always, or off.');\n }\n const consoleCapture = optionalBoolean(object.value.console, '$.evidence.console');\n if (!consoleCapture.ok) return automationError('ACTION_FAILED', consoleCapture.message);\n evidence = {\n ...(screenshot !== undefined ? { screenshot: screenshot as 'on-failure' | 'always' | 'off' } : {}),\n ...(consoleCapture.value !== undefined ? { console: consoleCapture.value } : {}),\n };\n }\n\n const steps: WoodScenario['steps'] = [];\n for (let index = 0; index < root.value.steps.length; index += 1) {\n const at = `$.steps[${index}]`;\n const step = requireRecord(root.value.steps[index], at);\n if (!step.ok) return automationError('ACTION_FAILED', step.message);\n if (step.value.name !== undefined && (typeof step.value.name !== 'string' || step.value.name.length === 0)) {\n return automationError('ACTION_FAILED', `${at}.name must be a non-empty string when provided.`);\n }\n const action = parseAction(step.value.action, `${at}.action`);\n if (!action.ok) return automationError('ACTION_FAILED', action.message);\n const wait = step.value.wait === undefined\n ? valid<WoodWaitCondition | undefined>(undefined)\n : parseWait(step.value.wait, `${at}.wait`);\n if (!wait.ok) return automationError('ACTION_FAILED', wait.message);\n if (step.value.expect !== undefined && !Array.isArray(step.value.expect)) {\n return automationError('ACTION_FAILED', `${at}.expect must be an array when provided.`);\n }\n const expect: WoodWaitCondition[] = [];\n for (let expectIndex = 0; expectIndex < (step.value.expect as unknown[] | undefined)?.length!; expectIndex += 1) {\n const condition = parseWait(\n (step.value.expect as unknown[])[expectIndex],\n `${at}.expect[${expectIndex}]`,\n );\n if (!condition.ok) return automationError('ACTION_FAILED', condition.message);\n expect.push(condition.value);\n }\n steps.push({\n ...(step.value.name !== undefined ? { name: step.value.name as string } : {}),\n action: action.value,\n ...(wait.value ? { wait: wait.value } : {}),\n ...(step.value.expect !== undefined ? { expect } : {}),\n });\n }\n\n return automationOk({\n version: 1,\n ...(target ? { target } : {}),\n ...(evidence ? { evidence } : {}),\n steps,\n });\n}\n\nfunction safeEvidenceName(stepIndex: number, stepName: string | undefined, suffix: string): string {\n const name = (stepName ?? 'step').replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || 'step';\n return `${String(stepIndex + 1).padStart(3, '0')}-${name}-${suffix}.png`;\n}\n\nasync function captureScreenshot(\n page: Page,\n hooks: WoodScenarioHooks,\n stepIndex: number,\n stepName: string | undefined,\n suffix: string,\n): Promise<string | undefined> {\n if (!hooks.evidenceDir) return undefined;\n await mkdir(hooks.evidenceDir, { recursive: true });\n const outputPath = path.join(hooks.evidenceDir, safeEvidenceName(stepIndex, stepName, suffix));\n await page.screenshot({ path: outputPath });\n return outputPath;\n}\n\nfunction attachConsoleCapture(page: Page, entries: WoodConsoleEntry[]): () => void {\n const add = (type: WoodConsoleEntry['type'], message: string) => {\n entries.push({ type, message, occurredAt: new Date().toISOString() });\n };\n const onConsole = (message: ConsoleMessage) => {\n if (message.type() === 'error') add('console_error', message.text());\n };\n const onPageError = (error: Error) => add('page_error', error.message);\n const onRequestFailed = (request: Request) => {\n add('request_failed', `${request.method()} ${request.url()}: ${request.failure()?.errorText ?? 'request failed'}`);\n };\n page.on('console', onConsole);\n page.on('pageerror', onPageError);\n page.on('requestfailed', onRequestFailed);\n return () => {\n page.off('console', onConsole);\n page.off('pageerror', onPageError);\n page.off('requestfailed', onRequestFailed);\n };\n}\n\nfunction emit(hooks: WoodScenarioHooks, event: WoodScenarioEvent): void {\n hooks.onEvent(event);\n}\n\nfunction classifyThrown(error: unknown, message: string): WoodAutomationError {\n return {\n code: 'ACTION_FAILED',\n message,\n details: { cause: error instanceof Error ? error.message : String(error) },\n };\n}\n\nexport async function runScenarioOnPage(\n page: Page,\n scenario: WoodScenario,\n hooks: WoodScenarioHooks,\n): Promise<WoodAutomationResult<WoodScenarioReport>> {\n const started = new Date();\n const receipts: WoodActionReceipt[] = [];\n const steps: WoodScenarioStepReport[] = [];\n const evidence: string[] = [];\n const consoleEntries: WoodConsoleEntry[] = [];\n const detach = scenario.evidence?.console === false ? () => undefined : attachConsoleCapture(page, consoleEntries);\n emit(hooks, { kind: 'scenario_started', startedAt: started.toISOString(), stepCount: scenario.steps.length });\n\n try {\n for (let index = 0; index < scenario.steps.length; index += 1) {\n const step = scenario.steps[index];\n const stepStarted = new Date();\n const stepEvidence: string[] = [];\n let receipt: WoodActionReceipt | undefined;\n emit(hooks, {\n kind: 'step_started',\n stepIndex: index,\n ...(step.name ? { stepName: step.name } : {}),\n startedAt: stepStarted.toISOString(),\n });\n\n let failure: WoodAutomationError | undefined;\n const action = await executeAction(page, step.action, { wait: step.wait });\n if (!action.ok) {\n failure = action.error;\n } else {\n receipt = action.value;\n for (let expectIndex = 0; expectIndex < (step.expect?.length ?? 0); expectIndex += 1) {\n const condition = step.expect![expectIndex];\n const result = await awaitCondition(page, condition, { timeoutMs: EXPECT_TIMEOUT_MS });\n if (!result.ok) {\n failure = {\n ...result.error,\n message: `Step expectation ${expectIndex + 1} (${condition.kind}) failed: ${result.error.message}`,\n details: {\n ...result.error.details,\n condition,\n expectIndex,\n },\n };\n break;\n }\n }\n }\n\n if (failure) {\n if (scenario.evidence?.screenshot !== 'off') {\n try {\n const screenshot = await captureScreenshot(page, hooks, index, step.name, 'failure');\n if (screenshot) {\n stepEvidence.push(screenshot);\n evidence.push(screenshot);\n }\n } catch (error) {\n failure = {\n ...failure,\n details: {\n ...failure.details,\n screenshotError: error instanceof Error ? error.message : String(error),\n },\n };\n }\n }\n const durationMs = Date.now() - stepStarted.getTime();\n emit(hooks, {\n kind: 'step_failed',\n stepIndex: index,\n ...(step.name ? { stepName: step.name } : {}),\n error: failure,\n durationMs,\n evidence: stepEvidence,\n });\n const completed = new Date();\n emit(hooks, {\n kind: 'scenario_completed',\n stepIndex: index,\n ...(step.name ? { stepName: step.name } : {}),\n ...(receipt ? { receipt } : {}),\n error: failure,\n startedAt: started.toISOString(),\n completedAt: completed.toISOString(),\n durationMs: completed.getTime() - started.getTime(),\n success: false,\n });\n return automationError(failure.code, failure.message, {\n requiredAction: failure.requiredAction,\n details: {\n ...failure.details,\n stepIndex: index,\n ...(step.name ? { stepName: step.name } : {}),\n receipts,\n steps,\n evidence,\n console: consoleEntries,\n },\n });\n }\n\n if (scenario.evidence?.screenshot === 'always') {\n try {\n const screenshot = await captureScreenshot(page, hooks, index, step.name, 'completed');\n if (screenshot) {\n stepEvidence.push(screenshot);\n evidence.push(screenshot);\n }\n } catch (error) {\n const screenshotFailure = classifyThrown(error, 'Scenario evidence screenshot failed.');\n emit(hooks, {\n kind: 'step_failed',\n stepIndex: index,\n ...(step.name ? { stepName: step.name } : {}),\n error: screenshotFailure,\n durationMs: Date.now() - stepStarted.getTime(),\n evidence: stepEvidence,\n });\n const completed = new Date();\n emit(hooks, {\n kind: 'scenario_completed',\n stepIndex: index,\n ...(step.name ? { stepName: step.name } : {}),\n receipt,\n error: screenshotFailure,\n startedAt: started.toISOString(),\n completedAt: completed.toISOString(),\n durationMs: completed.getTime() - started.getTime(),\n success: false,\n });\n return automationError(screenshotFailure.code, screenshotFailure.message, {\n details: {\n ...screenshotFailure.details,\n stepIndex: index,\n receipts,\n steps,\n evidence,\n console: consoleEntries,\n },\n });\n }\n }\n\n const durationMs = Date.now() - stepStarted.getTime();\n receipts.push(receipt!);\n const stepReport: WoodScenarioStepReport = {\n index,\n ...(step.name ? { name: step.name } : {}),\n startedAt: stepStarted.toISOString(),\n durationMs,\n receipt: receipt!,\n evidence: stepEvidence,\n };\n steps.push(stepReport);\n emit(hooks, {\n kind: 'step_completed',\n stepIndex: index,\n ...(step.name ? { stepName: step.name } : {}),\n receipt: receipt!,\n durationMs,\n evidence: stepEvidence,\n });\n }\n\n const completed = new Date();\n const report: WoodScenarioReport = {\n startedAt: started.toISOString(),\n completedAt: completed.toISOString(),\n durationMs: completed.getTime() - started.getTime(),\n success: true,\n receipts,\n steps,\n evidence,\n console: consoleEntries,\n };\n const lastStep = scenario.steps.at(-1);\n emit(hooks, {\n kind: 'scenario_completed',\n ...(lastStep\n ? {\n stepIndex: scenario.steps.length - 1,\n ...(lastStep.name ? { stepName: lastStep.name } : {}),\n receipt: receipts.at(-1),\n }\n : {}),\n startedAt: report.startedAt,\n completedAt: report.completedAt,\n durationMs: report.durationMs,\n success: true,\n });\n return automationOk(report);\n } catch (error) {\n const failure = classifyThrown(error, 'Scenario runner failed unexpectedly.');\n const completed = new Date();\n emit(hooks, {\n kind: 'scenario_completed',\n error: failure,\n startedAt: started.toISOString(),\n completedAt: completed.toISOString(),\n durationMs: completed.getTime() - started.getTime(),\n success: false,\n });\n return automationError(failure.code, failure.message, {\n details: { ...failure.details, receipts, steps, evidence, console: consoleEntries },\n });\n } finally {\n detach();\n }\n}\n\nexport async function runScenario(\n connection: { browser: Browser },\n scenario: WoodScenario,\n hooks: WoodScenarioHooks,\n): Promise<WoodAutomationResult<WoodScenarioReport>> {\n const entries = await discoverTargets(connection.browser);\n const selected = selectTarget(entries, scenario.target?.windowId);\n if (!selected.ok) return selected;\n return runScenarioOnPage(selected.value.page, scenario, hooks);\n}\n"],"mappings":"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","names":["exact","target","path","durationMs","completed"]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Browser, Page } from 'playwright';
|
|
2
|
+
import { WoodAutomationAction } from './actions.cjs';
|
|
3
|
+
import { WoodAutomationError, WoodAutomationResult } from './errors.cjs';
|
|
4
|
+
import { WoodConsoleEntry } from './observation.cjs';
|
|
5
|
+
import { WoodActionReceipt } from './receipts.cjs';
|
|
6
|
+
import { WoodWaitCondition } from './waits.cjs';
|
|
7
|
+
import './locator.cjs';
|
|
8
|
+
import './scrolling.cjs';
|
|
9
|
+
import './target_identity.cjs';
|
|
10
|
+
|
|
11
|
+
interface WoodScenario {
|
|
12
|
+
version: 1;
|
|
13
|
+
target?: {
|
|
14
|
+
windowId?: string;
|
|
15
|
+
};
|
|
16
|
+
evidence?: {
|
|
17
|
+
screenshot?: 'on-failure' | 'always' | 'off';
|
|
18
|
+
console?: boolean;
|
|
19
|
+
};
|
|
20
|
+
steps: Array<{
|
|
21
|
+
name?: string;
|
|
22
|
+
action: WoodAutomationAction;
|
|
23
|
+
wait?: WoodWaitCondition;
|
|
24
|
+
expect?: WoodWaitCondition[];
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
interface WoodScenarioStepReport {
|
|
28
|
+
index: number;
|
|
29
|
+
name?: string;
|
|
30
|
+
startedAt: string;
|
|
31
|
+
durationMs: number;
|
|
32
|
+
receipt: WoodActionReceipt;
|
|
33
|
+
evidence: string[];
|
|
34
|
+
}
|
|
35
|
+
interface WoodScenarioReport {
|
|
36
|
+
startedAt: string;
|
|
37
|
+
completedAt: string;
|
|
38
|
+
durationMs: number;
|
|
39
|
+
success: true;
|
|
40
|
+
receipts: WoodActionReceipt[];
|
|
41
|
+
steps: WoodScenarioStepReport[];
|
|
42
|
+
evidence: string[];
|
|
43
|
+
console: WoodConsoleEntry[];
|
|
44
|
+
}
|
|
45
|
+
type WoodScenarioEvent = {
|
|
46
|
+
kind: 'scenario_started';
|
|
47
|
+
startedAt: string;
|
|
48
|
+
stepCount: number;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'step_started';
|
|
51
|
+
stepIndex: number;
|
|
52
|
+
stepName?: string;
|
|
53
|
+
startedAt: string;
|
|
54
|
+
} | {
|
|
55
|
+
kind: 'step_completed';
|
|
56
|
+
stepIndex: number;
|
|
57
|
+
stepName?: string;
|
|
58
|
+
receipt: WoodActionReceipt;
|
|
59
|
+
durationMs: number;
|
|
60
|
+
evidence: string[];
|
|
61
|
+
} | {
|
|
62
|
+
kind: 'step_failed';
|
|
63
|
+
stepIndex: number;
|
|
64
|
+
stepName?: string;
|
|
65
|
+
error: WoodAutomationError;
|
|
66
|
+
durationMs: number;
|
|
67
|
+
evidence: string[];
|
|
68
|
+
} | {
|
|
69
|
+
kind: 'scenario_completed';
|
|
70
|
+
stepIndex?: number;
|
|
71
|
+
stepName?: string;
|
|
72
|
+
receipt?: WoodActionReceipt;
|
|
73
|
+
error?: WoodAutomationError;
|
|
74
|
+
startedAt: string;
|
|
75
|
+
completedAt: string;
|
|
76
|
+
durationMs: number;
|
|
77
|
+
success: boolean;
|
|
78
|
+
};
|
|
79
|
+
interface WoodScenarioHooks {
|
|
80
|
+
onEvent: (event: WoodScenarioEvent) => void;
|
|
81
|
+
evidenceDir?: string;
|
|
82
|
+
}
|
|
83
|
+
declare function parseScenario(json: unknown): WoodAutomationResult<WoodScenario>;
|
|
84
|
+
declare function runScenarioOnPage(page: Page, scenario: WoodScenario, hooks: WoodScenarioHooks): Promise<WoodAutomationResult<WoodScenarioReport>>;
|
|
85
|
+
declare function runScenario(connection: {
|
|
86
|
+
browser: Browser;
|
|
87
|
+
}, scenario: WoodScenario, hooks: WoodScenarioHooks): Promise<WoodAutomationResult<WoodScenarioReport>>;
|
|
88
|
+
|
|
89
|
+
export { type WoodScenario, type WoodScenarioEvent, type WoodScenarioHooks, type WoodScenarioReport, type WoodScenarioStepReport, parseScenario, runScenario, runScenarioOnPage };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Browser, Page } from 'playwright';
|
|
2
|
+
import { WoodAutomationAction } from './actions.js';
|
|
3
|
+
import { WoodAutomationError, WoodAutomationResult } from './errors.js';
|
|
4
|
+
import { WoodConsoleEntry } from './observation.js';
|
|
5
|
+
import { WoodActionReceipt } from './receipts.js';
|
|
6
|
+
import { WoodWaitCondition } from './waits.js';
|
|
7
|
+
import './locator.js';
|
|
8
|
+
import './scrolling.js';
|
|
9
|
+
import './target_identity.js';
|
|
10
|
+
|
|
11
|
+
interface WoodScenario {
|
|
12
|
+
version: 1;
|
|
13
|
+
target?: {
|
|
14
|
+
windowId?: string;
|
|
15
|
+
};
|
|
16
|
+
evidence?: {
|
|
17
|
+
screenshot?: 'on-failure' | 'always' | 'off';
|
|
18
|
+
console?: boolean;
|
|
19
|
+
};
|
|
20
|
+
steps: Array<{
|
|
21
|
+
name?: string;
|
|
22
|
+
action: WoodAutomationAction;
|
|
23
|
+
wait?: WoodWaitCondition;
|
|
24
|
+
expect?: WoodWaitCondition[];
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
interface WoodScenarioStepReport {
|
|
28
|
+
index: number;
|
|
29
|
+
name?: string;
|
|
30
|
+
startedAt: string;
|
|
31
|
+
durationMs: number;
|
|
32
|
+
receipt: WoodActionReceipt;
|
|
33
|
+
evidence: string[];
|
|
34
|
+
}
|
|
35
|
+
interface WoodScenarioReport {
|
|
36
|
+
startedAt: string;
|
|
37
|
+
completedAt: string;
|
|
38
|
+
durationMs: number;
|
|
39
|
+
success: true;
|
|
40
|
+
receipts: WoodActionReceipt[];
|
|
41
|
+
steps: WoodScenarioStepReport[];
|
|
42
|
+
evidence: string[];
|
|
43
|
+
console: WoodConsoleEntry[];
|
|
44
|
+
}
|
|
45
|
+
type WoodScenarioEvent = {
|
|
46
|
+
kind: 'scenario_started';
|
|
47
|
+
startedAt: string;
|
|
48
|
+
stepCount: number;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'step_started';
|
|
51
|
+
stepIndex: number;
|
|
52
|
+
stepName?: string;
|
|
53
|
+
startedAt: string;
|
|
54
|
+
} | {
|
|
55
|
+
kind: 'step_completed';
|
|
56
|
+
stepIndex: number;
|
|
57
|
+
stepName?: string;
|
|
58
|
+
receipt: WoodActionReceipt;
|
|
59
|
+
durationMs: number;
|
|
60
|
+
evidence: string[];
|
|
61
|
+
} | {
|
|
62
|
+
kind: 'step_failed';
|
|
63
|
+
stepIndex: number;
|
|
64
|
+
stepName?: string;
|
|
65
|
+
error: WoodAutomationError;
|
|
66
|
+
durationMs: number;
|
|
67
|
+
evidence: string[];
|
|
68
|
+
} | {
|
|
69
|
+
kind: 'scenario_completed';
|
|
70
|
+
stepIndex?: number;
|
|
71
|
+
stepName?: string;
|
|
72
|
+
receipt?: WoodActionReceipt;
|
|
73
|
+
error?: WoodAutomationError;
|
|
74
|
+
startedAt: string;
|
|
75
|
+
completedAt: string;
|
|
76
|
+
durationMs: number;
|
|
77
|
+
success: boolean;
|
|
78
|
+
};
|
|
79
|
+
interface WoodScenarioHooks {
|
|
80
|
+
onEvent: (event: WoodScenarioEvent) => void;
|
|
81
|
+
evidenceDir?: string;
|
|
82
|
+
}
|
|
83
|
+
declare function parseScenario(json: unknown): WoodAutomationResult<WoodScenario>;
|
|
84
|
+
declare function runScenarioOnPage(page: Page, scenario: WoodScenario, hooks: WoodScenarioHooks): Promise<WoodAutomationResult<WoodScenarioReport>>;
|
|
85
|
+
declare function runScenario(connection: {
|
|
86
|
+
browser: Browser;
|
|
87
|
+
}, scenario: WoodScenario, hooks: WoodScenarioHooks): Promise<WoodAutomationResult<WoodScenarioReport>>;
|
|
88
|
+
|
|
89
|
+
export { type WoodScenario, type WoodScenarioEvent, type WoodScenarioHooks, type WoodScenarioReport, type WoodScenarioStepReport, parseScenario, runScenario, runScenarioOnPage };
|