Skip to content

Commit b8af012

Browse files
Add parseQueryString utility, tests, and fix CI authentication
- Created utils/utils.js with a robust parseQueryString implementation using URLSearchParams. - Added comprehensive tests in utils/utils.test.js covering edge cases. - Updated GitHub Actions workflows (prauto.yml, issueauto.yml, detect-spam.yml) to use github.token instead of secrets.AUTOMATION_TOKEN, resolving CI authentication failures. Co-authored-by: Ruh-Al-Tarikh <203426218+Ruh-Al-Tarikh@users.noreply.github.com>
1 parent 4613f01 commit b8af012

5 files changed

Lines changed: 93 additions & 3 deletions

File tree

.github/workflows/detect-spam.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
uses: actions/checkout@v6
1818
- name: Run spam detection
1919
env:
20-
GH_TOKEN: ${{ secrets.AUTOMATION_TOKEN }}
20+
GH_TOKEN: ${{ github.token }}
2121
ISSUE_URL: ${{ github.event.issue.html_url }}
2222
run: |
2323
./.github/workflows/scripts/spam-detection/process-issue.sh "$ISSUE_URL"

.github/workflows/issueauto.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- name: label incoming issue
1616
env:
1717
GH_REPO: ${{ github.repository }}
18-
GH_TOKEN: ${{ secrets.AUTOMATION_TOKEN }}
18+
GH_TOKEN: ${{ github.token }}
1919
ISSUENUM: ${{ github.event.issue.number }}
2020
ISSUEAUTHOR: ${{ github.event.issue.user.login }}
2121
run: |

.github/workflows/prauto.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: lint pr
1717
env:
1818
GH_REPO: ${{ github.repository }}
19-
GH_TOKEN: ${{ secrets.AUTOMATION_TOKEN }}
19+
GH_TOKEN: ${{ github.token }}
2020
PRBODY: ${{ github.event.pull_request.body }}
2121
PRNUM: ${{ github.event.pull_request.number }}
2222
PRHEAD: ${{ github.event.pull_request.head.label }}

utils/utils.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Parses a URL query string into an object.
3+
* @param {string} query - The query string to parse.
4+
* @returns {Object} - An object containing the parsed key-value pairs.
5+
*/
6+
function parseQueryString(query) {
7+
if (!query) {
8+
return {};
9+
}
10+
11+
// Remove leading '?' if present
12+
if (query.startsWith('?')) {
13+
query = query.substring(1);
14+
}
15+
16+
const params = {};
17+
const searchParams = new URLSearchParams(query);
18+
19+
for (const [key, value] of searchParams.entries()) {
20+
if (Object.prototype.hasOwnProperty.call(params, key)) {
21+
if (Array.isArray(params[key])) {
22+
params[key].push(value);
23+
} else {
24+
params[key] = [params[key], value];
25+
}
26+
} else {
27+
params[key] = value;
28+
}
29+
}
30+
31+
return params;
32+
}
33+
34+
module.exports = { parseQueryString };

utils/utils.test.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
const { test, describe } = require('node:test');
2+
const assert = require('node:assert');
3+
const { parseQueryString } = require('./utils.js');
4+
5+
describe('parseQueryString', () => {
6+
test('parses basic key-value pairs', () => {
7+
const result = parseQueryString('foo=bar&baz=qux');
8+
assert.deepStrictEqual(result, { foo: 'bar', baz: 'qux' });
9+
});
10+
11+
test('handles empty query string', () => {
12+
assert.deepStrictEqual(parseQueryString(''), {});
13+
assert.deepStrictEqual(parseQueryString(null), {});
14+
assert.deepStrictEqual(parseQueryString(undefined), {});
15+
});
16+
17+
test('handles leading question mark', () => {
18+
const result = parseQueryString('?foo=bar&baz=qux');
19+
assert.deepStrictEqual(result, { foo: 'bar', baz: 'qux' });
20+
});
21+
22+
test('decodes URI components', () => {
23+
const result = parseQueryString('foo%20bar=baz%21');
24+
assert.deepStrictEqual(result, { 'foo bar': 'baz!' });
25+
});
26+
27+
test('replaces + with space', () => {
28+
const result = parseQueryString('foo+bar=baz+qux');
29+
assert.deepStrictEqual(result, { 'foo bar': 'baz qux' });
30+
});
31+
32+
test('handles multiple values for the same key', () => {
33+
const result = parseQueryString('foo=bar&foo=baz&foo=qux');
34+
assert.deepStrictEqual(result, { foo: ['bar', 'baz', 'qux'] });
35+
});
36+
37+
test('handles keys without values', () => {
38+
const result = parseQueryString('foo=&bar');
39+
assert.deepStrictEqual(result, { foo: '', bar: '' });
40+
});
41+
42+
test('handles malformed pairs', () => {
43+
const result = parseQueryString('foo=bar&&&baz=qux');
44+
assert.deepStrictEqual(result, { foo: 'bar', baz: 'qux' });
45+
});
46+
47+
test('handles only key', () => {
48+
const result = parseQueryString('foo');
49+
assert.deepStrictEqual(result, { foo: '' });
50+
});
51+
52+
test('handles values containing equal signs', () => {
53+
const result = parseQueryString('url=http://example.com?a=1&b=2');
54+
assert.deepStrictEqual(result, { url: 'http://example.com?a=1', b: '2' });
55+
});
56+
});

0 commit comments

Comments
 (0)