mockserver-client 7.0.0 → 7.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97517808097f2af911f727db3decbafcab8454285325b141ad5899a53af70be1
4
- data.tar.gz: 60b5bff4ef90906b229064f23b1593bec547dc428b9d93c61b387d29a2615dd0
3
+ metadata.gz: f1a47589dbc527bf772961f968c2235d9b64ebc13fd8a1f963e143e50319db9f
4
+ data.tar.gz: 85aa291fefefdce077d8f4eaca22a5fd56d473628ec819c2029fae9f8e91aa4e
5
5
  SHA512:
6
- metadata.gz: d91bb153b43f523a60812dc4f100fb1e7deb04c6ddc6353266d632f8f074df3683e0292d9cd77efb464034e618d4e4d63fafc3b11b333c009098cc5b48b49684
7
- data.tar.gz: 7484d0dfa3e38edb7ad83dd2bb760a2b17dd2c4f474538e5673630f9fd28c056f4f7c2d2389ddbda2aa56f43eb052915cb4b5a432b4f15e7594e4db54cf92c9f
6
+ metadata.gz: 1b5adcd45c05bc417a62ad3a6fab6e00b42ef1180b7a89cc0084f972bb83aac5d68832d2e02da83d899a7fb511a71fb2ff87576eba4487f51a0bfafc546d5c06
7
+ data.tar.gz: dd83794b0fd9ad0ffc7439b505bc7ff3c8461e076d6acf209ce8b273b6ca4d233c19638ece936faaacf43e196d39a1a9220206c1a559dbe86dd2154a15b078e8
data/README.md CHANGED
@@ -99,6 +99,222 @@ All 25 domain model classes are available under the `MockServer` module:
99
99
  - `Ports`
100
100
  - `RequestDefinition` (alias for `HttpRequest`)
101
101
 
