From ba95e09fc12b4909c836dd6a1d37ecd362ce51d4 Mon Sep 17 00:00:00 2001 From: aabccd021 Date: Wed, 18 Jan 2023 13:22:16 +0700 Subject: [PATCH] fix: checkpoint --- src/getDiffs.ts | 34 ++++++++++++++++++++++++++------- src/logErrorsF.ts | 48 ++++++++++++++++++++--------------------------- test/logErrors.ts | 35 +++++++++++++++++++++++++++------- test/primitive.ts | 12 ------------ 4 files changed, 75 insertions(+), 54 deletions(-) diff --git a/src/getDiffs.ts b/src/getDiffs.ts index 7a122e27..db22b06e 100644 --- a/src/getDiffs.ts +++ b/src/getDiffs.ts @@ -1,6 +1,6 @@ import { diffLines } from 'diff'; -import { apply, either, readonlyArray, readonlyRecord } from 'fp-ts'; -import { pipe } from 'fp-ts/function'; +import { apply, either, readonlyArray, readonlyRecord, string } from 'fp-ts'; +import { flow, pipe } from 'fp-ts/function'; import { match } from 'ts-pattern'; const stringify = (obj: unknown) => @@ -19,6 +19,16 @@ const stringify = (obj: unknown) => (details: unknown) => ({ code: 'serialization failed' as const, details }) ); +const removeLastNewLine = (str: string) => + string.endsWith('\n')(str) + ? pipe( + str, + string.split(''), + readonlyArray.dropRight(1), + readonlyArray.intercalate(string.Monoid)('') + ) + : str; + export const getDiffs = (result: { readonly expected: unknown; readonly actual: unknown }) => pipe( result, @@ -26,11 +36,21 @@ export const getDiffs = (result: { readonly expected: unknown; readonly actual: apply.sequenceS(either.Apply), either.map(({ expected, actual }) => diffLines(expected, actual)), either.map( - readonlyArray.map((change) => - match(change) - .with({ added: true }, ({ value }) => ({ type: '+' as const, value })) - .with({ removed: true }, ({ value }) => ({ type: '-' as const, value })) - .otherwise(({ value }) => ({ type: '0' as const, value })) + flow( + readonlyArray.map((change) => + match(change) + .with({ added: true }, ({ value }) => ({ type: '+' as const, value })) + .with({ removed: true }, ({ value }) => ({ type: '-' as const, value })) + .otherwise(({ value }) => ({ type: '0' as const, value })) + ), + readonlyArray.chain((change) => + pipe( + change.value, + removeLastNewLine, + string.split('\n'), + readonlyArray.map((value) => ({ type: change.type, value })) + ) + ) ) ) ); diff --git a/src/logErrorsF.ts b/src/logErrorsF.ts index ac85bbdf..053a7943 100644 --- a/src/logErrorsF.ts +++ b/src/logErrorsF.ts @@ -8,16 +8,6 @@ import { match } from 'ts-pattern'; import type { Change, TestError, TestFailedResult } from './type'; -const removeLastNewLine = (str: string) => - string.endsWith('\n')(str) - ? pipe( - str, - string.split(''), - readonlyArray.dropRight(1), - readonlyArray.intercalate(string.Monoid)('') - ) - : str; - const getPrefix = (changeType: Change['type']) => match(changeType) .with('+', () => '+') @@ -32,31 +22,33 @@ const getColor = (changeType: Change['type']): ((s: string) => string) => .with('0', () => identity) .exhaustive(); -const formatChangeStr = ({ - str, - changeType, -}: { - readonly str: string; - readonly changeType: Change['type']; -}) => pipe(str, std.string.prepend(`${getPrefix(changeType)} `), getColor(changeType)); +const formatChangeStr = (change: Change) => + pipe(change.value, std.string.prepend(`${getPrefix(change.type)} `), getColor(change.type)); -const changeToString = (change: Change) => +const getChangeNum = (diff: readonly Change[], changeType: Change['type']) => pipe( - change.value, - removeLastNewLine, - string.split('\n'), - readonlyArray.map((str) => formatChangeStr({ str, changeType: change.type })), - readonlyArray.intercalate(string.Monoid)('\n') + diff, + readonlyArray.filter((change) => change.type === changeType), + readonlyArray.size ); -const diffToString = flow( - readonlyArray.map(changeToString), - readonlyArray.intercalate(string.Monoid)('\n') -); +const diffNums = (diff: readonly Change[]) => [ + c.green(`- Expected - ${getChangeNum(diff, '-')}`), + c.red(`+ Received + ${getChangeNum(diff, '+')}`), + '', +]; + +const diffToString = readonlyArray.map(formatChangeStr); const formatError = (error: TestError): string => match(error) - .with({ code: 'AssertionError' }, ({ diff }) => diffToString(diff)) + .with({ code: 'AssertionError' }, ({ diff }) => + pipe( + [diffNums(diff), diffToString(diff)], + readonlyArray.flatten, + readonlyArray.intercalate(string.Monoid)('\n') + ) + ) .otherwise((err) => JSON.stringify(err, undefined, 2)); const indent = flow( diff --git a/test/logErrors.ts b/test/logErrors.ts index 929a95a4..7b883b21 100644 --- a/test/logErrors.ts +++ b/test/logErrors.ts @@ -4,13 +4,6 @@ import { pipe } from 'fp-ts/function'; import { logErrorsF, runTests, test } from '../src'; import { testW } from '../src/test'; -type Case = { - readonly name: string; - readonly actual: unknown; - readonly expected: unknown; - readonly log: readonly string[]; -}; - const green = '\x1b[32m'; const red = '\x1b[31m'; const colorEnd = '\x1b[39m'; @@ -21,6 +14,15 @@ const boldEnd = '\x1b[22m'; const invert = '\x1b[7m'; const invertEnd = '\x1b[27m'; +type Case = { + readonly name: string; + readonly actual: unknown; + readonly expected: unknown; + readonly log: readonly string[]; + readonly numPlus: number; + readonly numMinus: number; +}; + const caseToTest = (tc: Case) => test({ name: tc.name, @@ -46,6 +48,9 @@ const caseToTest = (tc: Case) => `${red}${bold}${invert} FAIL ${invertEnd}${boldEnd}${colorEnd} foo`, `${red}${bold}AssertionError:${boldEnd}${colorEnd}`, ``, + ` ${green}- Expected - ${tc.numMinus}${colorEnd}`, + ` ${red}+ Received + ${tc.numPlus}${colorEnd}`, + ` `, ...tc.log, ``, ], @@ -56,6 +61,8 @@ const cases: readonly Case[] = [ name: 'minus diff is logged with minus(-) prefix and red(31) color', actual: { minus: 'minusValue' }, expected: {}, + numMinus: 1, + numPlus: 3, log: [ ` ${green}- {}${colorEnd}`, ` ${red}+ {${colorEnd}`, @@ -68,6 +75,8 @@ const cases: readonly Case[] = [ name: 'plus diff is logged with plus(+) prefix and green(32) color', actual: {}, expected: { plus: 'plusValue' }, + numMinus: 3, + numPlus: 1, log: [ ` ${green}- {${colorEnd}`, ` ${green}- "plus": "plusValue"${colorEnd}`, @@ -80,6 +89,8 @@ const cases: readonly Case[] = [ name: 'can use undefined in actual', actual: { minus: 'minusValue' }, expected: undefined, + numMinus: 1, + numPlus: 3, log: [ ` ${green}- undefined${colorEnd}`, ` ${red}+ {${colorEnd}`, @@ -92,6 +103,8 @@ const cases: readonly Case[] = [ name: 'can use undefined in expected', actual: undefined, expected: { plus: 'plusValue' }, + numMinus: 3, + numPlus: 1, log: [ ` ${green}- {${colorEnd}`, ` ${green}- "plus": "plusValue"${colorEnd}`, @@ -104,6 +117,8 @@ const cases: readonly Case[] = [ name: 'can use undefined in actual', actual: { minus: 'minusValue' }, expected: undefined, + numPlus: 3, + numMinus: 1, log: [ ` ${green}- undefined${colorEnd}`, ` ${red}+ {${colorEnd}`, @@ -116,6 +131,8 @@ const cases: readonly Case[] = [ name: 'can use undefined in expected', actual: undefined, expected: { plus: 'plusValue' }, + numPlus: 1, + numMinus: 3, log: [ ` ${green}- {${colorEnd}`, ` ${green}- "plus": "plusValue"${colorEnd}`, @@ -128,6 +145,8 @@ const cases: readonly Case[] = [ name: 'can differentiate actual undefined and expected string "undefined"', actual: 'undefined', expected: undefined, + numPlus: 1, + numMinus: 1, log: [` ${green}- undefined${colorEnd}`, ` ${red}+ "undefined"${colorEnd}`], }, @@ -135,6 +154,8 @@ const cases: readonly Case[] = [ name: 'can differentiate actual string "undefined" and expected undefined', actual: undefined, expected: 'undefined', + numPlus: 1, + numMinus: 1, log: [` ${green}- "undefined"${colorEnd}`, ` ${red}+ undefined${colorEnd}`], }, ]; diff --git a/test/primitive.ts b/test/primitive.ts index d5668e17..5ad89c14 100644 --- a/test/primitive.ts +++ b/test/primitive.ts @@ -29,18 +29,6 @@ export const tests = [ assert: 10, }), - test({ - name: 'should be able to compare foobar', - act: task.of(['fo > ba', 'zz', 'ba']), - assert: ['foo > bar', 'zz', 'baz'], - }), - - test({ - name: 'should be able to compare aab', - act: task.of(['aacc']), - assert: ['aabccd'], - }), - test({ name: 'should return left when comparing functions', act: pipe(