Files
trade-message-center/apps/chrome-extension/test/onetalk-quote-source-index.test.js
T
YBF 784bbec2a0 feat: 支持 OneTalk 文本引用回复协议 (#66)
* feat: add OneTalk quote reply support

* chore(task): archive 09-17-onetalk-quote-reply-protocol

* chore: record journal

* docs: format OneTalk DOM card collection plan

* chore: release 0.8.29

* chore: release 0.8.30
2026-09-17 11:56:35 +08:00

199 lines
6.7 KiB
JavaScript

// 验证 MAIN-only OneTalk 引用原始来源索引。
import assert from "node:assert/strict";
import test from "node:test";
import { createOneTalkQuoteSourceIndex } from "../src/onetalk/main-page/message-observer/quote-source-index.ts";
import { createHistoryMessageBatch } from "../src/onetalk/main-page/message-observer/history.ts";
import { parseOneTalkMessages } from "../src/onetalk/main-page/message-observer/index.ts";
const conversationId = "buyer-seller#tenant@icbu";
const observed = {
messageType: "history",
upstreamType: 1,
messageId: "123456",
conversationId,
senderId: "buyer@icbu",
direction: "received",
sentAtMs: 1_700_000_000_000,
content: { version: 1, kind: "text", text: "raw text" },
participantIds: ["buyer@icbu", "seller@icbu"],
readStatus: 0,
messageStatus: 1,
unreadCount: 0,
};
const rawMessage = {
messageId: 123456,
conversationCode: conversationId,
subType: 1,
messageType: "rec",
sender: { targetId: "buyer" },
contact: { name: "Buyer" },
originalData: { text: "raw text", sdkOnly: "kept-main-only" },
sendTime: 1_700_000_000_000,
};
const pageWindow = (accountId = "account-1") => ({
location: { href: "https://onetalk.alibaba.com/" },
currentUserAccountId: accountId,
});
test("resolves a verified raw text source into the SDK-only quote input", () => {
const index = createOneTalkQuoteSourceIndex();
const page = pageWindow();
index.register(page, rawMessage, observed);
assert.deepEqual(index.lookup(page, conversationId, "123456"), {
msgId: "123456.PNM",
subType: 1,
senderAliId: "buyer",
senderName: "Buyer",
contentAbstract: "raw text",
originalData: { text: "raw text", sdkOnly: "kept-main-only" },
sendTime: 1_700_000_000_000,
});
assert.equal(index.lookup(page, conversationId, "123456.PNM"), null);
});
test("uses the owner name for a verified outgoing text quote source", () => {
const index = createOneTalkQuoteSourceIndex();
const page = pageWindow();
index.register(
page,
{
messageId: "outgoing-1",
cid: conversationId,
subType: 1,
messageType: "send",
sender: { targetId: "seller" },
owner: { name: "Seller" },
originalData: { text: "outgoing raw text" },
createAt: 1_700_000_000_010,
},
{
messageType: "new",
upstreamType: 1,
messageId: "outgoing-1",
conversationId,
senderId: "seller@icbu",
direction: "sent",
sentAtMs: 1_700_000_000_010,
content: { version: 1, kind: "text", text: "outgoing raw text" },
participantIds: ["buyer@icbu", "seller@icbu"],
readStatus: 0,
messageStatus: 1,
unreadCount: 0,
},
);
assert.equal(index.lookup(page, conversationId, "outgoing-1")?.senderName, "Seller");
});
test("rejects incomplete, mismatched, cross-conversation, and account-switched quote sources", () => {
const index = createOneTalkQuoteSourceIndex();
const page = pageWindow();
index.register(page, { ...rawMessage, originalData: { text: "" } }, observed);
assert.equal(index.lookup(page, conversationId, "123456"), null);
index.register(page, rawMessage, observed);
assert.equal(index.lookup(page, "other-conversation", "123456"), null);
assert.equal(index.lookup(pageWindow("account-2"), conversationId, "123456"), null);
});
test("registers only validated text sources from both history and live parsers", () => {
const index = createOneTalkQuoteSourceIndex();
const page = {
...pageWindow(),
__conversationListFullData__: [{ owner: { accountId: "account-1", aliId: "seller" } }],
};
const historyRaw = {
...rawMessage,
type: 1,
msgType: 101,
status: 1,
unread: 0,
content: "SDK display text",
};
const history = createHistoryMessageBatch([historyRaw], page, undefined, index);
assert.equal(history.messages.length, 1);
assert.equal(index.lookup(page, conversationId, "123456")?.msgId, "123456.PNM");
const liveRaw = {
messageId: "live-1",
cid: conversationId,
createAt: 1_700_000_000_001,
subType: 1,
messageType: "rec",
sender: { uid: "buyer@icbu", targetId: "buyer" },
contact: { name: "Buyer" },
originalData: { text: "live raw text" },
content: { contentType: 1, text: { content: "live raw text" } },
unreadCount: 0,
};
const live = parseOneTalkMessages(
page,
JSON.stringify({
code: 200,
body: [
{
singleChatUserConversation: {
lastMessage: { message: liveRaw, readStatus: 0, msgStatus: 1 },
singleChatConversation: {
pairFirst: "buyer@icbu",
pairSecond: "seller@icbu",
},
},
},
],
}),
index,
);
assert.equal(live.messages.length, 1);
assert.equal(index.lookup(page, conversationId, "live-1")?.contentAbstract, "live raw text");
});
test("registers a live text source when the live envelope omits the history messageType", () => {
const index = createOneTalkQuoteSourceIndex();
const page = {
...pageWindow(),
__conversationListFullData__: [{ owner: { accountId: "account-1", aliId: "seller" } }],
};
const liveRaw = {
type: 1,
messageId: "live-without-message-type",
cid: conversationId,
createAt: 1_700_000_000_001,
subType: 1,
sender: { uid: "buyer@icbu", targetId: "buyer" },
contact: { name: "Buyer" },
originalData: { text: "live raw text" },
content: { contentType: 1, text: { content: "live raw text" } },
unreadCount: 0,
};
const live = parseOneTalkMessages(
page,
JSON.stringify({
code: 200,
body: [
{
singleChatUserConversation: {
lastMessage: { message: liveRaw, readStatus: 0, msgStatus: 1 },
singleChatConversation: {
pairFirst: "buyer@icbu",
pairSecond: "seller@icbu",
},
},
},
],
}),
index,
);
assert.equal(live.messages.length, 1);
assert.equal(
index.lookup(page, conversationId, "live-without-message-type")?.msgId,
"live-without-message-type",
);
});