Skip to content

Commit 9826160

Browse files
committed
Add fetch + URLSearchParams integration tests
Verify body serialization and auto Content-Type when passing URLSearchParams as fetch body.
1 parent f639ff1 commit 9826160

3 files changed

Lines changed: 91 additions & 2 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ openworkers-core = { git = "https://github.com/openworkers/openworkers-core", ta
6262
openworkers-transform = { git = "https://github.com/openworkers/openworkers-transform", tag = "v0.1.0" }
6363

6464
# Runtime backend (v8 only for now, others require older version of core)
65-
openworkers-runtime-v8 = { path = "../openworkers-runtime-v8", optional = true, features = ["ptrcomp"] }
65+
openworkers-runtime-v8 = { git = "https://github.com/openworkers/openworkers-runtime-v8", tag = "v0.13.9", optional = true, features = ["ptrcomp"] }
6666

6767
# WASM runtime (optional)
6868
# openworkers-runtime-wasm = { path = "../openworkers-runtime-wasm", optional = true }

tests/web_api_test.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,93 @@ async fn test_url_search_params_as_fetch_body() {
415415
.await;
416416
}
417417

418+
// ============================================================================
419+
// URLSearchParams + fetch integration
420+
// ============================================================================
421+
422+
#[tokio::test]
423+
async fn test_fetch_url_search_params_body_serialization() {
424+
run_local(|| async {
425+
let result = eval_js(
426+
r#"addEventListener('fetch', async (event) => {
427+
// Monkey-patch __nativeFetchStreaming to capture what fetch() sends
428+
const captured = {};
429+
const origFetch = __nativeFetchStreaming;
430+
globalThis.__nativeFetchStreaming = function(opts, resolve, reject) {
431+
captured.body = opts.body;
432+
captured.headers = opts.headers;
433+
// Call resolve with a fake response
434+
resolve({ status: 200, statusText: 'OK', headers: {}, streamId: null });
435+
};
436+
437+
const params = new URLSearchParams({
438+
grant_type: 'authorization_code',
439+
client_id: 'my-client',
440+
code: 'abc123'
441+
});
442+
443+
await fetch('https://example.com/token', {
444+
method: 'POST',
445+
body: params
446+
});
447+
448+
// Restore
449+
globalThis.__nativeFetchStreaming = origFetch;
450+
451+
// Verify the body was serialized to Uint8Array
452+
const bodyStr = new TextDecoder().decode(captured.body);
453+
const ct = captured.headers['Content-Type'] || '';
454+
455+
event.respondWith(new Response(JSON.stringify({ body: bodyStr, ct })));
456+
});"#,
457+
)
458+
.await;
459+
460+
let parsed: serde_json::Value = serde_json::from_str(&result).unwrap();
461+
assert_eq!(
462+
parsed["body"],
463+
"grant_type=authorization_code&client_id=my-client&code=abc123"
464+
);
465+
assert!(
466+
parsed["ct"]
467+
.as_str()
468+
.unwrap()
469+
.starts_with("application/x-www-form-urlencoded")
470+
);
471+
})
472+
.await;
473+
}
474+
475+
#[tokio::test]
476+
async fn test_fetch_url_search_params_does_not_override_explicit_content_type() {
477+
run_local(|| async {
478+
let result = eval_js(
479+
r#"addEventListener('fetch', async (event) => {
480+
const captured = {};
481+
const origFetch = __nativeFetchStreaming;
482+
globalThis.__nativeFetchStreaming = function(opts, resolve, reject) {
483+
captured.headers = opts.headers;
484+
resolve({ status: 200, statusText: 'OK', headers: {}, streamId: null });
485+
};
486+
487+
await fetch('https://example.com/token', {
488+
method: 'POST',
489+
headers: { 'Content-Type': 'text/plain' },
490+
body: new URLSearchParams({ key: 'value' })
491+
});
492+
493+
globalThis.__nativeFetchStreaming = origFetch;
494+
event.respondWith(new Response(captured.headers['Content-Type']));
495+
});"#,
496+
)
497+
.await;
498+
499+
// Explicit Content-Type should be preserved
500+
assert_eq!(result, "text/plain");
501+
})
502+
.await;
503+
}
504+
418505
// ============================================================================
419506
// btoa / atob (binary strings, NOT UTF-8)
420507
// ============================================================================

0 commit comments

Comments
 (0)