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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ To use kdriver, add the following to your `build.gradle.kts`:

```kotlin
dependencies {
implementation("dev.kdriver:core:0.5.7")
implementation("dev.kdriver:core:0.5.8")
}
```

Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {

allprojects {
group = "dev.kdriver"
version = "0.5.7"
version = "0.5.8"
project.ext.set("url", "https://github.com/cdpdriver/kdriver")
project.ext.set("license.name", "Apache 2.0")
project.ext.set("license.url", "https://www.apache.org/licenses/LICENSE-2.0.txt")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import dev.kdriver.core.tab.Tab
*/
class BaseBatchRequestExpectation(
tab: Tab,
urlPatterns: List<Regex>,
urlPatterns: List<Regex?>,
) : BatchRequestExpectation {

override val expectations: Map<Regex, RequestExpectation> =
override val expectations: Map<Regex?, RequestExpectation> =
urlPatterns.associateWith { pattern -> BaseRequestExpectation(tab, pattern) }

override suspend fun <T> use(block: suspend BatchRequestExpectation.() -> T): T {
Expand All @@ -20,5 +19,4 @@ class BaseBatchRequestExpectation(
}
return nest(0, block)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ import kotlin.coroutines.coroutineContext
*/
open class BaseFetchInterception(
private val tab: Tab,
override val urlPattern: String,
override val requestStage: Fetch.RequestStage,
override val resourceType: Network.ResourceType,
override val urlPattern: String? = null,
override val requestStage: Fetch.RequestStage? = null,
override val resourceType: Network.ResourceType? = null,
) : FetchInterception {

private var responseDeferred = CompletableDeferred<Fetch.RequestPausedParameter>()
private var job: Job? = null

Expand Down Expand Up @@ -131,5 +130,4 @@ open class BaseFetchInterception(
binaryResponseHeaders = binaryResponseHeaders
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ import kotlin.coroutines.coroutineContext
*/
open class BaseRequestExpectation(
private val tab: Tab,
override val urlPattern: Regex,
override val urlPattern: Regex? = null,
) : RequestExpectation {

private var requestJob: Job? = null
private var responseJob: Job? = null
private var loadingFinishedJob: Job? = null
Expand All @@ -29,7 +28,8 @@ open class BaseRequestExpectation(

private val requestHandler: suspend (Network.RequestWillBeSentParameter) -> Unit =
requestHandler@{ event ->
if (!urlPattern.containsMatchIn(event.request.url)) return@requestHandler
val urlPattern = urlPattern
if (urlPattern != null && !urlPattern.containsMatchIn(event.request.url)) return@requestHandler
requestId = event.requestId
requestDeferred.complete(event)
requestJob?.cancel()
Expand Down Expand Up @@ -103,5 +103,4 @@ open class BaseRequestExpectation(
loadingFinishedDeferred.await() // Ensure the loading is finished before fetching the body
return EncodedBody(tab.network.getResponseBody(requestId))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ package dev.kdriver.core.network
* Represents a batch of request expectations, each defined by a URL pattern and its corresponding expectation.
*/
interface BatchRequestExpectation {

/**
* A map of URL patterns (as [Regex]) to their corresponding [RequestExpectation]s.
*/
val expectations: Map<Regex, RequestExpectation>
val expectations: Map<Regex?, RequestExpectation>

/**
* Activate all expectations for the duration of [block]. Expectations are enabled concurrently
* by nesting RequestExpectation.use calls, so all handlers are active while [block] executes.
*/
suspend fun <T> use(block: suspend BatchRequestExpectation.() -> T): T

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,20 @@ import dev.kdriver.cdp.domain.Network
* @param resourceType The type of resource to intercept (e.g., document, script, etc.).
*/
interface FetchInterception {

/**
* The URL pattern to match requests and responses.
*/
val urlPattern: String
val urlPattern: String?

/**
* The stage of the fetch request to intercept (e.g., request or response).
*/
val requestStage: Fetch.RequestStage
val requestStage: Fetch.RequestStage?

/**
* The type of resource to intercept (e.g., document, script, etc.).
*/
val resourceType: Network.ResourceType
val resourceType: Network.ResourceType?

/**
* Resets the internal state, allowing the interception to be reused.
Expand Down Expand Up @@ -125,5 +124,4 @@ interface FetchInterception {
responseHeaders: List<HeaderEntry>? = null,
binaryResponseHeaders: String? = null,
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ import dev.kdriver.cdp.domain.Network
* @param urlPattern The URL pattern to match requests and responses.
*/
interface RequestExpectation {

/**
* The URL pattern to match requests and responses.
*/
val urlPattern: Regex
val urlPattern: Regex?

/**
* Resets the internal state, allowing the expectation to be reused.
Expand Down Expand Up @@ -51,5 +50,4 @@ interface RequestExpectation {
* Fetches the raw response body once it has been received.
*/
suspend fun getRawResponseBody(): EncodedBody

}
10 changes: 5 additions & 5 deletions core/src/commonMain/kotlin/dev/kdriver/core/tab/DefaultTab.kt
Original file line number Diff line number Diff line change
Expand Up @@ -620,23 +620,23 @@ open class DefaultTab(
}

override suspend fun <T> expect(
urlPattern: Regex,
urlPattern: Regex?,
block: suspend RequestExpectation.() -> T,
): T {
return BaseRequestExpectation(this, urlPattern).use(block)
}

override suspend fun <T> expectBatch(
urlPatterns: List<Regex>,
urlPatterns: List<Regex?>,
block: suspend BatchRequestExpectation.() -> T,
): T {
return BaseBatchRequestExpectation(this, urlPatterns).use(block)
}

override suspend fun <T> intercept(
urlPattern: String,
requestStage: Fetch.RequestStage,
resourceType: Network.ResourceType,
urlPattern: String?,
requestStage: Fetch.RequestStage?,
resourceType: Network.ResourceType?,
block: suspend FetchInterception.() -> T,
): T {
return BaseFetchInterception(this, urlPattern, requestStage, resourceType).use(block)
Expand Down
12 changes: 5 additions & 7 deletions core/src/commonMain/kotlin/dev/kdriver/core/tab/Tab.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import kotlin.io.encoding.ExperimentalEncodingApi
* ```
*/
interface Tab : Connection {

/**
* Last mouse X position for this tab (for natural trajectories in anti-detection).
* Each tab maintains its own mouse position to prevent concurrent operations from interfering.
Expand Down Expand Up @@ -448,7 +447,7 @@ interface Tab : Connection {
* @param block The block to execute during which the expectation is active.
*/
suspend fun <T> expect(
urlPattern: Regex,
urlPattern: Regex? = null,
block: suspend RequestExpectation.() -> T,
): T

Expand All @@ -460,7 +459,7 @@ interface Tab : Connection {
* @param block The block to execute during which the expectations are active.
*/
suspend fun <T> expectBatch(
urlPatterns: List<Regex>,
urlPatterns: List<Regex?>,
block: suspend BatchRequestExpectation.() -> T,
): T

Expand All @@ -479,9 +478,9 @@ interface Tab : Connection {
* }
*/
suspend fun <T> intercept(
urlPattern: String,
requestStage: Fetch.RequestStage,
resourceType: Network.ResourceType,
urlPattern: String? = null,
requestStage: Fetch.RequestStage? = null,
resourceType: Network.ResourceType? = null,
block: suspend FetchInterception.() -> T,
): T

Expand Down Expand Up @@ -528,5 +527,4 @@ interface Tab : Connection {
* @return List of URLs as [String].
*/
suspend fun getAllUrls(absolute: Boolean = true): List<String>

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@ class FetchInterceptionTest {
browser.stop()
}

@Test
fun testInterceptNoResourceTypeFilter() = runBlocking {
val browser = createBrowser(this, headless = true, sandbox = false)
val tab = browser.mainTab ?: error("Main tab is not available")

val userData = tab.intercept(
"*/user-data.json",
Fetch.RequestStage.RESPONSE,
) {
tab.get(sampleFile("profile.html"))
val originalResponse = withTimeout(3000L) { getResponseBody<UserData>() }
withTimeout(3000L) { continueRequest() }
originalResponse
}

assertEquals("Zendriver", userData.name)
browser.stop()
}

@Test
fun testInterceptWithReload() = runBlocking {
val browser = createBrowser(this, headless = true, sandbox = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,26 @@ class RequestExpectationTest {
browser.stop()
}

@Test
fun testExpectNoFilter() = runBlocking {
val browser = createBrowser(this, headless = true, sandbox = false)
val tab = browser.mainTab ?: error("Main tab is not available")

tab.expect {
tab.get(sampleFile("groceries.html"))

val request = withTimeout(3000L) { this@expect.getRequest() }
val response = withTimeout(3000L) { this@expect.getResponse() }
val responseBody = withTimeout(3000L) { this@expect.getRawResponseBody() }

assertEquals(request.url, response.url)
assertEquals(200, response.status)
assertTrue(responseBody.body.isNotEmpty())
}

browser.stop()
}

@Test
fun testExpectWithReload() = runBlocking {
val browser = createBrowser(this, headless = true, sandbox = false)
Expand Down
2 changes: 1 addition & 1 deletion docs/home/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ To install, add the dependency to your `build.gradle.kts`:

```kotlin
dependencies {
implementation("dev.kdriver:core:0.5.7")
implementation("dev.kdriver:core:0.5.8")
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class OpenTelemetryTab(
private val tab: Tab,
private val tracer: Tracer,
) : Tab {

override var lastMouseX: Double?
get() = tab.lastMouseX
set(value) {
Expand Down Expand Up @@ -339,30 +338,30 @@ class OpenTelemetryTab(
}

override suspend fun <T> expect(
urlPattern: Regex,
urlPattern: Regex?,
block: suspend RequestExpectation.() -> T,
): T = executeInSpan("kdriver.tab.expect", SpanKind.INTERNAL) { span ->
span.setAttribute("urlPattern", urlPattern.pattern)
urlPattern?.pattern?.let { span.setAttribute("urlPattern", it) }
tab.expect(urlPattern, block)
}

override suspend fun <T> expectBatch(
urlPatterns: List<Regex>,
urlPatterns: List<Regex?>,
block: suspend BatchRequestExpectation.() -> T,
): T = executeInSpan("kdriver.tab.expectBatch", SpanKind.INTERNAL) { span ->
span.setAttribute("urlPatterns", urlPatterns.joinToString(",") { it.pattern })
span.setAttribute("urlPatterns", urlPatterns.joinToString(",") { it?.pattern ?: "null" })
tab.expectBatch(urlPatterns, block)
}

override suspend fun <T> intercept(
urlPattern: String,
requestStage: Fetch.RequestStage,
resourceType: Network.ResourceType,
urlPattern: String?,
requestStage: Fetch.RequestStage?,
resourceType: Network.ResourceType?,
block: suspend FetchInterception.() -> T,
): T = executeInSpan("kdriver.tab.intercept", SpanKind.INTERNAL) { span ->
span.setAttribute("urlPattern", urlPattern)
span.setAttribute("requestStage", requestStage.name)
span.setAttribute("resourceType", resourceType.name)
urlPattern?.let { span.setAttribute("urlPattern", it) }
requestStage?.name?.let { span.setAttribute("requestStage", it) }
resourceType?.name?.let { span.setAttribute("resourceType", it) }
tab.intercept(urlPattern, requestStage, resourceType, block)
}

Expand Down Expand Up @@ -450,5 +449,4 @@ class OpenTelemetryTab(
span.end()
}
}

}
Loading