Mocking & Throttling
When to use it
Section titled “When to use it”| Situation | Mode to reach for |
|---|---|
| Test a UI flow without a real server | mock |
| Simulate an API error or empty state | mock with status: 4xx/5xx |
| Block an analytics endpoint in dev | block |
| Point production API calls at localhost | redirectTo (Map Remote) |
| Inject a header or reshape a response | rewrite |
| Reproduce a flaky connection | ThrottleEngine |
Mock rules
Section titled “Mock rules”Rules are matched in insertion order. The first enabled rule whose pattern and method filter both match wins.
See Core Overview for how MockEngine fits into the capture pipeline.
Rule modes
Section titled “Rule modes”| Mode | Network hit | Use for |
|---|---|---|
mock (default) |
No | Canned responses, happy-path or error fixtures |
rewrite |
Yes | Transform the real request or response |
block |
No | Simulate network errors for one endpoint |
redirectTo |
Yes (new URL) | Map Remote — send the request to a different URL |
Add a mock rule
Section titled “Add a mock rule”-
Import
mockEnginefrom hakka-coreyour-setup.ts import { mockEngine } from 'hakka-core' -
Add a rule for the endpoint you want to mock
your-setup.ts mockEngine.addRule({pattern: '/api/users',method: 'GET',mode: 'mock',enabled: true,response: {status: 200,headers: { 'content-type': 'application/json' },body: { users: [] },delay: 200, // optional artificial delay in ms},})The
bodyfield accepts a string or a plain object (serialized to JSON). Thedelayfield adds artificial latency in milliseconds before the response is returned. -
Use
bodyProviderfor dynamic responsesWhen
response.bodyProvideris set, it is called with the matched request context and its return value replacesbody. Useful for echoing request fields or sequencing responses.your-setup.ts response: {status: 200,body: '',bodyProvider: async (req) => {const parsed = JSON.parse(req.body ?? '{}')return { echo: parsed, ts: Date.now() }},},bodyProvideris async-safe. If it throws, the engine falls back toresponse.body. -
Verify it works
Make a request to
/api/usersin your app. The inspector shows the record withmocked: trueand the response body you configured — no network request was made.
Block an endpoint
Section titled “Block an endpoint”mockEngine.addRule({ pattern: '/api/checkout', block: true, enabled: true, response: { status: 0, body: '' }, // response is ignored when block is true})The fetch interceptor throws TypeError('Failed to fetch'), which is what the caller sees for any real network failure. The captured record shows error: 'Blocked by Hakka' and status: null.
Redirect to a different URL (Map Remote)
Section titled “Redirect to a different URL (Map Remote)”Redirect a matched request to a different URL without any JS function. The real request is sent to redirectTo; the original URL is not hit.
mockEngine.addRule({ pattern: 'api.production.example.com', redirectTo: 'http://localhost:3000', enabled: true, response: { status: 0, body: '' }, // response is ignored for redirectTo})The captured record shows the target URL and rewritten: true. You can combine redirectTo with rewriteResponse to also transform the response that comes back.
Rewrite request or response
Section titled “Rewrite request or response”mockEngine.addRule({ pattern: '/api/search', mode: 'rewrite', enabled: true, rewriteRequest: async (req) => ({ ...req, headers: { ...req.headers, 'x-internal': 'true' }, }), rewriteResponse: async (res, req) => ({ ...res, body: JSON.stringify({ ...JSON.parse(res.body), injected: true }), }), response: { status: 0, body: '' }, // response is unused in rewrite mode})Rule API
Section titled “Rule API”const id = mockEngine.addRule(ruleInput) // returns rule idmockEngine.removeRule(id)mockEngine.enableRule(id)mockEngine.disableRule(id)mockEngine.getRules() // MockRule[]mockEngine.clearRules()getRules() returns a shallow copy. hitCount on each rule is the number of times that rule was actually applied.
Persistence
Section titled “Persistence”MockEngine has serialize() / deserialize() methods for saving and restoring rules.
// Saveconst json = mockEngine.serialize()localStorage.setItem('hakka-mock-rules', json)
// Restoreconst saved = localStorage.getItem('hakka-mock-rules')if (saved) mockEngine.deserialize(saved)React Native native sync
Section titled “React Native native sync”On React Native, MockEngine mirrors rules to the native layer via NativeMockBridge (set with registerNativeBridge). Native sync is best-effort — JS mock state is authoritative. mock, block, redirectTo, and declarative modify all sync to the native engines; only rewrite-mode function hooks (rewriteRequest/rewriteResponse/bodyProvider) are JS-only, since functions cannot cross the bridge.
Throttle profiles
Section titled “Throttle profiles”ThrottleEngine adds latency and simulates offline before the real network request is made.
import { ThrottleEngine } from 'hakka-core'
ThrottleEngine.setProfile('slow-3g')ThrottleEngine.setProfile('none') // disablePresets
Section titled “Presets”| Profile | Latency | downloadKbps |
|---|---|---|
none |
0 ms | — |
fast-3g |
150 ms | 1500 |
slow-3g |
400 ms | 400 |
edge |
250 ms | 240 |
offline |
— | 0 |
Custom latency
Section titled “Custom latency”ThrottleEngine.setCustom(500) // 500 ms latency, unlimited bandwidthThrottleEngine.setCustom(300, 800) // 300 ms latency, 800 kbps (not yet enforced)React to profile changes
Section titled “React to profile changes”const off = ThrottleEngine.onChange((config) => { console.log(config.profile, config.latencyMs)})// lateroff()Interaction with mock rules
Section titled “Interaction with mock rules”Throttle delay runs after the mock engine check. mock and block rules bypass throttling — they return or abort before ThrottleEngine.applyDelay() is called. rewrite and redirectTo rules apply throttle latency because they send a real network request.