"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// Neo4j envelope-warning passthrough.
//
// Pure-function tests for the helpers in cypher-shim-read.ts:
//   - filterEnvelopeNotifications: keeps only ^0[12]N5\d$ GQL status codes
//   - stitchWarningsIntoResponse:  prepends a warnings content block
//   - runReadProbe:                runs cypher through a shim-side session
//                                  and returns notifications from the summary
//
// Failure mode this closes: the agent ran `RETURN h.hostname` against a node
// whose property is `hostnameValue`, Neo4j emitted gql_status=01N52
// "property does not exist", but the warning was dropped by the upstream
// envelope and the agent saw `[]`. Without these warnings reaching the tool
// result, the same recurrence will hit other property names too.
const node_test_1 = __importDefault(require("node:test"));
const strict_1 = __importDefault(require("node:assert/strict"));
const cypher_shim_read_js_1 = require("../cypher-shim-read.js");
(0, node_test_1.default)("filterEnvelopeNotifications keeps 01N5x and 02N5x, drops everything else", () => {
    const input = [
        { gqlStatus: "01N52", title: "...", description: "property does not exist (foo)", position: { offset: 0, line: 1, column: 1 } },
        { gqlStatus: "02N50", title: "...", description: "label does not exist (Foo)", position: null },
        { gqlStatus: "01N40", title: "...", description: "wrong family", position: null },
        { gqlStatus: "03N42", title: "...", description: "unrelated", position: null },
        { gqlStatus: "00N00", title: "...", description: "neutral status", position: null },
    ];
    const filtered = (0, cypher_shim_read_js_1.filterEnvelopeNotifications)(input);
    strict_1.default.equal(filtered.length, 2);
    strict_1.default.equal(filtered[0].gql_status, "01N52");
    strict_1.default.equal(filtered[0].description, "property does not exist (foo)");
    strict_1.default.deepEqual(filtered[0].position, { offset: 0, line: 1, column: 1 });
    strict_1.default.equal(filtered[1].gql_status, "02N50");
    strict_1.default.equal(filtered[1].position, null);
});
(0, node_test_1.default)("filterEnvelopeNotifications on an empty or all-irrelevant list returns []", () => {
    strict_1.default.deepEqual((0, cypher_shim_read_js_1.filterEnvelopeNotifications)([]), []);
    strict_1.default.deepEqual((0, cypher_shim_read_js_1.filterEnvelopeNotifications)([
        { gqlStatus: "03N42", title: "", description: "", position: null },
        { gqlStatus: "01N40", title: "", description: "", position: null },
    ]), []);
});
(0, node_test_1.default)("stitchWarningsIntoResponse prepends a warnings content block when warnings exist", () => {
    const original = {
        jsonrpc: "2.0",
        id: 42,
        result: { content: [{ type: "text", text: "[]" }] },
    };
    const warnings = [
        { gql_status: "01N52", description: "property hostname does not exist", position: null },
    ];
    const out = (0, cypher_shim_read_js_1.stitchWarningsIntoResponse)(original, warnings);
    strict_1.default.notEqual(out, null);
    const parsed = JSON.parse(out);
    strict_1.default.equal(parsed.id, 42);
    strict_1.default.equal(parsed.result.content.length, 2);
    strict_1.default.equal(parsed.result.content[0].type, "text");
    strict_1.default.match(parsed.result.content[0].text, /Neo4j envelope warnings/);
    strict_1.default.match(parsed.result.content[0].text, /01N52/);
    strict_1.default.match(parsed.result.content[0].text, /property hostname does not exist/);
    // Original row block preserved verbatim, after the warnings prefix.
    strict_1.default.equal(parsed.result.content[1].text, "[]");
});
(0, node_test_1.default)("stitchWarningsIntoResponse returns null when no warnings (no envelope rewrite)", () => {
    const original = { jsonrpc: "2.0", id: 1, result: { content: [{ type: "text", text: "[]" }] } };
    strict_1.default.equal((0, cypher_shim_read_js_1.stitchWarningsIntoResponse)(original, []), null);
});
(0, node_test_1.default)("stitchWarningsIntoResponse handles missing result.content defensively", () => {
    const original = { jsonrpc: "2.0", id: 1, result: {} };
    const warnings = [{ gql_status: "01N52", description: "x", position: null }];
    const out = (0, cypher_shim_read_js_1.stitchWarningsIntoResponse)(original, warnings);
    strict_1.default.notEqual(out, null);
    const parsed = JSON.parse(out);
    strict_1.default.equal(parsed.result.content.length, 1);
    strict_1.default.match(parsed.result.content[0].text, /01N52/);
});
(0, node_test_1.default)("runReadProbe returns notifications captured from the driver summary", async () => {
    const session = {
        run: async () => ({
            summary: {
                notifications: [
                    { gqlStatus: "01N52", title: "", description: "missing prop", position: null },
                ],
            },
        }),
        close: async () => { },
    };
    const driver = { session: () => session };
    const notifs = await (0, cypher_shim_read_js_1.runReadProbe)(driver, "MATCH (n) RETURN n.foo", {});
    strict_1.default.equal(notifs.length, 1);
    strict_1.default.equal(notifs[0].gqlStatus, "01N52");
});
(0, node_test_1.default)("runReadProbe returns [] when driver summary has no notifications", async () => {
    const session = {
        run: async () => ({ summary: {} }),
        close: async () => { },
    };
    const driver = { session: () => session };
    strict_1.default.deepEqual(await (0, cypher_shim_read_js_1.runReadProbe)(driver, "RETURN 1", {}), []);
});
(0, node_test_1.default)("runReadProbe closes the session even when run() throws", async () => {
    let closed = false;
    const session = {
        run: async () => {
            throw new Error("boom");
        },
        close: async () => {
            closed = true;
        },
    };
    const driver = { session: () => session };
    await strict_1.default.rejects(() => (0, cypher_shim_read_js_1.runReadProbe)(driver, "RETURN 1", {}));
    strict_1.default.equal(closed, true, "session must be closed on error");
});
(0, node_test_1.default)("end-to-end: filter + stitch on a real-shape upstream response surfaces 01N52", () => {
    // Models the failure mode in the original log: upstream returned an empty
    // row list; Neo4j attached an 01N52 notification that the upstream Python
    // server dropped.
    const upstreamResponse = {
        jsonrpc: "2.0",
        id: 99,
        result: { content: [{ type: "text", text: "[]" }] },
    };
    const driverNotifications = [
        {
            gqlStatus: "01N52",
            title: "Property does not exist",
            description: "The property 'hostname' does not exist on the node",
            position: { offset: 38, line: 1, column: 39 },
        },
    ];
    const warnings = (0, cypher_shim_read_js_1.filterEnvelopeNotifications)(driverNotifications);
    const stitched = (0, cypher_shim_read_js_1.stitchWarningsIntoResponse)(upstreamResponse, warnings);
    const parsed = JSON.parse(stitched);
    strict_1.default.match(parsed.result.content[0].text, /01N52/);
    strict_1.default.match(parsed.result.content[0].text, /hostname/);
});
//# sourceMappingURL=warnings-envelope.test.js.map