*/
export const apollo = {
- uri: import.meta.env.VITE_APOLLO_SERVER,
- name,
- version: packageVersion
+ uri: import.meta.env.VITE_APOLLO_SERVER,
+ name,
+ version: packageVersion
};
export const socketServer = import.meta.env.FORUM_SOCKET_SERVER;
const internals = {
+ kDehyphenRegex: /[-]/g,
kSplitterRegex: /.{1,8}/g,
- kGlyphs: ['☽', '☆', '♢', '♡', '╱', '╲', '╳', '〰', '▷', '⏊', '〒', '▢', '◯', '⏃', '⏀', '⏆']
+ 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
// Return an array of glyphs based on a UUIDv4
export const getGlyphHash = function (uuid) {
- const hashFragments = uuid.replace(/[-]/g, '').match(internals.kSplitterRegex);
+ const dehyphenedUuid = uuid.replace(/[-]/g, '');
+
+ if (dehyphenedUuid.length !== 32) {
+ throw new internals.unexpectedUUIDLength();
+ }
+
+ const hashFragments = dehyphenedUuid.match(internals.kSplitterRegex);
return hashFragments.map(getGlyphHashFragment);
};
--- /dev/null
+import { getGlyphHash } from './glyph_hash';
+
+
+describe('readableTime', () => {
+
+ 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 = {};
+
+ beforeEach(() => {
+
+ state.glyphHash = getGlyphHash('f7722355-2285-46c0-a55f-3483a826f3a6');
+ });
+
+ test('there should be four glyph fragments', () => {
+
+ expect(state.glyphHash.length).toBe(4);
+ });
+
+ 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);
+ }
+ });
+
+ 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}/));
+ }
+ });
+ });
+});
--- /dev/null
+import { readableTime } from './readable_time';
+
+describe('readableTime', () => {
+
+ test('it shows negative time as 0', () => {
+
+ const response = readableTime(-1000);
+
+ expect(response.count).toBe(0);
+ expect(response.label).toContain('seconds');
+ });
+
+ test('uses seconds as the smallest unit', () => {
+
+ const response = readableTime(10);
+
+ expect(response.count).toBe(0);
+ expect(response.label).toContain('seconds');
+ });
+
+ test('correctly divides miliseconds into seconds', () => {
+
+ const response = readableTime(4000);
+
+ expect(response.count).toBe(4);
+ });
+
+ test('uses seconds if the time is < 1 minute', () => {
+
+ const response = readableTime(59 * 1000);
+
+ expect(response.label).toContain('seconds');
+ });
+
+ test('correctly divides miliseconds into minutes', () => {
+
+ const response = readableTime(2 * 60 * 1000);
+
+ expect(response.count).toBe(2);
+ });
+
+ test('uses minutes if the time is < 1 hour', () => {
+
+ const response = readableTime(59 * 60 * 1000);
+
+ expect(response.label).toContain('minutes');
+ });
+
+ test('correctly divides miliseconds into hours', () => {
+
+ const response = readableTime(2 * 60 * 60 * 1000);
+
+ 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');
+ });
+});