// SPDX-FileCopyrightText: 2026 Kerstin Humm // // SPDX-License-Identifier: AGPL-3.0-or-later import { describe, expect, test } from "vitest"; import { annotateAt, AnnotatedJson, Annotation, getPath, JsonPath, JsonValue, mergeAnnotatedJson, Result, } from "./types.js"; const annotationA: Annotation = { kind: "Violation", id: "A", text: "Some text", }; const annotationB: Annotation = { kind: "Warning", id: "B", text: "Some other text", }; describe("mergeAnnotatedJson", () => { const tests: { a: AnnotatedJson; b: AnnotatedJson; path?: JsonPath; merge: Result; }[] = [ { a: annotationA, b: annotationB, merge: { ok: true, value: [annotationA, annotationB] }, }, { a: [annotationA], b: [annotationB], merge: { ok: true, value: [annotationA, annotationB] }, }, { a: annotationA, b: [annotationB], merge: { ok: true, value: [annotationA, annotationB] }, }, { a: [annotationA], b: annotationB, merge: { ok: true, value: [annotationA, annotationB] }, }, { a: { annotations: [], object: { "some": [annotationA] } }, b: { annotations: [], object: { "some": annotationB } }, merge: { ok: true, value: { annotations: [], object: { "some": [annotationA, annotationB] }, }, }, }, { a: { annotations: [], object: {} }, b: { annotations: [], object: { "some": annotationB } }, merge: { ok: true, value: { annotations: [], object: { "some": [annotationB] }, }, }, }, { a: { annotations: [], object: { "some": annotationA } }, b: { annotations: [], object: { "other": annotationB } }, merge: { ok: true, value: { annotations: [], object: { "some": [annotationA], "other": [annotationB] }, }, }, }, { a: { annotations: [], object: { "some": annotationA } }, b: { annotations: [], object: {} }, merge: { ok: true, value: { annotations: [], object: { "some": [annotationA] }, }, }, }, { a: { annotations: [], array: [annotationA] }, b: { annotations: [], array: [annotationB] }, merge: { ok: true, value: { annotations: [], array: [annotationA, annotationB] }, }, }, { a: { annotations: [], array: [annotationA] }, b: { annotations: [], array: [{ annotations: [], array: [annotationB] }], }, merge: { ok: true, value: { annotations: [], array: [annotationA, { annotations: [], array: [annotationB] }], }, }, }, { a: { annotations: [], object: { "some": [annotationA] } }, b: { annotations: [], array: [annotationB] }, merge: { ok: false, error: "Can't merge as types differ: object, array" }, }, { a: { annotations: [], array: [annotationA] }, b: annotationB, path: [0], merge: { ok: true, value: { annotations: [], array: [[annotationA, annotationB], annotationA], }, }, }, ]; tests.forEach(({ a, b, path, merge }) => { test(JSON.stringify(merge), () => { expect(mergeAnnotatedJson(a, b, path ? path : [])).toStrictEqual(merge); }); }); }); describe("getPath", () => { const tests: { data: JsonValue; path: JsonPath; result: Result; }[] = [ { data: { "a": { "b": 2 } }, path: ["a"], result: { ok: true, value: { "b": 2 } }, }, { data: { "a": 2 }, path: [1], result: { ok: false, error: '{"a":2} is not an Array' }, }, { data: { "a": 2 }, path: ["b"], result: { ok: false, error: '{"a":2} doesn\'t have name "b"' }, }, { data: [true, false], path: [1], result: { ok: true, value: false }, }, { data: [true, false], path: [3], result: { ok: false, error: "3 isn't a correct index in [true,false]" }, }, ]; tests.forEach(({ data, path, result }) => { test(JSON.stringify(result), () => { expect(getPath(data, path)).toStrictEqual(result); }); }); }); describe("annotateAt", () => { const tests: { annotated: AnnotatedJson; path: JsonPath; annotation: Annotation; result: Result; }[] = [ { annotated: [], path: [], annotation: annotationA, result: { ok: true, value: annotationA }, }, { annotated: { annotations: [], object: { "a": annotationA } }, path: [], annotation: annotationB, result: { ok: true, value: { annotations: [annotationB], object: { "a": annotationA } }, }, }, { annotated: { annotations: [], array: [annotationA] }, path: [], annotation: annotationB, result: { ok: true, value: { annotations: [annotationB], array: [annotationA] }, }, }, { annotated: { annotations: [], array: [annotationA] }, path: [1], annotation: annotationB, result: { ok: true, value: { annotations: [], array: [annotationA, annotationB] }, }, }, { annotated: { annotations: [], object: { "a": annotationA } }, path: ["b"], annotation: annotationB, result: { ok: true, value: { annotations: [], object: { "a": annotationA, "b": annotationB }, }, }, }, ]; tests.forEach(({ annotated, path, annotation, result }) => { test(JSON.stringify(result), () => { expect(annotateAt(annotated, path, annotation)).toStrictEqual(result); }); }); });