Some code cleanup, add jest coverage and begin using it for utility functions
This commit is contained in:
parent
ca39830333
commit
1eb3ea2ee4
29 changed files with 2044 additions and 134 deletions
56
resources/scripts/lib/formatters.spec.ts
Normal file
56
resources/scripts/lib/formatters.spec.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import { bytesToString, ip, mbToBytes } from '@/lib/formatters';
|
||||
|
||||
describe('@/lib/formatters.ts', function () {
|
||||
describe('mbToBytes()', function () {
|
||||
it('should convert from MB to Bytes', function () {
|
||||
expect(mbToBytes(1)).toBe(1_000_000);
|
||||
expect(mbToBytes(0)).toBe(0);
|
||||
expect(mbToBytes(0.1)).toBe(100_000);
|
||||
expect(mbToBytes(0.001)).toBe(1000);
|
||||
expect(mbToBytes(1024)).toBe(1_024_000_000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('bytesToString()', function () {
|
||||
it.each([
|
||||
[ 0, '0 Bytes' ],
|
||||
[ 0.5, '0 Bytes' ],
|
||||
[ 0.9, '0 Bytes' ],
|
||||
[ 100, '100 Bytes' ],
|
||||
[ 100.25, '100.25 Bytes' ],
|
||||
[ 100.998, '101 Bytes' ],
|
||||
[ 512, '512 Bytes' ],
|
||||
[ 1000, '1 KB' ],
|
||||
[ 1024, '1.02 KB' ],
|
||||
[ 5068, '5.07 KB' ],
|
||||
[ 10_000, '10 KB' ],
|
||||
[ 11_864, '11.86 KB' ],
|
||||
[ 1_000_000, '1 MB' ],
|
||||
[ 1_356_000, '1.36 MB' ],
|
||||
[ 1_024_000, '1.02 MB' ],
|
||||
[ 1_000_000_000, '1 GB' ],
|
||||
[ 1_024_000_000, '1.02 GB' ],
|
||||
[ 1_678_342_000, '1.68 GB' ],
|
||||
[ 1_000_000_000_000, '1 TB' ],
|
||||
])('should format %d bytes as "%s"', function (input, output) {
|
||||
expect(bytesToString(input)).toBe(output);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ip()', function () {
|
||||
it('should format an IPv4 address', function () {
|
||||
expect(ip('127.0.0.1')).toBe('127.0.0.1');
|
||||
});
|
||||
|
||||
it('should format an IPv6 address', function () {
|
||||
expect(ip(':::1')).toBe('[:::1]');
|
||||
expect(ip('2001:db8::')).toBe('[2001:db8::]');
|
||||
});
|
||||
|
||||
it('should handle random inputs', function () {
|
||||
expect(ip('1')).toBe('1');
|
||||
expect(ip('foobar')).toBe('foobar');
|
||||
expect(ip('127.0.0.1:25565')).toBe('[127.0.0.1:25565]');
|
||||
});
|
||||
});
|
||||
});
|
35
resources/scripts/lib/formatters.ts
Normal file
35
resources/scripts/lib/formatters.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
const _CONVERSION_UNIT = 1000;
|
||||
|
||||
/**
|
||||
* Given a value in megabytes converts it back down into bytes.
|
||||
*/
|
||||
function mbToBytes (megabytes: number): number {
|
||||
return Math.floor(megabytes * _CONVERSION_UNIT * _CONVERSION_UNIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an amount of bytes, converts them into a human readable string format
|
||||
* using "1000" as the divisor.
|
||||
*/
|
||||
function bytesToString (bytes: number): string {
|
||||
if (bytes < 1) return '0 Bytes';
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(_CONVERSION_UNIT));
|
||||
const value = Number((bytes / Math.pow(_CONVERSION_UNIT, i)).toFixed(2));
|
||||
|
||||
return `${value} ${[ 'Bytes', 'KB', 'MB', 'GB', 'TB' ][i]}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an IPv4 or IPv6 address.
|
||||
*/
|
||||
function ip (value: string): string {
|
||||
// noinspection RegExpSimplifiable
|
||||
return /([a-f0-9:]+:+)+[a-f0-9]+/.test(value) ? `[${value}]` : value;
|
||||
}
|
||||
|
||||
export {
|
||||
ip,
|
||||
mbToBytes,
|
||||
bytesToString,
|
||||
};
|
29
resources/scripts/lib/helpers.spec.ts
Normal file
29
resources/scripts/lib/helpers.spec.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { hexToRgba } from '@/lib/helpers';
|
||||
|
||||
describe('@/lib/helpers.ts', function () {
|
||||
describe('hexToRgba()', function () {
|
||||
it('should return the expected rgba', function () {
|
||||
expect(hexToRgba('#ffffff')).toBe('rgba(255, 255, 255, 1)');
|
||||
expect(hexToRgba('#00aabb')).toBe('rgba(0, 170, 187, 1)');
|
||||
expect(hexToRgba('#efefef')).toBe('rgba(239, 239, 239, 1)');
|
||||
});
|
||||
|
||||
it('should ignore case', function () {
|
||||
expect(hexToRgba('#FF00A3')).toBe('rgba(255, 0, 163, 1)');
|
||||
});
|
||||
|
||||
it('should allow alpha channel changes', function () {
|
||||
expect(hexToRgba('#ece5a8', 0.5)).toBe('rgba(236, 229, 168, 0.5)');
|
||||
expect(hexToRgba('#ece5a8', 0.1)).toBe('rgba(236, 229, 168, 0.1)');
|
||||
expect(hexToRgba('#000000', 0)).toBe('rgba(0, 0, 0, 0)');
|
||||
});
|
||||
|
||||
it('should handle invalid strings', function () {
|
||||
expect(hexToRgba('')).toBe('');
|
||||
expect(hexToRgba('foobar')).toBe('foobar');
|
||||
expect(hexToRgba('#fff')).toBe('#fff');
|
||||
expect(hexToRgba('#')).toBe('#');
|
||||
expect(hexToRgba('#fffffy')).toBe('#fffffy');
|
||||
});
|
||||
});
|
||||
});
|
17
resources/scripts/lib/helpers.ts
Normal file
17
resources/scripts/lib/helpers.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Given a valid six character HEX color code, converts it into its associated
|
||||
* RGBA value with a user controllable alpha channel.
|
||||
*/
|
||||
function hexToRgba (hex: string, alpha = 1): string {
|
||||
// noinspection RegExpSimplifiable
|
||||
if (!/#?([a-fA-F0-9]{2}){3}/.test(hex)) {
|
||||
return hex;
|
||||
}
|
||||
|
||||
// noinspection RegExpSimplifiable
|
||||
const [ r, g, b ] = hex.match(/[a-fA-F0-9]{2}/g)!.map(v => parseInt(v, 16));
|
||||
|
||||
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
||||
}
|
||||
|
||||
export { hexToRgba };
|
30
resources/scripts/lib/objects.spec.ts
Normal file
30
resources/scripts/lib/objects.spec.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { isObject } from '@/lib/objects';
|
||||
|
||||
describe('@/lib/objects.ts', function () {
|
||||
describe('isObject()', function () {
|
||||
it('should return true for objects', function () {
|
||||
expect(isObject({})).toBe(true);
|
||||
expect(isObject({ foo: 123 })).toBe(true);
|
||||
expect(isObject(Object.freeze({}))).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for null', function () {
|
||||
expect(isObject(null)).toBe(false);
|
||||
});
|
||||
|
||||
it.each([
|
||||
undefined,
|
||||
123,
|
||||
'foobar',
|
||||
() => ({}),
|
||||
Function,
|
||||
String(123),
|
||||
isObject,
|
||||
() => null,
|
||||
[],
|
||||
[ 1, 2, 3 ],
|
||||
])('should return false for %p', function (value) {
|
||||
expect(isObject(value)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
29
resources/scripts/lib/objects.ts
Normal file
29
resources/scripts/lib/objects.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Determines if the value provided to the function is an object type that
|
||||
* is not null.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
function isObject (val: unknown): val is {} {
|
||||
return typeof val === 'object' && val !== null && !Array.isArray(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an object is truly empty by looking at the keys present
|
||||
* and the prototype value.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
function isEmptyObject (val: {}): boolean {
|
||||
return Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function for use in TypeScript that returns all of the keys
|
||||
* for an object, but in a typed manner to make working with them a little
|
||||
* easier.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
function getObjectKeys<T extends {}> (o: T): (keyof T)[] {
|
||||
return Object.keys(o) as (keyof typeof o)[];
|
||||
}
|
||||
|
||||
export { isObject, isEmptyObject, getObjectKeys };
|
14
resources/scripts/lib/strings.spec.ts
Normal file
14
resources/scripts/lib/strings.spec.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { capitalize } from '@/lib/strings';
|
||||
|
||||
describe('@/lib/strings.ts', function () {
|
||||
describe('capitalize()', function () {
|
||||
it('should capitalize a string', function () {
|
||||
expect(capitalize('foo bar')).toBe('Foo bar');
|
||||
expect(capitalize('FOOBAR')).toBe('Foobar');
|
||||
});
|
||||
|
||||
it('should handle empty strings', function () {
|
||||
expect(capitalize('')).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
5
resources/scripts/lib/strings.ts
Normal file
5
resources/scripts/lib/strings.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
function capitalize (value: string): string {
|
||||
return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
|
||||
}
|
||||
|
||||
export { capitalize };
|
Reference in a new issue