Created
March 20, 2026 16:10
-
-
Save 5cover/fd4e136a16b33c82a18a55b0e11ce122 to your computer and use it in GitHub Desktop.
format testing.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { expect, describe, it } from 'bun:test'; | |
| import jsonVariantsHandler, { JSON_VARIANTS, variantToFormat } from '../../src/handlers/jsonVariants.js'; | |
| import CommonFormats from '../../src/CommonFormats.ts'; | |
| import { FileFormat } from '../../src/FormatHandler.js'; | |
| describe('jsonVariants', () => { | |
| const encoder = new TextEncoder(); | |
| const decoder = new TextDecoder(); | |
| const jsonFormat = CommonFormats.JSON.supported('json', true, true, true); | |
| const basenames = { | |
| vals: ['', '.', '..', 'file', 'file.dots'] as const, | |
| at(i: number) { | |
| return this.vals[i % this.vals.length]; | |
| }, | |
| }; | |
| type Variant = keyof typeof JSON_VARIANTS; | |
| type TestContext = { handler: jsonVariantsHandler; variantFormat: FileFormat; i: number }; | |
| type Transform = (ctx: TestContext, cases: readonly [string, PositiveCase][]) => Promise<void>; | |
| // have a case for each identifiable distinct statement on what is supported | |
| type PositiveCase = { | |
| content: string; | |
| value: unknown; | |
| // the canonical representation of content. defaults to content if unspecified. | |
| // e.g. specify with the minified representation of content contains formatting | |
| canonical?: string; | |
| }; | |
| type NegativeCase = { content: string; error: ErrorConstructor }; | |
| interface TestCases { | |
| positive: Record<string, PositiveCase>; | |
| negative: Record<string, NegativeCase>; | |
| } | |
| const testCases = { | |
| json5: { | |
| positive: { | |
| 'basic object 1': { | |
| content: `{ | |
| // comment | |
| unquoted: 'value', | |
| trailing: [1, 2,], | |
| }`, | |
| value: { | |
| unquoted: 'value', | |
| trailing: [1, 2], | |
| }, | |
| canonical: "{unquoted:'value',trailing:[1,2]}", | |
| }, | |
| 'basic object 2': { | |
| content: '{"enabled":true,"nested":{"value":3}}', | |
| value: { | |
| enabled: true, | |
| nested: { value: 3 }, | |
| }, | |
| canonical: '{enabled:true,nested:{value:3}}', | |
| }, | |
| }, | |
| negative: {}, | |
| }, | |
| } as const satisfies Record<Variant, TestCases>; | |
| const transforms = { | |
| parses: [parse, stringify], | |
| roundtrips: [stringify, parse, stringify], | |
| minifies: [parse, stringify, parse], | |
| idempotence: [parse, parse, parse, stringify, stringify, stringify], | |
| } as const satisfies Record<string, Transform[]>; | |
| Object.entries(testCases).forEach(([variantKey, testCase], i) => { | |
| const variant = JSON_VARIANTS[variantKey as Variant]; | |
| const variantFormat = variantToFormat([variantKey, variant]); | |
| Object.entries(transforms).forEach(([transformKey, transforms], j) => | |
| describe(`${variantKey}: ${transformKey}`, () => { | |
| testPositive( | |
| { | |
| handler: new jsonVariantsHandler(), | |
| i: i + j, | |
| variantFormat, | |
| }, | |
| Object.entries(testCase.positive), | |
| transforms | |
| ); | |
| }) | |
| ); | |
| }); | |
| async function testPositive( | |
| ctx: TestContext, | |
| cases: readonly [string, PositiveCase][], | |
| transforms: readonly Transform[] | |
| ) { | |
| for (const t of transforms) { | |
| describe(t.name, () => t(ctx, cases)); | |
| } | |
| } | |
| // convert Variant -> JSON | |
| async function parse(ctx: TestContext, cases: readonly [string, PositiveCase][]) { | |
| ( | |
| await ctx.handler.doConvert( | |
| cases.map(([, { content }], i) => ({ | |
| name: `${basenames.at(ctx.i + i)}.json`, | |
| bytes: encoder.encode(content), | |
| })), | |
| ctx.variantFormat, | |
| jsonFormat | |
| ) | |
| ).forEach((output, i) => | |
| it(cases[i][0], () => { | |
| expect(output.name).toBe(`${basenames.at(ctx.i + i)}.json`); | |
| const value = JSON.parse(decoder.decode(output.bytes)) as unknown; | |
| expect(value).toEqual(cases[i][1].value); | |
| }) | |
| ); | |
| } | |
| // convert JSON -> Variant | |
| async function stringify(ctx: TestContext, cases: readonly [string, PositiveCase][]) { | |
| return ( | |
| await ctx.handler.doConvert( | |
| cases.map(([, { value }], i) => ({ | |
| name: `${basenames.at(ctx.i + i)}.json`, | |
| bytes: encoder.encode(JSON.stringify(value)), | |
| })), | |
| jsonFormat, | |
| ctx.variantFormat | |
| ) | |
| ).forEach((output, i) => | |
| it(cases[i][0], () => { | |
| expect(output.name).toBe(`${basenames.at(ctx.i + i)}.${ctx.variantFormat.extension}`); | |
| const content = decoder.decode(output.bytes); | |
| expect(content).toBe(cases[i][1].canonical ?? cases[i][1].content); | |
| }) | |
| ); | |
| } | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment