|
1 | 1 | import { describe, expect, it } from 'vitest';
|
2 |
| -import { getSanitizedUrlString, parseStringToURL, parseUrl, stripUrlQueryAndFragment } from '../../src/utils-hoist/url'; |
| 2 | +import { |
| 3 | + getSanitizedUrlString, |
| 4 | + parseUrl, |
| 5 | + stripUrlQueryAndFragment, |
| 6 | + parseStringToURLObject, |
| 7 | + isURLObjectRelative, |
| 8 | + getSanitizedUrlStringFromUrlObject, |
| 9 | +} from '../../src/utils-hoist/url'; |
3 | 10 |
|
4 | 11 | describe('stripQueryStringAndFragment', () => {
|
5 | 12 | const urlString = 'http://dogs.are.great:1231/yay/';
|
@@ -62,8 +69,6 @@ describe('getSanitizedUrlString', () => {
|
62 | 69 | 'https://[filtered]:[filtered]@somedomain.com',
|
63 | 70 | ],
|
64 | 71 | ['same-origin url', '/api/v4/users?id=123', '/api/v4/users'],
|
65 |
| - ['url without a protocol', 'example.com', 'example.com'], |
66 |
| - ['url without a protocol with a path', 'example.com/sub/path?id=123', 'example.com/sub/path'], |
67 | 72 | ['url with port 8080', 'http://172.31.12.144:8080/test', 'http://172.31.12.144:8080/test'],
|
68 | 73 | ['url with port 4433', 'http://172.31.12.144:4433/test', 'http://172.31.12.144:4433/test'],
|
69 | 74 | ['url with port 443', 'http://172.31.12.144:443/test', 'http://172.31.12.144/test'],
|
@@ -197,19 +202,95 @@ describe('parseUrl', () => {
|
197 | 202 | });
|
198 | 203 | });
|
199 | 204 |
|
200 |
| -describe('parseStringToURL', () => { |
| 205 | +describe('parseStringToURLObject', () => { |
201 | 206 | it('returns undefined for invalid URLs', () => {
|
202 |
| - expect(parseStringToURL('invalid-url')).toBeUndefined(); |
| 207 | + expect(parseStringToURLObject('invalid-url')).toBeUndefined(); |
203 | 208 | });
|
204 | 209 |
|
205 | 210 | it('returns a URL object for valid URLs', () => {
|
206 |
| - expect(parseStringToURL('https://somedomain.com')).toBeInstanceOf(URL); |
| 211 | + expect(parseStringToURLObject('https://somedomain.com')).toBeInstanceOf(URL); |
| 212 | + }); |
| 213 | + |
| 214 | + it('returns a URL object for valid URLs with a base URL', () => { |
| 215 | + expect(parseStringToURLObject('https://somedomain.com', 'https://base.com')).toBeInstanceOf(URL); |
| 216 | + }); |
| 217 | + |
| 218 | + it('returns a relative URL object for relative URLs', () => { |
| 219 | + expect(parseStringToURLObject('/path/to/happiness')).toEqual({ |
| 220 | + isRelative: true, |
| 221 | + pathname: '/path/to/happiness', |
| 222 | + search: '', |
| 223 | + hash: '', |
| 224 | + }); |
207 | 225 | });
|
208 | 226 |
|
209 | 227 | it('does not throw an error if URl.canParse is not defined', () => {
|
210 | 228 | const canParse = (URL as any).canParse;
|
211 | 229 | delete (URL as any).canParse;
|
212 |
| - expect(parseStringToURL('https://somedomain.com')).toBeInstanceOf(URL); |
| 230 | + expect(parseStringToURLObject('https://somedomain.com')).toBeInstanceOf(URL); |
213 | 231 | (URL as any).canParse = canParse;
|
214 | 232 | });
|
215 | 233 | });
|
| 234 | + |
| 235 | +describe('isURLObjectRelative', () => { |
| 236 | + it('returns true for relative URLs', () => { |
| 237 | + expect(isURLObjectRelative(parseStringToURLObject('/path/to/happiness')!)).toBe(true); |
| 238 | + }); |
| 239 | + |
| 240 | + it('returns false for absolute URLs', () => { |
| 241 | + expect(isURLObjectRelative(parseStringToURLObject('https://somedomain.com')!)).toBe(false); |
| 242 | + }); |
| 243 | +}); |
| 244 | + |
| 245 | +describe('getSanitizedUrlStringFromUrlObject', () => { |
| 246 | + it.each([ |
| 247 | + ['regular url', 'https://somedomain.com', 'https://somedomain.com/'], |
| 248 | + ['regular url with a path', 'https://somedomain.com/path/to/happiness', 'https://somedomain.com/path/to/happiness'], |
| 249 | + [ |
| 250 | + 'url with standard http port 80', |
| 251 | + 'http://somedomain.com:80/path/to/happiness', |
| 252 | + 'http://somedomain.com/path/to/happiness', |
| 253 | + ], |
| 254 | + [ |
| 255 | + 'url with standard https port 443', |
| 256 | + 'https://somedomain.com:443/path/to/happiness', |
| 257 | + 'https://somedomain.com/path/to/happiness', |
| 258 | + ], |
| 259 | + [ |
| 260 | + 'url with non-standard port', |
| 261 | + 'https://somedomain.com:4200/path/to/happiness', |
| 262 | + 'https://somedomain.com:4200/path/to/happiness', |
| 263 | + ], |
| 264 | + [ |
| 265 | + 'url with query params', |
| 266 | + 'https://somedomain.com:4200/path/to/happiness?auhtToken=abc123¶m2=bar', |
| 267 | + 'https://somedomain.com:4200/path/to/happiness', |
| 268 | + ], |
| 269 | + [ |
| 270 | + 'url with a fragment', |
| 271 | + 'https://somedomain.com/path/to/happiness#somewildfragment123', |
| 272 | + 'https://somedomain.com/path/to/happiness', |
| 273 | + ], |
| 274 | + [ |
| 275 | + 'url with a fragment and query params', |
| 276 | + 'https://somedomain.com/path/to/happiness#somewildfragment123?auhtToken=abc123¶m2=bar', |
| 277 | + 'https://somedomain.com/path/to/happiness', |
| 278 | + ], |
| 279 | + [ |
| 280 | + 'url with authorization', |
| 281 | + 'https://username:password@somedomain.com', |
| 282 | + 'https://%filtered%:%filtered%@somedomain.com/', |
| 283 | + ], |
| 284 | + ['same-origin url', '/api/v4/users?id=123', '/api/v4/users'], |
| 285 | + ['url with port 8080', 'http://172.31.12.144:8080/test', 'http://172.31.12.144:8080/test'], |
| 286 | + ['url with port 4433', 'http://172.31.12.144:4433/test', 'http://172.31.12.144:4433/test'], |
| 287 | + ['url with port 443', 'http://172.31.12.144:443/test', 'http://172.31.12.144/test'], |
| 288 | + ['url with IP and port 80', 'http://172.31.12.144:80/test', 'http://172.31.12.144/test'], |
| 289 | + ])('returns a sanitized URL for a %s', (_, rawUrl: string, sanitizedURL: string) => { |
| 290 | + const urlObject = parseStringToURLObject(rawUrl); |
| 291 | + if (!urlObject) { |
| 292 | + throw new Error('Invalid URL'); |
| 293 | + } |
| 294 | + expect(getSanitizedUrlStringFromUrlObject(urlObject)).toEqual(sanitizedURL); |
| 295 | + }); |
| 296 | +}); |
0 commit comments