-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8c2cd93
commit f0925a4
Showing
9 changed files
with
392 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. | ||
|
||
export { describe, it } from "https://deno.land/std@0.185.0/testing/bdd.ts"; | ||
export { | ||
assert, | ||
assertEquals, | ||
assertFalse, | ||
assertRejects, | ||
assertThrows, | ||
} from "https://deno.land/std@0.185.0/testing/asserts.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
|
||
import { isResponse } from "./is.ts"; | ||
|
||
/** Create a new `Response`. | ||
* | ||
* If you create a new `Response` from an existing `Response`, any options you set | ||
* in an options argument for the new response replace any corresponding options | ||
* set in the original `Response`. | ||
* | ||
* @example | ||
* ```ts | ||
* import { createResponse } from "https://deno.land/x/response_utils@$VERSION/create.ts"; | ||
* import { assertEquals } from "https://deno.land/std/testing/asserts.ts"; | ||
* | ||
* declare const init: Response; | ||
* const response = createResponse(init, { status: 201 }); | ||
* | ||
* assertEquals(response.status, 201); | ||
* ``` | ||
*/ | ||
export function createResponse( | ||
input: Response | Body, | ||
init?: ResponseInit, | ||
): Response { | ||
init = isResponse(input) | ||
? { | ||
headers: input.headers, | ||
status: input.status, | ||
statusText: input.statusText, | ||
...init, | ||
} | ||
: init; | ||
|
||
return new Response(input.body, init); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. | ||
|
||
import { createResponse } from "./create.ts"; | ||
import { equalsResponse } from "./equal.ts"; | ||
import { assert, assertEquals, describe, it } from "./_dev_deps.ts"; | ||
|
||
describe("createResponse", () => { | ||
it("should return new response", async () => { | ||
const init = new Response(); | ||
const response = createResponse(init); | ||
|
||
assert(init !== response); | ||
assert(await equalsResponse(init, response, true)); | ||
}); | ||
|
||
it("should return partial updated response", () => { | ||
const init = new Response(null, { status: 201 }); | ||
const response = createResponse(init, { status: 202 }); | ||
|
||
assertEquals(response.status, 202); | ||
}); | ||
|
||
it("should extern body", async () => { | ||
const response = createResponse(new Response("test"), { status: 202 }); | ||
|
||
assert( | ||
await equalsResponse( | ||
response, | ||
new Response("test", { status: 202 }), | ||
true, | ||
), | ||
); | ||
}); | ||
|
||
it("should not merge headers", async () => { | ||
const response = createResponse( | ||
new Response(null, { headers: { "x-test": "test" } }), | ||
{ headers: { "x-test2": "test2" } }, | ||
); | ||
|
||
assert( | ||
await equalsResponse( | ||
response, | ||
new Response(null, { headers: { "x-test2": "test2" } }), | ||
true, | ||
), | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"version": "2", | ||
"remote": { | ||
"https://deno.land/std@0.185.0/fmt/colors.ts": "d67e3cd9f472535241a8e410d33423980bec45047e343577554d3356e1f0ef4e", | ||
"https://deno.land/std@0.185.0/testing/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea", | ||
"https://deno.land/std@0.185.0/testing/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7", | ||
"https://deno.land/std@0.185.0/testing/_test_suite.ts": "30f018feeb3835f12ab198d8a518f9089b1bcb2e8c838a8b615ab10d5005465c", | ||
"https://deno.land/std@0.185.0/testing/asserts.ts": "e16d98b4d73ffc4ed498d717307a12500ae4f2cbe668f1a215632d19fcffc22f", | ||
"https://deno.land/std@0.185.0/testing/bdd.ts": "59f7f7503066d66a12e50ace81bfffae5b735b6be1208f5684b630ae6b4de1d0", | ||
"https://deno.land/x/headers_utils@1.0.0/equal.ts": "ef72aa7e96fe317df43f8e5948b4bb4e3c0d5935cfa4984a335aeb7ecf51f11c", | ||
"https://deno.land/x/isx@1.3.1/is_null.ts": "02b30255073843d001e715a04382f1d6aebd77ed5506ffbb44bf77b9e20ebf7d" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
|
||
export { equalsHeaders } from "https://deno.land/x/headers_utils@1.0.0/equal.ts"; | ||
export { isNull } from "https://deno.land/x/isx@1.3.1/is_null.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
|
||
import { equalsHeaders, isNull } from "./deps.ts"; | ||
|
||
/** Check two `Response` fields equality. | ||
* | ||
* @example | ||
* ```ts | ||
* import { equalsResponse } from "https://deno.land/x/response_utils@$VERSION/equal.ts"; | ||
* import { assert } from "https://deno.land/std/testing/asserts.ts"; | ||
* | ||
* assert( | ||
* equalsResponse( | ||
* new Response(null, { status: 204, headers: { "content-length": "0" } }), | ||
* new Response(null, { status: 204, headers: { "content-length": "0" } }), | ||
* ), | ||
* ); | ||
* ``` | ||
*/ | ||
export function equalsResponse(left: Response, right: Response): boolean; | ||
/** Strict check two `Response` fields equality. | ||
* | ||
* @example | ||
* ```ts | ||
* import { equalsResponse } from "https://deno.land/x/response_utils@$VERSION/equal.ts"; | ||
* import { assert } from "https://deno.land/std/testing/asserts.ts"; | ||
* | ||
* assert( | ||
* await equalsResponse( | ||
* new Response("test1", { status: 200, headers: { "content-length": "5" } }), | ||
* new Response("test2", { status: 200, headers: { "content-length": "5" } }), | ||
* false, | ||
* ), | ||
* ); | ||
* ``` | ||
* | ||
* @throws {Error} In strict mode, if response body has already been read. | ||
*/ | ||
export function equalsResponse( | ||
left: Response, | ||
right: Response, | ||
strict: boolean, | ||
): boolean | Promise<boolean>; | ||
export function equalsResponse( | ||
left: Response, | ||
right: Response, | ||
strict?: boolean, | ||
): boolean | Promise<boolean> { | ||
strict ??= false; | ||
|
||
const staticResult = left.ok === right.ok && | ||
left.bodyUsed === right.bodyUsed && | ||
left.redirected === right.redirected && | ||
left.status === right.status && | ||
left.statusText === right.statusText && | ||
left.type === right.type && | ||
left.url === right.url && | ||
equalsBodyType(left.body, right.body) && | ||
equalsHeaders(left.headers, right.headers); | ||
|
||
if (!staticResult || !strict) return staticResult; | ||
|
||
if (left.bodyUsed || right.bodyUsed) { | ||
throw Error( | ||
"response body has already been read and the body cannot be strictly compared", | ||
); | ||
} | ||
|
||
return Promise.all([left.clone().text(), right.clone().text()]).then(( | ||
[left, right], | ||
) => Object.is(left, right)); | ||
} | ||
|
||
function equalsBodyType( | ||
left: Response["body"], | ||
right: Response["body"], | ||
): boolean { | ||
if (isNull(left)) { | ||
return isNull(right); | ||
} | ||
|
||
if (isNull(right)) { | ||
return isNull(left); | ||
} | ||
|
||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. | ||
|
||
import { equalsResponse } from "./equal.ts"; | ||
import { | ||
assert, | ||
assertEquals, | ||
assertFalse, | ||
assertThrows, | ||
describe, | ||
it, | ||
} from "./_dev_deps.ts"; | ||
|
||
describe("equalsResponse", () => { | ||
it("should pass cases", () => { | ||
const table: [Response, Response, boolean][] = [ | ||
[new Response(), new Response(), true], | ||
[new Response(null), new Response(), true], | ||
[new Response(undefined), new Response(), true], | ||
[ | ||
new Response(null, { | ||
status: 500, | ||
}), | ||
new Response(null, { | ||
status: 500, | ||
}), | ||
true, | ||
], | ||
[ | ||
new Response(null, { | ||
statusText: "", | ||
}), | ||
new Response(null, { | ||
statusText: "", | ||
}), | ||
true, | ||
], | ||
[ | ||
new Response(null, { | ||
headers: { | ||
a: "", | ||
}, | ||
}), | ||
new Response(null, { | ||
headers: { | ||
a: "", | ||
}, | ||
}), | ||
true, | ||
], | ||
[ | ||
new Response(null, { | ||
headers: { | ||
a: "test", | ||
}, | ||
}), | ||
new Response(null, { | ||
headers: { | ||
a: "", | ||
}, | ||
}), | ||
false, | ||
], | ||
[ | ||
new Response(null, { | ||
statusText: "", | ||
}), | ||
new Response(null, { | ||
statusText: "a", | ||
}), | ||
false, | ||
], | ||
[ | ||
new Response(null, { | ||
status: 200, | ||
}), | ||
new Response(null, { | ||
status: 201, | ||
}), | ||
false, | ||
], | ||
[ | ||
new Response(null, { | ||
status: 300, | ||
}), | ||
new Response(), | ||
false, | ||
], | ||
[new Response("test"), new Response(), false], | ||
[new Response(""), new Response(""), true], | ||
[new Response("a"), new Response(""), true], | ||
[new Response("a"), new Response("a"), true], | ||
]; | ||
|
||
Promise.all(table.map(([left, right, result]) => { | ||
assertEquals(equalsResponse(left, right), result); | ||
})); | ||
}); | ||
|
||
it("should pass if strict mode", async () => { | ||
const table: [Response, Response, boolean][] = [ | ||
[new Response(""), new Response(""), true], | ||
[new Response("a"), new Response("a"), true], | ||
[new Response("test"), new Response(), false], | ||
[new Response("a"), new Response(""), false], | ||
]; | ||
|
||
await Promise.all(table.map(async ([left, right, result]) => { | ||
assertEquals(await equalsResponse(left, right, true), result); | ||
})); | ||
}); | ||
|
||
it("should throw error if strict mode and the response body has been read", async () => { | ||
const response = new Response(""); | ||
await response.text(); | ||
|
||
assert(response.bodyUsed); | ||
assertThrows(() => equalsResponse(response, response, true)); | ||
}); | ||
|
||
it("should not throw when the response body has used", async () => { | ||
const res = new Response(""); | ||
|
||
await res.text(); | ||
|
||
assert(res.bodyUsed); | ||
assertFalse(equalsResponse(res, new Response(""))); | ||
}); | ||
|
||
it("should use cloned response", async () => { | ||
const res = new Response(""); | ||
|
||
assert(equalsResponse(res, new Response(""))); | ||
assertFalse(res.bodyUsed); | ||
assertEquals(await res.text(), ""); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. | ||
// This module is browser compatible. | ||
|
||
/** Whether the input is `Response` or not. | ||
* | ||
* @example | ||
* ```ts | ||
* import { isResponse } from "https://deno.land/x/response_utils@$VERSION/is.ts"; | ||
* import { assert, assertFalse } from "https://deno.land/std/testing/asserts.ts"; | ||
* | ||
* assert(isResponse(new Response())); | ||
* assertFalse(isResponse({})); | ||
* assertFalse(isResponse(null)); | ||
* ``` | ||
*/ | ||
export function isResponse(input: unknown): input is Response { | ||
return input instanceof Response; | ||
} |
Oops, something went wrong.