mockserver-client 7.3.0__tar.gz → 7.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/PKG-INFO +59 -2
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/README.md +58 -1
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/__init__.py +58 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/async_client.py +32 -3
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/client.py +11 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/launcher.py +1 -1
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/llm.py +174 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/models.py +882 -7
- mockserver_client-7.5.0/mockserver/pytest_plugin.py +131 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/websocket_client.py +20 -8
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver_client.egg-info/PKG-INFO +59 -2
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver_client.egg-info/SOURCES.txt +4 -0
- mockserver_client-7.5.0/mockserver_client.egg-info/entry_points.txt +2 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/pyproject.toml +4 -1
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_control_plane.py +31 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_integration.py +38 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_llm.py +85 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_models.py +711 -2
- mockserver_client-7.5.0/tests/test_pytest_plugin.py +64 -0
- mockserver_client-7.5.0/tests/test_roundtrip_fidelity.py +233 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/a2a.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/exceptions.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/fluent.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver/mcp.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver_client.egg-info/dependency_links.txt +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver_client.egg-info/requires.txt +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/mockserver_client.egg-info/top_level.txt +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/setup.cfg +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_a2a.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_async_client.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_auth_tls.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_breakpoint.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_client.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_exceptions.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_fluent.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_init.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_launcher.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_mcp.py +0 -0
- {mockserver_client-7.3.0 → mockserver_client-7.5.0}/tests/test_websocket_client.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mockserver-client
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.5.0
|
|
4
4
|
Summary: Official Python client for MockServer — create expectations, verify requests, and register dynamic callbacks via WebSocket
|
|
5
5
|
Author-email: James Bloom <jamesdbloom@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -190,6 +190,63 @@ client.verify_sequence(
|
|
|
190
190
|
client.verify_zero_interactions()
|
|
191
191
|
```
|
|
192
192
|
|
|
193
|
+
## Request Matching
|
|
194
|
+
|
|
195
|
+
### JWT matcher
|
|
196
|
+
|
|
197
|
+
Match requests by the claims (and metadata) of a JWT carried in a header. Each
|
|
198
|
+
claim value is exact-or-regex; prefix a value with `!` to negate it.
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
from mockserver import HttpRequest, HttpResponse, Jwt
|
|
202
|
+
|
|
203
|
+
client.when(
|
|
204
|
+
HttpRequest.request("/secure")
|
|
205
|
+
.with_method("GET")
|
|
206
|
+
.with_jwt(
|
|
207
|
+
claims={
|
|
208
|
+
"sub": "user-123", # exact match
|
|
209
|
+
"email": "^.+@example.com$", # regex match
|
|
210
|
+
"role": "!admin", # negated — matches any role except admin
|
|
211
|
+
},
|
|
212
|
+
issuer="https://issuer.example.com",
|
|
213
|
+
audience="my-api",
|
|
214
|
+
algorithm="RS256",
|
|
215
|
+
header="authorization", # optional (defaults to Authorization)
|
|
216
|
+
scheme="Bearer", # optional token scheme
|
|
217
|
+
)
|
|
218
|
+
).respond(
|
|
219
|
+
HttpResponse.response("granted", status_code=200)
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# ...or pass a Jwt object directly:
|
|
223
|
+
HttpRequest.request("/secure").with_jwt(Jwt(claims={"sub": "user-123"}))
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### allOf body matcher
|
|
227
|
+
|
|
228
|
+
Require a request body to satisfy **all** of several body matchers at once.
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
from mockserver import AllOfBody, Body, JsonPathBody, RegexBody, HttpRequest
|
|
232
|
+
|
|
233
|
+
client.when(
|
|
234
|
+
HttpRequest.request("/api/orders")
|
|
235
|
+
.with_method("POST")
|
|
236
|
+
.with_body(AllOfBody(body_all_of=[
|
|
237
|
+
JsonPathBody(json_path="$.name"), # body has a name field
|
|
238
|
+
RegexBody(regex=".*active.*"), # and mentions "active"
|
|
239
|
+
]))
|
|
240
|
+
).respond(
|
|
241
|
+
HttpResponse.response("ok")
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
# Shorthand factory:
|
|
245
|
+
HttpRequest.request("/api/orders").with_body(
|
|
246
|
+
Body.all_of(JsonPathBody(json_path="$.name"), RegexBody(regex=".*active.*"))
|
|
247
|
+
)
|
|
248
|
+
```
|
|
249
|
+
|
|
193
250
|
## Retrieval
|
|
194
251
|
|
|
195
252
|
```python
|
|
@@ -429,7 +486,7 @@ launcher_path = ensure_binary() # returns Path to the launcher executable
|
|
|
429
486
|
```python
|
|
430
487
|
from mockserver.launcher import start
|
|
431
488
|
|
|
432
|
-
server = start(port=1080, version="7.
|
|
489
|
+
server = start(port=1080, version="7.5.0")
|
|
433
490
|
# ...
|
|
434
491
|
server.stop()
|
|
435
492
|
```
|
|
@@ -160,6 +160,63 @@ client.verify_sequence(
|
|
|
160
160
|
client.verify_zero_interactions()
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
+
## Request Matching
|
|
164
|
+
|
|
165
|
+
### JWT matcher
|
|
166
|
+
|
|
167
|
+
Match requests by the claims (and metadata) of a JWT carried in a header. Each
|
|
168
|
+
claim value is exact-or-regex; prefix a value with `!` to negate it.
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
from mockserver import HttpRequest, HttpResponse, Jwt
|
|
172
|
+
|
|
173
|
+
client.when(
|
|
174
|
+
HttpRequest.request("/secure")
|
|
175
|
+
.with_method("GET")
|
|
176
|
+
.with_jwt(
|
|
177
|
+
claims={
|
|
178
|
+
"sub": "user-123", # exact match
|
|
179
|
+
"email": "^.+@example.com$", # regex match
|
|
180
|
+
"role": "!admin", # negated — matches any role except admin
|
|
181
|
+
},
|
|
182
|
+
issuer="https://issuer.example.com",
|
|
183
|
+
audience="my-api",
|
|
184
|
+
algorithm="RS256",
|
|
185
|
+
header="authorization", # optional (defaults to Authorization)
|
|
186
|
+
scheme="Bearer", # optional token scheme
|
|
187
|
+
)
|
|
188
|
+
).respond(
|
|
189
|
+
HttpResponse.response("granted", status_code=200)
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# ...or pass a Jwt object directly:
|
|
193
|
+
HttpRequest.request("/secure").with_jwt(Jwt(claims={"sub": "user-123"}))
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### allOf body matcher
|
|
197
|
+
|
|
198
|
+
Require a request body to satisfy **all** of several body matchers at once.
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
from mockserver import AllOfBody, Body, JsonPathBody, RegexBody, HttpRequest
|
|
202
|
+
|
|
203
|
+
client.when(
|
|
204
|
+
HttpRequest.request("/api/orders")
|
|
205
|
+
.with_method("POST")
|
|
206
|
+
.with_body(AllOfBody(body_all_of=[
|
|
207
|
+
JsonPathBody(json_path="$.name"), # body has a name field
|
|
208
|
+
RegexBody(regex=".*active.*"), # and mentions "active"
|
|
209
|
+
]))
|
|
210
|
+
).respond(
|
|
211
|
+
HttpResponse.response("ok")
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Shorthand factory:
|
|
215
|
+
HttpRequest.request("/api/orders").with_body(
|
|
216
|
+
Body.all_of(JsonPathBody(json_path="$.name"), RegexBody(regex=".*active.*"))
|
|
217
|
+
)
|
|
218
|
+
```
|
|
219
|
+
|
|
163
220
|
## Retrieval
|
|
164
221
|
|
|
165
222
|
```python
|
|
@@ -399,7 +456,7 @@ launcher_path = ensure_binary() # returns Path to the launcher executable
|
|
|
399
456
|
```python
|
|
400
457
|
from mockserver.launcher import start
|
|
401
458
|
|
|
402
|
-
server = start(port=1080, version="7.
|
|
459
|
+
server = start(port=1080, version="7.5.0")
|
|
403
460
|
# ...
|
|
404
461
|
server.stop()
|
|
405
462
|
```
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
from mockserver.models import (
|
|
2
2
|
AfterAction,
|
|
3
|
+
AllOfBody,
|
|
3
4
|
BinaryResponse,
|
|
4
5
|
Body,
|
|
6
|
+
CaptureRule,
|
|
7
|
+
CaptureSource,
|
|
5
8
|
ConnectionOptions,
|
|
6
9
|
CrossProtocolScenario,
|
|
7
10
|
CrossProtocolTrigger,
|
|
8
11
|
Delay,
|
|
9
12
|
DelayDistribution,
|
|
10
13
|
DnsRecord,
|
|
14
|
+
DnsRecordClass,
|
|
15
|
+
DnsRecordType,
|
|
16
|
+
DnsRequestDefinition,
|
|
11
17
|
DnsResponse,
|
|
12
18
|
Expectation,
|
|
13
19
|
ExpectationId,
|
|
14
20
|
ExpectationStep,
|
|
21
|
+
GraphQLBody,
|
|
15
22
|
GrpcBidiResponse,
|
|
16
23
|
GrpcBidiRule,
|
|
17
24
|
GrpcStreamMessage,
|
|
@@ -20,6 +27,8 @@ from mockserver.models import (
|
|
|
20
27
|
HttpClassCallback,
|
|
21
28
|
HttpError,
|
|
22
29
|
HttpForward,
|
|
30
|
+
HttpForwardValidateAction,
|
|
31
|
+
HttpForwardWithFallback,
|
|
23
32
|
HttpObjectCallback,
|
|
24
33
|
HttpOverrideForwardedRequest,
|
|
25
34
|
HttpRequest,
|
|
@@ -30,7 +39,19 @@ from mockserver.models import (
|
|
|
30
39
|
HttpWebSocketResponse,
|
|
31
40
|
JsonPathBody,
|
|
32
41
|
JsonRpcBody,
|
|
42
|
+
JsonSchemaBody,
|
|
43
|
+
Jwt,
|
|
33
44
|
KeyToMultiValue,
|
|
45
|
+
MultipartBody,
|
|
46
|
+
ParameterBody,
|
|
47
|
+
Protocol,
|
|
48
|
+
RateLimit,
|
|
49
|
+
RateLimitAlgorithm,
|
|
50
|
+
ValidationMode,
|
|
51
|
+
WasmBody,
|
|
52
|
+
XmlBody,
|
|
53
|
+
XmlSchemaBody,
|
|
54
|
+
XPathBody,
|
|
34
55
|
LoadCapture,
|
|
35
56
|
LoadFeeder,
|
|
36
57
|
LoadPacing,
|
|
@@ -44,6 +65,7 @@ from mockserver.models import (
|
|
|
44
65
|
OpenAPIDefinition,
|
|
45
66
|
OpenAPIExpectation,
|
|
46
67
|
Ports,
|
|
68
|
+
RegexBody,
|
|
47
69
|
RequestDefinition,
|
|
48
70
|
ResponseMode,
|
|
49
71
|
SocketAddress,
|
|
@@ -53,10 +75,12 @@ from mockserver.models import (
|
|
|
53
75
|
Verification,
|
|
54
76
|
VerificationSequence,
|
|
55
77
|
VerificationTimes,
|
|
78
|
+
WebSocketFrameMatcher,
|
|
56
79
|
WebSocketMessage,
|
|
57
80
|
)
|
|
58
81
|
from mockserver.llm import (
|
|
59
82
|
Completion,
|
|
83
|
+
ContentFilter,
|
|
60
84
|
ConversationPredicates,
|
|
61
85
|
EmbeddingResponse,
|
|
62
86
|
HttpLlmResponse,
|
|
@@ -65,14 +89,17 @@ from mockserver.llm import (
|
|
|
65
89
|
LlmConversationBuilder,
|
|
66
90
|
LlmFailoverBuilder,
|
|
67
91
|
LlmMockBuilder,
|
|
92
|
+
ModerationResponse,
|
|
68
93
|
NormalizationOptions,
|
|
69
94
|
Provider,
|
|
95
|
+
RerankResponse,
|
|
70
96
|
Role,
|
|
71
97
|
StreamingPhysics,
|
|
72
98
|
ToolUse,
|
|
73
99
|
TurnBuilder,
|
|
74
100
|
Usage,
|
|
75
101
|
completion,
|
|
102
|
+
content_filter,
|
|
76
103
|
conversation,
|
|
77
104
|
cookie,
|
|
78
105
|
embedding,
|
|
@@ -80,7 +107,9 @@ from mockserver.llm import (
|
|
|
80
107
|
llm_failover,
|
|
81
108
|
llm_mock,
|
|
82
109
|
llm_response,
|
|
110
|
+
moderation,
|
|
83
111
|
query_parameter,
|
|
112
|
+
rerank,
|
|
84
113
|
streaming_physics,
|
|
85
114
|
time_to_first_token,
|
|
86
115
|
tool_use,
|
|
@@ -119,19 +148,26 @@ from mockserver.launcher import (
|
|
|
119
148
|
|
|
120
149
|
__all__ = [
|
|
121
150
|
"AfterAction",
|
|
151
|
+
"AllOfBody",
|
|
122
152
|
"AsyncMockServerClient",
|
|
123
153
|
"BinaryResponse",
|
|
124
154
|
"Body",
|
|
155
|
+
"CaptureRule",
|
|
156
|
+
"CaptureSource",
|
|
125
157
|
"ConnectionOptions",
|
|
126
158
|
"CrossProtocolScenario",
|
|
127
159
|
"CrossProtocolTrigger",
|
|
128
160
|
"Delay",
|
|
129
161
|
"DelayDistribution",
|
|
130
162
|
"DnsRecord",
|
|
163
|
+
"DnsRecordClass",
|
|
164
|
+
"DnsRecordType",
|
|
165
|
+
"DnsRequestDefinition",
|
|
131
166
|
"DnsResponse",
|
|
132
167
|
"Expectation",
|
|
133
168
|
"ExpectationId",
|
|
134
169
|
"ExpectationStep",
|
|
170
|
+
"GraphQLBody",
|
|
135
171
|
"GrpcBidiResponse",
|
|
136
172
|
"GrpcBidiRule",
|
|
137
173
|
"GrpcStreamMessage",
|
|
@@ -140,6 +176,8 @@ __all__ = [
|
|
|
140
176
|
"HttpClassCallback",
|
|
141
177
|
"HttpError",
|
|
142
178
|
"HttpForward",
|
|
179
|
+
"HttpForwardValidateAction",
|
|
180
|
+
"HttpForwardWithFallback",
|
|
143
181
|
"HttpObjectCallback",
|
|
144
182
|
"HttpOverrideForwardedRequest",
|
|
145
183
|
"HttpRequest",
|
|
@@ -150,7 +188,19 @@ __all__ = [
|
|
|
150
188
|
"HttpWebSocketResponse",
|
|
151
189
|
"JsonPathBody",
|
|
152
190
|
"JsonRpcBody",
|
|
191
|
+
"JsonSchemaBody",
|
|
192
|
+
"Jwt",
|
|
153
193
|
"KeyToMultiValue",
|
|
194
|
+
"MultipartBody",
|
|
195
|
+
"ParameterBody",
|
|
196
|
+
"Protocol",
|
|
197
|
+
"RateLimit",
|
|
198
|
+
"RateLimitAlgorithm",
|
|
199
|
+
"ValidationMode",
|
|
200
|
+
"WasmBody",
|
|
201
|
+
"XmlBody",
|
|
202
|
+
"XmlSchemaBody",
|
|
203
|
+
"XPathBody",
|
|
154
204
|
"LoadCapture",
|
|
155
205
|
"LoadFeeder",
|
|
156
206
|
"LoadPacing",
|
|
@@ -162,6 +212,7 @@ __all__ = [
|
|
|
162
212
|
"LoadThreshold",
|
|
163
213
|
"MockMode",
|
|
164
214
|
"Completion",
|
|
215
|
+
"ContentFilter",
|
|
165
216
|
"ConversationPredicates",
|
|
166
217
|
"EmbeddingResponse",
|
|
167
218
|
"HttpLlmResponse",
|
|
@@ -170,14 +221,17 @@ __all__ = [
|
|
|
170
221
|
"LlmConversationBuilder",
|
|
171
222
|
"LlmFailoverBuilder",
|
|
172
223
|
"LlmMockBuilder",
|
|
224
|
+
"ModerationResponse",
|
|
173
225
|
"NormalizationOptions",
|
|
174
226
|
"Provider",
|
|
227
|
+
"RerankResponse",
|
|
175
228
|
"Role",
|
|
176
229
|
"StreamingPhysics",
|
|
177
230
|
"ToolUse",
|
|
178
231
|
"TurnBuilder",
|
|
179
232
|
"Usage",
|
|
180
233
|
"completion",
|
|
234
|
+
"content_filter",
|
|
181
235
|
"conversation",
|
|
182
236
|
"cookie",
|
|
183
237
|
"embedding",
|
|
@@ -185,7 +239,9 @@ __all__ = [
|
|
|
185
239
|
"llm_failover",
|
|
186
240
|
"llm_mock",
|
|
187
241
|
"llm_response",
|
|
242
|
+
"moderation",
|
|
188
243
|
"query_parameter",
|
|
244
|
+
"rerank",
|
|
189
245
|
"streaming_physics",
|
|
190
246
|
"time_to_first_token",
|
|
191
247
|
"tool_use",
|
|
@@ -208,6 +264,7 @@ __all__ = [
|
|
|
208
264
|
"OpenAPIDefinition",
|
|
209
265
|
"OpenAPIExpectation",
|
|
210
266
|
"Ports",
|
|
267
|
+
"RegexBody",
|
|
211
268
|
"RequestDefinition",
|
|
212
269
|
"ResponseMode",
|
|
213
270
|
"SocketAddress",
|
|
@@ -217,6 +274,7 @@ __all__ = [
|
|
|
217
274
|
"Verification",
|
|
218
275
|
"VerificationSequence",
|
|
219
276
|
"VerificationTimes",
|
|
277
|
+
"WebSocketFrameMatcher",
|
|
220
278
|
"WebSocketMessage",
|
|
221
279
|
"MockServerProcess",
|
|
222
280
|
"bundle_base_name",
|
|
@@ -58,7 +58,7 @@ class AsyncScenarioHandle:
|
|
|
58
58
|
async def state(self) -> str | None:
|
|
59
59
|
"""GET the current state of this scenario (``None`` if not yet set)."""
|
|
60
60
|
result = await self._client._scenario_request(
|
|
61
|
-
"GET", f"/mockserver/scenario/{urllib.parse.quote(self._name, safe=
|
|
61
|
+
"GET", f"/mockserver/scenario/{urllib.parse.quote(self._name, safe='')}"
|
|
62
62
|
)
|
|
63
63
|
return result.get("currentState")
|
|
64
64
|
|
|
@@ -78,7 +78,7 @@ class AsyncScenarioHandle:
|
|
|
78
78
|
payload["nextState"] = next_state
|
|
79
79
|
return await self._client._scenario_request(
|
|
80
80
|
"PUT",
|
|
81
|
-
f"/mockserver/scenario/{urllib.parse.quote(self._name, safe=
|
|
81
|
+
f"/mockserver/scenario/{urllib.parse.quote(self._name, safe='')}",
|
|
82
82
|
json.dumps(payload),
|
|
83
83
|
)
|
|
84
84
|
|
|
@@ -86,7 +86,7 @@ class AsyncScenarioHandle:
|
|
|
86
86
|
"""PUT an external trigger advancing this scenario to ``new_state``."""
|
|
87
87
|
return await self._client._scenario_request(
|
|
88
88
|
"PUT",
|
|
89
|
-
f"/mockserver/scenario/{urllib.parse.quote(self._name, safe=
|
|
89
|
+
f"/mockserver/scenario/{urllib.parse.quote(self._name, safe='')}/trigger",
|
|
90
90
|
json.dumps({"newState": new_state}),
|
|
91
91
|
)
|
|
92
92
|
|
|
@@ -383,6 +383,35 @@ class AsyncMockServerClient:
|
|
|
383
383
|
)
|
|
384
384
|
return response_body or ""
|
|
385
385
|
|
|
386
|
+
async def retrieve_drift(self) -> dict:
|
|
387
|
+
"""Retrieve the recorded mock drift report.
|
|
388
|
+
|
|
389
|
+
Issues ``GET /mockserver/drift`` and returns the parsed report, a dict of
|
|
390
|
+
the form ``{"count": <n>, "drifts": [ ... ]}`` where each entry describes a
|
|
391
|
+
difference detected between a mock's configured response and the live
|
|
392
|
+
upstream response for the same request. When no drift has been recorded the
|
|
393
|
+
server returns an empty report (``{}``).
|
|
394
|
+
"""
|
|
395
|
+
status, response_body = await self._request("GET", "/mockserver/drift")
|
|
396
|
+
if status >= 400:
|
|
397
|
+
raise MockServerError(
|
|
398
|
+
f"Failed to retrieve drift (status={status}): {response_body}"
|
|
399
|
+
)
|
|
400
|
+
return json.loads(response_body) if response_body else {}
|
|
401
|
+
|
|
402
|
+
async def clear_drift(self) -> None:
|
|
403
|
+
"""Clear all recorded mock drift.
|
|
404
|
+
|
|
405
|
+
Issues ``PUT /mockserver/drift/clear``.
|
|
406
|
+
"""
|
|
407
|
+
status, response_body = await self._request(
|
|
408
|
+
"PUT", "/mockserver/drift/clear"
|
|
409
|
+
)
|
|
410
|
+
if status >= 400:
|
|
411
|
+
raise MockServerError(
|
|
412
|
+
f"Failed to clear drift (status={status}): {response_body}"
|
|
413
|
+
)
|
|
414
|
+
|
|
386
415
|
async def pact_import(self, pact_json: str) -> str:
|
|
387
416
|
"""Import a Pact v3 contract as expectations.
|
|
388
417
|
|
|
@@ -224,6 +224,17 @@ class MockServerClient:
|
|
|
224
224
|
"""
|
|
225
225
|
return self._run(self._async_client.update_configuration(config_json))
|
|
226
226
|
|
|
227
|
+
def retrieve_drift(self) -> dict:
|
|
228
|
+
"""Retrieve the recorded mock drift report
|
|
229
|
+
(``GET /mockserver/drift``); returns a dict of the form
|
|
230
|
+
``{"count": <n>, "drifts": [ ... ]}``.
|
|
231
|
+
"""
|
|
232
|
+
return self._run(self._async_client.retrieve_drift())
|
|
233
|
+
|
|
234
|
+
def clear_drift(self) -> None:
|
|
235
|
+
"""Clear all recorded mock drift (``PUT /mockserver/drift/clear``)."""
|
|
236
|
+
return self._run(self._async_client.clear_drift())
|
|
237
|
+
|
|
227
238
|
def pact_import(self, pact_json: str) -> str:
|
|
228
239
|
"""Import a Pact v3 contract as expectations; returns the upserted
|
|
229
240
|
expectations JSON (``PUT /mockserver/pact/import``).
|
|
@@ -45,7 +45,7 @@ logger = logging.getLogger(__name__)
|
|
|
45
45
|
|
|
46
46
|
# The version shipped with this client. ``ensure_binary()`` defaults to this
|
|
47
47
|
# when no explicit version is passed.
|
|
48
|
-
_CLIENT_VERSION = "7.
|
|
48
|
+
_CLIENT_VERSION = "7.5.0"
|
|
49
49
|
|
|
50
50
|
_REPO = "mock-server/mockserver-monorepo"
|
|
51
51
|
|