Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
291 changes: 211 additions & 80 deletions core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package dev.kdriver.core.dom

import dev.kdriver.cdp.Serialization
import dev.kdriver.cdp.domain.*
import dev.kdriver.core.exceptions.EvaluateException
import dev.kdriver.core.tab.Tab
import io.ktor.util.logging.*
import kotlinx.io.files.Path
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.decodeFromJsonElement
import kotlin.random.Random

/**
* Default implementation of the [Element] interface.
Expand All @@ -20,12 +23,6 @@

private var remoteObject: Runtime.RemoteObject? = null

// Track last mouse position for natural trajectories (P2 - Anti-detection)
companion object {
private var lastMouseX: Double? = null
private var lastMouseY: Double? = null
}

override val tag: String
get() = node.nodeName.lowercase()

Expand Down Expand Up @@ -136,6 +133,76 @@
)
}

/**
* Gets stable element coordinates by waiting for position to stabilize across multiple frames.
* This prevents race conditions on slow systems where scroll or layout changes may still be in progress.
*
* @return Stable coordinates, or null if element is not visible/connected
*/
private suspend fun getStableCoordinates(): CoordinateResult? {

Check warning on line 142 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L142

The function getStableCoordinates is too long (63). The maximum length is 60. (detekt.LongMethod)
return try {
apply<CoordinateResult?>(
jsFunction = """
function() {
if (!this || !this.isConnected) return null;

return new Promise(resolve => {
let lastTop = null;
let lastLeft = null;
let stableFrames = 0;
const maxAttempts = 10;
let attempts = 0;

const checkStable = () => {
attempts++;
const rect = this.getBoundingClientRect();

if (rect.width === 0 || rect.height === 0) {
resolve(null);
return;
}

if (lastTop !== null &&
Math.abs(rect.top - lastTop) < 1 &&
Math.abs(rect.left - lastLeft) < 1) {
stableFrames++;
if (stableFrames >= 2) {
resolve({
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
});
return;
}
} else {
stableFrames = 0;
}

lastTop = rect.top;
lastLeft = rect.left;

if (attempts < maxAttempts) {
requestAnimationFrame(checkStable);
} else {
// Timeout: use current position
resolve({
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
});
}
};

requestAnimationFrame(checkStable);
});
}
""".trimIndent(),
awaitPromise = true
)
} catch (e: EvaluateException) {
logger.warn("Could not get stable coordinates for $this: ${e.jsError}")
null
}
}

/**
* Moves the mouse to the target coordinates using a natural Bezier curve trajectory (P2 - Anti-detection).
* This creates smooth, human-like mouse movements instead of instant teleportation.
Expand All @@ -144,20 +211,54 @@
* @param targetY Target Y coordinate
*/
private suspend fun mouseMoveWithTrajectory(targetX: Double, targetY: Double) {
val startX = lastMouseX ?: kotlin.random.Random.nextDouble(100.0, 400.0)
val startY = lastMouseY ?: kotlin.random.Random.nextDouble(100.0, 300.0)
val startX: Double
val startY: Double

if (tab.lastMouseX != null && tab.lastMouseY != null) {
startX = tab.lastMouseX!!
startY = tab.lastMouseY!!
} else {
// Get actual viewport dimensions to avoid placing mouse outside visible area
val viewportData = try {
val viewportJson = tab.rawEvaluate(
"""
({
width: window.innerWidth,
height: window.innerHeight
})
""".trimIndent()
)
if (viewportJson != null) {
Serialization.json.decodeFromJsonElement<dev.kdriver.core.dom.ViewportData>(viewportJson)
} else null
} catch (e: Exception) {

Check warning on line 234 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L234

The caught exception is swallowed. The original exception could be lost. (detekt.SwallowedException)

Check warning on line 234 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L234

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled. (detekt.TooGenericExceptionCaught)
null
}

if (viewportData != null) {
// Use random position within viewport bounds, with margins
val maxX = (viewportData.width - 50).coerceAtLeast(100.0)

Check warning on line 240 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L240

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 240 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L240

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
val maxY = (viewportData.height - 50).coerceAtLeast(100.0)

Check warning on line 241 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L241

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 241 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L241

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
startX = Random.nextDouble(50.0, maxX)

Check warning on line 242 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L242

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
startY = Random.nextDouble(50.0, maxY)

Check warning on line 243 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L243

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
} else {
// Fallback: use target coordinates with offset if viewport query fails
startX = (targetX - Random.nextDouble(50.0, 150.0)).coerceAtLeast(0.0)

Check warning on line 246 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L246

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 246 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L246

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
startY = (targetY - Random.nextDouble(50.0, 150.0)).coerceAtLeast(0.0)

Check warning on line 247 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L247

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 247 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L247

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
}
}

// Don't create trajectory if we're already at the target
if (startX == targetX && startY == targetY) {
return
}

// Random number of steps for natural variation (8-15 steps)
val steps = kotlin.random.Random.nextInt(8, 15)
val steps = Random.nextInt(8, 15)

Check warning on line 257 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L257

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 257 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L257

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

// Control point for quadratic Bezier curve with random offset
val ctrlX = (startX + targetX) / 2 + kotlin.random.Random.nextDouble(-30.0, 30.0)
val ctrlY = (startY + targetY) / 2 + kotlin.random.Random.nextDouble(-20.0, 20.0)
val ctrlX = (startX + targetX) / 2 + Random.nextDouble(-30.0, 30.0)

Check warning on line 260 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L260

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 260 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L260

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
val ctrlY = (startY + targetY) / 2 + Random.nextDouble(-20.0, 20.0)

Check warning on line 261 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L261

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 261 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L261

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

logger.debug("Mouse trajectory from ($startX, $startY) to ($targetX, $targetY) via control point ($ctrlX, $ctrlY) in $steps steps")

Expand All @@ -171,14 +272,12 @@
tab.input.dispatchMouseEvent(type = "mouseMoved", x = x, y = y)

// Random delay between steps for natural variation
if (i < steps) {
tab.sleep(kotlin.random.Random.nextLong(8, 25))
}
if (i < steps) tab.sleep(Random.nextLong(8, 25))

Check warning on line 275 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L275

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 275 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L275

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
}

// Update last position
lastMouseX = targetX
lastMouseY = targetY
tab.lastMouseX = targetX
tab.lastMouseY = targetY
}

override suspend fun mouseMove() {
Expand Down Expand Up @@ -212,8 +311,8 @@
val (centerX, centerY) = coordinates

// Add jitter to mouse coordinates (P1 - Anti-detection)
val jitterX = (kotlin.random.Random.nextDouble() * 10 - 5) // -5 to +5 pixels
val jitterY = (kotlin.random.Random.nextDouble() * 6 - 3) // -3 to +3 pixels
val jitterX = (Random.nextDouble() * 10 - 5) // -5 to +5 pixels

Check warning on line 314 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L314

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 314 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L314

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
val jitterY = (Random.nextDouble() * 6 - 3) // -3 to +3 pixels

Check warning on line 315 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L315

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 315 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L315

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
val x = centerX + jitterX
val y = centerY + jitterY

Expand Down Expand Up @@ -280,25 +379,9 @@
tab.scrollTo(scrollData.scrollX, scrollData.scrollY)
}

// Get updated coordinates after scrolling
val coordinates = try {
apply<CoordinateResult?>(
jsFunction = """
function() {
if (!this || !this.isConnected) return null;
const rect = this.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) return null;
return {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
};
}
""".trimIndent()
)
} catch (e: EvaluateException) {
logger.warn("Could not get coordinates for $this: ${e.jsError}")
return
}
// Get updated coordinates after scrolling, waiting for position stability
// This is critical on slow systems where scroll may not complete immediately
val coordinates = getStableCoordinates()