102
+ ## LLM Mocking
103
+
104
+ Fluent builders under `MockServer::LLM` mock LLM provider endpoints. They produce
105
+ expectations whose action is carried in the `httpLlmResponse` field; MockServer
106
+ re-encodes the provider-agnostic completion into the configured provider's wire
107
+ shape (OpenAI / Anthropic / Gemini / Bedrock / ...) when serving the request.
108
+
109
+ ```ruby
110
+ require 'mockserver-client'
111
+
112
+ client = MockServer::Client.new('localhost', 1080)
113
+
114
+ # A single completion mock
115
+ MockServer::LLM.llm_mock('/v1/chat/completions')
116
+ .with_provider(MockServer::LLM::Provider::OPENAI)
117
+ .with_model('gpt-4o')
118
+ .responding_with(
119
+ MockServer::LLM.completion
120
+ .with_text('Hello!')
121
+ .with_usage(MockServer::LLM.usage.with_input_tokens(10).with_output_tokens(5))
122
+ )
123
+ .apply_to(client)
124
+ ```
125
+
126
+ Multi-turn **conversations** use MockServer scenario-state advancement so each
127
+ turn is served once, in order. Add per-turn predicates with `when_*` methods and
128
+ optionally isolate per session with `isolate_by`:
129
+
130
+ ```ruby
131
+ MockServer::LLM.conversation
132
+ .with_path('/v1/chat/completions')
133
+ .with_provider(MockServer::LLM::Provider::OPENAI)
134
+ .isolate_by(MockServer::LLM.header('x-session-id'))
135
+ .turn.when_latest_message_contains('weather')
136
+ .responding_with(MockServer::LLM.completion.with_text('It is sunny.'))
137
+ .turn.responding_with(MockServer::LLM.completion.with_text('Anything else?'))
138
+ .apply_to(client)
139
+ ```
140
+
141
+ **Failover** scenarios script N upstream failures (consecutive identical failures
142
+ are coalesced) followed by a success; default JSON error bodies are generated per
143
+ status code unless a custom body is supplied:
144
+
145
+ ```ruby
146
+ MockServer::LLM.llm_failover
147
+ .with_path('/v1/chat/completions')
148
+ .with_provider(MockServer::LLM::Provider::OPENAI)
149
+ .fail_with(429, 2) # two rate-limit failures
150
+ .fail_with(503) # then one service-unavailable
151
+ .then_respond_with(MockServer::LLM.completion.with_text('Recovered'))
152
+ .apply_to(client)
153
+ ```
154
+
155
+ Each builder also exposes `build` to obtain the raw expectation Hash(es) without
156
+ registering them.
157
+
158
+ ## MCP Mocking
159
+
160
+ `MockServer::MCP.mcp_mock` builds the set of expectations needed to emulate a
161
+ Streamable-HTTP MCP (Model Context Protocol) server speaking JSON-RPC 2.0. It
162
+ generates `initialize`, `ping`, `notifications/initialized`, and per-capability
163
+ `tools`, `resources`, and `prompts` handlers.
164
+
165
+ ```ruby
166
+ MockServer::MCP.mcp_mock('/mcp')
167
+ .with_server_name('MyServer')
168
+ .with_tool('get_weather')
169
+ .with_description('Get the weather for a city')
170
+ .with_input_schema('{"type":"object","properties":{"city":{"type":"string"}}}')
171
+ .responding_with('72F and sunny')
172
+ .and_then
173
+ .with_resource('file:///config.json')
174
+ .with_name('config')
175
+ .with_content('{"debug":true}')
176
+ .and_then
177
+ .with_prompt('greet')
178
+ .with_argument('name', 'who to greet', true)
179
+ .responding_with('user', 'Hello there')
180
+ .and_then
181
+ .apply_to(client)
182
+ ```
183
+
184
+ `build` returns the raw expectation Hashes if you prefer to register them yourself.
185
+
186
+ ## Interactive Breakpoints
187
+
188
+ The client supports matcher-driven interactive breakpoints over the callback WebSocket. Register a breakpoint matcher to pause forwarded/proxied exchanges at specific phases and inspect/modify/continue them via callback handlers.
189
+
190
+ ### Register a breakpoint
191
+
192
+ ```ruby
193
+ client = MockServer::Client.new('localhost', 1080)
194
+
195
+ # REQUEST phase only
196
+ bp_id = client.add_request_breakpoint(
197
+ MockServer::HttpRequest.new(path: '/api/.*'),
198
+ ->(request) { request } # continue unchanged (or return HttpResponse to abort)
199
+ )
200
+
201
+ # REQUEST + RESPONSE
202
+ bp_id = client.add_request_and_response_breakpoint(
203
+ MockServer::HttpRequest.new(path: '/api/.*'),
204
+ ->(request) { request }, # REQUEST handler
205
+ ->(request, response) { response } # RESPONSE handler
206
+ )
207
+
208
+ # All phases with stream frame handler
209
+ bp_id = client.add_breakpoint(
210
+ MockServer::HttpRequest.new(path: '/stream/.*'),
211
+ %w[REQUEST RESPONSE RESPONSE_STREAM INBOUND_STREAM],
212
+ request_handler: ->(request) { request },
213
+ response_handler: ->(request, response) { response },
214
+ stream_frame_handler: ->(frame) { { 'action' => 'CONTINUE' } }
215
+ # Other actions: MODIFY (with body), DROP, INJECT (with body), CLOSE
216
+ )
217
+ ```
218
+
219
+ ### Manage breakpoints
220
+
221
+ ```ruby
222
+ # List all matchers
223
+ matchers = client.list_breakpoint_matchers # {"matchers" => [...]}
224
+
225
+ # Remove a specific matcher
226
+ client.remove_breakpoint_matcher(bp_id)
227
+
228
+ # Clear all matchers
229
+ client.clear_breakpoint_matchers
230
+ ```
231
+
232
+ ## Start / Launch MockServer
233
+
234
+ The Ruby client can download and launch a local MockServer instance directly -- no Java installation and no Docker required. The launcher downloads a self-contained platform bundle (`mockserver-<version>-<os>-<arch>`) from the GitHub Release, verifies its SHA-256, caches it per-user, and starts it.
235
+
236
+ ### Quick start
237
+
238
+ ```ruby
239
+ require 'mockserver-client'
240
+
241
+ # Download (first run) and start MockServer on port 1080
242
+ handle = MockServer::BinaryLauncher.start(port: 1080)
243
+ puts "MockServer running on port #{handle.port}, PID #{handle.pid}"
244
+
245
+ # ... use MockServer ...
246
+
247
+ handle.stop
248
+ ```
249
+
250
+ ### Just ensure the binary is present
251
+
252
+ ```ruby
253
+ launcher_path = MockServer::BinaryLauncher.ensure_launcher
254
+ ```
255
+
256
+ ### Specify a version
257
+
258
+ ```ruby
259
+ handle = MockServer::BinaryLauncher.start(port: 1080, version: '7.2.0')
260
+ ```
261
+
262
+ ### API reference
263
+
264
+ | Method / Class | Description |
265
+ |---|---|
266
+ | `MockServer::BinaryLauncher.ensure_launcher(version:, log:)` | Download, verify, cache, and return the launcher path. Defaults to `MockServer::VERSION`. |
267
+ | `MockServer::BinaryLauncher.start(port:, version:, extra_args:, log:)` | Ensure the binary and start MockServer. Returns a `ServerHandle`. |
268
+ | `MockServer::BinaryLauncher::ServerHandle` | Handle to the running process. Methods: `stop(timeout:)`, `running?`. Attributes: `pid`, `port`, `launcher`. |
269
+
270
+ ### Supported platforms
271
+
272
+ | OS | Architecture |
273
+ |---|---|
274
+ | Linux | x86_64, aarch64 |
275
+ | macOS (darwin) | x86_64, aarch64 |
276
+ | Windows | x86_64, aarch64 |
277
+
278
+ ### Environment variables
279
+
280
+ | Variable | Purpose |
281
+ |---|---|
282
+ | `MOCKSERVER_BINARY_BASE_URL` | Mirror host for the release assets (corporate / air-gapped networks) |
283
+ | `MOCKSERVER_BINARY_CACHE` | Override the cache directory (default: `~/.cache/mockserver/binaries` on Unix) |
284
+ | `MOCKSERVER_SKIP_BINARY_DOWNLOAD` | Fail instead of downloading (use with a pre-seeded cache in CI) |
285
+
286
+ ### Version
287
+
288
+ By default the launcher downloads the MockServer version matching this client gem (currently `MockServer::VERSION` from `lib/mockserver/version.rb`). Pass an explicit `version:` keyword to override.
289
+
290
+ ## Using in tests (RSpec)
291
+
292
+ Require `mockserver/rspec` to get a shared context that provides a fresh
293
+ `MockServer::Client` per example and resets the server before and after each
294
+ example, so recorded requests, expectations and logs never leak between
295
+ examples:
296
+
297
+ ```ruby
298
+ # spec_helper.rb
299
+ require 'mockserver/rspec'
300
+
301
+ # any spec tagged :mockserver gets a reset `mockserver` client
302
+ RSpec.describe 'my integration', :mockserver do
303
+ it 'records the request' do
304
+ # `mockserver` is the shared, reset client
305
+ mockserver.when(
306
+ MockServer::HttpRequest.request(path: '/hello')
307
+ ).respond(
308
+ MockServer::HttpResponse.response(body: 'world', status_code: 200)
309
+ )
310
+ end
311
+ end
312
+ ```
313
+
314
+ Host and port default to `127.0.0.1:1080` and can be overridden with the
315
+ `MOCKSERVER_HOST` / `MOCKSERVER_PORT` environment variables, or by defining a
316
+ `mockserver_host` / `mockserver_port` `let` in your example group.
317
+
102
318
  ## License
103
319
 
104
320
  Apache-2.0