UNPKG

@langchain/langgraph

Version:

LangGraph

181 lines 7.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const vitest_1 = require("vitest"); const runnables_1 = require("@langchain/core/runnables"); const write_js_1 = require("./write.cjs"); const constants_js_1 = require("../constants.cjs"); const errors_js_1 = require("../errors.cjs"); (0, vitest_1.describe)("ChannelWrite", () => { (0, vitest_1.it)("should write a value to a channel", async () => { // Setup write tracking const writes = []; // Mock config with send function const mockSend = vitest_1.vi .fn() .mockImplementation((values) => { writes.push(...values); }); const config = { configurable: { [constants_js_1.CONFIG_KEY_SEND]: mockSend, }, }; // Create a channel write const write = new write_js_1.ChannelWrite([ { channel: "output", value: "test_output" }, ]); // Run the write with input const result = await write.invoke("input_value", config); // Verify the input is passed through (0, vitest_1.expect)(result).toBe("input_value"); // Verify the write happened (0, vitest_1.expect)(writes).toEqual([["output", "test_output"]]); }); (0, vitest_1.it)("should support writing multiple channels", async () => { // Setup write tracking const writes = []; // Mock config with send function const mockSend = vitest_1.vi .fn() .mockImplementation((values) => { writes.push(...values); }); const config = { configurable: { [constants_js_1.CONFIG_KEY_SEND]: mockSend, }, }; // Create a channel write with multiple channels const write = new write_js_1.ChannelWrite([ { channel: "output1", value: "value1" }, { channel: "output2", value: "value2" }, ]); // Run the write with input await write.invoke("input_value", config); // Verify the writes happened (0, vitest_1.expect)(writes).toEqual([ ["output1", "value1"], ["output2", "value2"], ]); }); (0, vitest_1.it)("should support using PASSTHROUGH to pass input value to channel", async () => { // Setup write tracking const writes = []; // Mock config with send function const mockSend = vitest_1.vi .fn() .mockImplementation((values) => { writes.push(...values); }); const config = { configurable: { [constants_js_1.CONFIG_KEY_SEND]: mockSend, }, }; // Create a channel write with PASSTHROUGH const write = new write_js_1.ChannelWrite([{ channel: "output", value: write_js_1.PASSTHROUGH }]); // Run the write with input await write.invoke("input_value", config); // Verify the input value was written to the channel (0, vitest_1.expect)(writes).toEqual([["output", "input_value"]]); }); (0, vitest_1.it)("should support using mapper to transform value", async () => { // Setup write tracking const writes = []; // Mock config with send function const mockSend = vitest_1.vi .fn() .mockImplementation((values) => { writes.push(...values); }); const config = { configurable: { [constants_js_1.CONFIG_KEY_SEND]: mockSend, }, }; // Create a transformer as a Runnable const transformer = new runnables_1.RunnablePassthrough().pipe((value) => `transformed_${value}`); // Create a channel write with a mapper const write = new write_js_1.ChannelWrite([ { channel: "output", value: "original", mapper: transformer }, ]); // Run the write await write.invoke("input_value", config); // Verify the transformed value was written (0, vitest_1.expect)(writes).toEqual([["output", "transformed_original"]]); }); (0, vitest_1.it)("should support SKIP_WRITE to conditionally skip writing", async () => { // Setup write tracking const writes = []; // Mock config with send function const mockSend = vitest_1.vi .fn() .mockImplementation((values) => { writes.push(...values); }); const config = { configurable: { [constants_js_1.CONFIG_KEY_SEND]: mockSend, }, }; // Create a mapper that returns SKIP_WRITE const conditionalMapper = new runnables_1.RunnablePassthrough().pipe((_) => write_js_1.SKIP_WRITE); // Create a channel write with writes that should and shouldn't happen const write = new write_js_1.ChannelWrite([ { channel: "output1", value: "value1" }, { channel: "output2", value: "value2", mapper: conditionalMapper }, ]); // Run the write await write.invoke("input_value", config); // Verify only the first write happened (0, vitest_1.expect)(writes).toEqual([["output1", "value1"]]); }); (0, vitest_1.it)("should handle Send objects by writing to TASKS", async () => { // Setup write tracking const writes = []; // Mock config with send function const mockSend = vitest_1.vi .fn() .mockImplementation((values) => { writes.push(...values); }); const config = { configurable: { [constants_js_1.CONFIG_KEY_SEND]: mockSend, }, }; // Create a Send object const send = new constants_js_1.Send("target_node", { arg: "value" }); // Create a channel write with a Send const write = new write_js_1.ChannelWrite([send]); // Run the write await write.invoke("input_value", config); // Verify the Send was written to the TASKS channel (0, vitest_1.expect)(writes).toEqual([[constants_js_1.TASKS, send]]); }); (0, vitest_1.it)("should throw error when trying to write to reserved TASKS channel", async () => { // Create a channel write with an invalid channel const write = new write_js_1.ChannelWrite([{ channel: constants_js_1.TASKS, value: "value" }]); // Mock config with send function const config = { configurable: { [constants_js_1.CONFIG_KEY_SEND]: vitest_1.vi.fn(), }, }; // Verify it throws an error await (0, vitest_1.expect)(write.invoke("input_value", config)).rejects.toThrow(errors_js_1.InvalidUpdateError); await (0, vitest_1.expect)(write.invoke("input_value", config)).rejects.toThrow("Cannot write to the reserved channel TASKS"); }); }); (0, vitest_1.describe)("ChannelWrite static methods", () => { (0, vitest_1.it)("isWriter should identify ChannelWrite instances", () => { const write = new write_js_1.ChannelWrite([{ channel: "output", value: "value" }]); (0, vitest_1.expect)(write_js_1.ChannelWrite.isWriter(write)).toBe(true); }); (0, vitest_1.it)("registerWriter should mark a Runnable as a writer", () => { const runnable = new runnables_1.RunnablePassthrough(); const writer = write_js_1.ChannelWrite.registerWriter(runnable); (0, vitest_1.expect)(write_js_1.ChannelWrite.isWriter(writer)).toBe(true); }); }); //# sourceMappingURL=write.test.js.map