added some more tests

This commit is contained in:
Chris Kruining 2025-02-20 11:36:35 +11:00
parent 20a0fc679b
commit 04b55e02fb
No known key found for this signature in database
GPG key ID: EB894A3560CCCAD2
5 changed files with 168 additions and 47 deletions

View file

@ -54,6 +54,7 @@ describe('dataset', () => {
});
it('update if the source value changes', () => {
// Arrange
const [data, setData] = createSignal([
{ id: '1', name: 'a first name', amount: 30 },
{ id: '2', name: 'a second name', amount: 20 },
@ -61,19 +62,18 @@ describe('dataset', () => {
]);
const dataset = createDataSet(data);
dataset.mutateEach(item => ({ ...item, amount: item.amount * 2 }))
dataset.mutateEach(item => ({ ...item, amount: item.amount * 2 }));
return testEffect(done =>
createEffect((run: number = 0) => {
data();
if (run === 0) {
// Act
setData([
{ id: '4', name: 'a first name', amount: 30 },
{ id: '5', name: 'a second name', amount: 20 },
{ id: '6', name: 'a third name', amount: 10 },
]);
} else if (run === 1) {
// Assert
return testEffect(done =>
createEffect(() => {
expect(dataset.value).toEqual([
{ id: '4', name: 'a first name', amount: 60 },
{ id: '5', name: 'a second name', amount: 40 },
@ -81,8 +81,6 @@ describe('dataset', () => {
])
done()
}
return run + 1
})
);
});

View file

@ -0,0 +1,49 @@
import { describe, expect } from "vitest";
import { createSource } from "./source";
import { it } from "~/test-helpers";
import { testEffect } from "@solidjs/testing-library";
import { createEffect, createSignal } from "solid-js";
describe('Source', () => {
describe('Source', () => {
it('should return a `Source`', () => {
// Arrange
// Act
const actual = createSource('');
// Assert
expect(actual.out).toBe('');
});
it('should transform the input format to output format', () => {
// Arrange
const given = '**text**\n';
const expected = '<p><strong>text</strong></p>';
// Act
const actual = createSource(given);
// Assert
expect(actual.out).toBe(expected);
});
it('should contain query results', () => {
// Arrange
const expected: [number, number][] = [[8, 9], [12, 13], [15, 16]];
const source = createSource('this is a seachable string');
// Act
source.query = 'a';
// Assert
return testEffect(done => {
createEffect(() => {
expect(source.queryResults).toEqual(expected);
done()
});
});
});
});
});

View file

@ -37,16 +37,12 @@ const inToOutProcessor = unified().use(remarkParse).use(remarkRehype).use(rehype
const outToInProcessor = unified().use(rehypeParse).use(rehypeRemark).use(remarkStringify, { bullet: '-' });
export function createSource(initalValue: string): Source {
const [store, setStore] = createStore<SourceStore>({ in: initalValue, out: '', plain: '', query: '', metadata: { spellingErrors: [], grammarErrors: [], queryResults: [] } });
onMount(() => {
const ast = inToOutProcessor.runSync(inToOutProcessor.parse(initalValue));
const out = String(inToOutProcessor.stringify(ast));
const plain = String(unified().use(plainTextStringify).stringify(ast));
setStore({
out: String(inToOutProcessor.stringify(ast)),
plain: String(unified().use(plainTextStringify).stringify(ast)),
});
});
const [store, setStore] = createStore<SourceStore>({ in: initalValue, out, plain, query: '', metadata: { spellingErrors: [], grammarErrors: [], queryResults: [] } });
createEffect(() => {
const value = store.plain;

View file

@ -1,23 +1,9 @@
import { afterAll, beforeEach, describe, expect, vi } from 'vitest';
import { describe, expect, vi } from 'vitest';
import { decode, deepCopy, deepDiff, filter, gen__split_by_filter, map, MutarionKind, split_by_filter, splitAt } from './utilities';
import { install } from '@sinonjs/fake-timers';
import { it } from '~/test-helpers';
const { spyOn } = vi;
type MilliSeconds = number;
const useFakeTimers = () => {
const clock = install();
beforeEach(() => clock.reset());
afterAll(() => clock.uninstall());
return {
tick(timeToAdvance: MilliSeconds) {
clock.tick(timeToAdvance);
},
};
};
const first = <T>(iterable: Iterable<T>): T | undefined => {
for (const value of iterable) {
return value;
@ -126,6 +112,18 @@ describe('utilities', () => {
expect(actual).toBe(expected);
});
it('should decode \\b characters', async () => {
// Arrange
const given = 'this is\\ba string';
const expected = 'this is\ba string';
// Act
const actual = decode(given);
// Assert
expect(actual).toBe(expected);
});
it('should decode \\n characters', async () => {
// Arrange
const given = 'this is\\na string';
@ -138,6 +136,54 @@ describe('utilities', () => {
expect(actual).toBe(expected);
});
it('should decode \\r characters', async () => {
// Arrange
const given = 'this is\\ra string';
const expected = 'this is\ra string';
// Act
const actual = decode(given);
// Assert
expect(actual).toBe(expected);
});
it('should decode \\f characters', async () => {
// Arrange
const given = 'this is\\fa string';
const expected = 'this is\fa string';
// Act
const actual = decode(given);
// Assert
expect(actual).toBe(expected);
});
it('should decode \' characters', async () => {
// Arrange
const given = 'this is\\\'a string';
const expected = 'this is\'a string';
// Act
const actual = decode(given);
// Assert
expect(actual).toBe(expected);
});
it('should decode \" characters', async () => {
// Arrange
const given = 'this is\"a string';
const expected = 'this is"a string';
// Act
const actual = decode(given);
// Assert
expect(actual).toBe(expected);
});
it('should decode \\uHHHH characters', async () => {
// Arrange
const given = 'this is \\u1234 a string';
@ -301,6 +347,18 @@ describe('utilities', () => {
expect(actual).toEqual({ kind: MutarionKind.Create, key: 'key', value: 'value' });
});
it('should yield a mutation of type create when `b` contains a value that `a` does not', async () => {
// arrange
const a = { key: null };
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' };
@ -313,6 +371,18 @@ describe('utilities', () => {
expect(actual).toEqual({ kind: MutarionKind.Delete, key: 'key', original: '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 = { key: undefined };
// Act
const actual = first(deepDiff(a, b));
// Arrange
expect(actual).toEqual({ kind: MutarionKind.Delete, key: 'key', original: 'value' });
});
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' };

View file

@ -27,8 +27,11 @@ export function split_by_filter(subject: string, filter: string): (readonly [boo
return Array.from<readonly [boolean, string]>(gen__split_by_filter(subject, filter));
}
type Hex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 'a' | 'b' | 'c' | 'd' | 'e' | 'f';
type EncodedChar = 't' | 'b' | 'n' | 'r' | 'f' | '\'' | '"' | `u${Hex}${Hex | ''}${Hex | ''}${Hex | ''}`
const decodeRegex = /(?<!\\)\\(t|b|n|r|f|'|"|u[0-9a-f]{1,4})/gi;
const decodeReplacer = (_: any, char: string) => ({
const decodeReplacer = (_: any, char: EncodedChar) => ({
t: '\t',
b: '\b',
n: '\n',
@ -37,7 +40,7 @@ const decodeReplacer = (_: any, char: string) => ({
"'": '\'',
'"': '\"',
u: String.fromCharCode(Number.parseInt(`0x${char.slice(1)}`)),
}[char.charAt(0)] ?? '');
}[char.charAt(0) as ('t' | 'b' | 'n' | 'r' | 'f' | '\'' | '"' | 'u')]);
export const decode = (subject: string): string => subject.replace(decodeRegex, decodeReplacer);
export const deepCopy = <T>(original: T): T => {
@ -110,8 +113,13 @@ export function* deepDiff<T1 extends object, T2 extends object>(a: T1, b: T2, pa
const key = path.concat(keyA!.toString()).join('.');
yield ((): Mutation => {
if (valueA === null || valueA === undefined) return { key, kind: MutarionKind.Create, value: valueB };
if (valueB === null || valueB === undefined) return { key, kind: MutarionKind.Delete, original: valueA };
if (valueA === null || valueA === undefined) {
return { key, kind: MutarionKind.Create, value: valueB };
}
if (valueB === null || valueB === undefined) {
return { key, kind: MutarionKind.Delete, original: valueA };
}
return { key, kind: MutarionKind.Update, value: valueB, original: valueA };
})();
@ -200,7 +208,7 @@ const bufferredIterator = <T extends readonly [string | number, any]>(subject: I
const next = () => {
const res = iterator.next();
done = res.done ?? false;
done = res.done!;
if (!done) {
buffer.push(res.value);