import { afterEach, describe, expect, it, vi } from "vitest"; const { executeAddressMcpQueryMock } = vi.hoisted(() => ({ executeAddressMcpQueryMock: vi.fn() })); vi.mock("../src/services/addressMcpClient", async () => { const actual = await vi.importActual( "../src/services/addressMcpClient" ); return { ...actual, executeAddressMcpQuery: executeAddressMcpQueryMock }; }); import { AddressQueryService } from "../src/services/addressQueryService"; afterEach(() => { executeAddressMcpQueryMock.mockReset(); vi.restoreAllMocks(); }); describe("implicit self-scope stock snapshot", () => { it("does not turn 'у нас' into a literal warehouse anchor", async () => { executeAddressMcpQueryMock.mockResolvedValueOnce({ fetched_rows: 1, matched_rows: 1, raw_rows: [ { Period: "2026-04-15T23:59:59Z", Registrator: "Остатки товаров на складах", AccountDt: "41.01", AccountKt: "00.00", Amount: 498472.5, Quantity: 3, SubcontoDt1: "Конструкция трансформер рабочей станции 1300*900*2000", Warehouse: "Основной склад", Organization: 'ООО "Альтернатива Плюс"' } ], rows: [], error: null }); const service = new AddressQueryService(); const result = await service.tryHandle("что на складе у нас"); expect(result?.handled).toBe(true); expect(result?.reply_type).toBe("factual"); expect(result?.response_type).toBe("FACTUAL_LIST"); expect(result?.debug.detected_intent).toBe("inventory_on_hand_as_of_date"); expect(result?.debug.selected_recipe).toBe("address_inventory_on_hand_as_of_date_v1"); expect(result?.debug.mcp_call_status).toBe("matched_non_empty"); expect(result?.debug.extracted_filters?.warehouse).toBeUndefined(); expect(result?.debug.as_of_date_basis).toBe("implicit_current_snapshot"); expect(result?.debug.semantic_frame?.scope_kind).toBe("implicit_self_scope"); expect(result?.debug.semantic_frame?.anchor_kind).toBe("self_scope"); expect(result?.debug.semantic_frame?.date_scope_kind).toBe("implicit_current"); expect(String(result?.reply_text ?? "")).toContain("Конструкция трансформер рабочей станции 1300*900*2000"); expect(executeAddressMcpQueryMock).toHaveBeenCalledTimes(1); }); it("grounds implicit self-scope to active organization when one is in focus", async () => { executeAddressMcpQueryMock.mockResolvedValueOnce({ fetched_rows: 1, matched_rows: 1, raw_rows: [ { Period: "2026-04-15T23:59:59Z", Registrator: "Остатки товаров на складах", AccountDt: "41.01", AccountKt: "00.00", Amount: 34490, Quantity: 1, SubcontoDt1: "Диван трехместный", Warehouse: "Основной склад", Organization: 'ООО "Альтернатива Плюс"' } ], rows: [], error: null }); const service = new AddressQueryService(); const result = await service.tryHandle("что на складе у нас", { activeOrganization: "ООО Альтернатива Плюс", knownOrganizations: ["ООО Альтернатива Плюс", "ООО Лайсвуд"] }); expect(result?.handled).toBe(true); expect(result?.debug.extracted_filters?.organization).toBe("ООО Альтернатива Плюс"); expect(result?.debug.semantic_frame?.scope_kind).toBe("implicit_self_scope"); expect(result?.debug.semantic_frame?.anchor_kind).toBe("self_scope"); expect(result?.debug.reasons).toContain("organization_from_active_scope"); expect(String(result?.reply_text ?? "")).toContain("Диван трехместный"); }); });