Skip to content

Commit c577672

Browse files
abcarrellkoral--
authored andcommitted
- Expand PathQueryCondition to enable matching requests on multiple query parameters (per issue [#16](#16))
- Compatibility is maintained with previous versions
1 parent 3748ca3 commit c577672

File tree

6 files changed

+268
-31
lines changed

6 files changed

+268
-31
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
### 1.1.7 - 01.08.2023
2+
3+
- Expand `PathQueryCondition` to enable matching requests on multiple query parameters (per issue [#16](https://github.com/DroidsOnRoids/mockwebserver-path-dispatcher/issues/16))
4+
- Compatibility is maintained with previous versions
5+
6+
### 1.1.6 - 09.01.2023
7+
8+
- Add option to mock timeout failure
9+
110
### 1.1.5 - 01.12.2022
211

312
- Make FixtureDispatcher thread-safe

README.md

+17-3
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ fun factory() {
126126
dispatcher.putResponse(factory.withPathSuffixAndQueryParameter("suffix", "param"), "response_with_query_parameter")
127127
// match all URLs with path ending with "suffix" and have "param" with "value" as query parameter e.g. http://example.test/prefix/user/suffix?param=value
128128
dispatcher.putResponse(factory.withPathSuffixAndQueryParameter("suffix", "param", "value"), "response_with_query_parameter_and_value")
129+
// match all URLs with path ending with "suffix" and have multiple parameter name/value pairs e.g.http://example.test/prefix/user/suffix?param=value&param2=value2
130+
dispatcher.putResponse(
131+
factory.withPathSuffixAndQueryParameters("suffix", mapOf("param" to "value", "param2" to "value2")),
132+
"response_with_multiple_query_parameters"
133+
)
129134
mockWebServer.setDispatcher(dispatcher)
130135
}
131136
```
@@ -140,6 +145,15 @@ fun pathQueryCondition() {
140145
141146
}
142147
```
148+
Also supports a map of multiple query parameters:
149+
150+
```kotlin
151+
fun pathQueryConditions() {
152+
val dispatcher = FixtureDispatcher()
153+
dispatcher.putResponse(PathQueryCondition("/prefix/suffix", mapOf("param" to "value", "param2" to "value2")), "response_with_query_parameters_and_values")
154+
mockWebServer.setDispatcher(dispatcher)
155+
}
156+
```
143157

144158
`HttpUrlCondition` - when you want to match by some part of URL other than path or single query
145159
parameter:
@@ -175,15 +189,15 @@ fun condition() {
175189
For unit tests:
176190

177191
```gradle
178-
testImplementation 'pl.droidsonroids.testing:mockwebserver-path-dispatcher:1.1.1'
192+
testImplementation 'pl.droidsonroids.testing:mockwebserver-path-dispatcher:1.1.7'
179193
```
180194

181195
or for Android instrumentation tests:
182196

183197
```gradle
184-
androidTestImplementation 'pl.droidsonroids.testing:mockwebserver-path-dispatcher:1.1.1'
198+
androidTestImplementation 'pl.droidsonroids.testing:mockwebserver-path-dispatcher:1.1.7'
185199
```
186200

187201
### License
188202

189-
Library uses the MIT License. See [LICENSE](LICENSE) file.
203+
Library uses the MIT License. See [LICENSE](LICENSE) file.

dispatcher/src/main/kotlin/pl/droidsonroids/testing/mockwebserver/condition/PathQueryCondition.kt

+30-22
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,36 @@ package pl.droidsonroids.testing.mockwebserver.condition
33
import okhttp3.HttpUrl
44

55
/**
6-
* A [Condition] matching by URL path, optional query parameter name and optional query parameter value for that name.
7-
* Instances are sorted from least to most general e.g. one containing query parameter name comes before
8-
* another containing path only.
6+
* A [Condition] matching by URL path and a [Map] of query parameter name/value pairs.
7+
* Instances are sorted from least to most general, based on the number of specified query parameter names and
8+
* the corresponding non-null values.
99
* @property path URL path, required
10-
* @property queryParameterName query parameter name, optional
11-
* @property queryParameterName query parameter value for given name, optional
10+
* @property httpMethod [HTTPMethod] to map to for the given condition, optional
11+
* @property queryParameters [Map] query parameter name/value pairs, optional, defaulting to an empty map
1212
*/
1313
data class PathQueryCondition(
1414
internal val path: String,
1515
override val httpMethod: HTTPMethod,
16-
internal val queryParameterName: String? = null,
17-
internal val queryParameterValue: String? = null
16+
internal val queryParameters: Map<String, String?> = emptyMap()
1817
) : HttpUrlCondition() {
18+
constructor(path: String, queryParameters: Map<String, String?>) :
19+
this(path, HTTPMethod.ANY, queryParameters)
20+
21+
/**
22+
*
23+
* A [Condition] matching by URL path, optional query parameter name and optional query parameter value for that name.
24+
* Instances are sorted from least to most general e.g. one containing query parameter name comes before
25+
* another containing path only.
26+
* @property path URL path, required
27+
* @property httpMethod [HTTPMethod] to map to for the given condition, optional
28+
* @property queryParameterName query parameter name, optional
29+
* @property queryParameterName query parameter value for given name, optional
30+
*/
31+
constructor(path: String, httpMethod: HTTPMethod, queryParameterName: String, queryParameterValue: String? = null) :
32+
this(path, httpMethod, mapOf(queryParameterName to queryParameterValue))
33+
34+
constructor(path: String, queryParameterName: String, queryParameterValue: String? = null) :
35+
this(path, HTTPMethod.ANY, mapOf(queryParameterName to queryParameterValue))
1936

2037
override fun compareTo(other: Condition) = when {
2138
other == this -> 0
@@ -26,14 +43,12 @@ data class PathQueryCondition(
2643
}
2744

2845
override fun isUrlMatching(url: HttpUrl): Boolean {
29-
val requestQueryParameterNames = url.queryParameterNames
3046
if (url.encodedPath == path) {
3147
when {
32-
queryParameterName == null -> return true
33-
requestQueryParameterNames.contains(queryParameterName) -> {
34-
val requestQueryParameterValue = url.queryParameter(queryParameterName)
35-
if (queryParameterValue == null || queryParameterValue == requestQueryParameterValue) {
36-
return true
48+
queryParameters.isEmpty() -> return true
49+
queryParameters.keys.all { it in url.queryParameterNames } -> {
50+
return queryParameters.all {
51+
it.value == null || it.value == url.queryParameter(it.key)
3752
}
3853
}
3954
}
@@ -42,13 +57,6 @@ data class PathQueryCondition(
4257
}
4358

4459
private val score: Int
45-
get() {
46-
if (queryParameterName == null) {
47-
return 0
48-
} else if (queryParameterValue == null) {
49-
return 1
50-
}
51-
return 2
52-
}
53-
60+
get() = queryParameters.keys.count() +
61+
queryParameters.values.count { !it.isNullOrEmpty() }
5462
}

dispatcher/src/main/kotlin/pl/droidsonroids/testing/mockwebserver/condition/PathQueryConditionFactory.kt

+24-1
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,33 @@ package pl.droidsonroids.testing.mockwebserver.condition
77
* @constructor creates new factory with given prefix
88
*/
99
class PathQueryConditionFactory constructor(private val pathPrefix: String = "") {
10+
/**
11+
* Creates condition with <code>path</code> and a <code>Map</code> of one or more query parameter name/value pairs.
12+
* @param pathSuffix path suffix, may be empty
13+
* @param queryParameters <code>Map</code> of query parameter name/value pairs
14+
* @param httpMethod optional HTTPMethod for matching, defaults to HTTPMethod.ANY
15+
* @return a PathQueryCondition
16+
* @since 1.1.7
17+
*/
18+
@JvmOverloads
19+
fun withPathSuffixAndQueryParameters(
20+
pathSuffix: String,
21+
queryParameters: Map<String, String?>,
22+
httpMethod: HTTPMethod = HTTPMethod.ANY
23+
) =
24+
PathQueryCondition(
25+
pathPrefix + pathSuffix,
26+
httpMethod,
27+
queryParameters
28+
)
29+
1030
/**
1131
* Creates condition with both <code>path</code>, <code>queryParameterName</code>
1232
* and <code>queryParameterValue</code>.
1333
* @param pathSuffix path suffix, may be empty
1434
* @param queryParameterName query parameter name <code>queryParameterName</code>
1535
* @param queryParameterValue query parameter value for given
36+
* @param httpMethod optional HTTPMethod for matching, defaults to HTTPMethod.ANY
1637
* @return a PathQueryCondition
1738
* @since 1.1.0
1839
*/
@@ -33,6 +54,7 @@ class PathQueryConditionFactory constructor(private val pathPrefix: String = "")
3354
/**
3455
* Creates condition with <code>path</code> only.
3556
* @param pathSuffix path suffix, may be empty
57+
* @param httpMethod optional HTTPMethod for matching, defaults to HTTPMethod.ANY
3658
* @return a PathQueryCondition
3759
* @since 1.1.0
3860
*/
@@ -48,6 +70,7 @@ class PathQueryConditionFactory constructor(private val pathPrefix: String = "")
4870
/**
4971
* Creates condition with <code>path</code> only.
5072
* @param path the path
73+
* @param httpMethod optional HTTPMethod for matching, defaults to HTTPMethod.ANY
5174
* @return a PathQueryCondition
5275
*/
5376
fun withPath(
@@ -108,4 +131,4 @@ class PathQueryConditionFactory constructor(private val pathPrefix: String = "")
108131
@Deprecated("Infix renamed to suffix", replaceWith = ReplaceWith("withPathSuffix"))
109132
fun withPathInfix(pathInfix: String) =
110133
withPathSuffix(pathInfix)
111-
}
134+
}

0 commit comments

Comments
 (0)