@ricsam/isolate-playwright 0.1.12 → 0.1.14
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/README.md +254 -15
- package/dist/cjs/client.cjs +5 -318
- package/dist/cjs/client.cjs.map +3 -3
- package/dist/cjs/handler.cjs +1406 -0
- package/dist/cjs/handler.cjs.map +10 -0
- package/dist/cjs/index.cjs +793 -576
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/types.cjs +14 -1
- package/dist/cjs/types.cjs.map +4 -3
- package/dist/mjs/client.mjs +8 -317
- package/dist/mjs/client.mjs.map +3 -3
- package/dist/mjs/handler.mjs +1378 -0
- package/dist/mjs/handler.mjs.map +10 -0
- package/dist/mjs/index.mjs +802 -576
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/types.mjs +6 -1
- package/dist/mjs/types.mjs.map +4 -3
- package/dist/types/client.d.ts +3 -13
- package/dist/types/handler.d.ts +44 -0
- package/dist/types/index.d.ts +7 -72
- package/dist/types/types.d.ts +65 -11
- package/package.json +1 -1
package/dist/cjs/client.cjs.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/client.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Client-safe exports for @ricsam/isolate-playwright\n * This module can be imported without loading isolated-vm\n */\n\nimport type { Page, Locator as PlaywrightLocator } from \"playwright\";\nimport type {\n PlaywrightOperation,\n PlaywrightResult,\n} from \"@ricsam/isolate-protocol\";\n\n// Re-export types\nexport type {\n NetworkRequestInfo,\n NetworkResponseInfo,\n BrowserConsoleLogEntry,\n PlaywrightSetupOptions,\n PlaywrightOptions,\n PlaywrightHandle,\n} from \"./types.cjs\";\n\n// Import PlaywrightCallback for use in function return type\nimport type { PlaywrightCallback } from \"./types.cjs\";\nexport type { PlaywrightCallback };\n\nexport type { PlaywrightOperation, PlaywrightResult, PlaywrightEvent } from \"@ricsam/isolate-protocol\";\n\n// ============================================================================\n// Helper: Get locator from selector info\n// ============================================================================\n\nfunction getLocator(\n page: Page,\n selectorType: string,\n selectorValue: string,\n optionsJson: string | null\n): PlaywrightLocator {\n // Parse options and extract nth if present\n const options = optionsJson ? JSON.parse(optionsJson) : undefined;\n const nthIndex = options?.nth;\n\n // For role selectors, pass options (excluding nth) to getByRole\n const roleOptions = options ? { ...options } : undefined;\n if (roleOptions) {\n delete roleOptions.nth;\n delete roleOptions.filter;\n // Deserialize regex name\n if (roleOptions.name && typeof roleOptions.name === 'object' && roleOptions.name.$regex) {\n roleOptions.name = new RegExp(roleOptions.name.$regex, roleOptions.name.$flags);\n }\n }\n\n let locator: PlaywrightLocator;\n switch (selectorType) {\n case \"css\":\n locator = page.locator(selectorValue);\n break;\n case \"role\":\n locator = page.getByRole(\n selectorValue as Parameters<Page[\"getByRole\"]>[0],\n roleOptions && Object.keys(roleOptions).length > 0 ? roleOptions : undefined\n );\n break;\n case \"text\":\n locator = page.getByText(selectorValue);\n break;\n case \"label\":\n locator = page.getByLabel(selectorValue);\n break;\n case \"placeholder\":\n locator = page.getByPlaceholder(selectorValue);\n break;\n case \"testId\":\n locator = page.getByTestId(selectorValue);\n break;\n case \"or\": {\n // Composite locator: selectorValue is JSON array of [firstInfo, secondInfo]\n const [firstInfo, secondInfo] = JSON.parse(selectorValue) as [[string, string, string | null], [string, string, string | null]];\n const first = getLocator(page, firstInfo[0], firstInfo[1], firstInfo[2]);\n const second = getLocator(page, secondInfo[0], secondInfo[1], secondInfo[2]);\n locator = first.or(second);\n break;\n }\n default:\n locator = page.locator(selectorValue);\n }\n\n // Apply nth if specified\n if (nthIndex !== undefined) {\n locator = locator.nth(nthIndex);\n }\n\n // Apply filter if specified\n if (options?.filter) {\n const filterOpts = { ...options.filter };\n if (filterOpts.hasText && typeof filterOpts.hasText === 'object' && filterOpts.hasText.$regex) {\n filterOpts.hasText = new RegExp(filterOpts.hasText.$regex, filterOpts.hasText.$flags);\n }\n if (filterOpts.hasNotText && typeof filterOpts.hasNotText === 'object' && filterOpts.hasNotText.$regex) {\n filterOpts.hasNotText = new RegExp(filterOpts.hasNotText.$regex, filterOpts.hasNotText.$flags);\n }\n locator = locator.filter(filterOpts);\n }\n\n return locator;\n}\n\n// ============================================================================\n// Helper: Execute locator action\n// ============================================================================\n\nasync function executeLocatorAction(\n locator: PlaywrightLocator,\n action: string,\n actionArg: unknown,\n timeout: number\n): Promise<unknown> {\n switch (action) {\n case \"click\":\n await locator.click({ timeout });\n return null;\n case \"dblclick\":\n await locator.dblclick({ timeout });\n return null;\n case \"fill\":\n await locator.fill(String(actionArg ?? \"\"), { timeout });\n return null;\n case \"type\":\n await locator.pressSequentially(String(actionArg ?? \"\"), { timeout });\n return null;\n case \"check\":\n await locator.check({ timeout });\n return null;\n case \"uncheck\":\n await locator.uncheck({ timeout });\n return null;\n case \"selectOption\":\n await locator.selectOption(String(actionArg ?? \"\"), { timeout });\n return null;\n case \"clear\":\n await locator.clear({ timeout });\n return null;\n case \"press\":\n await locator.press(String(actionArg ?? \"\"), { timeout });\n return null;\n case \"hover\":\n await locator.hover({ timeout });\n return null;\n case \"focus\":\n await locator.focus({ timeout });\n return null;\n case \"getText\":\n return await locator.textContent({ timeout });\n case \"getValue\":\n return await locator.inputValue({ timeout });\n case \"isVisible\":\n return await locator.isVisible();\n case \"isEnabled\":\n return await locator.isEnabled();\n case \"isChecked\":\n return await locator.isChecked();\n case \"count\":\n return await locator.count();\n case \"getAttribute\":\n return await locator.getAttribute(String(actionArg ?? \"\"), { timeout });\n case \"isDisabled\":\n return await locator.isDisabled();\n case \"isHidden\":\n return await locator.isHidden();\n case \"innerHTML\":\n return await locator.innerHTML({ timeout });\n case \"innerText\":\n return await locator.innerText({ timeout });\n case \"allTextContents\":\n return await locator.allTextContents();\n case \"allInnerTexts\":\n return await locator.allInnerTexts();\n case \"waitFor\": {\n const opts = actionArg && typeof actionArg === 'object' ? actionArg as Record<string, unknown> : {};\n await locator.waitFor({ state: opts.state as any, timeout: (opts.timeout as number) ?? timeout });\n return null;\n }\n case \"boundingBox\":\n return await locator.boundingBox({ timeout });\n default:\n throw new Error(`Unknown action: ${action}`);\n }\n}\n\n// ============================================================================\n// Helper: Execute expect assertion\n// ============================================================================\n\nasync function executeExpectAssertion(\n locator: PlaywrightLocator,\n matcher: string,\n expected: unknown,\n negated: boolean,\n timeout: number\n): Promise<void> {\n switch (matcher) {\n case \"toBeVisible\": {\n const isVisible = await locator.isVisible();\n if (negated) {\n if (isVisible) throw new Error(\"Expected element to not be visible, but it was visible\");\n } else {\n if (!isVisible) throw new Error(\"Expected element to be visible, but it was not\");\n }\n break;\n }\n case \"toContainText\": {\n const text = await locator.textContent({ timeout });\n const matches = text?.includes(String(expected)) ?? false;\n if (negated) {\n if (matches) throw new Error(`Expected text to not contain \"${expected}\", but got \"${text}\"`);\n } else {\n if (!matches) throw new Error(`Expected text to contain \"${expected}\", but got \"${text}\"`);\n }\n break;\n }\n case \"toHaveValue\": {\n const value = await locator.inputValue({ timeout });\n const matches = value === String(expected);\n if (negated) {\n if (matches) throw new Error(`Expected value to not be \"${expected}\", but it was`);\n } else {\n if (!matches) throw new Error(`Expected value to be \"${expected}\", but got \"${value}\"`);\n }\n break;\n }\n case \"toBeEnabled\": {\n const isEnabled = await locator.isEnabled();\n if (negated) {\n if (isEnabled) throw new Error(\"Expected element to be disabled, but it was enabled\");\n } else {\n if (!isEnabled) throw new Error(\"Expected element to be enabled, but it was disabled\");\n }\n break;\n }\n case \"toBeChecked\": {\n const isChecked = await locator.isChecked();\n if (negated) {\n if (isChecked) throw new Error(\"Expected element to not be checked, but it was checked\");\n } else {\n if (!isChecked) throw new Error(\"Expected element to be checked, but it was not\");\n }\n break;\n }\n default:\n throw new Error(`Unknown matcher: ${matcher}`);\n }\n}\n\n// ============================================================================\n// Create Playwright Handler (for remote use)\n// ============================================================================\n\n/**\n * Create a playwright handler from a Page object.\n * This handler is called by the daemon (via callback) when sandbox needs page operations.\n * Used for remote runtime where the browser runs on the client.\n */\nexport function createPlaywrightHandler(\n page: Page,\n options?: { timeout?: number }\n): PlaywrightCallback {\n const timeout = options?.timeout ?? 30000;\n\n return async (op: PlaywrightOperation): Promise<PlaywrightResult> => {\n try {\n switch (op.type) {\n case \"goto\": {\n const [url, waitUntil] = op.args as [string, string?];\n await page.goto(url, {\n timeout,\n waitUntil: (waitUntil as \"load\" | \"domcontentloaded\" | \"networkidle\") ?? \"load\",\n });\n return { ok: true };\n }\n case \"reload\":\n await page.reload({ timeout });\n return { ok: true };\n case \"url\":\n return { ok: true, value: page.url() };\n case \"title\":\n return { ok: true, value: await page.title() };\n case \"content\":\n return { ok: true, value: await page.content() };\n case \"waitForSelector\": {\n const [selector, optionsJson] = op.args as [string, string?];\n const opts = optionsJson ? JSON.parse(optionsJson) : {};\n await page.waitForSelector(selector, { timeout, ...opts });\n return { ok: true };\n }\n case \"waitForTimeout\": {\n const [ms] = op.args as [number];\n await page.waitForTimeout(ms);\n return { ok: true };\n }\n case \"waitForLoadState\": {\n const [state] = op.args as [string?];\n await page.waitForLoadState(\n (state as \"load\" | \"domcontentloaded\" | \"networkidle\") ?? \"load\",\n { timeout }\n );\n return { ok: true };\n }\n case \"evaluate\": {\n const [script] = op.args as [string];\n const result = await page.evaluate(script);\n return { ok: true, value: result };\n }\n case \"locatorAction\": {\n const [selectorType, selectorValue, roleOptions, action, actionArg] = op.args as [\n string,\n string,\n string | null,\n string,\n unknown\n ];\n const locator = getLocator(page, selectorType, selectorValue, roleOptions);\n const result = await executeLocatorAction(locator, action, actionArg, timeout);\n return { ok: true, value: result };\n }\n case \"expectLocator\": {\n const [selectorType, selectorValue, roleOptions, matcher, expected, negated, customTimeout] = op.args as [\n string,\n string,\n string | null,\n string,\n unknown,\n boolean,\n number?\n ];\n const locator = getLocator(page, selectorType, selectorValue, roleOptions);\n const effectiveTimeout = customTimeout ?? timeout;\n await executeExpectAssertion(locator, matcher, expected, negated ?? false, effectiveTimeout);\n return { ok: true };\n }\n case \"request\": {\n const [url, method, data, headers] = op.args as [\n string,\n string,\n unknown,\n Record<string, string>?\n ];\n const requestOptions: {\n method?: string;\n data?: unknown;\n headers?: Record<string, string>;\n timeout?: number;\n } = {\n timeout,\n };\n if (headers) {\n requestOptions.headers = headers;\n }\n if (data !== undefined && data !== null) {\n requestOptions.data = data;\n }\n\n const response = await page.request.fetch(url, {\n method: method as \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\" | \"HEAD\" | \"OPTIONS\",\n ...requestOptions,\n });\n\n // Get response data - try to parse as JSON, fall back to text\n const text = await response.text();\n let json: unknown = null;\n try {\n json = JSON.parse(text);\n } catch {\n // Not valid JSON, that's ok\n }\n\n return {\n ok: true,\n value: {\n status: response.status(),\n ok: response.ok(),\n headers: response.headers(),\n text,\n json,\n body: null, // ArrayBuffer not easily serializable, use text/json instead\n },\n };\n }\n case \"goBack\": {\n const [waitUntil] = op.args as [string?];\n await page.goBack({\n timeout,\n waitUntil: (waitUntil as \"load\" | \"domcontentloaded\" | \"networkidle\") ?? \"load\",\n });\n return { ok: true };\n }\n case \"goForward\": {\n const [waitUntil] = op.args as [string?];\n await page.goForward({\n timeout,\n waitUntil: (waitUntil as \"load\" | \"domcontentloaded\" | \"networkidle\") ?? \"load\",\n });\n return { ok: true };\n }\n case \"waitForURL\": {\n const [url, customTimeout, waitUntil] = op.args as [string, number?, string?];\n await page.waitForURL(url, {\n timeout: customTimeout ?? timeout,\n waitUntil: (waitUntil as \"load\" | \"domcontentloaded\" | \"networkidle\") ?? undefined,\n });\n return { ok: true };\n }\n case \"clearCookies\": {\n await page.context().clearCookies();\n return { ok: true };\n }\n default:\n return { ok: false, error: { name: \"Error\", message: `Unknown operation: ${(op as PlaywrightOperation).type}` } };\n }\n } catch (err) {\n const error = err as Error;\n return { ok: false, error: { name: error.name, message: error.message } };\n }\n };\n}\n"
|
|
5
|
+
"/**\n * Client-safe exports for @ricsam/isolate-playwright\n * This module can be imported without loading isolated-vm\n */\n\n// Re-export types from types.ts\nexport type {\n NetworkRequestInfo,\n NetworkResponseInfo,\n BrowserConsoleLogEntry,\n DefaultPlaywrightHandler,\n DefaultPlaywrightHandlerMetadata,\n DefaultPlaywrightHandlerOptions,\n PlaywrightSetupOptions,\n PlaywrightHandle,\n PlaywrightCallback,\n} from \"./types.cjs\";\n\nexport type { PlaywrightOperation, PlaywrightResult, PlaywrightEvent, PlaywrightFileData } from \"@ricsam/isolate-protocol\";\n\n// Re-export handler functions\nexport {\n createPlaywrightHandler,\n defaultPlaywrightHandler,\n getDefaultPlaywrightHandlerMetadata,\n} from \"./handler.cjs\";\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBO,IAJP;",
|
|
8
|
+
"debugId": "12B76442A83E341864756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|