From da016f2e0319cf99e93a988d3f0715a1787294a8 Mon Sep 17 00:00:00 2001 From: Chris Kruining Date: Tue, 12 Nov 2024 16:08:50 +0100 Subject: [PATCH] tiny bit of cleanup --- src/components/tabs.tsx | 1 - src/entry-server.tsx | 6 +- src/utilities.spec.ts | 719 ++++++++++++++++++++-------------------- 3 files changed, 365 insertions(+), 361 deletions(-) diff --git a/src/components/tabs.tsx b/src/components/tabs.tsx index 9d05645..0b62146 100644 --- a/src/components/tabs.tsx +++ b/src/components/tabs.tsx @@ -22,7 +22,6 @@ const useTabs = () => { } export const Tabs: ParentComponent<{ active?: Setter, onClose?: CommandType<[string]> }> = (props) => { - const commandsContext = useCommands(); const [active, setActive] = createSignal(undefined); createEffect(() => { diff --git a/src/entry-server.tsx b/src/entry-server.tsx index 220923e..ad923a1 100644 --- a/src/entry-server.tsx +++ b/src/entry-server.tsx @@ -1,6 +1,7 @@ // @refresh reload import { createHandler, StartServer } from "@solidjs/start/server"; import { installIntoGlobal } from "iterator-helpers-polyfill"; +import { isServer } from "solid-js/web"; installIntoGlobal(); @@ -26,11 +27,14 @@ export default createHandler(({ nonce }) => { ); }, event => { const nonce = crypto.randomUUID(); - const base = `'self' 'nonce-${nonce}'`; + const isDev = process.env.NODE_ENV === 'development'; + + const base = `'self' 'nonce-${nonce}' ${isDev ? `'unsafe-eval'` : ''}`; const policies = { default: base, connect: `${base} ws://localhost:*`, + script: `${base}`, style: `'self' data: https://fonts.googleapis.com 'unsafe-inline'`, // style: `${base} data: https://fonts.googleapis.com`, font: `${base} https://*.gstatic.com`, diff --git a/src/utilities.spec.ts b/src/utilities.spec.ts index 6b87caf..556ab78 100644 --- a/src/utilities.spec.ts +++ b/src/utilities.spec.ts @@ -21,410 +21,411 @@ const first = (iterable: Iterable): T | undefined => { } } -describe('splitAt', () => { - it('should split the given string at the given index', async () => { - // Arrange - const given = 'this.is.some.concatenated.string'; - const expected = [ - 'this.is.some.concatenated', - 'string', - ] as const; +describe('utilities', () => { + describe('splitAt', () => { + it('should split the given string at the given index', async () => { + // Arrange + const given = 'this.is.some.concatenated.string'; + const expected = [ + 'this.is.some.concatenated', + 'string', + ] as const; - // Act - const [a, b] = splitAt(given, given.lastIndexOf('.')); + // Act + const [a, b] = splitAt(given, given.lastIndexOf('.')); - // Assert - expect(a).toBe(expected[0]); - expect(b).toBe(expected[1]); + // Assert + expect(a).toBe(expected[0]); + expect(b).toBe(expected[1]); + }); + + it('should return an empty second result when the index is negative', async () => { + // Arrange + const given = 'this.is.some.concatenated.string'; + const expected = [ + 'this.is.some.concatenated.string', + '', + ] as const; + + // Act + const [a, b] = splitAt(given, -1); + + // Assert + expect(a).toBe(expected[0]); + expect(b).toBe(expected[1]); + }); + + it('should return an empty second result when the index is larger then subject length', async () => { + // Arrange + const given = 'this.is.some.concatenated.string'; + const expected = [ + 'this.is.some.concatenated.string', + '', + ] as const; + + // Act + const [a, b] = splitAt(given, given.length * 2); + + // Assert + expect(a).toBe(expected[0]); + expect(b).toBe(expected[1]); + }); }); - it('should return an empty second result when the index is negative', async () => { - // Arrange - const given = 'this.is.some.concatenated.string'; - const expected = [ - 'this.is.some.concatenated.string', - '', - ] as const; + describe('debounce', () => { + const { tick } = useFakeTimers(); - // Act - const [a, b] = splitAt(given, -1); + it('should run the given callback after the provided time', async () => { + // Arrange + const callback = mock(() => { }); + const delay = 1000; + const debounced = debounce(callback, delay); - // Assert - expect(a).toBe(expected[0]); - expect(b).toBe(expected[1]); + // Act + debounced(); + tick(delay); + + // Assert + expect(callback).toHaveBeenCalledTimes(1); + }); + + it('should reset if another call is made', async () => { + // Arrange + const callback = mock(() => { }); + const delay = 1000; + const debounced = debounce(callback, delay); + + // Act + debounced(); + tick(delay / 2); + debounced(); + tick(delay); + + // Assert + expect(callback).toHaveBeenCalledTimes(1); + }); }); - it('should return an empty second result when the index is larger then subject length', async () => { - // Arrange - const given = 'this.is.some.concatenated.string'; - const expected = [ - 'this.is.some.concatenated.string', - '', - ] as const; + describe('deepCopy', () => { + it('can skip values passed by reference (non-objects, null, and undefined)', async () => { + // arrange + const given = 'some string'; - // Act - const [a, b] = splitAt(given, given.length * 2); + // Act + const actual = deepCopy(given); - // Assert - expect(a).toBe(expected[0]); - expect(b).toBe(expected[1]); - }); -}); + // Arrange + expect(actual).toBe(given); + }); -describe('debounce', () => { - const { tick } = useFakeTimers(); + it('should return a value that does not point to same memory', async () => { + // Arrange + const given = {}; - it('should run the given callback after the provided time', async () => { - // Arrange - const callback = mock(() => { }); - const delay = 1000; - const debounced = debounce(callback, delay); + // Act + const actual = deepCopy(given); - // Act - debounced(); - tick(delay); + // Assert + expect(actual).not.toBe(given); + }); - // Assert - expect(callback).toHaveBeenCalledTimes(1); - }); + it('should handle Date types', async () => { + // Arrange + const given = new Date(); - it('should reset if another call is made', async () => { - // Arrange - const callback = mock(() => { }); - const delay = 1000; - const debounced = debounce(callback, delay); + // Act + const actual = deepCopy(given); - // Act - debounced(); - tick(delay / 2); - debounced(); - tick(delay); + // Assert + expect(actual).not.toBe(given); + }); - // Assert - expect(callback).toHaveBeenCalledTimes(1); - }); -}); + it('should handle Arrays', async () => { + // Arrange + const given: any[] = []; -describe('deepCopy', () => { - it('can skip values passed by reference (non-objects, null, and undefined)', async () => { - // arrange - const given = 'some string'; + // Act + const actual = deepCopy(given); - // Act - const actual = deepCopy(given); + // Assert + expect(actual).not.toBe(given); + }); - // Arrange - expect(actual).toBe(given); - }); + it('should handle Sets', async () => { + // Arrange + const given = new Set(); - it('should return a value that does not point to same memory', async () => { - // Arrange - const given = {}; + // Act + const actual = deepCopy(given); - // Act - const actual = deepCopy(given); + // Assert + expect(actual).not.toBe(given); + }); - // Assert - expect(actual).not.toBe(given); - }); + it('should handle Maps', async () => { + // Arrange + const given = new Map(); - it('should handle Date types', async () => { - // Arrange - const given = new Date(); + // Act + const actual = deepCopy(given); - // Act - const actual = deepCopy(given); + // Assert + expect(actual).not.toBe(given); + }); - // Assert - expect(actual).not.toBe(given); - }); - - it('should handle Arrays', async () => { - // Arrange - const given: any[] = []; - - // Act - const actual = deepCopy(given); - - // Assert - expect(actual).not.toBe(given); - }); - - it('should handle Sets', async () => { - // Arrange - const given = new Set(); - - // Act - const actual = deepCopy(given); - - // Assert - expect(actual).not.toBe(given); - }); - - it('should handle Maps', async () => { - // Arrange - const given = new Map(); - - // Act - const actual = deepCopy(given); - - // Assert - expect(actual).not.toBe(given); - }); - - it('should return a value that does not point to same memory for nested properties', async () => { - // Arrange - const given = { - some: { - deep: { - value: {} + it('should return a value that does not point to same memory for nested properties', async () => { + // Arrange + const given = { + some: { + deep: { + value: {} + } } - } - }; + }; - // Act - const actual = deepCopy(given); + // Act + const actual = deepCopy(given); - // Assert - expect(actual.some.deep.value).not.toBe(given.some.deep.value); - }); -}); - -describe('deepDiff', () => { - it('should immedietly return when either `a` is not iterable', async () => { - // arrange - const a: any = 0; - const b = {}; - const spy = spyOn(console, 'error').mockReturnValue(undefined); - - // Act - const actual = deepDiff(a, b).toArray(); - - // Arrange - expect(actual).toEqual([]); - expect(spy).toHaveBeenCalled(); + // Assert + expect(actual.some.deep.value).not.toBe(given.some.deep.value); + }); }); - it('should immedietly return when either `b` is not iterable', async () => { - // arrange - const a = {}; - const b: any = 0; - const spy = spyOn(console, 'error').mockReturnValue(undefined); + describe('deepDiff', () => { + it('should immedietly return when either `a` is not iterable', async () => { + // arrange + const a: any = 0; + const b = {}; + const spy = spyOn(console, 'error').mockReturnValue(undefined); - // Act - const actual = deepDiff(a, b).toArray(); + // Act + const actual = deepDiff(a, b).toArray(); - // Arrange - expect(actual).toEqual([]); - expect(spy).toHaveBeenCalled(); + // Arrange + expect(actual).toEqual([]); + expect(spy).toHaveBeenCalled(); + }); + + it('should immedietly return when either `b` is not iterable', async () => { + // arrange + const a = {}; + const b: any = 0; + const spy = spyOn(console, 'error').mockReturnValue(undefined); + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([]); + expect(spy).toHaveBeenCalled(); + }); + + it('should yield no results when both a and b are empty', async () => { + // arrange + const a = {}; + const b = {}; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([]); + }); + + it('should yield no results when both a and b are equal', async () => { + // arrange + const a = { key: 'value' }; + const b = { key: 'value' }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([]); + }); + + it('should yield a mutation of type create when `b` contains a key that `a` does not', async () => { + // arrange + const a = {}; + const b = { key: 'value' }; + + // Act + const actual = first(deepDiff(a, b)); + + // Arrange + expect(actual).toEqual({ kind: MutarionKind.Create, key: 'key', value: 'value' }); + }); + + it('should yield a mutation of type delete when `a` contains a key that `b` does not', async () => { + // arrange + const a = { key: 'value' }; + const b = {}; + + // Act + const actual = first(deepDiff(a, b)); + + // Arrange + expect(actual).toEqual({ kind: MutarionKind.Delete, key: 'key' }); + }); + + it('should yield a mutation of type update when the value of a key in `a` is not equal to the value of the same key in `b`', async () => { + // arrange + const a = { key: 'old' }; + const b = { key: 'new' }; + + // Act + const actual = first(deepDiff(a, b)); + + // Arrange + expect(actual).toEqual({ kind: MutarionKind.Update, key: 'key', original: 'old', value: 'new' }); + }); + + it('should iterate over nested values', async () => { + // arrange + const a = { some: { nested: { key: 'old' } } }; + const b = { some: { nested: { key: 'new' } } }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([{ kind: MutarionKind.Update, key: 'some.nested.key', original: 'old', value: 'new' }]); + }); + + it('should handle deleted keys', async () => { + // arrange + const a = { key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4', key5: 'value5' }; + const b = { key1: 'value1', key4: 'value4', key5: 'value5' }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Delete, key: 'key2' }, + { kind: MutarionKind.Delete, key: 'key3' }, + ]); + }); + + it('should handle created keys', async () => { + // arrange + const a = { key1: 'value1', key4: 'value4', key5: 'value5' }; + const b = { key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4', key5: 'value5' }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Create, key: 'key2', value: 'value2' }, + { kind: MutarionKind.Create, key: 'key3', value: 'value3' }, + ]); + }); + + it('should handle renamed keys', async () => { + // arrange + const a = { key1: 'value1', key2_old: 'value2', key3: 'value3' }; + const b = { key1: 'value1', key2_new: 'value2', key3: 'value3', }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Delete, key: 'key2_old' }, + { kind: MutarionKind.Create, key: 'key2_new', value: 'value2' }, + ]); + }); + + it('should handle `Array` values', async () => { + // arrange + const a = { key: [1] }; + const b = { key: [2] }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Update, key: 'key.0', original: 1, value: 2 }, + ]); + }); + + it('should handle `Set` values', async () => { + // arrange + const a = { key: new Set([1, 2, 3]) }; + const b = { key: new Set([1, 5, 3]) }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Delete, key: 'key.2' }, + { kind: MutarionKind.Create, key: 'key.5', value: 5 }, + ]); + }); + + it('should handle `Map` values', async () => { + // arrange + const a = { key: new Map([['key', 'old']]) }; + const b = { key: new Map([['key', 'new']]) }; + + // Act + const actual = deepDiff(a, b).toArray(); + + // Arrange + expect(actual).toEqual([ + { kind: MutarionKind.Update, key: 'key.key', original: 'old', value: 'new' }, + ]); + }); }); - it('should yield no results when both a and b are empty', async () => { - // arrange - const a = {}; - const b = {}; + describe('filter', () => { + it('should yield a value when the predicate returns true', async () => { + // arrange + const generator = async function* () { + for (const i of new Array(10).fill('').map((_, i) => i)) { + yield i; + } + }; + const predicate = (i: number) => i % 2 === 0; - // Act - const actual = deepDiff(a, b).toArray(); + // Act + const actual = await Array.fromAsync(filter(generator(), predicate as any)); - // Arrange - expect(actual).toEqual([]); + // Arrange + expect(actual).toEqual([0, 2, 4, 6, 8]); + }); }); - it('should yield no results when both a and b are equal', async () => { - // arrange - const a = { key: 'value' }; - const b = { key: 'value' }; - - // Act - const actual = deepDiff(a, b).toArray(); - - // Arrange - expect(actual).toEqual([]); - }); - - it('should yield a mutation of type create when `b` contains a key that `a` does not', async () => { - // arrange - const a = {}; - const b = { key: 'value' }; - - // Act - const actual = first(deepDiff(a, b)); - - // Arrange - expect(actual).toEqual({ kind: MutarionKind.Create, key: 'key', value: 'value' }); - }); - - it('should yield a mutation of type delete when `a` contains a key that `b` does not', async () => { - // arrange - const a = { key: 'value' }; - const b = {}; - - // Act - const actual = first(deepDiff(a, b)); - - // Arrange - expect(actual).toEqual({ kind: MutarionKind.Delete, key: 'key' }); - }); - - it('should yield a mutation of type update when the value of a key in `a` is not equal to the value of the same key in `b`', async () => { - // arrange - const a = { key: 'old' }; - const b = { key: 'new' }; - - // Act - const actual = first(deepDiff(a, b)); - - // Arrange - expect(actual).toEqual({ kind: MutarionKind.Update, key: 'key', original: 'old', value: 'new' }); - }); - - it('should iterate over nested values', async () => { - // arrange - const a = { some: { nested: { key: 'old' } } }; - const b = { some: { nested: { key: 'new' } } }; - - // Act - const actual = deepDiff(a, b).toArray(); - - // Arrange - expect(actual).toEqual([{ kind: MutarionKind.Update, key: 'some.nested.key', original: 'old', value: 'new' }]); - }); - - it('should handle deleted keys', async () => { - // arrange - const a = { key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4', key5: 'value5' }; - const b = { key1: 'value1', key4: 'value4', key5: 'value5' }; - - // Act - const actual = deepDiff(a, b).toArray(); - - // Arrange - expect(actual).toEqual([ - { kind: MutarionKind.Delete, key: 'key2' }, - { kind: MutarionKind.Delete, key: 'key3' }, - ]); - }); - - it('should handle created keys', async () => { - // arrange - const a = { key1: 'value1', key4: 'value4', key5: 'value5' }; - const b = { key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4', key5: 'value5' }; - - // Act - const actual = deepDiff(a, b).toArray(); - - // Arrange - expect(actual).toEqual([ - { kind: MutarionKind.Create, key: 'key2', value: 'value2' }, - { kind: MutarionKind.Create, key: 'key3', value: 'value3' }, - ]); - }); - - it('should handle renamed keys', async () => { - // arrange - const a = { key1: 'value1', key2_old: 'value2', key3: 'value3' }; - const b = { key1: 'value1', key2_new: 'value2', key3: 'value3', }; - - // Act - const actual = deepDiff(a, b).toArray(); - - // Arrange - expect(actual).toEqual([ - { kind: MutarionKind.Delete, key: 'key2_old' }, - { kind: MutarionKind.Create, key: 'key2_new', value: 'value2' }, - ]); - }); - - it('should handle `Array` values', async () => { - // arrange - const a = { key: [1] }; - const b = { key: [2] }; - - // Act - const actual = deepDiff(a, b).toArray(); - - // Arrange - expect(actual).toEqual([ - { kind: MutarionKind.Update, key: 'key.0', original: 1, value: 2 }, - ]); - }); - - it('should handle `Set` values', async () => { - // arrange - const a = { key: new Set([1, 2, 3]) }; - const b = { key: new Set([1, 5, 3]) }; - - // Act - const actual = deepDiff(a, b).toArray(); - - // Arrange - expect(actual).toEqual([ - { kind: MutarionKind.Delete, key: 'key.2' }, - { kind: MutarionKind.Create, key: 'key.5', value: 5 }, - ]); - }); - - it('should handle `Map` values', async () => { - // arrange - const a = { key: new Map([['key', 'old']]) }; - const b = { key: new Map([['key', 'new']]) }; - - // Act - const actual = deepDiff(a, b).toArray(); - - // Arrange - expect(actual).toEqual([ - { kind: MutarionKind.Update, key: 'key.key', original: 'old', value: 'new' }, - ]); - }); -}); - -describe('filter', () => { - it('should yield a value when the predicate returns true', async () => { - // arrange + describe('map', () => { const generator = async function* () { for (const i of new Array(10).fill('').map((_, i) => i)) { yield i; } }; - const predicate = (i: number) => i % 2 === 0; - // Act - const actual = await Array.fromAsync(filter(generator(), predicate as any)); + it('should yield a value when the predicate returns true', async () => { + // arrange + const mapFn = (i: number) => `nr ${i}`; - // Arrange - expect(actual).toEqual([0, 2, 4, 6, 8]); + // Act + const actual = await Array.fromAsync(map(generator(), mapFn)); + + // Arrange + expect(actual).toEqual([ + 'nr 0', + 'nr 1', + 'nr 2', + 'nr 3', + 'nr 4', + 'nr 5', + 'nr 6', + 'nr 7', + 'nr 8', + 'nr 9', + ]); + }); }); }); - -describe('map', () => { - const generator = async function* () { - for (const i of new Array(10).fill('').map((_, i) => i)) { - yield i; - } - }; - - it('should yield a value when the predicate returns true', async () => { - // arrange - const mapFn = (i: number) => `nr ${i}`; - - // Act - const actual = await Array.fromAsync(map(generator(), mapFn)); - - // Arrange - expect(actual).toEqual([ - 'nr 0', - 'nr 1', - 'nr 2', - 'nr 3', - 'nr 4', - 'nr 5', - 'nr 6', - 'nr 7', - 'nr 8', - 'nr 9', - ]); - }); -}); -