Skip to content

Commit 7aa84ed

Browse files
committed
Fix querystring parser and add edge case tests
1 parent ce21823 commit 7aa84ed

2 files changed

Lines changed: 73 additions & 10 deletions

File tree

Sprint-2/implement/querystring.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,43 @@
1+
/**
2+
* parseQueryString()
3+
*
4+
* Parses a query string into an object of key-value pairs.
5+
*
6+
* Example:
7+
* parseQueryString("name=Richard&city=Sheffield")
8+
* returns { name: "Richard", city: "Sheffield" }
9+
*/
10+
111
function parseQueryString(queryString) {
212
const queryParams = {};
3-
if (queryString.length === 0) {
13+
14+
// Return an empty object if the input is an empty string
15+
if (typeof queryString !== "string" || queryString.length === 0) {
416
return queryParams;
517
}
18+
19+
// Split the full query string into key-value pairs
620
const keyValuePairs = queryString.split("&");
721

822
for (const pair of keyValuePairs) {
9-
const [key, value] = pair.split("=");
23+
// Skip empty pairs, for example from a trailing "&"
24+
if (pair === "") {
25+
continue;
26+
}
27+
28+
// Find the position of the first "="
29+
const separatorIndex = pair.indexOf("=");
30+
31+
// If there is no "=" sign, treat it as a key with an empty value
32+
if (separatorIndex === -1) {
33+
queryParams[pair] = "";
34+
continue;
35+
}
36+
37+
// Extract the key and everything after the first "=" as the value
38+
const key = pair.slice(0, separatorIndex);
39+
const value = pair.slice(separatorIndex + 1);
40+
1041
queryParams[key] = value;
1142
}
1243

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,44 @@
1-
// In the prep, we implemented a function to parse query strings.
2-
// Unfortunately, it contains several bugs!
3-
// Below is one test case for an edge case the implementation doesn't handle well.
4-
// Fix the implementation for this test, and try to think of as many other edge cases as possible - write tests and fix those too.
1+
const parseQueryString = require("./querystring.js");
52

6-
const parseQueryString = require("./querystring.js")
3+
describe("parseQueryString()", () => {
4+
test("parses querystring values containing =", () => {
5+
expect(parseQueryString("equation=x=y+1")).toEqual({
6+
equation: "x=y+1",
7+
});
8+
});
9+
10+
test("returns an empty object for an empty string", () => {
11+
expect(parseQueryString("")).toEqual({});
12+
});
13+
14+
test("parses a single key-value pair", () => {
15+
expect(parseQueryString("name=Richard")).toEqual({
16+
name: "Richard",
17+
});
18+
});
19+
20+
test("parses multiple key-value pairs", () => {
21+
expect(parseQueryString("name=Richard&city=Sheffield")).toEqual({
22+
name: "Richard",
23+
city: "Sheffield",
24+
});
25+
});
26+
27+
test("handles a key with an empty value", () => {
28+
expect(parseQueryString("name=")).toEqual({
29+
name: "",
30+
});
31+
});
32+
33+
test("handles a key with no equals sign", () => {
34+
expect(parseQueryString("name")).toEqual({
35+
name: "",
36+
});
37+
});
738

8-
test("parses querystring values containing =", () => {
9-
expect(parseQueryString("equation=x=y+1")).toEqual({
10-
"equation": "x=y+1",
39+
test("ignores an empty trailing pair", () => {
40+
expect(parseQueryString("name=Richard&")).toEqual({
41+
name: "Richard",
42+
});
1143
});
1244
});

0 commit comments

Comments
 (0)