Files
ai-agent/web/lib/sdk/cs-ai-agent-sdk.test.mjs
T
mlogclub bd9fad68a7 refactor: update Kefu widget configuration to use dynamic user token retrieval
- Changed `userToken` property to `getUserToken` function in KefuWidgetHostConfig for dynamic token fetching.
- Introduced KefuWidgetRuntimeConfig to manage runtime-specific configurations.
- Updated readKefuWidgetConfig and setKefuWidgetConfig functions to accommodate new configuration structure.
- Enhanced cs-ai-agent-sdk.js to handle user token resolution and frame configuration.
- Added tests for dynamic user token retrieval in cs-ai-agent-sdk.test.mjs.
- Removed deprecated cs-agent-widget.js file as part of the refactor.
2026-05-06 18:19:49 +08:00

135 lines
3.4 KiB
JavaScript

import assert from "node:assert/strict"
import { readFile } from "node:fs/promises"
import test from "node:test"
import vm from "node:vm"
function createElement(tagName) {
return {
tagName,
children: [],
dataset: {},
style: {},
attributes: {},
listeners: {},
parentNode: null,
contentWindow: {},
setAttribute(name, value) {
this.attributes[name] = String(value)
},
appendChild(child) {
child.parentNode = this
this.children.push(child)
return child
},
removeChild(child) {
this.children = this.children.filter((item) => item !== child)
child.parentNode = null
return child
},
addEventListener(type, handler) {
this.listeners[type] = handler
},
click() {
this.listeners.click?.()
},
}
}
async function loadSdk(config) {
const source = await readFile(new URL("./cs-ai-agent-sdk.js", import.meta.url), "utf8")
const body = createElement("body")
const sandbox = {
URL,
console,
fetch: async () => ({
json: async () => ({
success: true,
data: {
title: "在线客服",
themeColor: "#2563eb",
},
}),
}),
document: {
body,
currentScript: {
src: "https://chat.example/sdk/cs-ai-agent-sdk.min.js",
},
createElement,
createElementNS: (_namespace, tagName) => createElement(tagName),
},
window: {
CSAgentConfig: config,
location: {
origin: "https://host.example",
},
addEventListener() {},
clearTimeout() {},
setTimeout(handler) {
handler()
return 1
},
},
}
sandbox.window.window = sandbox.window
sandbox.window.document = sandbox.document
sandbox.window.fetch = sandbox.fetch
sandbox.window.console = console
sandbox.window.URL = URL
sandbox.window.setTimeout = sandbox.window.setTimeout
sandbox.window.clearTimeout = sandbox.window.clearTimeout
vm.runInNewContext(source, sandbox)
await Promise.resolve()
await Promise.resolve()
return sandbox
}
async function flushPromises(count = 5) {
for (let i = 0; i < count; i += 1) {
await Promise.resolve()
}
}
test("getChatUrl resolves a fresh userToken for each call", async () => {
let calls = 0
const sandbox = await loadSdk({
channelId: "ch_1",
baseUrl: "https://api.example",
getUserToken: async () => `token_${++calls}`,
})
assert.equal(typeof sandbox.window.CSAgentWidget.getChatUrl, "function")
const first = await sandbox.window.CSAgentWidget.getChatUrl()
const second = await sandbox.window.CSAgentWidget.getChatUrl()
assert.equal(new URL(first).searchParams.get("userToken"), "token_1")
assert.equal(new URL(second).searchParams.get("userToken"), "token_2")
assert.equal(calls, 2)
})
test("launcher click creates chat iframe with a freshly resolved userToken", async () => {
const sandbox = await loadSdk({
channelId: "ch_1",
baseUrl: "https://api.example",
getUserToken: async () => "click_token",
})
await flushPromises()
const launcher = sandbox.document.body.children.find(
(child) => child.dataset.csAgentWidget === "launcher"
)
assert.ok(launcher)
launcher.click()
await flushPromises()
const frame = sandbox.document.body.children.find(
(child) => child.dataset.csAgentWidget === "frame"
)
assert.ok(frame)
assert.equal(new URL(frame.src).searchParams.get("userToken"), "click_token")
})