UNPKG

@labnex/cli

Version:

CLI for Labnex, an AI-Powered Testing Automation Platform

135 lines 6.22 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.handleType = handleType; const elementFinderV2_1 = require("../elementFinderV2"); // Updated import const inquirer_1 = __importDefault(require("inquirer")); const placeholderCache = {}; // persisted per run async function handleType(page, currentFrame, addLog, selector, textToType, originalStep, retryApiCallFn) { if (!page) throw new Error('Page not available for type'); if (!currentFrame) throw new Error('Current frame not available for type'); if (!selector) throw new Error('Type selector not provided'); if (textToType === undefined) throw new Error('Text to type not provided'); let finalText = textToType; // Handle placeholder prompting const interactive = process.env.RUNNER_NON_INTERACTIVE !== 'true' && process.stdout.isTTY; if (finalText === '__PROMPT_VALID_USERNAME__') { if (!placeholderCache.username && interactive) { const answer = await inquirer_1.default.prompt([ { type: 'input', name: 'username', message: 'Enter a valid username to use for this test run:', validate: (val) => val.trim() ? true : 'Username cannot be empty', }, ]); placeholderCache.username = answer.username.trim(); } if (!placeholderCache.username) { throw new Error('Username placeholder encountered but not provided and prompts are disabled.'); } finalText = placeholderCache.username; addLog(`[PlaceholderPrompt] Filled username placeholder with user-provided value.`); } else if (finalText === '__PROMPT_VALID_PASSWORD__') { if (!placeholderCache.password && interactive) { const answer = await inquirer_1.default.prompt([ { type: 'password', name: 'password', message: 'Enter a valid password to use for this test run:', mask: '*', validate: (val) => val.trim() ? true : 'Password cannot be empty', }, ]); placeholderCache.password = answer.password; } if (!placeholderCache.password) { throw new Error('Password placeholder encountered but not provided and prompts are disabled.'); } finalText = placeholderCache.password; addLog(`[PlaceholderPrompt] Filled password placeholder with user-provided value.`); } addLog(`Attempting to type "${finalText}" into element identified by "${selector}"`); const elementToTypeIn = await (0, elementFinderV2_1.findElementWithFallbacks)(page, currentFrame, addLog, selector, selector, originalStep, false, retryApiCallFn); if (!elementToTypeIn) { throw new Error('Element not found'); } // Clear the field before typing only if it's likely to be the correct field const elementTag = await elementToTypeIn.evaluate((el) => el.tagName.toLowerCase()); const elementType = await elementToTypeIn.evaluate((el) => el.getAttribute('type') || ''); const shouldClear = (elementTag === 'input' || elementTag === 'textarea') && !(finalText.toLowerCase().includes('password') && elementType !== 'password'); if (shouldClear) { await elementToTypeIn.evaluate((el) => { if (el.value !== undefined) el.value = ''; // For input, textarea else if (el.isContentEditable) el.textContent = ''; // For contenteditable divs }); addLog(`Cleared field before typing.`); } else { addLog(`Skipped clearing field due to mismatch or password input.`); } await elementToTypeIn.type(finalText, { delay: 50 }); await elementToTypeIn.dispose(); addLog(`Successfully typed "${finalText}" into element "${selector}"`); // If the element was a password field, attempt auto submit if (elementType === 'password') { await autoSubmitIfLogin(page, currentFrame, addLog, retryApiCallFn); } } // Helper: attempt to click a likely submit/login button async function autoSubmitIfLogin(page, frame, addLog, retryApiCallFn) { const candidateSelectors = [ 'button[type="submit"]', 'input[type="submit"]', '[id*="login" i]', '[class*="login" i]', '[data-testid*="login" i]', '[aria-label*="login" i]', '[id*="sign" i]', '[class*="sign" i]', '[data-testid*="sign" i]' ]; for (const sel of candidateSelectors) { try { const element = await (0, elementFinderV2_1.findElementWithFallbacks)(page, frame, addLog, sel, sel, 'auto-submit', true, retryApiCallFn, 0); if (element) { const navPromise = page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 15000 }).catch(() => { }); await element.click({ delay: 50 }); await navPromise; try { await page.waitForSelector('.inventory_item_name', { timeout: 10000 }); } catch { } addLog(`[AutoSubmit] Clicked potential submit button: ${sel}`); await page.evaluate(() => { window.__labnexSubmitted = true; }); await element.dispose(); return true; } } catch { // ignore and continue } } // Fallback: press Enter key on page const navPromiseKey = page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 15000 }).catch(() => { }); await page.keyboard.press('Enter'); await navPromiseKey; try { await page.waitForSelector('.inventory_item_name', { timeout: 10000 }); } catch { } await page.evaluate(() => { window.__labnexSubmitted = true; }); addLog('[AutoSubmit] Pressed Enter key as fallback submit.'); return true; } //# sourceMappingURL=handleType.js.map