Error correction

This commit is contained in:
2025-11-11 15:01:02 +01:00
parent 108c9bf215
commit 3f65ac83cd
4 changed files with 46 additions and 223 deletions

View File

@@ -151,181 +151,5 @@ export async function waitForElementSmart(
}
}
/**
* Wait for navigation to complete intelligently
* Uses URL change + DOM ready instead of fixed timeouts
*/
export async function waitForNavigationSmart(
page: Page,
options: {
expectedUrl?: string | RegExp
maxWaitMs?: number
logFn?: (msg: string) => void
} = {}
): Promise<{ completed: boolean; timeMs: number; url: string }> {
const startTime = Date.now()
const maxWaitMs = options.maxWaitMs ?? 15000
const logFn = options.logFn ?? (() => { })
try {
// Wait for URL to change (if we expect it to)
if (options.expectedUrl) {
const urlPattern = typeof options.expectedUrl === 'string'
? new RegExp(options.expectedUrl.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
: options.expectedUrl
let urlChanged = false
const checkInterval = 100
const maxChecks = maxWaitMs / checkInterval
for (let i = 0; i < maxChecks; i++) {
const currentUrl = page.url()
if (urlPattern.test(currentUrl)) {
urlChanged = true
logFn(`✓ URL changed to expected pattern (${Date.now() - startTime}ms)`)
break
}
await page.waitForTimeout(checkInterval)
}
if (!urlChanged) {
const elapsed = Date.now() - startTime
logFn(`⚠ URL did not match expected pattern after ${elapsed}ms`)
return { completed: false, timeMs: elapsed, url: page.url() }
}
}
// Wait for page to be ready after navigation
const readyResult = await waitForPageReady(page, {
logFn
})
const elapsed = Date.now() - startTime
return { completed: readyResult.ready, timeMs: elapsed, url: page.url() }
} catch (error) {
const elapsed = Date.now() - startTime
const errorMsg = error instanceof Error ? error.message : String(error)
logFn(`✗ Navigation wait failed after ${elapsed}ms: ${errorMsg}`)
return { completed: false, timeMs: elapsed, url: page.url() }
}
}
/**
* Click element with smart waiting (wait for element + click + verify action)
*/
export async function clickElementSmart(
page: Page,
selector: string,
options: {
waitBeforeClick?: number
waitAfterClick?: number
verifyDisappeared?: boolean
maxWaitMs?: number
logFn?: (msg: string) => void
} = {}
): Promise<{ success: boolean; timeMs: number }> {
const startTime = Date.now()
const waitBeforeClick = options.waitBeforeClick ?? 100
const waitAfterClick = options.waitAfterClick ?? 500
const logFn = options.logFn ?? (() => { })
try {
// Wait for element to be clickable
const elementResult = await waitForElementSmart(page, selector, {
state: 'visible',
initialTimeoutMs: options.maxWaitMs ? Math.floor(options.maxWaitMs * 0.4) : 2000,
extendedTimeoutMs: options.maxWaitMs ? Math.floor(options.maxWaitMs * 0.6) : 5000,
logFn
})
if (!elementResult.found || !elementResult.element) {
return { success: false, timeMs: Date.now() - startTime }
}
// Small delay for stability
if (waitBeforeClick > 0) {
await page.waitForTimeout(waitBeforeClick)
}
// Click the element
await elementResult.element.click()
logFn('✓ Clicked element')
// Wait for action to process
if (waitAfterClick > 0) {
await page.waitForTimeout(waitAfterClick)
}
// Verify element disappeared (optional)
if (options.verifyDisappeared) {
const disappeared = await page.locator(selector).isVisible()
.then(() => false)
.catch(() => true)
if (disappeared) {
logFn('✓ Element disappeared after click (expected)')
}
}
const elapsed = Date.now() - startTime
return { success: true, timeMs: elapsed }
} catch (error) {
const elapsed = Date.now() - startTime
const errorMsg = error instanceof Error ? error.message : String(error)
logFn(`✗ Click failed after ${elapsed}ms: ${errorMsg}`)
return { success: false, timeMs: elapsed }
}
}
/**
* Type text into input field with smart waiting
*/
export async function typeIntoFieldSmart(
page: Page,
selector: string,
text: string,
options: {
clearFirst?: boolean
delay?: number
maxWaitMs?: number
logFn?: (msg: string) => void
} = {}
): Promise<{ success: boolean; timeMs: number }> {
const startTime = Date.now()
const delay = options.delay ?? 20
const logFn = options.logFn ?? (() => { })
try {
// Wait for input field
const elementResult = await waitForElementSmart(page, selector, {
state: 'visible',
initialTimeoutMs: options.maxWaitMs ? Math.floor(options.maxWaitMs * 0.4) : 2000,
extendedTimeoutMs: options.maxWaitMs ? Math.floor(options.maxWaitMs * 0.6) : 5000,
logFn
})
if (!elementResult.found || !elementResult.element) {
return { success: false, timeMs: Date.now() - startTime }
}
// Clear field if requested
if (options.clearFirst) {
await elementResult.element.clear()
}
// Type text with delay
await elementResult.element.type(text, { delay })
logFn('✓ Typed into field')
const elapsed = Date.now() - startTime
return { success: true, timeMs: elapsed }
} catch (error) {
const elapsed = Date.now() - startTime
const errorMsg = error instanceof Error ? error.message : String(error)
logFn(`✗ Type failed after ${elapsed}ms: ${errorMsg}`)
return { success: false, timeMs: elapsed }
}
}
// DEAD CODE REMOVED: waitForNavigationSmart, clickElementSmart, and typeIntoFieldSmart
// These functions were never used in the codebase and have been removed to reduce complexity

View File

@@ -9,23 +9,8 @@ export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : String(error)
}
/**
* Format a standardized error message for logging
* Ensures consistent error message formatting across all modules
*
* @param context - Context string (e.g., 'SEARCH-BING', 'LOGIN')
* @param error - Error object or unknown value
* @param prefix - Optional custom prefix (defaults to 'Error')
* @returns Formatted error message
*
* @example
* formatErrorMessage('SEARCH', err) // 'Error in SEARCH: Network timeout'
* formatErrorMessage('LOGIN', err, 'Failed') // 'Failed in LOGIN: Invalid credentials'
*/
export function formatErrorMessage(context: string, error: unknown, prefix: string = 'Error'): string {
const errorMsg = getErrorMessage(error)
return `${prefix} in ${context}: ${errorMsg}`
}
// DEAD CODE REMOVED: formatErrorMessage() was never used (only JSDoc examples existed)
// Use formatDetailedError() instead for error formatting with optional stack traces
/**
* Utility class for common operations