if (coordinates == null) {
logger.warn("Could not find location for $this, not clicking")
Expand All @@ -309,8 +392,8 @@

// Add jitter to click coordinates (P1 - Anti-detection)
// Humans don't click exactly at the mathematical center
val jitterX = (kotlin.random.Random.nextDouble() * 10 - 5) // -5 to +5 pixels
val jitterY = (kotlin.random.Random.nextDouble() * 6 - 3) // -3 to +3 pixels
val jitterX = (Random.nextDouble() * 10 - 5) // -5 to +5 pixels

Check warning on line 395 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L395

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 395 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L395

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
val jitterY = (Random.nextDouble() * 6 - 3) // -3 to +3 pixels

Check warning on line 396 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L396

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 396 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L396

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
val x = centerX + jitterX
val y = centerY + jitterY

Expand All @@ -321,32 +404,92 @@
mouseMoveWithTrajectory(x, y)

// Randomized delay to make it more realistic (P1 - Anti-detection)
tab.sleep(kotlin.random.Random.nextLong(5, 20))

// 2. Press mouse button
tab.input.dispatchMouseEvent(
type = "mousePressed",
x = x,
y = y,
button = button,
buttons = button.buttonsMask,
clickCount = clickCount,
modifiers = modifiers
)
tab.sleep(Random.nextLong(5, 20))

Check warning on line 407 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L407

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 407 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L407

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

// Randomized delay between press and release (P1 - Anti-detection)
tab.sleep(kotlin.random.Random.nextLong(40, 120))

// 3. Release mouse button
tab.input.dispatchMouseEvent(
type = "mouseReleased",
x = x,
y = y,
button = button,
buttons = button.buttonsMask,
clickCount = clickCount,
modifiers = modifiers
)
// 2. Verify element hasn't moved during trajectory (handles React re-renders, animations, etc.)
val finalCoordinates = try {
apply<CoordinateResult?>(
jsFunction = """
function() {
if (!this || !this.isConnected) return null;
const rect = this.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) return null;
return {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2
};
}
""".trimIndent()
)
} catch (e: EvaluateException) {

Check warning on line 424 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L424

The caught exception is swallowed. The original exception could be lost. (detekt.SwallowedException)
null
}

// Adjust click position if element moved significantly (>5px threshold)
val finalX: Double
val finalY: Double
if (finalCoordinates != null) {
val (finalCenterX, finalCenterY) = finalCoordinates
val deltaX = finalCenterX - centerX
val deltaY = finalCenterY - centerY
val moved = kotlin.math.sqrt(deltaX * deltaX + deltaY * deltaY) > 5.0

Check warning on line 435 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L435

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

if (moved) {
logger.debug("Element moved during trajectory by ($deltaX, $deltaY), adjusting click position")
finalX = finalCenterX + jitterX
finalY = finalCenterY + jitterY
// Move mouse to adjusted position
tab.input.dispatchMouseEvent(type = "mouseMoved", x = finalX, y = finalY)
tab.lastMouseX = finalX
tab.lastMouseY = finalY
} else {
finalX = x
finalY = y
}
} else {
// Element disappeared or error occurred, use original position
finalX = x
finalY = y
}

// 3. Press and release mouse button with guaranteed cleanup
// Use try-finally to ensure button state is always cleaned up even on error
try {
tab.input.dispatchMouseEvent(
type = "mousePressed",
x = finalX,
y = finalY,
button = button,
buttons = button.buttonsMask,
clickCount = clickCount,
modifiers = modifiers
)

// Randomized delay between press and release (P1 - Anti-detection)
tab.sleep(Random.nextLong(40, 120))

Check warning on line 469 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L469

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 469 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L469

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

// 4. Release mouse button
tab.input.dispatchMouseEvent(
type = "mouseReleased",
x = finalX,
y = finalY,
button = button,
buttons = button.buttonsMask,
clickCount = clickCount,
modifiers = modifiers
)
} catch (e: Exception) {

Check warning on line 481 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L481

The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled. (detekt.TooGenericExceptionCaught)
// Ensure button is released even on error to prevent stuck button state
runCatching {
tab.input.dispatchMouseEvent(
type = "mouseReleased",
x = finalX,
y = finalY,
button = button
)
}
throw e
}
}

override suspend fun focus() {
Expand Down Expand Up @@ -392,7 +535,6 @@
}

override suspend fun clearInputByDeleting() {
// Focus the element first
focus()

// Set selection range to the beginning and get initial value length atomically
Expand All @@ -402,7 +544,7 @@
el.setSelectionRange(0, 0);
return el.value.length;
}
""".trimIndent()
""".trimIndent()
) ?: 0

// Delete each character using CDP Input.dispatchKeyEvent (P3 - Anti-detection)
Expand Down Expand Up @@ -432,26 +574,15 @@
"""
(el) => {
el.value = el.value.slice(1);
el.dispatchEvent(new Event('input', { bubbles: true }));
return el.value.length;
}
""".trimIndent()
""".trimIndent()
) ?: 0

// Random delay between deletions (50-100ms) for natural variation
if (remaining > 0) {
tab.sleep(kotlin.random.Random.nextLong(50, 100))
}
if (remaining > 0) tab.sleep(Random.nextLong(50, 100))

Check warning on line 584 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L584

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)

Check warning on line 584 in core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt

View check run for this annotation

codefactor.io / CodeFactor

core/src/commonMain/kotlin/dev/kdriver/core/dom/DefaultElement.kt#L584

This expression contains a magic number. Consider defining it to a well named constant. (detekt.MagicNumber)
}

// Dispatch input event to notify the page of the change
apply<String?>(
"""
(el) => {
el.dispatchEvent(new Event('input', { bubbles: true }));
return null;
}
""".trimIndent()
)
}

override suspend fun rawApply(
Expand Down
Loading