@@ -156,6 +156,86 @@ fn response_getter() {
156156 ] ) ;
157157}
158158
159+ #[ test]
160+ fn response_redirect_default_status ( ) {
161+ run_test_actions ( [
162+ TestAction :: harness ( ) ,
163+ TestAction :: inspect_context ( |ctx| register ( & [ ] , ctx) ) ,
164+ TestAction :: run (
165+ r#"
166+ const response = Response.redirect("http://example.com/");
167+ assertEq(response.status, 302);
168+ assertEq(response.headers.get("location"), "http://example.com/");
169+ "# ,
170+ ) ,
171+ ] ) ;
172+ }
173+
174+ #[ test]
175+ fn response_redirect_custom_status_and_coercion ( ) {
176+ run_test_actions ( [
177+ TestAction :: harness ( ) ,
178+ TestAction :: inspect_context ( |ctx| register ( & [ ] , ctx) ) ,
179+ TestAction :: run (
180+ r#"
181+ const response = Response.redirect("http://example.com/", 301);
182+ assertEq(response.status, 301);
183+
184+ // Tests Web IDL coercion of the URL parameter
185+ const response2 = Response.redirect(12345);
186+ assertEq(response2.headers.get("location"), "12345");
187+ "# ,
188+ ) ,
189+ ] ) ;
190+ }
191+
192+ #[ test]
193+ fn response_redirect_invalid_status ( ) {
194+ run_test_actions ( [
195+ TestAction :: harness ( ) ,
196+ TestAction :: inspect_context ( |ctx| register ( & [ ] , ctx) ) ,
197+ TestAction :: run (
198+ r#"
199+ let threw = false;
200+ try {
201+ Response.redirect("http://example.com/", 200);
202+ } catch (e) {
203+ threw = true;
204+ if (!(e instanceof RangeError)) {
205+ throw new Error("Expected RangeError, got " + e.name);
206+ }
207+ }
208+ if (!threw) {
209+ throw new Error("Expected RangeError, but no error was thrown");
210+ }
211+ "# ,
212+ ) ,
213+ ] ) ;
214+ }
215+
216+ #[ test]
217+ fn response_json_static ( ) {
218+ run_test_actions ( [
219+ TestAction :: harness ( ) ,
220+ TestAction :: inspect_context ( |ctx| register ( & [ ] , ctx) ) ,
221+ TestAction :: run (
222+ r#"
223+ globalThis.p = (async () => {
224+ const response = Response.json({ hello: "world" });
225+ assertEq(response.status, 200);
226+ assertEq(response.headers.get("content-type"), "application/json");
227+ const body = await response.json();
228+ assertEq(body.hello, "world");
229+ })();
230+ "# ,
231+ ) ,
232+ TestAction :: inspect_context ( |ctx| {
233+ let p = ctx. global_object ( ) . get ( js_str ! ( "p" ) , ctx) . unwrap ( ) ;
234+ p. as_promise ( ) . unwrap ( ) . await_blocking ( ctx) . unwrap ( ) ;
235+ } ) ,
236+ ] ) ;
237+ }
238+
159239#[ test]
160240fn response_headers_get_combines_duplicate_values_with_comma_space ( ) {
161241 run_test_actions ( [
@@ -184,3 +264,93 @@ fn response_headers_get_combines_duplicate_values_with_comma_space() {
184264 } ) ,
185265 ] ) ;
186266}
267+
268+ #[ test]
269+ fn response_clone_read_both ( ) {
270+ run_test_actions ( [
271+ TestAction :: harness ( ) ,
272+ TestAction :: inspect_context ( |ctx| {
273+ register (
274+ & [ ( "http://unit.test" , Response :: new ( b"Hello World" . to_vec ( ) ) ) ] ,
275+ ctx,
276+ ) ;
277+ } ) ,
278+ TestAction :: run (
279+ r#"
280+ globalThis.response = (async () => {
281+ const response = await fetch(new Request("http://unit.test"));
282+ const cloned = response.clone();
283+ const t1 = await response.text();
284+ const t2 = await cloned.text();
285+ assertEq(t1, "Hello World");
286+ assertEq(t2, "Hello World");
287+ })();
288+ "# ,
289+ ) ,
290+ TestAction :: inspect_context ( |ctx| {
291+ let response = ctx. global_object ( ) . get ( js_str ! ( "response" ) , ctx) . unwrap ( ) ;
292+ response. as_promise ( ) . unwrap ( ) . await_blocking ( ctx) . unwrap ( ) ;
293+ } ) ,
294+ ] ) ;
295+ }
296+
297+ #[ test]
298+ fn response_clone_header_independence ( ) {
299+ run_test_actions ( [
300+ TestAction :: harness ( ) ,
301+ TestAction :: inspect_context ( |ctx| {
302+ let mut resp = Response :: new ( b"body" . to_vec ( ) ) ;
303+ resp. headers_mut ( )
304+ . append ( "x-original" , "value" . parse ( ) . unwrap ( ) ) ;
305+ register ( & [ ( "http://unit.test" , resp) ] , ctx) ;
306+ } ) ,
307+ TestAction :: run (
308+ r#"
309+ globalThis.response = (async () => {
310+ const response = await fetch(new Request("http://unit.test"));
311+ const cloned = response.clone();
312+
313+ cloned.headers.set("x-original", "mutated");
314+ cloned.headers.set("x-new", "added");
315+
316+ assertEq(response.headers.get("x-original"), "value");
317+ assertEq(response.headers.get("x-new"), null);
318+ assertEq(cloned.headers.get("x-original"), "mutated");
319+ assertEq(cloned.headers.get("x-new"), "added");
320+ })();
321+ "# ,
322+ ) ,
323+ TestAction :: inspect_context ( |ctx| {
324+ let response = ctx. global_object ( ) . get ( js_str ! ( "response" ) , ctx) . unwrap ( ) ;
325+ response. as_promise ( ) . unwrap ( ) . await_blocking ( ctx) . unwrap ( ) ;
326+ } ) ,
327+ ] ) ;
328+ }
329+
330+ #[ test]
331+ fn response_clone_preserves_status ( ) {
332+ run_test_actions ( [
333+ TestAction :: harness ( ) ,
334+ TestAction :: inspect_context ( |ctx| {
335+ register ( & [ ( "http://unit.test" , Response :: new ( b"ok" . to_vec ( ) ) ) ] , ctx) ;
336+ } ) ,
337+ TestAction :: run (
338+ r#"
339+ globalThis.response = (async () => {
340+ const response = await fetch(new Request("http://unit.test"));
341+ const cloned = response.clone();
342+
343+ assertEq(cloned.status, response.status);
344+ assertEq(cloned.statusText, response.statusText);
345+ assertEq(cloned.type, response.type);
346+ assertEq(cloned.url, response.url);
347+ assertEq(cloned.ok, response.ok);
348+ })();
349+ "# ,
350+ ) ,
351+ TestAction :: inspect_context ( |ctx| {
352+ let response = ctx. global_object ( ) . get ( js_str ! ( "response" ) , ctx) . unwrap ( ) ;
353+ response. as_promise ( ) . unwrap ( ) . await_blocking ( ctx) . unwrap ( ) ;
354+ } ) ,
355+ ] ) ;
356+ }
0 commit comments