webdriverio-execute 0.1.0 → 0.2.1
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 +1 -1
- package/bin/wdiox.js +14 -0
- package/build/cli.d.ts +2 -1
- package/build/cli.js +4 -6
- package/build/cli.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
package/bin/wdiox.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* wdiox — Interactive browser and app CLI for developers using WebdriverIO
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
// Set log level before importing webdriverio (logger initializes on import)
|
|
9
|
+
process.env.WDIO_LOG_LEVEL ??= 'error'
|
|
10
|
+
|
|
11
|
+
;(async () => {
|
|
12
|
+
const cli = await import('../build/cli.js');
|
|
13
|
+
return cli.run();
|
|
14
|
+
})();
|
package/build/cli.d.ts
CHANGED
package/build/cli.js
CHANGED
|
@@ -512,7 +512,6 @@ async function handler7(argv) {
|
|
|
512
512
|
}
|
|
513
513
|
|
|
514
514
|
// src/cli.ts
|
|
515
|
-
process.env.WDIO_LOG_LEVEL ??= "error";
|
|
516
515
|
var commands = [
|
|
517
516
|
open_exports,
|
|
518
517
|
close_exports,
|
|
@@ -522,7 +521,7 @@ var commands = [
|
|
|
522
521
|
screenshot_exports,
|
|
523
522
|
session_list_exports
|
|
524
523
|
];
|
|
525
|
-
async function
|
|
524
|
+
async function run() {
|
|
526
525
|
process.on("unhandledRejection", () => {
|
|
527
526
|
});
|
|
528
527
|
let cli = yargs(hideBin(process.argv)).scriptName("wdiox").usage("$0 <command> [options]").option("session", {
|
|
@@ -537,8 +536,7 @@ async function main() {
|
|
|
537
536
|
await cli.demandCommand(1, "You need to specify a command. Try: wdiox open <url>").strict().help().version().parse();
|
|
538
537
|
process.exit(0);
|
|
539
538
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
});
|
|
539
|
+
export {
|
|
540
|
+
run
|
|
541
|
+
};
|
|
544
542
|
//# sourceMappingURL=cli.js.map
|
package/build/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/open.ts","../src/session.ts","../src/commands/close.ts","../src/commands/snapshot.ts","../src/refs.ts","../src/format.ts","../src/commands/click.ts","../src/commands/type.ts","../src/commands/screenshot.ts","../src/commands/session-list.ts"],"sourcesContent":["process.env.WDIO_LOG_LEVEL ??= 'error';\n\nimport yargs from 'yargs';\nimport type { CommandModule } from 'yargs';\nimport { hideBin } from 'yargs/helpers';\n\nimport * as openCmd from './commands/open.js';\nimport * as closeCmd from './commands/close.js';\nimport * as snapshotCmd from './commands/snapshot.js';\nimport * as clickCmd from './commands/click.js';\nimport * as fillCmd from './commands/type';\nimport * as screenshotCmd from './commands/screenshot.js';\nimport * as sessionListCmd from './commands/session-list.js';\n\nconst commands = [\n openCmd, closeCmd, snapshotCmd, clickCmd,\n fillCmd, screenshotCmd, sessionListCmd,\n] as unknown as CommandModule[];\n\nasync function main () {\n\n // webdriverio's attach() can spawn async BiDi connections that fail after\n // the function returns (e.g. stale session). Suppress these so the CLI\n // doesn't crash during close/reconnect of dead sessions.\n process.on('unhandledRejection', () => {});\n\n let cli = yargs(hideBin(process.argv))\n .scriptName('wdiox')\n .usage('$0 <command> [options]')\n .option('session', {\n alias: 's',\n type: 'string',\n default: process.env.WDIO_SESSION || 'default',\n describe: 'Session name',\n });\n\n for (const cmd of commands) {\n cli = cli.command(cmd);\n }\n\n await cli\n .demandCommand(1, 'You need to specify a command. Try: wdiox open <url>')\n .strict()\n .help()\n .version()\n .parse();\n\n // webdriverio keeps HTTP agents alive — force clean exit after command completes\n process.exit(0);\n}\n\nmain().catch((err: unknown) => {\n console.error('✗ WebdriverIO Execute failed:', err instanceof Error ? err.message : String(err));\n process.exit(1);\n});","import readline from 'node:readline/promises';\nimport type { ArgumentsCamelCase, Argv } from 'yargs';\nimport type { Capabilities } from '@wdio/types';\nimport { attach, remote } from 'webdriverio';\n\nimport { writeSession, readSession, getSessionDir, buildAttachOptions, deleteSessionFiles } from '../session.js';\n\nexport const command = ['open [url]', 'new [url]', 'start [url]'];\nexport const desc = 'Open a browser or Appium session';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('url', {\n type: 'string',\n describe: 'URL to navigate to',\n })\n .option('browser', {\n alias: 'b',\n type: 'string',\n default: 'chrome',\n describe: 'Browser to use (chrome, firefox, edge, safari)',\n })\n .option('app', {\n type: 'string',\n describe: 'Path to mobile app (.apk, .ipa, .app)',\n })\n .option('device', {\n alias: 'd',\n type: 'string',\n describe: 'Device name for mobile testing',\n })\n .option('platform', {\n type: 'string',\n describe: 'Mobile platform (android, ios)',\n })\n .option('path', {\n type: 'string',\n describe: 'WebDriver/Appium server session path (default: /)',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n describe: 'WebDriver/Appium server port (default: 4723)',\n })\n .option('hostname', {\n type: 'string',\n describe: 'WebDriver/Appium server hostname (default: localhost)',\n })\n .option('grant-permissions', {\n type: 'boolean',\n default: true,\n describe: 'Auto-grant app permissions (Appium only)',\n })\n .option('accept-alert', {\n type: 'boolean',\n default: true,\n describe: 'Auto-accept native alerts (Appium only)',\n })\n .option('auto-dismiss', {\n type: 'boolean',\n default: false,\n describe: 'Auto-dismiss native alerts (Appium only)',\n });\n};\n\ninterface OpenArgs {\n url?: string\n browser: string\n session: string\n app?: string\n device?: string\n platform?: string\n port?: number\n hostname?: string\n grantPermissions: boolean\n acceptAlert: boolean\n autoDismiss: boolean\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<OpenArgs>) {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const existing = await readSession(sessionName, sessionsDir);\n if (existing) {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const context = existing.url || (existing.capabilities['appium:app'] as string) || '';\n const answer = await rl.question(`Session [${sessionName}] is already active${context ? ` (${context})` : ''}.\\nClose it and start a new one? (y/N) `);\n rl.close();\n\n if (answer.trim().toLowerCase() !== 'y') {\n return;\n }\n\n try {\n const old = await attach(buildAttachOptions(existing));\n await old.deleteSession();\n } catch {\n // Already dead\n }\n await deleteSessionFiles(sessionName, sessionsDir);\n }\n\n const capabilities: Record<string, unknown> = {};\n\n const isMobile = !!argv.app;\n if (isMobile) {\n const platform = argv.platform ?? (argv.app?.endsWith('.apk') ? 'android' : 'ios');\n\n capabilities.platformName = platform === 'ios' ? 'iOS' : 'Android';\n capabilities['appium:app'] = argv.app;\n capabilities['appium:deviceName'] = argv.device ?? 'emulator-5554';\n capabilities['appium:newCommandTimeout'] = 300;\n capabilities['appium:automationName'] = platform === 'ios' ? 'XCUITest' : 'UiAutomator2';\n capabilities['appium:autoGrantPermissions'] = argv.grantPermissions;\n capabilities['appium:autoAcceptAlerts'] = argv.acceptAlert;\n capabilities['appium:autoDismissAlerts'] = argv.autoDismiss;\n } else {\n capabilities.browserName = argv.browser;\n }\n\n const remoteOpts: Record<string, unknown> = { capabilities, logLevel: process.env.WDIO_LOG_LEVEL ?? 'error' };\n // For mobile / Appium, explicit connection is required\n if (argv.hostname || argv.port || isMobile) {\n remoteOpts.hostname = argv.hostname ?? 'localhost';\n remoteOpts.port = argv.port ?? (isMobile ? 4723 : 4444);\n remoteOpts.path = argv.path ?? '/';\n }\n\n const browser = await remote(remoteOpts as unknown as Capabilities.WebdriverIOConfig);\n\n if (argv.url) {\n await browser.url(argv.url);\n }\n\n const opts = browser.options as Capabilities.WebdriverIOConfig;\n await writeSession(sessionName, {\n sessionId: browser.sessionId,\n hostname: opts?.hostname || 'localhost',\n port: opts?.port || 4444,\n capabilities: { ...capabilities, ...browser.capabilities as Record<string, unknown> },\n created: new Date().toISOString(),\n url: argv.url || '',\n }, sessionsDir);\n\n console.log(`Session \"${sessionName}\" started.`);\n}\n","import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { AttachOptions } from 'webdriverio';\nimport type { ArgumentsCamelCase } from 'yargs';\n\nexport interface SessionMetadata {\n sessionId: string\n hostname: string\n port: number\n capabilities: Record<string, unknown>\n created: string\n url: string\n}\n\nexport interface SessionEntry {\n name: string\n metadata: SessionMetadata\n}\n\nconst DEFAULT_SESSION_DIR = path.join(os.homedir(), '.wdio-x', 'sessions');\n\nfunction isEnoent(err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Build attach options from session metadata for use with webdriverio's `attach()`.\n */\nexport function buildAttachOptions(meta: SessionMetadata): AttachOptions {\n return {\n sessionId: meta.sessionId,\n capabilities: meta.capabilities as WebdriverIO.Capabilities,\n options: {\n hostname: meta.hostname,\n port: meta.port,\n logLevel: process.env.WDIO_LOG_LEVEL ?? 'error',\n },\n } as AttachOptions;\n}\n\n/**\n * Returns the session directory path. Defaults to ~/.wdio-x/sessions/.\n */\nexport function getSessionDir (baseDir?: string): string {\n return baseDir ?? DEFAULT_SESSION_DIR;\n}\n\n/**\n * Returns the file path for a session's metadata JSON file.\n */\nexport function getSessionPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.json`);\n}\n\n/**\n * Returns the file path for a session's refs JSON file.\n */\nexport function getRefsPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.refs.json`);\n}\n\n/**\n * Writes session metadata to disk, creating the directory if needed.\n */\nexport async function writeSession (\n name: string,\n metadata: SessionMetadata,\n baseDir?: string,\n): Promise<void> {\n const dir = getSessionDir(baseDir);\n await fs.mkdir(dir, { recursive: true });\n const filePath = getSessionPath(name, baseDir);\n await fs.writeFile(filePath, JSON.stringify(metadata, null, 2));\n}\n\n/**\n * Reads session metadata from disk. Returns null if the session file does not exist.\n */\nexport async function readSession (\n name: string,\n baseDir?: string,\n): Promise<SessionMetadata | null> {\n const filePath = getSessionPath(name, baseDir);\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as SessionMetadata;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Deletes both the .json and .refs.json files for a session.\n * Does not throw if the files do not exist.\n */\nexport async function deleteSessionFiles (\n name: string,\n baseDir?: string,\n): Promise<void> {\n const sessionPath = getSessionPath(name, baseDir);\n const refsPath = getRefsPath(name, baseDir);\n await Promise.all([\n fs.rm(sessionPath, { force: true }),\n fs.rm(refsPath, { force: true }),\n ]);\n}\n\n/**\n * Lists all sessions in the session directory.\n * Only considers .json files (excludes .refs.json).\n * Returns an empty array if the directory does not exist.\n */\nexport async function listSessions (baseDir?: string): Promise<SessionEntry[]> {\n const dir = getSessionDir(baseDir);\n let files: string[];\n try {\n files = await fs.readdir(dir);\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return [];\n }\n throw err;\n }\n\n const sessionFiles = files.filter(\n (f) => f.endsWith('.json') && !f.endsWith('.refs.json'),\n );\n\n return await Promise.all(\n sessionFiles.map(async (f) => {\n const name = f.replace(/\\.json$/, '');\n const metadata = await readSession(name, baseDir);\n return { name, metadata: metadata! };\n }),\n );\n}\n\ninterface SessionArgs {\n session: string\n _sessionsDir?: string\n}\n\n/**\n * Wraps a command handler that requires an active session.\n * Reads the session from disk and exits early with an error if not found.\n */\nexport function withSession<T extends SessionArgs>(\n fn: (argv: ArgumentsCamelCase<T>, meta: SessionMetadata, sessionsDir: string) => Promise<void>,\n): (argv: ArgumentsCamelCase<T>) => Promise<void> {\n return async function handler(argv: ArgumentsCamelCase<T>): Promise<void> {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const meta = await readSession(sessionName, sessionsDir);\n if (!meta) {\n console.error(`Error: No active session [${sessionName}]. Run wdiox open <url> first.`);\n return;\n }\n\n await fn(argv, meta, sessionsDir);\n };\n}\n","import type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { deleteSessionFiles, buildAttachOptions, withSession } from '../session.js';\n\nexport const command = ['close', 'stop'];\nexport const desc = 'Close the current session';\n\ninterface CloseArgs {\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<CloseArgs>(async (argv: ArgumentsCamelCase<CloseArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n\n try {\n const browser = await attach(buildAttachOptions(meta));\n await browser.deleteSession();\n } catch {\n // Session may already be dead - clean up anyway\n }\n\n await deleteSessionFiles(sessionName, sessionsDir);\n console.log(`Session \"${sessionName}\" closed.`);\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { writeRefs, type RefMap } from '../refs.js';\nimport { getInteractableBrowserElements, getMobileVisibleElements } from '@wdio/mcp/snapshot';\nimport {\n formatBrowserElement,\n formatMobileElement,\n} from '../format.js';\n\nexport const command = 'snapshot';\nexport const desc = 'Capture interactive elements on the page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .option('visible', {\n type: 'boolean',\n default: true,\n describe: 'Only show elements in viewport',\n });\n};\n\ninterface SnapshotArgs {\n session: string\n visible: boolean\n _sessionsDir?: string\n}\n\nexport const handler = withSession<SnapshotArgs>(async (argv: ArgumentsCamelCase<SnapshotArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const browser = await attach(buildAttachOptions(meta));\n\n const isMobile = browser.isAndroid || browser.isIOS;\n const refs: RefMap = {};\n\n if (isMobile) {\n const platform = browser.isIOS ? 'ios' : 'android';\n const elements = await getMobileVisibleElements(browser, platform);\n const filtered = argv.visible\n ? elements.filter(el => el.isInViewport)\n : elements;\n\n const appName = (meta.capabilities['appium:app'] as string) || 'unknown';\n console.log(`\\n App: ${appName}\\n`);\n\n filtered.forEach((el, i) => {\n const ref = `e${i + 1}`;\n console.log(formatMobileElement(ref, {\n tagName: el.tagName,\n text: el.text,\n selector: el.selector,\n accessibilityId: el.accessibilityId,\n resourceId: el.resourceId,\n }));\n refs[ref] = {\n selector: el.selector,\n tagName: el.tagName,\n text: el.text,\n };\n });\n\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\n } else {\n const elements = await getInteractableBrowserElements(browser);\n const filtered = argv.visible\n ? elements.filter(el => el.isInViewport)\n : elements;\n\n const currentUrl = await browser.getUrl();\n console.log(`\\n Page: ${currentUrl}\\n`);\n\n filtered.forEach((el, i) => {\n const ref = `e${i + 1}`;\n console.log(formatBrowserElement(ref, el));\n refs[ref] = {\n selector: el.selector,\n tagName: el.tagName,\n text: el.name || '',\n };\n });\n\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\n }\n\n await writeRefs(getRefsPath(sessionName, sessionsDir), refs);\n});\n","import fs from 'node:fs/promises';\n\nexport interface RefEntry {\n selector?: string\n tagName: string\n text?: string\n placeholder?: string\n [key: string]: unknown\n}\n\nexport type RefMap = Record<string, RefEntry>;\n\nfunction isEnoent (err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Writes a ref map to disk as JSON.\n */\nexport async function writeRefs (refsPath: string, refs: RefMap): Promise<void> {\n await fs.writeFile(refsPath, JSON.stringify(refs, null, 2), 'utf-8');\n}\n\n/**\n * Reads a ref map from disk. Returns null if the file doesn't exist.\n */\nexport async function readRefs (refsPath: string): Promise<RefMap | null> {\n try {\n const content = await fs.readFile(refsPath, 'utf-8');\n return JSON.parse(content) as RefMap;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Look up a ref by key: reads refs file, finds the entry, resolves its selector.\n * Logs appropriate error messages and returns null on failure.\n */\nexport async function lookupRef (\n refsPath: string,\n refKey: string,\n): Promise<{ ref: RefEntry; selector: string } | null> {\n const refs = await readRefs(refsPath);\n if (!refs) {\n console.error('Error: No snapshot taken. Run wdiox snapshot first.');\n return null;\n }\n\n const ref = refs[refKey];\n if (!ref) {\n const available = Object.keys(refs);\n const range = available.length > 0\n ? `Available: ${available[0]}-${available[available.length - 1]}`\n : 'No refs available';\n console.error(`Error: ${refKey} not found in snapshot. ${range}`);\n return null;\n }\n\n if (!ref.selector) {\n console.error(`Error: Could not resolve selector for ${refKey}`);\n return null;\n }\n\n return { ref, selector: ref.selector };\n}\n","export interface BrowserElementFormatInput {\n tagName: string\n role?: string\n type?: string\n name?: string\n href?: string\n selector: string\n}\n\nexport interface MobileElementFormatInput {\n tagName: string\n text?: string\n selector: string\n accessibilityId?: string\n resourceId?: string\n}\n\nexport interface SessionListEntry {\n name: string\n browser: string\n url: string\n status: string\n}\n\nfunction truncate(str: string, max = 80): string {\n return str.length <= max ? str : str.slice(0, max - 3) + '...';\n}\n\nexport function formatBrowserElement(ref: string, el: BrowserElementFormatInput): string {\n const tag = (el.role && el.role !== el.tagName ? el.role : el.tagName) + (el.type ? `[${el.type}]` : '');\n const desc = [el.name && `\"${truncate(el.name)}\"`, el.href && `-> ${truncate(el.href)}`].filter(Boolean).join(' ');\n return [ref.padEnd(4), tag, desc, el.selector].filter(Boolean).join(' ');\n}\n\nexport function formatMobileElement(ref: string, el: MobileElementFormatInput): string {\n const selector = el.accessibilityId ? `[accessibility-id: ${el.accessibilityId}]`\n : el.resourceId ? `[resource-id: ${el.resourceId}]`\n : truncate(el.selector);\n const parts = [ref.padEnd(4), el.tagName.padEnd(28), el.text && `\"${truncate(el.text)}\"`, selector];\n return parts.filter(Boolean).join(' ');\n}\n\nexport function formatSessionList(entries: SessionListEntry[]): string {\n if (entries.length === 0) return 'No active sessions.';\n\n const cols = (['name', 'browser', 'url', 'status'] as const).map((key) => ({\n key,\n header: key.toUpperCase(),\n width: Math.max(key.length, ...entries.map((e) => e[key].length)),\n }));\n\n const row = (e: SessionListEntry) => cols.map((c) => e[c.key].padEnd(c.width)).join(' ');\n const header = cols.map((c) => c.header.padEnd(c.width)).join(' ');\n\n return [header, ...entries.map(row)].join('\\n');\n}\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, getRefsPath, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = 'click <ref>';\nexport const desc = 'Click an element by snapshot reference (e.g., e1)';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1, a3)',\n });\n};\n\ninterface ClickArgs {\n ref: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ClickArgs>(async (argv: ArgumentsCamelCase<ClickArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n await browser.$(result.selector).click();\n console.log(`Clicked ${refKey} (${result.ref.selector})`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error clicking ${refKey}: ${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = ['type <ref> <text>', 'fill <ref> <text>'];\nexport const desc = 'Clear and type text into an input element by snapshot reference';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1)',\n })\n .positional('text', {\n type: 'string',\n describe: 'Text to type',\n });\n};\n\ninterface FillArgs {\n ref: string\n text: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<FillArgs>(async (argv: ArgumentsCamelCase<FillArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n const element = await browser.$(result.selector);\n await element.clearValue();\n await element.addValue(argv.text as string);\n console.log(`Filled ${refKey} with \"${argv.text}\"`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error: ${refKey} not found on page — the page may have changed. Run wdiox snapshot to refresh.\\n${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, withSession } from '../session.js';\n\nexport const command = 'screenshot [path]';\nexport const desc = 'Save a screenshot of the current page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('path', {\n type: 'string',\n describe: 'File path to save screenshot (default: ./screenshot-<timestamp>.png)',\n });\n};\n\ninterface ScreenshotArgs {\n path?: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ScreenshotArgs>(async (argv: ArgumentsCamelCase<ScreenshotArgs>, meta) => {\n const browser = await attach(buildAttachOptions(meta));\n\n const filePath = (argv.path as string) ||\n `screenshot-${new Date().toISOString().replace(/[:.]/g, '-')}.png`;\n\n await browser.saveScreenshot(filePath);\n console.log(`Screenshot saved to ${filePath}`);\n});\n","import type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { listSessions, getSessionDir, deleteSessionFiles, buildAttachOptions } from '../session.js';\nimport { formatSessionList, type SessionListEntry } from '../format.js';\n\nexport const command = ['session-list', 'ls'];\nexport const desc = 'List all active sessions';\n\ninterface SessionListArgs {\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<SessionListArgs>) {\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n const sessions = await listSessions(sessionsDir);\n\n if (sessions.length === 0) {\n console.log('No active sessions.');\n return;\n }\n\n const entries: SessionListEntry[] = [];\n\n for (const session of sessions) {\n let status = 'active';\n try {\n const browser = await attach(buildAttachOptions(session.metadata));\n await browser.getPageSource();\n } catch {\n status = 'expired';\n await deleteSessionFiles(session.name, sessionsDir);\n }\n\n const caps = session.metadata.capabilities;\n const browserName = (caps.browserName as string)\n || (caps.platformName as string)\n || 'unknown';\n entries.push({\n name: session.name,\n browser: browserName,\n url: session.metadata.url,\n status,\n });\n }\n\n console.log(formatSessionList(entries));\n}\n"],"mappings":"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","names":["handler","yargs","command","desc","handler","attach","command","desc","handler","attach","builder","command","desc","handler","attach","fs","isEnoent","desc","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","command","desc","handler","attach","command","desc","handler","attach"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/open.ts","../src/session.ts","../src/commands/close.ts","../src/commands/snapshot.ts","../src/refs.ts","../src/format.ts","../src/commands/click.ts","../src/commands/type.ts","../src/commands/screenshot.ts","../src/commands/session-list.ts"],"sourcesContent":["import yargs from 'yargs';\nimport type { CommandModule } from 'yargs';\nimport { hideBin } from 'yargs/helpers';\n\nimport * as openCmd from './commands/open.js';\nimport * as closeCmd from './commands/close.js';\nimport * as snapshotCmd from './commands/snapshot.js';\nimport * as clickCmd from './commands/click.js';\nimport * as fillCmd from './commands/type';\nimport * as screenshotCmd from './commands/screenshot.js';\nimport * as sessionListCmd from './commands/session-list.js';\n\nconst commands = [\n openCmd, closeCmd, snapshotCmd, clickCmd,\n fillCmd, screenshotCmd, sessionListCmd,\n] as unknown as CommandModule[];\n\nexport async function run() {\n\n // webdriverio's attach() can spawn async BiDi connections that fail after\n // the function returns (e.g. stale session). Suppress these so the CLI\n // doesn't crash during close/reconnect of dead sessions.\n process.on('unhandledRejection', () => {});\n\n let cli = yargs(hideBin(process.argv))\n .scriptName('wdiox')\n .usage('$0 <command> [options]')\n .option('session', {\n alias: 's',\n type: 'string',\n default: process.env.WDIO_SESSION || 'default',\n describe: 'Session name',\n });\n\n for (const cmd of commands) {\n cli = cli.command(cmd);\n }\n\n await cli\n .demandCommand(1, 'You need to specify a command. Try: wdiox open <url>')\n .strict()\n .help()\n .version()\n .parse();\n\n // webdriverio keeps HTTP agents alive — force clean exit after command completes\n process.exit(0);\n}\n","import readline from 'node:readline/promises';\nimport type { ArgumentsCamelCase, Argv } from 'yargs';\nimport type { Capabilities } from '@wdio/types';\nimport { attach, remote } from 'webdriverio';\n\nimport { writeSession, readSession, getSessionDir, buildAttachOptions, deleteSessionFiles } from '../session.js';\n\nexport const command = ['open [url]', 'new [url]', 'start [url]'];\nexport const desc = 'Open a browser or Appium session';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('url', {\n type: 'string',\n describe: 'URL to navigate to',\n })\n .option('browser', {\n alias: 'b',\n type: 'string',\n default: 'chrome',\n describe: 'Browser to use (chrome, firefox, edge, safari)',\n })\n .option('app', {\n type: 'string',\n describe: 'Path to mobile app (.apk, .ipa, .app)',\n })\n .option('device', {\n alias: 'd',\n type: 'string',\n describe: 'Device name for mobile testing',\n })\n .option('platform', {\n type: 'string',\n describe: 'Mobile platform (android, ios)',\n })\n .option('path', {\n type: 'string',\n describe: 'WebDriver/Appium server session path (default: /)',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n describe: 'WebDriver/Appium server port (default: 4723)',\n })\n .option('hostname', {\n type: 'string',\n describe: 'WebDriver/Appium server hostname (default: localhost)',\n })\n .option('grant-permissions', {\n type: 'boolean',\n default: true,\n describe: 'Auto-grant app permissions (Appium only)',\n })\n .option('accept-alert', {\n type: 'boolean',\n default: true,\n describe: 'Auto-accept native alerts (Appium only)',\n })\n .option('auto-dismiss', {\n type: 'boolean',\n default: false,\n describe: 'Auto-dismiss native alerts (Appium only)',\n });\n};\n\ninterface OpenArgs {\n url?: string\n browser: string\n session: string\n app?: string\n device?: string\n platform?: string\n port?: number\n hostname?: string\n grantPermissions: boolean\n acceptAlert: boolean\n autoDismiss: boolean\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<OpenArgs>) {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const existing = await readSession(sessionName, sessionsDir);\n if (existing) {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const context = existing.url || (existing.capabilities['appium:app'] as string) || '';\n const answer = await rl.question(`Session [${sessionName}] is already active${context ? ` (${context})` : ''}.\\nClose it and start a new one? (y/N) `);\n rl.close();\n\n if (answer.trim().toLowerCase() !== 'y') {\n return;\n }\n\n try {\n const old = await attach(buildAttachOptions(existing));\n await old.deleteSession();\n } catch {\n // Already dead\n }\n await deleteSessionFiles(sessionName, sessionsDir);\n }\n\n const capabilities: Record<string, unknown> = {};\n\n const isMobile = !!argv.app;\n if (isMobile) {\n const platform = argv.platform ?? (argv.app?.endsWith('.apk') ? 'android' : 'ios');\n\n capabilities.platformName = platform === 'ios' ? 'iOS' : 'Android';\n capabilities['appium:app'] = argv.app;\n capabilities['appium:deviceName'] = argv.device ?? 'emulator-5554';\n capabilities['appium:newCommandTimeout'] = 300;\n capabilities['appium:automationName'] = platform === 'ios' ? 'XCUITest' : 'UiAutomator2';\n capabilities['appium:autoGrantPermissions'] = argv.grantPermissions;\n capabilities['appium:autoAcceptAlerts'] = argv.acceptAlert;\n capabilities['appium:autoDismissAlerts'] = argv.autoDismiss;\n } else {\n capabilities.browserName = argv.browser;\n }\n\n const remoteOpts: Record<string, unknown> = { capabilities, logLevel: process.env.WDIO_LOG_LEVEL ?? 'error' };\n // For mobile / Appium, explicit connection is required\n if (argv.hostname || argv.port || isMobile) {\n remoteOpts.hostname = argv.hostname ?? 'localhost';\n remoteOpts.port = argv.port ?? (isMobile ? 4723 : 4444);\n remoteOpts.path = argv.path ?? '/';\n }\n\n const browser = await remote(remoteOpts as unknown as Capabilities.WebdriverIOConfig);\n\n if (argv.url) {\n await browser.url(argv.url);\n }\n\n const opts = browser.options as Capabilities.WebdriverIOConfig;\n await writeSession(sessionName, {\n sessionId: browser.sessionId,\n hostname: opts?.hostname || 'localhost',\n port: opts?.port || 4444,\n capabilities: { ...capabilities, ...browser.capabilities as Record<string, unknown> },\n created: new Date().toISOString(),\n url: argv.url || '',\n }, sessionsDir);\n\n console.log(`Session \"${sessionName}\" started.`);\n}\n","import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { AttachOptions } from 'webdriverio';\nimport type { ArgumentsCamelCase } from 'yargs';\n\nexport interface SessionMetadata {\n sessionId: string\n hostname: string\n port: number\n capabilities: Record<string, unknown>\n created: string\n url: string\n}\n\nexport interface SessionEntry {\n name: string\n metadata: SessionMetadata\n}\n\nconst DEFAULT_SESSION_DIR = path.join(os.homedir(), '.wdio-x', 'sessions');\n\nfunction isEnoent(err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Build attach options from session metadata for use with webdriverio's `attach()`.\n */\nexport function buildAttachOptions(meta: SessionMetadata): AttachOptions {\n return {\n sessionId: meta.sessionId,\n capabilities: meta.capabilities as WebdriverIO.Capabilities,\n options: {\n hostname: meta.hostname,\n port: meta.port,\n logLevel: process.env.WDIO_LOG_LEVEL ?? 'error',\n },\n } as AttachOptions;\n}\n\n/**\n * Returns the session directory path. Defaults to ~/.wdio-x/sessions/.\n */\nexport function getSessionDir (baseDir?: string): string {\n return baseDir ?? DEFAULT_SESSION_DIR;\n}\n\n/**\n * Returns the file path for a session's metadata JSON file.\n */\nexport function getSessionPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.json`);\n}\n\n/**\n * Returns the file path for a session's refs JSON file.\n */\nexport function getRefsPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.refs.json`);\n}\n\n/**\n * Writes session metadata to disk, creating the directory if needed.\n */\nexport async function writeSession (\n name: string,\n metadata: SessionMetadata,\n baseDir?: string,\n): Promise<void> {\n const dir = getSessionDir(baseDir);\n await fs.mkdir(dir, { recursive: true });\n const filePath = getSessionPath(name, baseDir);\n await fs.writeFile(filePath, JSON.stringify(metadata, null, 2));\n}\n\n/**\n * Reads session metadata from disk. Returns null if the session file does not exist.\n */\nexport async function readSession (\n name: string,\n baseDir?: string,\n): Promise<SessionMetadata | null> {\n const filePath = getSessionPath(name, baseDir);\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as SessionMetadata;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Deletes both the .json and .refs.json files for a session.\n * Does not throw if the files do not exist.\n */\nexport async function deleteSessionFiles (\n name: string,\n baseDir?: string,\n): Promise<void> {\n const sessionPath = getSessionPath(name, baseDir);\n const refsPath = getRefsPath(name, baseDir);\n await Promise.all([\n fs.rm(sessionPath, { force: true }),\n fs.rm(refsPath, { force: true }),\n ]);\n}\n\n/**\n * Lists all sessions in the session directory.\n * Only considers .json files (excludes .refs.json).\n * Returns an empty array if the directory does not exist.\n */\nexport async function listSessions (baseDir?: string): Promise<SessionEntry[]> {\n const dir = getSessionDir(baseDir);\n let files: string[];\n try {\n files = await fs.readdir(dir);\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return [];\n }\n throw err;\n }\n\n const sessionFiles = files.filter(\n (f) => f.endsWith('.json') && !f.endsWith('.refs.json'),\n );\n\n return await Promise.all(\n sessionFiles.map(async (f) => {\n const name = f.replace(/\\.json$/, '');\n const metadata = await readSession(name, baseDir);\n return { name, metadata: metadata! };\n }),\n );\n}\n\ninterface SessionArgs {\n session: string\n _sessionsDir?: string\n}\n\n/**\n * Wraps a command handler that requires an active session.\n * Reads the session from disk and exits early with an error if not found.\n */\nexport function withSession<T extends SessionArgs>(\n fn: (argv: ArgumentsCamelCase<T>, meta: SessionMetadata, sessionsDir: string) => Promise<void>,\n): (argv: ArgumentsCamelCase<T>) => Promise<void> {\n return async function handler(argv: ArgumentsCamelCase<T>): Promise<void> {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const meta = await readSession(sessionName, sessionsDir);\n if (!meta) {\n console.error(`Error: No active session [${sessionName}]. Run wdiox open <url> first.`);\n return;\n }\n\n await fn(argv, meta, sessionsDir);\n };\n}\n","import type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { deleteSessionFiles, buildAttachOptions, withSession } from '../session.js';\n\nexport const command = ['close', 'stop'];\nexport const desc = 'Close the current session';\n\ninterface CloseArgs {\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<CloseArgs>(async (argv: ArgumentsCamelCase<CloseArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n\n try {\n const browser = await attach(buildAttachOptions(meta));\n await browser.deleteSession();\n } catch {\n // Session may already be dead - clean up anyway\n }\n\n await deleteSessionFiles(sessionName, sessionsDir);\n console.log(`Session \"${sessionName}\" closed.`);\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { writeRefs, type RefMap } from '../refs.js';\nimport { getInteractableBrowserElements, getMobileVisibleElements } from '@wdio/mcp/snapshot';\nimport {\n formatBrowserElement,\n formatMobileElement,\n} from '../format.js';\n\nexport const command = 'snapshot';\nexport const desc = 'Capture interactive elements on the page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .option('visible', {\n type: 'boolean',\n default: true,\n describe: 'Only show elements in viewport',\n });\n};\n\ninterface SnapshotArgs {\n session: string\n visible: boolean\n _sessionsDir?: string\n}\n\nexport const handler = withSession<SnapshotArgs>(async (argv: ArgumentsCamelCase<SnapshotArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const browser = await attach(buildAttachOptions(meta));\n\n const isMobile = browser.isAndroid || browser.isIOS;\n const refs: RefMap = {};\n\n if (isMobile) {\n const platform = browser.isIOS ? 'ios' : 'android';\n const elements = await getMobileVisibleElements(browser, platform);\n const filtered = argv.visible\n ? elements.filter(el => el.isInViewport)\n : elements;\n\n const appName = (meta.capabilities['appium:app'] as string) || 'unknown';\n console.log(`\\n App: ${appName}\\n`);\n\n filtered.forEach((el, i) => {\n const ref = `e${i + 1}`;\n console.log(formatMobileElement(ref, {\n tagName: el.tagName,\n text: el.text,\n selector: el.selector,\n accessibilityId: el.accessibilityId,\n resourceId: el.resourceId,\n }));\n refs[ref] = {\n selector: el.selector,\n tagName: el.tagName,\n text: el.text,\n };\n });\n\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\n } else {\n const elements = await getInteractableBrowserElements(browser);\n const filtered = argv.visible\n ? elements.filter(el => el.isInViewport)\n : elements;\n\n const currentUrl = await browser.getUrl();\n console.log(`\\n Page: ${currentUrl}\\n`);\n\n filtered.forEach((el, i) => {\n const ref = `e${i + 1}`;\n console.log(formatBrowserElement(ref, el));\n refs[ref] = {\n selector: el.selector,\n tagName: el.tagName,\n text: el.name || '',\n };\n });\n\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\n }\n\n await writeRefs(getRefsPath(sessionName, sessionsDir), refs);\n});\n","import fs from 'node:fs/promises';\n\nexport interface RefEntry {\n selector?: string\n tagName: string\n text?: string\n placeholder?: string\n [key: string]: unknown\n}\n\nexport type RefMap = Record<string, RefEntry>;\n\nfunction isEnoent (err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Writes a ref map to disk as JSON.\n */\nexport async function writeRefs (refsPath: string, refs: RefMap): Promise<void> {\n await fs.writeFile(refsPath, JSON.stringify(refs, null, 2), 'utf-8');\n}\n\n/**\n * Reads a ref map from disk. Returns null if the file doesn't exist.\n */\nexport async function readRefs (refsPath: string): Promise<RefMap | null> {\n try {\n const content = await fs.readFile(refsPath, 'utf-8');\n return JSON.parse(content) as RefMap;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Look up a ref by key: reads refs file, finds the entry, resolves its selector.\n * Logs appropriate error messages and returns null on failure.\n */\nexport async function lookupRef (\n refsPath: string,\n refKey: string,\n): Promise<{ ref: RefEntry; selector: string } | null> {\n const refs = await readRefs(refsPath);\n if (!refs) {\n console.error('Error: No snapshot taken. Run wdiox snapshot first.');\n return null;\n }\n\n const ref = refs[refKey];\n if (!ref) {\n const available = Object.keys(refs);\n const range = available.length > 0\n ? `Available: ${available[0]}-${available[available.length - 1]}`\n : 'No refs available';\n console.error(`Error: ${refKey} not found in snapshot. ${range}`);\n return null;\n }\n\n if (!ref.selector) {\n console.error(`Error: Could not resolve selector for ${refKey}`);\n return null;\n }\n\n return { ref, selector: ref.selector };\n}\n","export interface BrowserElementFormatInput {\n tagName: string\n role?: string\n type?: string\n name?: string\n href?: string\n selector: string\n}\n\nexport interface MobileElementFormatInput {\n tagName: string\n text?: string\n selector: string\n accessibilityId?: string\n resourceId?: string\n}\n\nexport interface SessionListEntry {\n name: string\n browser: string\n url: string\n status: string\n}\n\nfunction truncate(str: string, max = 80): string {\n return str.length <= max ? str : str.slice(0, max - 3) + '...';\n}\n\nexport function formatBrowserElement(ref: string, el: BrowserElementFormatInput): string {\n const tag = (el.role && el.role !== el.tagName ? el.role : el.tagName) + (el.type ? `[${el.type}]` : '');\n const desc = [el.name && `\"${truncate(el.name)}\"`, el.href && `-> ${truncate(el.href)}`].filter(Boolean).join(' ');\n return [ref.padEnd(4), tag, desc, el.selector].filter(Boolean).join(' ');\n}\n\nexport function formatMobileElement(ref: string, el: MobileElementFormatInput): string {\n const selector = el.accessibilityId ? `[accessibility-id: ${el.accessibilityId}]`\n : el.resourceId ? `[resource-id: ${el.resourceId}]`\n : truncate(el.selector);\n const parts = [ref.padEnd(4), el.tagName.padEnd(28), el.text && `\"${truncate(el.text)}\"`, selector];\n return parts.filter(Boolean).join(' ');\n}\n\nexport function formatSessionList(entries: SessionListEntry[]): string {\n if (entries.length === 0) return 'No active sessions.';\n\n const cols = (['name', 'browser', 'url', 'status'] as const).map((key) => ({\n key,\n header: key.toUpperCase(),\n width: Math.max(key.length, ...entries.map((e) => e[key].length)),\n }));\n\n const row = (e: SessionListEntry) => cols.map((c) => e[c.key].padEnd(c.width)).join(' ');\n const header = cols.map((c) => c.header.padEnd(c.width)).join(' ');\n\n return [header, ...entries.map(row)].join('\\n');\n}\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, getRefsPath, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = 'click <ref>';\nexport const desc = 'Click an element by snapshot reference (e.g., e1)';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1, a3)',\n });\n};\n\ninterface ClickArgs {\n ref: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ClickArgs>(async (argv: ArgumentsCamelCase<ClickArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n await browser.$(result.selector).click();\n console.log(`Clicked ${refKey} (${result.ref.selector})`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error clicking ${refKey}: ${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = ['type <ref> <text>', 'fill <ref> <text>'];\nexport const desc = 'Clear and type text into an input element by snapshot reference';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1)',\n })\n .positional('text', {\n type: 'string',\n describe: 'Text to type',\n });\n};\n\ninterface FillArgs {\n ref: string\n text: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<FillArgs>(async (argv: ArgumentsCamelCase<FillArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n const element = await browser.$(result.selector);\n await element.clearValue();\n await element.addValue(argv.text as string);\n console.log(`Filled ${refKey} with \"${argv.text}\"`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error: ${refKey} not found on page — the page may have changed. Run wdiox snapshot to refresh.\\n${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, withSession } from '../session.js';\n\nexport const command = 'screenshot [path]';\nexport const desc = 'Save a screenshot of the current page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('path', {\n type: 'string',\n describe: 'File path to save screenshot (default: ./screenshot-<timestamp>.png)',\n });\n};\n\ninterface ScreenshotArgs {\n path?: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ScreenshotArgs>(async (argv: ArgumentsCamelCase<ScreenshotArgs>, meta) => {\n const browser = await attach(buildAttachOptions(meta));\n\n const filePath = (argv.path as string) ||\n `screenshot-${new Date().toISOString().replace(/[:.]/g, '-')}.png`;\n\n await browser.saveScreenshot(filePath);\n console.log(`Screenshot saved to ${filePath}`);\n});\n","import type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { listSessions, getSessionDir, deleteSessionFiles, buildAttachOptions } from '../session.js';\nimport { formatSessionList, type SessionListEntry } from '../format.js';\n\nexport const command = ['session-list', 'ls'];\nexport const desc = 'List all active sessions';\n\ninterface SessionListArgs {\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<SessionListArgs>) {\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n const sessions = await listSessions(sessionsDir);\n\n if (sessions.length === 0) {\n console.log('No active sessions.');\n return;\n }\n\n const entries: SessionListEntry[] = [];\n\n for (const session of sessions) {\n let status = 'active';\n try {\n const browser = await attach(buildAttachOptions(session.metadata));\n await browser.getPageSource();\n } catch {\n status = 'expired';\n await deleteSessionFiles(session.name, sessionsDir);\n }\n\n const caps = session.metadata.capabilities;\n const browserName = (caps.browserName as string)\n || (caps.platformName as string)\n || 'unknown';\n entries.push({\n name: session.name,\n browser: browserName,\n url: session.metadata.url,\n status,\n });\n }\n\n console.log(formatSessionList(entries));\n}\n"],"mappings":"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","names":["handler","yargs","command","desc","handler","attach","command","desc","handler","attach","builder","command","desc","handler","attach","fs","isEnoent","desc","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","command","desc","handler","attach","command","desc","handler","attach"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webdriverio-execute",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/Winify/webdriverio-execute.git"
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"homepage": "https://github.com/Winify/webdriverio-execute",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"bin": {
|
|
13
|
-
"wdiox": "./
|
|
13
|
+
"wdiox": "./bin/wdiox.js"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
16
16
|
"node": ">=18.20.0"
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"type": "module",
|
|
30
30
|
"files": [
|
|
31
|
+
"bin",
|
|
31
32
|
"build",
|
|
32
33
|
"README.md"
|
|
33
34
|
],
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
"link": "pnpm run bundle && pnpm i && pnpm link --global"
|
|
43
44
|
},
|
|
44
45
|
"dependencies": {
|
|
45
|
-
"@wdio/mcp": "
|
|
46
|
+
"@wdio/mcp": "^2.3.0",
|
|
46
47
|
"@wdio/types": "^9.24.0",
|
|
47
48
|
"webdriverio": "^9.24.0",
|
|
48
49
|
"yargs": "^17.7.2"
|