aboutsummaryrefslogtreecommitdiff
path: root/src/lib/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/utils')
-rw-r--r--src/lib/utils/glyph_hash.test.ts90
-rw-r--r--src/lib/utils/glyph_hash.ts60
-rw-r--r--src/lib/utils/readable_time.test.ts104
-rw-r--r--src/lib/utils/readable_time.ts67
-rw-r--r--src/lib/utils/resolve_after.test.ts53
-rw-r--r--src/lib/utils/resolve_after.ts39
6 files changed, 179 insertions, 234 deletions
diff --git a/src/lib/utils/glyph_hash.test.ts b/src/lib/utils/glyph_hash.test.ts
index 5f57a2a..e791bab 100644
--- a/src/lib/utils/glyph_hash.test.ts
+++ b/src/lib/utils/glyph_hash.test.ts
@@ -2,67 +2,55 @@ import { getGlyphHash } from './glyph_hash';
import type { GlyphHash } from './glyph_hash';
type TestState = {
- glyphHash?: GlyphHash
+ glyphHash?: GlyphHash;
};
-
describe('Glyph Hash utility', () => {
+ test('it throws an exception if the string is too short', () => {
+ expect(() => {
+ getGlyphHash('short');
+ }).toThrow();
- test('it throws an exception if the string is too short', () => {
-
- expect(() => {
-
- getGlyphHash('short');
- }).toThrow();
-
- expect(() => {
-
- getGlyphHash('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
- }).toThrow();
-
- expect(() => {
-
- getGlyphHash('abcdefghijklmnopqrstuvwxyzABCDEF');
- }).not.toThrow();
- });
-
- test('it treats UUIDs with hyphens the same as those without', () => {
-
- const uuidWithHyphens = 'f7722355-2285-46c0-a55f-3483a826f3a6';
- const uuidWithoutHyphens = 'f7722355228546c0a55f3483a826f3a6';
-
- expect(getGlyphHash(uuidWithHyphens)).toEqual(getGlyphHash(uuidWithoutHyphens));
- });
-
- describe('it generates four sets of glyphs and colors', () => {
-
- const state: TestState = {};
+ expect(() => {
+ getGlyphHash('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
+ }).toThrow();
- beforeEach(() => {
+ expect(() => {
+ getGlyphHash('abcdefghijklmnopqrstuvwxyzABCDEF');
+ }).not.toThrow();
+ });
- state.glyphHash = getGlyphHash('f7722355-2285-46c0-a55f-3483a826f3a6');
- });
+ test('it treats UUIDs with hyphens the same as those without', () => {
+ const uuidWithHyphens = 'f7722355-2285-46c0-a55f-3483a826f3a6';
+ const uuidWithoutHyphens = 'f7722355228546c0a55f3483a826f3a6';
- test('there should be four glyph fragments', () => {
+ expect(getGlyphHash(uuidWithHyphens)).toEqual(getGlyphHash(uuidWithoutHyphens));
+ });
- expect(state.glyphHash.length).toBe(4);
- });
+ describe('it generates four sets of glyphs and colors', () => {
+ const state: TestState = {};
- test('each fragment should have a single character glyph', () => {
+ beforeEach(() => {
+ state.glyphHash = getGlyphHash('f7722355-2285-46c0-a55f-3483a826f3a6');
+ });
- for (const glyphHashFragment of state.glyphHash) {
- expect(typeof glyphHashFragment.glyph).toBe('string');
- expect(glyphHashFragment.glyph.length).toBe(1);
- }
- });
+ test('there should be four glyph fragments', () => {
+ expect(state.glyphHash.length).toBe(4);
+ });
- test('each fragment should have a hexadecimal color', () => {
+ test('each fragment should have a single character glyph', () => {
+ for (const glyphHashFragment of state.glyphHash) {
+ expect(typeof glyphHashFragment.glyph).toBe('string');
+ expect(glyphHashFragment.glyph.length).toBe(1);
+ }
+ });
- for (const glyphHashFragment of state.glyphHash) {
- expect(typeof glyphHashFragment.color).toBe('string');
- expect(glyphHashFragment.color.length).toBe(7);
- expect(glyphHashFragment.color).toEqual(expect.stringMatching(/#[0-9a-f]{6}/));
- }
- });
- });
+ test('each fragment should have a hexadecimal color', () => {
+ for (const glyphHashFragment of state.glyphHash) {
+ expect(typeof glyphHashFragment.color).toBe('string');
+ expect(glyphHashFragment.color.length).toBe(7);
+ expect(glyphHashFragment.color).toEqual(expect.stringMatching(/#[0-9a-f]{6}/));
+ }
+ });
+ });
});
diff --git a/src/lib/utils/glyph_hash.ts b/src/lib/utils/glyph_hash.ts
index b704569..7ac6448 100644
--- a/src/lib/utils/glyph_hash.ts
+++ b/src/lib/utils/glyph_hash.ts
@@ -1,55 +1,37 @@
export type GlyphHash = GlyphHashFragment[];
type GlyphHashFragment = {
- glyph: string,
- color: string
+ glyph: string;
+ color: string;
};
const internals = {
- kDehyphenRegex: /[-]/g,
- kSplitterRegex: /.{1,8}/g,
- kGlyphs: [
- '☽',
- '☆',
- '♢',
- '♡',
- '╱',
- '╲',
- '╳',
- '〰',
- '▷',
- '⏊',
- '〒',
- '▢',
- '◯',
- '⏃',
- '⏀',
- '⏆'
- ],
- unexpectedUUIDLength: class UnexpectedUUIDLength extends Error {
- name = 'UnexpectedUUIDLength';
- message = 'The provided string was not a valid UUIDv4, please provide a 32 character long string'
- }
+ kDehyphenRegex: /[-]/g,
+ kSplitterRegex: /.{1,8}/g,
+ kGlyphs: ['☽', '☆', '♢', '♡', '╱', '╲', '╳', '〰', '▷', '⏊', '〒', '▢', '◯', '⏃', '⏀', '⏆'],
+ unexpectedUUIDLength: class UnexpectedUUIDLength extends Error {
+ name = 'UnexpectedUUIDLength';
+ message =
+ 'The provided string was not a valid UUIDv4, please provide a 32 character long string';
+ }
};
// Return a glyph with color based on a 4 byte fragment of a UUIDv4
const getGlyphHashFragment = function (uuidFragment: string): GlyphHashFragment {
-
- const glyphIndex = parseInt(uuidFragment.substring(0, 2), 16) % 16;
- return {
- glyph: internals.kGlyphs[glyphIndex],
- color: `#${uuidFragment.substring(2, 8)}`
- };
+ const glyphIndex = parseInt(uuidFragment.substring(0, 2), 16) % 16;
+ return {
+ glyph: internals.kGlyphs[glyphIndex],
+ color: `#${uuidFragment.substring(2, 8)}`
+ };
};
// Return an array of glyphs based on a UUIDv4
export const getGlyphHash = function (uuid: string): GlyphHash {
+ const dehyphenedUuid = uuid.replace(/[-]/g, '');
- const dehyphenedUuid = uuid.replace(/[-]/g, '');
-
- if (dehyphenedUuid.length !== 32) {
- throw new internals.unexpectedUUIDLength();
- }
+ if (dehyphenedUuid.length !== 32) {
+ throw new internals.unexpectedUUIDLength();
+ }
- const hashFragments = dehyphenedUuid.match(internals.kSplitterRegex);
- return hashFragments.map(getGlyphHashFragment);
+ const hashFragments = dehyphenedUuid.match(internals.kSplitterRegex);
+ return hashFragments.map(getGlyphHashFragment);
};
diff --git a/src/lib/utils/readable_time.test.ts b/src/lib/utils/readable_time.test.ts
index 5d8ba27..6c4b4d4 100644
--- a/src/lib/utils/readable_time.test.ts
+++ b/src/lib/utils/readable_time.test.ts
@@ -1,83 +1,71 @@
import { readableTime } from './readable_time';
describe('readableTime', () => {
+ test('it shows negative time as 0', () => {
+ const response = readableTime(-1000);
- test('it shows negative time as 0', () => {
+ expect(response.count).toBe(0);
+ expect(response.label).toContain('seconds');
+ });
- const response = readableTime(-1000);
+ test('uses seconds as the smallest unit', () => {
+ const response = readableTime(10);
- expect(response.count).toBe(0);
- expect(response.label).toContain('seconds');
- });
+ expect(response.count).toBe(0);
+ expect(response.label).toContain('seconds');
+ });
- test('uses seconds as the smallest unit', () => {
+ test('correctly divides miliseconds into seconds', () => {
+ const response = readableTime(4000);
- const response = readableTime(10);
+ expect(response.count).toBe(4);
+ });
- expect(response.count).toBe(0);
- expect(response.label).toContain('seconds');
- });
+ test('uses seconds if the time is < 1 minute', () => {
+ const response = readableTime(59 * 1000);
- test('correctly divides miliseconds into seconds', () => {
+ expect(response.label).toContain('seconds');
+ });
- const response = readableTime(4000);
+ test('correctly divides miliseconds into minutes', () => {
+ const response = readableTime(2 * 60 * 1000);
- expect(response.count).toBe(4);
- });
+ expect(response.count).toBe(2);
+ });
- test('uses seconds if the time is < 1 minute', () => {
+ test('uses minutes if the time is < 1 hour', () => {
+ const response = readableTime(59 * 60 * 1000);
- const response = readableTime(59 * 1000);
+ expect(response.label).toContain('minutes');
+ });
- expect(response.label).toContain('seconds');
- });
+ test('correctly divides miliseconds into hours', () => {
+ const response = readableTime(2 * 60 * 60 * 1000);
- test('correctly divides miliseconds into minutes', () => {
+ expect(response.count).toBe(2);
+ });
- const response = readableTime(2 * 60 * 1000);
+ test('uses hours if the time is < 1 days', () => {
+ const response = readableTime(23 * 60 * 60 * 1000);
- expect(response.count).toBe(2);
- });
+ expect(response.label).toContain('hours');
+ });
- test('uses minutes if the time is < 1 hour', () => {
+ test('correctly divides miliseconds into days', () => {
+ const response = readableTime(2 * 24 * 60 * 60 * 1000);
- const response = readableTime(59 * 60 * 1000);
+ expect(response.count).toBe(2);
+ });
- expect(response.label).toContain('minutes');
- });
+ test('uses days if the time is >= 1 day', () => {
+ const response = readableTime(364 * 24 * 60 * 60 * 1000);
- test('correctly divides miliseconds into hours', () => {
+ expect(response.label).toContain('days');
+ });
- const response = readableTime(2 * 60 * 60 * 1000);
+ test('uses days as the maximum unit', () => {
+ const response = readableTime(Number.MAX_VALUE);
- expect(response.count).toBe(2);
- });
-
- test('uses hours if the time is < 1 days', () => {
-
- const response = readableTime(23 * 60 * 60 * 1000);
-
- expect(response.label).toContain('hours');
- });
-
- test('correctly divides miliseconds into days', () => {
-
- const response = readableTime(2 * 24 * 60 * 60 * 1000);
-
- expect(response.count).toBe(2);
- });
-
- test('uses days if the time is >= 1 day', () => {
-
- const response = readableTime(364 * 24 * 60 * 60 * 1000);
-
- expect(response.label).toContain('days');
- });
-
- test('uses days as the maximum unit', () => {
-
- const response = readableTime(Number.MAX_VALUE);
-
- expect(response.label).toContain('days');
- });
+ expect(response.label).toContain('days');
+ });
});
diff --git a/src/lib/utils/readable_time.ts b/src/lib/utils/readable_time.ts
index 86ba044..c949981 100644
--- a/src/lib/utils/readable_time.ts
+++ b/src/lib/utils/readable_time.ts
@@ -1,46 +1,43 @@
type DateMagnitude = 'day' | 'hour' | 'minute' | 'second';
type ReadableTime = {
- count: number,
- label: string
+ count: number;
+ label: string;
};
-
const internals = {
- magnitudes: {
- day: 86400000,
- hour: 3600000,
- minute: 60000,
- second: 1000
- },
- labels: {
- day: 'time.days',
- hour: 'time.hours',
- minute: 'time.minutes',
- second: 'time.seconds'
- },
-
- makeTimeReadable(time: number, magnitude: DateMagnitude): ReadableTime {
+ magnitudes: {
+ day: 86400000,
+ hour: 3600000,
+ minute: 60000,
+ second: 1000
+ },
+ labels: {
+ day: 'time.days',
+ hour: 'time.hours',
+ minute: 'time.minutes',
+ second: 'time.seconds'
+ },
- return {
- count: Math.floor(time / internals.magnitudes[magnitude]),
- label: internals.labels[magnitude]
- };
- }
+ makeTimeReadable(time: number, magnitude: DateMagnitude): ReadableTime {
+ return {
+ count: Math.floor(time / internals.magnitudes[magnitude]),
+ label: internals.labels[magnitude]
+ };
+ }
};
export const readableTime = function readableTime(time: number): ReadableTime {
-
- switch (true) {
- case time >= internals.magnitudes.day:
- return internals.makeTimeReadable(time, 'day');
- case time >= internals.magnitudes.hour:
- return internals.makeTimeReadable(time, 'hour');
- case time >= internals.magnitudes.minute:
- return internals.makeTimeReadable(time, 'minute');
- case time < 0:
- return internals.makeTimeReadable(0, 'second');
- default:
- return internals.makeTimeReadable(time, 'second');
- }
+ switch (true) {
+ case time >= internals.magnitudes.day:
+ return internals.makeTimeReadable(time, 'day');
+ case time >= internals.magnitudes.hour:
+ return internals.makeTimeReadable(time, 'hour');
+ case time >= internals.magnitudes.minute:
+ return internals.makeTimeReadable(time, 'minute');
+ case time < 0:
+ return internals.makeTimeReadable(0, 'second');
+ default:
+ return internals.makeTimeReadable(time, 'second');
+ }
};
diff --git a/src/lib/utils/resolve_after.test.ts b/src/lib/utils/resolve_after.test.ts
index 7e0cc3c..4b30d3c 100644
--- a/src/lib/utils/resolve_after.test.ts
+++ b/src/lib/utils/resolve_after.test.ts
@@ -1,37 +1,30 @@
import { resolveAfter } from './resolve_after';
describe('Resolve After', () => {
+ test('it should throw if given 0', () => {
+ expect(() => {
+ resolveAfter(0);
+ }).toThrow();
+ });
- test('it should throw if given 0', () => {
+ test('it should throw if given a negative number', () => {
+ expect(() => {
+ resolveAfter(-1);
+ }).toThrow();
+ });
- expect(() => {
+ test('it should resolve after the specified number of times', () => {
+ expect(() => {
+ const { counter, promise: resolveAfterThree } = resolveAfter(3);
+ let resolved = false;
- resolveAfter(0);
- }).toThrow();
- });
-
- test('it should throw if given a negative number', () => {
-
- expect(() => {
-
- resolveAfter(-1);
- }).toThrow();
- });
-
- test('it should resolve after the specified number of times', () => {
-
- expect(() => {
-
- const { counter, promise: resolveAfterThree } = resolveAfter(3);
- let resolved = false;
-
- resolveAfterThree.then(() => (resolved = true));
- counter();
- expect(resolved).toBe(false);
- counter();
- expect(resolved).toBe(false);
- counter();
- expect(resolved).toBe(true);
- }).toThrow();
- });
+ resolveAfterThree.then(() => (resolved = true));
+ counter();
+ expect(resolved).toBe(false);
+ counter();
+ expect(resolved).toBe(false);
+ counter();
+ expect(resolved).toBe(true);
+ }).toThrow();
+ });
});
diff --git a/src/lib/utils/resolve_after.ts b/src/lib/utils/resolve_after.ts
index 95a477e..5d35f1c 100644
--- a/src/lib/utils/resolve_after.ts
+++ b/src/lib/utils/resolve_after.ts
@@ -1,29 +1,26 @@
export type ResolveAfterPromise = {
- counter: () => void,
- promise: Promise<void>
+ counter: () => void;
+ promise: Promise<void>;
};
export const resolveAfter = function (timesUntilResolve: number): ResolveAfterPromise {
+ let counter = null;
+ let currentValue = 0;
- let counter = null;
- let currentValue = 0;
+ if (timesUntilResolve <= 0) {
+ throw new Error('Resolve after requires a positive integer');
+ }
- if (timesUntilResolve <= 0) {
- throw new Error('Resolve after requires a positive integer');
- }
+ const promise: Promise<void> = new Promise((resolvePromise) => {
+ counter = () => {
+ if (++currentValue === timesUntilResolve) {
+ resolvePromise();
+ }
+ };
+ });
- const promise: Promise<void> = new Promise((resolvePromise) => {
-
- counter = () => {
-
- if (++currentValue === timesUntilResolve) {
- resolvePromise();
- }
- };
- });
-
- return {
- counter,
- promise
- };
+ return {
+ counter,
+ promise
+ };
};