Created
April 1, 2020 12:53
-
-
Save donavon/450e1f0978bed97fba2291ebe3bd4a64 to your computer and use it in GitHub Desktop.
buildUrl - constructs a URL from an href and a search query object, e.g. {foo: 'bar'}
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
/* | |
buildUrl constructs a URL given on a URL and a search query object. | |
Search query keys are sorted alphabetically. The URL may contain an | |
existing search query, in which case it will be sorted. | |
Example: | |
```js | |
const url = buildUrl('http://example.com/?x=y&a=b', { | |
foo: 'bar' | |
}); | |
``` | |
This creates the URL string http://example.com/?a=b&foo=bar&x=y | |
*/ | |
const comparePairs = ([a], [b]) => { | |
if (a < b) { | |
return -1; | |
} else if (a > b) { | |
return 1; | |
} | |
return 0; | |
}; | |
export const buildUrl = (href, queryObj = {}) => { | |
const url = new URL(href); | |
const clonedObj = url.search | |
? { ...Object.fromEntries(url.searchParams.entries()), ...queryObj } | |
: queryObj; | |
url.search = ''; | |
Object.entries(clonedObj) | |
.sort(comparePairs) | |
.forEach(pair => url.searchParams.set(...pair)); | |
return url.href; | |
}; | |
// copped this off of the interwebs. it seems fine for now | |
export const shuffle = array => { | |
let currentIndex = array.length; | |
while (0 !== currentIndex) { | |
const randomIndex = Math.floor(Math.random() * currentIndex); | |
currentIndex -= 1; | |
const temporaryValue = array[currentIndex]; | |
array[currentIndex] = array[randomIndex]; | |
array[randomIndex] = temporaryValue; | |
} | |
return array; | |
}; |
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
import { buildUrl } from '../utils'; | |
import './polyfills/ObjectFromEntries'; // If running on node 10 or < | |
const domain = 'http://example.com/'; | |
describe('buildUrl', () => { | |
it('can accept a path only', () => { | |
const url = buildUrl(domain); | |
expect(url).toBe(domain); | |
}); | |
it('accepts both a path and a query object', () => { | |
const url = buildUrl(domain, { foo: 'foo', bar: 'bar' }); | |
expect(url).toBe(`${domain}?bar=bar&foo=foo`); | |
}); | |
it('accepts a path with an existing query string and a query object', () => { | |
const url = buildUrl(`${domain}?x=y&a=b`, { foo: 'foo', bar: 'bar' }); | |
expect(url).toBe(`${domain}?a=b&bar=bar&foo=foo&x=y`); | |
}); | |
it('accepts a path with an existing query string and a query object', () => { | |
const url = buildUrl(`${domain}?a=b`, { foo: 'foo', bar: 'bar' }); | |
expect(url).toBe(`${domain}?a=b&bar=bar&foo=foo`); | |
}); | |
it('accepts a path with an existing query string and a query object', () => { | |
const url = buildUrl(`${domain}?a=b`, { foo: 'foo', a: 'c', bar: 'bar' }); | |
expect(url).toBe(`${domain}?a=c&bar=bar&foo=foo`); | |
}); | |
it('url encodes the query string', () => { | |
const url = buildUrl(domain, { foo: 'f=o&o', bar: 'b?a%r' }); | |
expect(url).toBe(`${domain}?bar=b%3Fa%25r&foo=f%3Do%26o`); | |
}); | |
}); |
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
// https://github.com/tc39/proposal-object-from-entries/blob/master/polyfill.js | |
if (!Object.fromEntries) { | |
Object.fromEntries = function ObjectFromEntries(iter) { | |
const obj = {}; | |
for (const pair of iter) { | |
if (Object(pair) !== pair) { | |
throw new TypeError('iterable for fromEntries should yield objects'); | |
} | |
// Consistency with Map: contract is that entry has "0" and "1" keys, not | |
// that it is an array or iterable. | |
const { '0': key, '1': val } = pair; | |
Object.defineProperty(obj, key, { | |
configurable: true, | |
enumerable: true, | |
writable: true, | |
value: val, | |
}); | |
} | |
return obj; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment