mirror of
https://github.com/sinanyuntu/trade-message-center.git
synced 2026-09-17 13:22:11 +08:00
* 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
696 lines
23 KiB
JavaScript
696 lines
23 KiB
JavaScript
// 验证 OneTalk SPA 当前会话身份和 PWA 出站入口
|
|
|
|
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import { handleOneTalkSendCommand } from "../src/onetalk/main-page/commands/send.ts";
|
|
import { handleOneTalkHistoryCommand } from "../src/onetalk/main-page/current-conversation-history/page-command.ts";
|
|
import {
|
|
readCurrentConversationId,
|
|
readSelectedConversationIds,
|
|
} from "../src/onetalk/main-page/page-context.ts";
|
|
import { createHistoryMessageBatch } from "../src/onetalk/main-page/message-observer/history.ts";
|
|
import { installCurrentConversationHistorySync } from "../src/onetalk/main-page/current-conversation-history/entry.ts";
|
|
import { createSendObservationCorrelator } from "../src/onetalk/main-page/message-observer/send-observation.ts";
|
|
import { createOneTalkQuoteSourceIndex } from "../src/onetalk/main-page/message-observer/quote-source-index.ts";
|
|
import { installOneTalkMainPageBridge } from "../src/onetalk/page-bridge/main.ts";
|
|
import {
|
|
createOneTalkPageObservedMessage,
|
|
decodeOneTalkPageMessage,
|
|
ONE_TALK_PAGE_BRIDGE_VERSION,
|
|
} from "../src/onetalk/page-bridge/model.ts";
|
|
|
|
const pageOrigin = "https://onetalk.alibaba.com";
|
|
|
|
const selectedElement = (conversationId) => ({
|
|
getAttribute: (name) => (name === "data-cid" ? conversationId : null),
|
|
});
|
|
|
|
const createSendPage = (selectedIds = ["conversation-1"]) => {
|
|
const calls = [];
|
|
const rejectedCalls = [];
|
|
const selectors = [];
|
|
const selection = { ids: [...selectedIds] };
|
|
const messageService = {
|
|
sendUIMessages: async (input) => {
|
|
calls.push(input);
|
|
return { opId: "local-acceptance" };
|
|
},
|
|
sendMessage: () => rejectedCalls.push("sendMessage"),
|
|
sendTextMessage: () => rejectedCalls.push("sendTextMessage"),
|
|
};
|
|
const pageWindow = {
|
|
location: {
|
|
href: `${pageOrigin}/?activeAccountId=account-1&conversationId=url-value`,
|
|
},
|
|
currentUserAccountId: "login-account-1",
|
|
document: {
|
|
querySelectorAll: (selector) => {
|
|
selectors.push(selector);
|
|
return selection.ids.map(selectedElement);
|
|
},
|
|
addEventListener: () => {},
|
|
},
|
|
IcbuIM: {
|
|
IMBaaSSDK: {
|
|
default: {
|
|
getMessageService: () => messageService,
|
|
},
|
|
},
|
|
},
|
|
};
|
|
return { pageWindow, selection, calls, rejectedCalls, selectors };
|
|
};
|
|
|
|
const sendCommand = (conversationId = "conversation-1", text = "hello") => ({
|
|
command: { action: "onetalk.send", conversationId, content: { kind: "text", text } },
|
|
});
|
|
|
|
const handleSendCommand = (pageWindow, message = sendCommand()) =>
|
|
handleOneTalkSendCommand(pageWindow, message, createSendObservationCorrelator(1));
|
|
|
|
const createHistorySyncPage = () => {
|
|
const conversation = {
|
|
cid: "buyer-seller#tenant@icbu",
|
|
lastContactTimeLong: 1_700_000_000_001,
|
|
accountId: "buyer-account",
|
|
accountIdEncrypt: "buyer-encrypt",
|
|
aliId: "buyer",
|
|
};
|
|
const flatItem = {
|
|
messageId: 123456,
|
|
conversationCode: conversation.cid,
|
|
sendTime: 1_700_000_000_000,
|
|
msgType: 101,
|
|
type: 1,
|
|
subType: 1,
|
|
messageType: "rec",
|
|
status: 1,
|
|
unread: 2,
|
|
sender: { targetId: "buyer" },
|
|
content: "SDK display text is not canonical history content",
|
|
originalData: { text: "Order draft notification" },
|
|
localizedUiText: "订单草稿通知",
|
|
dataOriginal: "not-json",
|
|
};
|
|
const posted = [];
|
|
const events = [];
|
|
let historyFailure = false;
|
|
const messageService = {
|
|
fetchMessagesWithoutUpdateToRead: async () => {
|
|
if (historyFailure) throw new Error("onetalk_history_message_request_failed");
|
|
return {
|
|
code: 200,
|
|
body: { list: [flatItem], hasMore: 0 },
|
|
};
|
|
},
|
|
};
|
|
const pageWindow = {
|
|
location: {
|
|
href: "https://onetalk.alibaba.com/?activeAccountId=buyer",
|
|
origin: "https://onetalk.alibaba.com",
|
|
},
|
|
currentUserAccountId: "login-account-1",
|
|
__conversationListFullData__: [
|
|
{ owner: { accountId: "login-account-1", aliId: "seller" } },
|
|
],
|
|
addEventListener: () => {},
|
|
postMessage: (message, targetOrigin) => {
|
|
posted.push({ message, targetOrigin });
|
|
events.push("progress");
|
|
},
|
|
IcbuIM: {
|
|
IMBaaSSDK: {
|
|
default: {
|
|
getConversationServiceV2: () => ({
|
|
getConversationListByPagination: async () => ({
|
|
list: [conversation],
|
|
hasMore: false,
|
|
}),
|
|
}),
|
|
getMessageService: () => messageService,
|
|
},
|
|
},
|
|
},
|
|
};
|
|
return {
|
|
flatItem,
|
|
pageWindow,
|
|
posted,
|
|
events,
|
|
failHistory: () => {
|
|
historyFailure = true;
|
|
},
|
|
};
|
|
};
|
|
|
|
test("reads selected SPA DOM data-cid instead of URL conversationId", () => {
|
|
const { pageWindow, selectors } = createSendPage(["dom-conversation"]);
|
|
|
|
assert.deepEqual(readSelectedConversationIds(pageWindow), ["dom-conversation"]);
|
|
assert.equal(readCurrentConversationId(pageWindow), "dom-conversation");
|
|
assert.deepEqual(selectors, [
|
|
".contact-item-container.selected[data-cid]",
|
|
".contact-item-container.selected[data-cid]",
|
|
]);
|
|
});
|
|
|
|
test("calls sendUIMessages once with the verified input and never treats opId as confirmed", async () => {
|
|
const { pageWindow, calls, rejectedCalls } = createSendPage();
|
|
|
|
const result = await handleSendCommand(pageWindow);
|
|
|
|
assert.deepEqual(result, {
|
|
status: "delivery_unknown",
|
|
reason: "send_state_lost",
|
|
});
|
|
assert.deepEqual(calls, [
|
|
{ cid: "conversation-1", conversationCode: "conversation-1", content: "hello" },
|
|
]);
|
|
assert.deepEqual(rejectedCalls, []);
|
|
});
|
|
|
|
test("passes a MAIN-only raw text quote as a top-level SDK referMessage", async () => {
|
|
const { pageWindow, calls } = createSendPage();
|
|
const quoteSources = createOneTalkQuoteSourceIndex();
|
|
quoteSources.register(
|
|
pageWindow,
|
|
{
|
|
messageId: 123456,
|
|
conversationCode: "conversation-1",
|
|
subType: 1,
|
|
messageType: "rec",
|
|
sender: { targetId: "buyer" },
|
|
contact: { name: "Buyer" },
|
|
originalData: { text: "quoted raw text" },
|
|
sendTime: 1_700_000_000_000,
|
|
},
|
|
{
|
|
messageType: "history",
|
|
upstreamType: 1,
|
|
messageId: "123456",
|
|
conversationId: "conversation-1",
|
|
senderId: "buyer@icbu",
|
|
direction: "received",
|
|
sentAtMs: 1_700_000_000_000,
|
|
content: { version: 1, kind: "text", text: "quoted raw text" },
|
|
participantIds: ["buyer@icbu", "seller@icbu"],
|
|
readStatus: 0,
|
|
messageStatus: 1,
|
|
unreadCount: 0,
|
|
},
|
|
);
|
|
|
|
assert.deepEqual(
|
|
await handleOneTalkSendCommand(
|
|
pageWindow,
|
|
{
|
|
command: {
|
|
action: "onetalk.send",
|
|
conversationId: "conversation-1",
|
|
content: { kind: "text", text: "reply" },
|
|
replyToMessageId: "123456",
|
|
},
|
|
},
|
|
createSendObservationCorrelator(1),
|
|
quoteSources,
|
|
),
|
|
{ status: "delivery_unknown", reason: "send_state_lost" },
|
|
);
|
|
assert.deepEqual(calls, [
|
|
{
|
|
cid: "conversation-1",
|
|
conversationCode: "conversation-1",
|
|
content: "reply",
|
|
referMessage: {
|
|
msgId: "123456.PNM",
|
|
subType: 1,
|
|
senderAliId: "buyer",
|
|
senderName: "Buyer",
|
|
contentAbstract: "quoted raw text",
|
|
originalData: { text: "quoted raw text" },
|
|
sendTime: 1_700_000_000_000,
|
|
},
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("rejects missing and non-text quote sources before invoking the SDK", async () => {
|
|
const { pageWindow, calls } = createSendPage();
|
|
const quoteSources = createOneTalkQuoteSourceIndex();
|
|
for (const command of [
|
|
{
|
|
action: "onetalk.send",
|
|
conversationId: "conversation-1",
|
|
content: { kind: "text", text: "reply" },
|
|
replyToMessageId: "missing",
|
|
},
|
|
{
|
|
action: "onetalk.send",
|
|
conversationId: "conversation-1",
|
|
content: {
|
|
kind: "image",
|
|
source: {
|
|
downloadUrl: "https://mind.example.test/bridge/image-1",
|
|
fileName: "image.jpg",
|
|
mimeType: "image/jpeg",
|
|
},
|
|
},
|
|
replyToMessageId: "123456",
|
|
},
|
|
]) {
|
|
assert.deepEqual(
|
|
await handleOneTalkSendCommand(
|
|
pageWindow,
|
|
{ command },
|
|
createSendObservationCorrelator(1),
|
|
quoteSources,
|
|
),
|
|
{ status: "rejected_before_send", reason: "invalid_request" },
|
|
);
|
|
}
|
|
assert.deepEqual(calls, []);
|
|
});
|
|
|
|
test("does not use selected conversation as a send gate", async () => {
|
|
const empty = createSendPage([]);
|
|
assert.deepEqual(await handleSendCommand(empty.pageWindow), {
|
|
status: "delivery_unknown",
|
|
reason: "send_state_lost",
|
|
});
|
|
|
|
const ambiguous = createSendPage(["conversation-1", "conversation-2"]);
|
|
assert.deepEqual(await handleSendCommand(ambiguous.pageWindow), {
|
|
status: "delivery_unknown",
|
|
reason: "send_state_lost",
|
|
});
|
|
|
|
const mismatch = createSendPage(["conversation-2"]);
|
|
assert.deepEqual(await handleSendCommand(mismatch.pageWindow), {
|
|
status: "delivery_unknown",
|
|
reason: "send_state_lost",
|
|
});
|
|
|
|
const invalidContent = createSendPage();
|
|
assert.deepEqual(
|
|
await handleSendCommand(invalidContent.pageWindow, sendCommand("conversation-1", 7)),
|
|
{ status: "rejected_before_send", reason: "invalid_request" },
|
|
);
|
|
assert.deepEqual(empty.calls, [
|
|
{ cid: "conversation-1", conversationCode: "conversation-1", content: "hello" },
|
|
]);
|
|
assert.deepEqual(ambiguous.calls, [
|
|
{ cid: "conversation-1", conversationCode: "conversation-1", content: "hello" },
|
|
]);
|
|
assert.deepEqual(mismatch.calls, [
|
|
{ cid: "conversation-1", conversationCode: "conversation-1", content: "hello" },
|
|
]);
|
|
assert.deepEqual(invalidContent.calls, []);
|
|
});
|
|
|
|
test("fails closed for file commands when MAIN cannot resolve the native uploader", async () => {
|
|
const { pageWindow, calls } = createSendPage(["conversation-2"]);
|
|
|
|
const result = await handleOneTalkSendCommand(
|
|
pageWindow,
|
|
{
|
|
requestId: "file-send",
|
|
command: {
|
|
action: "onetalk.send",
|
|
conversationId: "conversation-1",
|
|
content: {
|
|
kind: "file",
|
|
source: {
|
|
downloadUrl: "https://mind.example.test/bridge/attachment-1",
|
|
fileName: "quotation.zip",
|
|
mimeType: "application/x-mind-approved-file",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
createSendObservationCorrelator(1),
|
|
);
|
|
|
|
assert.deepEqual(result, { status: "delivery_unknown", reason: "send_state_lost" });
|
|
assert.deepEqual(calls, []);
|
|
});
|
|
|
|
test("requires sendUIMessages even when an unverified send API is present", async () => {
|
|
const { pageWindow, rejectedCalls } = createSendPage();
|
|
delete pageWindow.IcbuIM.IMBaaSSDK.default.getMessageService;
|
|
pageWindow.IcbuIM.IMBaaSSDK.default.getMessageService = () => ({
|
|
sendMessage: () => rejectedCalls.push("sendMessage"),
|
|
sendTextMessage: () => rejectedCalls.push("sendTextMessage"),
|
|
});
|
|
|
|
assert.deepEqual(await handleSendCommand(pageWindow), {
|
|
status: "rejected_before_send",
|
|
reason: "send_not_supported",
|
|
});
|
|
assert.deepEqual(rejectedCalls, []);
|
|
});
|
|
|
|
test("rejects primitive ext values before invoking the SDK", async () => {
|
|
const { pageWindow, calls } = createSendPage();
|
|
assert.deepEqual(
|
|
await handleSendCommand(pageWindow, {
|
|
command: {
|
|
action: "onetalk.send",
|
|
conversationId: "conversation-1",
|
|
content: "hello",
|
|
ext: 7,
|
|
},
|
|
}),
|
|
{ status: "rejected_before_send", reason: "invalid_request" },
|
|
);
|
|
assert.deepEqual(calls, []);
|
|
});
|
|
|
|
test("publishes flat SDK history as a normalized bridge batch", async () => {
|
|
const { flatItem, pageWindow, posted, events } = createHistorySyncPage();
|
|
const batches = [];
|
|
|
|
const result = await handleOneTalkHistoryCommand(
|
|
pageWindow,
|
|
{ command: { action: "onetalk.sync" } },
|
|
(batch) => {
|
|
batches.push(batch);
|
|
events.push("observation");
|
|
},
|
|
);
|
|
|
|
assert.equal(result.status, "completed");
|
|
assert.deepEqual(batches[0].messages, [
|
|
{
|
|
messageType: "history",
|
|
upstreamType: 1,
|
|
messageId: "123456",
|
|
conversationId: flatItem.conversationCode,
|
|
senderId: "buyer@icbu",
|
|
direction: "received",
|
|
sentAtMs: flatItem.sendTime,
|
|
content: { version: 1, kind: "text", text: "Order draft notification" },
|
|
participantIds: ["buyer@icbu", "seller@icbu"],
|
|
readStatus: 2,
|
|
messageStatus: 1,
|
|
unreadCount: 0,
|
|
},
|
|
]);
|
|
const observed = createOneTalkPageObservedMessage(
|
|
batches[0].messages,
|
|
undefined,
|
|
batches[0].diagnostics,
|
|
);
|
|
assert.deepEqual(decodeOneTalkPageMessage(observed), observed);
|
|
assert.equal(JSON.stringify(batches).includes("订单草稿通知"), false);
|
|
assert.equal(JSON.stringify(batches).includes("not-json"), false);
|
|
assert.equal(JSON.stringify(posted).includes("订单草稿通知"), false);
|
|
assert.deepEqual(events, ["observation", "progress"]);
|
|
});
|
|
|
|
test("global history sync uses the same optional history publisher", async () => {
|
|
const { flatItem, pageWindow } = createHistorySyncPage();
|
|
const batches = [];
|
|
installCurrentConversationHistorySync(pageWindow, {
|
|
onHistoryItems: (items) => batches.push(createHistoryMessageBatch(items, pageWindow)),
|
|
});
|
|
|
|
const result = await pageWindow.__tradeMessageCenterOneTalk.syncCurrentConversationHistory();
|
|
|
|
assert.equal(result.exit, "history_exhausted");
|
|
assert.equal(batches.length, 1);
|
|
assert.equal(batches[0].messages[0].messageId, "123456");
|
|
assert.equal(batches[0].messages[0].messageType, "history");
|
|
assert.equal(flatItem.messageId, 123456);
|
|
});
|
|
|
|
test("settles bootstrap tooltip progress only after a successful or final history attempt", async () => {
|
|
const { pageWindow, failHistory } = createHistorySyncPage();
|
|
const calls = [];
|
|
const progress = {
|
|
beginDiscovery: () => calls.push(["begin"]),
|
|
completeDiscovery: (entries, terminalConversationIds) =>
|
|
calls.push([
|
|
"discovery",
|
|
entries.map((entry) => entry.conversationId),
|
|
terminalConversationIds,
|
|
]),
|
|
failDiscovery: () => calls.push(["discovery-failed"]),
|
|
completeConversation: (conversationId) => calls.push(["conversation", conversationId]),
|
|
};
|
|
|
|
const discovery = await handleOneTalkHistoryCommand(
|
|
pageWindow,
|
|
{
|
|
command: {
|
|
action: "onetalk.discover-conversations",
|
|
terminalConversationIds: ["buyer-seller#tenant@icbu"],
|
|
},
|
|
},
|
|
undefined,
|
|
progress,
|
|
);
|
|
assert.deepEqual(discovery.status, "completed");
|
|
failHistory();
|
|
|
|
assert.deepEqual(
|
|
await handleOneTalkHistoryCommand(
|
|
pageWindow,
|
|
{
|
|
command: {
|
|
action: "onetalk.sync.conversation",
|
|
conversationId: "buyer-seller#tenant@icbu",
|
|
finalAttempt: false,
|
|
},
|
|
},
|
|
undefined,
|
|
progress,
|
|
),
|
|
{ status: "failed", reason: "onetalk_history_message_request_failed" },
|
|
);
|
|
assert.deepEqual(calls, [
|
|
["begin"],
|
|
["discovery", ["buyer-seller#tenant@icbu"], ["buyer-seller#tenant@icbu"]],
|
|
]);
|
|
|
|
assert.deepEqual(
|
|
await handleOneTalkHistoryCommand(
|
|
pageWindow,
|
|
{
|
|
command: {
|
|
action: "onetalk.sync.conversation",
|
|
conversationId: "buyer-seller#tenant@icbu",
|
|
finalAttempt: true,
|
|
},
|
|
},
|
|
undefined,
|
|
progress,
|
|
),
|
|
{ status: "failed", reason: "onetalk_history_message_request_failed" },
|
|
);
|
|
assert.deepEqual(calls.at(-1), ["conversation", "buyer-seller#tenant@icbu"]);
|
|
});
|
|
|
|
test("keeps history command results unchanged when the local tooltip boundary fails", async () => {
|
|
const { pageWindow, failHistory } = createHistorySyncPage();
|
|
const throwingProgress = {
|
|
beginDiscovery: () => {
|
|
throw new Error("tooltip_begin_failed");
|
|
},
|
|
completeDiscovery: () => {
|
|
throw new Error("tooltip_complete_failed");
|
|
},
|
|
failDiscovery: () => {
|
|
throw new Error("tooltip_fail_failed");
|
|
},
|
|
completeConversation: () => {
|
|
throw new Error("tooltip_settle_failed");
|
|
},
|
|
};
|
|
|
|
assert.equal(
|
|
(
|
|
await handleOneTalkHistoryCommand(
|
|
pageWindow,
|
|
{ command: { action: "onetalk.discover-conversations" } },
|
|
undefined,
|
|
throwingProgress,
|
|
)
|
|
).status,
|
|
"completed",
|
|
);
|
|
assert.equal(
|
|
(
|
|
await handleOneTalkHistoryCommand(
|
|
pageWindow,
|
|
{
|
|
command: {
|
|
action: "onetalk.sync.conversation",
|
|
conversationId: "buyer-seller#tenant@icbu",
|
|
finalAttempt: true,
|
|
},
|
|
},
|
|
undefined,
|
|
throwingProgress,
|
|
)
|
|
).status,
|
|
"completed",
|
|
);
|
|
|
|
failHistory();
|
|
assert.deepEqual(
|
|
await handleOneTalkHistoryCommand(
|
|
pageWindow,
|
|
{
|
|
command: {
|
|
action: "onetalk.sync.conversation",
|
|
conversationId: "buyer-seller#tenant@icbu",
|
|
finalAttempt: true,
|
|
},
|
|
},
|
|
undefined,
|
|
throwingProgress,
|
|
),
|
|
{ status: "failed", reason: "onetalk_history_message_request_failed" },
|
|
);
|
|
|
|
const failedDiscovery = createHistorySyncPage();
|
|
failedDiscovery.pageWindow.IcbuIM = undefined;
|
|
assert.equal(
|
|
(
|
|
await handleOneTalkHistoryCommand(
|
|
failedDiscovery.pageWindow,
|
|
{ command: { action: "onetalk.discover-conversations" } },
|
|
undefined,
|
|
throwingProgress,
|
|
)
|
|
).status,
|
|
"failed",
|
|
);
|
|
});
|
|
|
|
test("does not turn a successful history result into a failure when tooltip settlement throws", async () => {
|
|
const { pageWindow } = createHistorySyncPage();
|
|
let throwTooltipError = true;
|
|
const progress = {
|
|
beginDiscovery: () => {},
|
|
completeDiscovery: () => {},
|
|
failDiscovery: () => {},
|
|
completeConversation: () => {
|
|
if (throwTooltipError) {
|
|
throwTooltipError = false;
|
|
throw new Error("tooltip_dom_failed");
|
|
}
|
|
},
|
|
};
|
|
|
|
await handleOneTalkHistoryCommand(
|
|
pageWindow,
|
|
{ command: { action: "onetalk.discover-conversations" } },
|
|
undefined,
|
|
progress,
|
|
);
|
|
|
|
const result = await handleOneTalkHistoryCommand(
|
|
pageWindow,
|
|
{
|
|
command: {
|
|
action: "onetalk.sync.conversation",
|
|
conversationId: "buyer-seller#tenant@icbu",
|
|
},
|
|
},
|
|
undefined,
|
|
progress,
|
|
);
|
|
|
|
assert.equal(result.status, "completed");
|
|
});
|
|
|
|
test("maps an invalid page action to the shared invalid_request reason", async () => {
|
|
const { pageWindow, calls } = createSendPage();
|
|
|
|
assert.deepEqual(
|
|
await handleOneTalkHistoryCommand(pageWindow, {
|
|
command: { action: "unknown.action" },
|
|
}),
|
|
{ status: "rejected_before_send", reason: "invalid_request" },
|
|
);
|
|
assert.deepEqual(calls, []);
|
|
});
|
|
|
|
class BridgePageWindow {
|
|
constructor() {
|
|
this.location = {
|
|
href: `${pageOrigin}/?activeAccountId=account-1&conversationId=url-value`,
|
|
origin: pageOrigin,
|
|
};
|
|
this.currentUserAccountId = "login-account-1";
|
|
this.selectedIds = ["conversation-1"];
|
|
this.posted = [];
|
|
this.listeners = [];
|
|
this.documentListeners = [];
|
|
this.document = {
|
|
querySelectorAll: () => this.selectedIds.map(selectedElement),
|
|
addEventListener: (type, listener) => {
|
|
this.documentListeners.push({ type, listener });
|
|
},
|
|
};
|
|
}
|
|
|
|
addEventListener(type, listener) {
|
|
this.listeners.push({ type, listener });
|
|
}
|
|
|
|
postMessage(message, targetOrigin) {
|
|
this.posted.push({ message, targetOrigin });
|
|
}
|
|
|
|
dispatchDocumentClick() {
|
|
for (const { type, listener } of this.documentListeners) {
|
|
if (type === "click") listener();
|
|
}
|
|
}
|
|
}
|
|
|
|
test("refreshes hello with the selected SPA identity after a click without URL changes", () => {
|
|
const pageWindow = new BridgePageWindow();
|
|
installOneTalkMainPageBridge(pageWindow);
|
|
|
|
pageWindow.selectedIds = ["conversation-2"];
|
|
pageWindow.dispatchDocumentClick();
|
|
|
|
assert.deepEqual(
|
|
pageWindow.posted.map(({ message }) => message),
|
|
[
|
|
{
|
|
source: "trade-message-center.onetalk.page-bridge",
|
|
version: ONE_TALK_PAGE_BRIDGE_VERSION,
|
|
type: "onetalk.page.hello",
|
|
channelAccountId: "login-account-1",
|
|
conversationId: "conversation-1",
|
|
},
|
|
{
|
|
source: "trade-message-center.onetalk.page-bridge",
|
|
version: ONE_TALK_PAGE_BRIDGE_VERSION,
|
|
type: "onetalk.page.hello",
|
|
channelAccountId: "login-account-1",
|
|
conversationId: "conversation-2",
|
|
},
|
|
],
|
|
);
|
|
});
|
|
|
|
test("encodes none and multiple selected DOM states in hello without inventing an ID", () => {
|
|
for (const conversationSelection of ["none", "multiple"]) {
|
|
const pageWindow = new BridgePageWindow();
|
|
pageWindow.selectedIds =
|
|
conversationSelection === "none" ? [] : ["conversation-1", "conversation-2"];
|
|
installOneTalkMainPageBridge(pageWindow);
|
|
|
|
const hello = pageWindow.posted[0].message;
|
|
assert.equal(hello.conversationId, undefined);
|
|
assert.equal(hello.conversationSelection, conversationSelection);
|
|
assert.deepEqual(decodeOneTalkPageMessage(hello), hello);
|
|
}
|
|
});
|