Skip to content
This repository was archived by the owner on Jun 24, 2025. It is now read-only.

Commit b47180a

Browse files
committed
feat(server): create unit tests for normalizing server URL, and fix logic based on feedback
1 parent 0fe8911 commit b47180a

2 files changed

Lines changed: 56 additions & 3 deletions

File tree

apps/server/src/services/utils.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,3 +628,56 @@ describe("#formatDownloadTitle", () => {
628628
});
629629
});
630630
});
631+
632+
describe("#normalizeUrl", () => {
633+
const testCases: TestCase<typeof utils.normalizeUrl>[] = [
634+
[ "should remove trailing slash from simple URL", [ "https://example.com/" ], "https://example.com" ],
635+
[ "should remove trailing slash from URL with path", [ "https://example.com/path/" ], "https://example.com/path" ],
636+
[ "should preserve URL without trailing slash", [ "https://example.com" ], "https://example.com" ],
637+
[ "should preserve URL without trailing slash with path", [ "https://example.com/path" ], "https://example.com/path" ],
638+
[ "should preserve protocol-only URLs", [ "https://" ], "https://" ],
639+
[ "should preserve protocol-only URLs", [ "http://" ], "http://" ],
640+
[ "should fix double slashes in path", [ "https://example.com//api//test" ], "https://example.com/api/test" ],
641+
[ "should handle multiple double slashes", [ "https://example.com///api///test" ], "https://example.com/api/test" ],
642+
[ "should handle trailing slash with double slashes", [ "https://example.com//api//" ], "https://example.com/api" ],
643+
[ "should preserve protocol double slash", [ "https://example.com/api" ], "https://example.com/api" ],
644+
[ "should handle empty string", [ "" ], "" ],
645+
[ "should handle whitespace-only string", [ " " ], "" ],
646+
[ "should trim whitespace", [ " https://example.com/ " ], "https://example.com" ],
647+
[ "should handle null as empty", [ null as any ], null ],
648+
[ "should handle undefined as empty", [ undefined as any ], undefined ]
649+
];
650+
651+
testCases.forEach((testCase) => {
652+
const [ desc, fnParams, expected ] = testCase;
653+
it(desc, () => {
654+
const result = utils.normalizeUrl(...fnParams);
655+
expect(result).toStrictEqual(expected);
656+
});
657+
});
658+
});
659+
660+
describe("#normalizeCustomHandlerPattern", () => {
661+
const testCases: TestCase<typeof utils.normalizeCustomHandlerPattern>[] = [
662+
[ "should handle pattern without ending - add both versions", [ "foo" ], [ "foo", "foo/" ] ],
663+
[ "should handle pattern with trailing slash - add both versions", [ "foo/" ], [ "foo", "foo/" ] ],
664+
[ "should handle pattern ending with $ - add optional slash", [ "foo$" ], [ "foo/?$" ] ],
665+
[ "should handle pattern with trailing slash and $ - add both versions", [ "foo/$" ], [ "foo$", "foo/$" ] ],
666+
[ "should preserve existing optional slash pattern", [ "foo/?$" ], [ "foo/?$" ] ],
667+
[ "should preserve existing optional slash pattern (alternative)", [ "foo/?)" ], [ "foo/?)" ] ],
668+
[ "should handle regex pattern with special chars", [ "api/[a-z]+$" ], [ "api/[a-z]+/?$" ] ],
669+
[ "should handle complex regex pattern", [ "user/([0-9]+)/profile$" ], [ "user/([0-9]+)/profile/?$" ] ],
670+
[ "should handle empty string", [ "" ], [ "" ] ],
671+
[ "should handle whitespace-only string", [ " " ], [ "" ] ],
672+
[ "should handle null", [ null as any ], [ null ] ],
673+
[ "should handle undefined", [ undefined as any ], [ undefined ] ]
674+
];
675+
676+
testCases.forEach((testCase) => {
677+
const [ desc, fnParams, expected ] = testCase;
678+
it(desc, () => {
679+
const result = utils.normalizeCustomHandlerPattern(...fnParams);
680+
expect(result).toStrictEqual(expected);
681+
});
682+
});
683+
});

apps/server/src/services/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,14 +394,14 @@ export function normalizeUrl(url: string): string {
394394
return url;
395395
}
396396

397+
// Fix double slashes (except in protocol) first
398+
url = url.replace(/([^:]\/)\/+/g, '$1');
399+
397400
// Remove trailing slash, but preserve protocol
398401
if (url.endsWith('/') && !url.match(/^https?:\/\/$/)) {
399402
url = url.slice(0, -1);
400403
}
401404

402-
// Fix double slashes (except in protocol)
403-
url = url.replace(/([^:]\/)\/+/g, '$1');
404-
405405
return url;
406406
}
407407

0 commit comments

Comments
 (0)