@ada-cx/messaging-sdk 1.0.0-setup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -0
- package/dist/client/ada-settings-reader.d.ts +10 -0
- package/dist/client/client-channel-handlers.d.ts +92 -0
- package/dist/client/client-errors.d.ts +7 -0
- package/dist/client/client-frame-constants.d.ts +41 -0
- package/dist/client/client-frame-runtime.d.ts +54 -0
- package/dist/client/client-host-runtime.d.ts +73 -0
- package/dist/client/client-types.d.ts +231 -0
- package/dist/client/client.d.ts +843 -0
- package/dist/client/config-helpers.d.ts +157 -0
- package/dist/client/constants.d.ts +61 -0
- package/dist/client/core-channel-test-harness.d.ts +47 -0
- package/dist/client/embed-interface.d.ts +172 -0
- package/dist/client/embed-lifecycle.d.ts +12 -0
- package/dist/client/fallback-html.d.ts +1 -0
- package/dist/client/frame-manager.d.ts +64 -0
- package/dist/client/frame-styles.d.ts +164 -0
- package/dist/client/frame-visibility.d.ts +53 -0
- package/dist/client/integration-manager.d.ts +73 -0
- package/dist/client/legacy-callback-adapter.d.ts +22 -0
- package/dist/client/mask-element.d.ts +19 -0
- package/dist/client/proactive/index.d.ts +5 -0
- package/dist/client/proactive/proactive-channel.d.ts +33 -0
- package/dist/client/proactive/proactive-runtime.d.ts +65 -0
- package/dist/client/proactive/proactive-utils.d.ts +51 -0
- package/dist/client/sdk-error-reporter.d.ts +22 -0
- package/dist/client/sdk-event-bus.d.ts +116 -0
- package/dist/client/service-worker-notifications.d.ts +1 -0
- package/dist/client/url-business-events.d.ts +19 -0
- package/dist/frame-channel/frame-channel.d.ts +64 -0
- package/dist/frame-channel/frame-child.d.ts +45 -0
- package/dist/frame-channel/index.d.ts +3 -0
- package/dist/frame-channel/types.d.ts +736 -0
- package/dist/helpers/rollout.d.ts +18 -0
- package/dist/host-telemetry.d.ts +15 -0
- package/dist/index.d.ts +8 -0
- package/dist/logger.d.ts +59 -0
- package/dist/mobile-webview-runtime.d.ts +122 -0
- package/dist/npm/build-info.d.cts +17 -0
- package/dist/npm/build-info.d.ts +17 -0
- package/dist/npm/index.cjs +276 -0
- package/dist/npm/index.cjs.map +1 -0
- package/dist/npm/index.d.cts +15 -0
- package/dist/npm/index.d.ts +9 -0
- package/dist/npm/index.js +270 -0
- package/dist/npm/index.js.map +1 -0
- package/dist/npm/loader.d.cts +120 -0
- package/dist/npm/loader.d.ts +120 -0
- package/dist/npm/testing.cjs +155 -0
- package/dist/npm/testing.cjs.map +1 -0
- package/dist/npm/testing.d.cts +39 -0
- package/dist/npm/testing.d.ts +39 -0
- package/dist/npm/testing.js +154 -0
- package/dist/npm/testing.js.map +1 -0
- package/dist/sdk-module-loader.d.ts +1 -0
- package/dist/shared-utils/clusters.d.ts +5 -0
- package/dist/shared-utils/csat.d.ts +116 -0
- package/dist/shared-utils/host-telemetry.d.ts +35 -0
- package/dist/shared-utils/index.d.ts +3 -0
- package/dist/voice/voice-manager.d.ts +120 -0
- package/package.json +77 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/npm/testing.ts
|
|
3
|
+
var EXACT_MATCH_EVENT_KEYS = new Set(["ada:message:sent", "ada:message:received"]);
|
|
4
|
+
function keyedSubscriptionMatches(subscriptionKey, eventKey) {
|
|
5
|
+
if (EXACT_MATCH_EVENT_KEYS.has(eventKey)) return subscriptionKey === eventKey;
|
|
6
|
+
return subscriptionKey === eventKey || eventKey.startsWith(subscriptionKey);
|
|
7
|
+
}
|
|
8
|
+
function toMetaFieldRecord(fields) {
|
|
9
|
+
const record = {};
|
|
10
|
+
for (const [key, value] of Object.entries(fields)) if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) record[key] = value;
|
|
11
|
+
return record;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create an in-memory messaging-interface stand-in for unit-testing an
|
|
15
|
+
* integration without loading the SDK from the CDN.
|
|
16
|
+
*
|
|
17
|
+
* Every method resolves, records itself in `calls`, and keeps just enough
|
|
18
|
+
* state to behave like the real interface: `sendMessage` appends a
|
|
19
|
+
* programmatic user message that `getMessages` returns, `open`/`close`/
|
|
20
|
+
* `toggle` drive `isOpen` and `getInfo`, `setMetaFields` feeds
|
|
21
|
+
* `getMetaFields` (sensitive fields are never returned, matching the real
|
|
22
|
+
* SDK), and `$emit` fans out to `subscribeEvent`/`subscribeAll` callbacks.
|
|
23
|
+
*
|
|
24
|
+
* Pass `overrides` to replace any method (e.g. with `vi.fn()`); overridden
|
|
25
|
+
* methods are still recorded in `calls`.
|
|
26
|
+
*/
|
|
27
|
+
function createMockAdaMessaging(overrides = {}) {
|
|
28
|
+
const calls = [];
|
|
29
|
+
let nextSubscriptionId = 1;
|
|
30
|
+
let nextMessageId = 1;
|
|
31
|
+
let chatOpen = false;
|
|
32
|
+
let conversationId = null;
|
|
33
|
+
const metaFields = {};
|
|
34
|
+
const messages = [];
|
|
35
|
+
const keyedSubscriptions = /* @__PURE__ */ new Map();
|
|
36
|
+
const wildcardSubscriptions = /* @__PURE__ */ new Map();
|
|
37
|
+
const emit = (key, data) => {
|
|
38
|
+
for (const subscription of keyedSubscriptions.values()) if (keyedSubscriptionMatches(subscription.key, key)) subscription.callback(data, { eventKey: key });
|
|
39
|
+
if (EXACT_MATCH_EVENT_KEYS.has(key)) return;
|
|
40
|
+
for (const callback of wildcardSubscriptions.values()) callback(key, data);
|
|
41
|
+
};
|
|
42
|
+
const clearTranscript = () => {
|
|
43
|
+
messages.length = 0;
|
|
44
|
+
conversationId = null;
|
|
45
|
+
};
|
|
46
|
+
const base = {
|
|
47
|
+
start: async () => void 0,
|
|
48
|
+
stop: async () => void 0,
|
|
49
|
+
toggle: async () => {
|
|
50
|
+
chatOpen = !chatOpen;
|
|
51
|
+
},
|
|
52
|
+
deleteHistory: async () => {
|
|
53
|
+
clearTranscript();
|
|
54
|
+
},
|
|
55
|
+
reset: async () => {
|
|
56
|
+
clearTranscript();
|
|
57
|
+
},
|
|
58
|
+
setMetaFields: async (fields) => {
|
|
59
|
+
Object.assign(metaFields, toMetaFieldRecord(fields));
|
|
60
|
+
},
|
|
61
|
+
setSensitiveMetaFields: async () => void 0,
|
|
62
|
+
setTestModeBanner: async () => void 0,
|
|
63
|
+
getInfo: async () => ({
|
|
64
|
+
isChatOpen: chatOpen,
|
|
65
|
+
isDrawerOpen: chatOpen,
|
|
66
|
+
hasActiveChatter: messages.length > 0,
|
|
67
|
+
hasClosedChat: false
|
|
68
|
+
}),
|
|
69
|
+
getMetaFields: async () => ({ ...metaFields }),
|
|
70
|
+
isOpen: async () => chatOpen,
|
|
71
|
+
getConversation: async () => ({
|
|
72
|
+
id: conversationId,
|
|
73
|
+
handoff: { inLiveChat: false }
|
|
74
|
+
}),
|
|
75
|
+
getMessages: async () => [...messages],
|
|
76
|
+
setComposerText: async () => void 0,
|
|
77
|
+
setDelegate: () => void 0,
|
|
78
|
+
trackEvent: async () => void 0,
|
|
79
|
+
subscribeEvent: async (key, callback) => {
|
|
80
|
+
const id = nextSubscriptionId++;
|
|
81
|
+
keyedSubscriptions.set(id, {
|
|
82
|
+
key,
|
|
83
|
+
callback
|
|
84
|
+
});
|
|
85
|
+
return id;
|
|
86
|
+
},
|
|
87
|
+
unsubscribeEvent: async (id) => {
|
|
88
|
+
keyedSubscriptions.delete(id);
|
|
89
|
+
wildcardSubscriptions.delete(id);
|
|
90
|
+
},
|
|
91
|
+
subscribeAll: async (callback) => {
|
|
92
|
+
const id = nextSubscriptionId++;
|
|
93
|
+
wildcardSubscriptions.set(id, callback);
|
|
94
|
+
return id;
|
|
95
|
+
},
|
|
96
|
+
open: async () => {
|
|
97
|
+
chatOpen = true;
|
|
98
|
+
},
|
|
99
|
+
close: async () => {
|
|
100
|
+
chatOpen = false;
|
|
101
|
+
},
|
|
102
|
+
setLanguage: async () => void 0,
|
|
103
|
+
setTheme: async () => void 0,
|
|
104
|
+
setDeviceToken: async () => void 0,
|
|
105
|
+
sendMessage: async (body) => {
|
|
106
|
+
const id = `mock-message-${nextMessageId++}`;
|
|
107
|
+
conversationId = conversationId ?? "mock-conversation";
|
|
108
|
+
messages.push({
|
|
109
|
+
id,
|
|
110
|
+
role: "user",
|
|
111
|
+
type: "text",
|
|
112
|
+
body,
|
|
113
|
+
createdAt: Math.floor(Date.now() / 1e3),
|
|
114
|
+
origin: "programmatic"
|
|
115
|
+
});
|
|
116
|
+
return { id };
|
|
117
|
+
},
|
|
118
|
+
handleNotification: async () => {
|
|
119
|
+
chatOpen = true;
|
|
120
|
+
},
|
|
121
|
+
requestNotifications: async () => "granted",
|
|
122
|
+
createProactive: async () => void 0,
|
|
123
|
+
triggerCampaign: async () => void 0,
|
|
124
|
+
evaluateCampaignConditions: async () => void 0,
|
|
125
|
+
closeCampaign: async () => void 0,
|
|
126
|
+
triggerAnswer: async () => void 0,
|
|
127
|
+
triggerProactive: async () => void 0,
|
|
128
|
+
triggerGreeting: async () => void 0,
|
|
129
|
+
destroy: async () => {
|
|
130
|
+
keyedSubscriptions.clear();
|
|
131
|
+
wildcardSubscriptions.clear();
|
|
132
|
+
chatOpen = false;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const definedOverrides = Object.fromEntries(Object.entries(overrides).filter(([, value]) => value !== void 0));
|
|
136
|
+
const implementation = {
|
|
137
|
+
...base,
|
|
138
|
+
...definedOverrides
|
|
139
|
+
};
|
|
140
|
+
return {
|
|
141
|
+
...Object.fromEntries(Object.entries(implementation).map(([method, fn]) => [method, (...args) => {
|
|
142
|
+
calls.push({
|
|
143
|
+
method,
|
|
144
|
+
args
|
|
145
|
+
});
|
|
146
|
+
return fn(...args);
|
|
147
|
+
}])),
|
|
148
|
+
calls,
|
|
149
|
+
$emit: emit
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
exports.createMockAdaMessaging = createMockAdaMessaging;
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=testing.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.cjs","names":[],"sources":["../../src/npm/testing.ts"],"sourcesContent":["import type {\n\tAdaSdkEventCallback,\n\tMetaFieldValue,\n\tPublicMessage,\n} from \"../client/client-types\";\nimport type { AdaMessagingInterface } from \"./loader\";\n\n/** One recorded method invocation on a {@link MockAdaMessaging}. */\nexport interface RecordedAdaMessagingCall {\n\tmethod: string;\n\targs: unknown[];\n}\n\n/**\n * The mock returned by {@link createMockAdaMessaging}: the full\n * {@link AdaMessagingInterface} plus test hooks for inspecting calls and\n * simulating SDK events.\n */\nexport interface MockAdaMessaging extends AdaMessagingInterface {\n\t/** Every method invocation, in call order. */\n\tcalls: RecordedAdaMessagingCall[];\n\t/**\n\t * Deliver an event to `subscribeEvent` and `subscribeAll` callbacks, as if\n\t * the SDK emitted it (e.g. `$emit(\"ada:ready\", { isRolledOut: true })`).\n\t * Routing matches the real SDK: keyed subscriptions match by prefix\n\t * (`\"ada:campaigns\"` catches `\"ada:campaigns:shown\"`), except the\n\t * transcript events `ada:message:sent`/`ada:message:received`, which reach\n\t * exact-key subscribers only and never `subscribeAll`.\n\t */\n\t$emit: (key: string, data?: unknown) => void;\n}\n\ninterface KeyedSubscription {\n\tkey: string;\n\tcallback: AdaSdkEventCallback;\n}\n\n// Mirrors EXACT_MATCH_EVENT_KEYS in client/client-host-runtime.ts: transcript\n// events reach exact-key subscribers only, never prefix or subscribeAll\n// subscribers. Duplicated (not imported) so the published testing entry stays\n// free of runtime modules; a drift test pins the mock against the real matcher.\nconst EXACT_MATCH_EVENT_KEYS = new Set([\n\t\"ada:message:sent\",\n\t\"ada:message:received\",\n]);\n\nfunction keyedSubscriptionMatches(\n\tsubscriptionKey: string,\n\teventKey: string,\n): boolean {\n\tif (EXACT_MATCH_EVENT_KEYS.has(eventKey)) {\n\t\treturn subscriptionKey === eventKey;\n\t}\n\t// Raw prefix match, same as the real SDK: \"ada:campaigns\" also catches\n\t// \"ada:campaigns:shown\" and underscore-suffixed keys.\n\treturn subscriptionKey === eventKey || eventKey.startsWith(subscriptionKey);\n}\n\nfunction toMetaFieldRecord(\n\tfields: Record<string, unknown>,\n): Record<string, MetaFieldValue> {\n\tconst record: Record<string, MetaFieldValue> = {};\n\tfor (const [key, value] of Object.entries(fields)) {\n\t\tif (\n\t\t\ttypeof value === \"string\" ||\n\t\t\ttypeof value === \"number\" ||\n\t\t\ttypeof value === \"boolean\" ||\n\t\t\tvalue === null\n\t\t) {\n\t\t\trecord[key] = value;\n\t\t}\n\t}\n\treturn record;\n}\n\n/**\n * Create an in-memory messaging-interface stand-in for unit-testing an\n * integration without loading the SDK from the CDN.\n *\n * Every method resolves, records itself in `calls`, and keeps just enough\n * state to behave like the real interface: `sendMessage` appends a\n * programmatic user message that `getMessages` returns, `open`/`close`/\n * `toggle` drive `isOpen` and `getInfo`, `setMetaFields` feeds\n * `getMetaFields` (sensitive fields are never returned, matching the real\n * SDK), and `$emit` fans out to `subscribeEvent`/`subscribeAll` callbacks.\n *\n * Pass `overrides` to replace any method (e.g. with `vi.fn()`); overridden\n * methods are still recorded in `calls`.\n */\nexport function createMockAdaMessaging(\n\toverrides: Partial<AdaMessagingInterface> = {},\n): MockAdaMessaging {\n\tconst calls: RecordedAdaMessagingCall[] = [];\n\tlet nextSubscriptionId = 1;\n\tlet nextMessageId = 1;\n\tlet chatOpen = false;\n\tlet conversationId: string | null = null;\n\tconst metaFields: Record<string, MetaFieldValue> = {};\n\tconst messages: PublicMessage[] = [];\n\tconst keyedSubscriptions = new Map<number, KeyedSubscription>();\n\tconst wildcardSubscriptions = new Map<\n\t\tnumber,\n\t\t(key: string, data: unknown) => void\n\t>();\n\n\tconst emit = (key: string, data?: unknown): void => {\n\t\tfor (const subscription of keyedSubscriptions.values()) {\n\t\t\tif (keyedSubscriptionMatches(subscription.key, key)) {\n\t\t\t\tsubscription.callback(data, { eventKey: key });\n\t\t\t}\n\t\t}\n\t\tif (EXACT_MATCH_EVENT_KEYS.has(key)) {\n\t\t\treturn;\n\t\t}\n\t\tfor (const callback of wildcardSubscriptions.values()) {\n\t\t\tcallback(key, data);\n\t\t}\n\t};\n\n\tconst clearTranscript = (): void => {\n\t\tmessages.length = 0;\n\t\tconversationId = null;\n\t};\n\n\tconst base: AdaMessagingInterface = {\n\t\tstart: async () => undefined,\n\t\tstop: async () => undefined,\n\t\ttoggle: async () => {\n\t\t\tchatOpen = !chatOpen;\n\t\t},\n\t\tdeleteHistory: async () => {\n\t\t\tclearTranscript();\n\t\t},\n\t\treset: async () => {\n\t\t\tclearTranscript();\n\t\t},\n\t\tsetMetaFields: async (fields) => {\n\t\t\tObject.assign(metaFields, toMetaFieldRecord(fields));\n\t\t},\n\t\t// Sensitive fields are accepted but never readable back, matching the\n\t\t// real SDK's getMetaFields contract.\n\t\tsetSensitiveMetaFields: async () => undefined,\n\t\tsetTestModeBanner: async () => undefined,\n\t\tgetInfo: async () => ({\n\t\t\tisChatOpen: chatOpen,\n\t\t\tisDrawerOpen: chatOpen,\n\t\t\thasActiveChatter: messages.length > 0,\n\t\t\thasClosedChat: false,\n\t\t}),\n\t\tgetMetaFields: async () => ({ ...metaFields }),\n\t\tisOpen: async () => chatOpen,\n\t\tgetConversation: async () => ({\n\t\t\tid: conversationId,\n\t\t\thandoff: { inLiveChat: false },\n\t\t}),\n\t\tgetMessages: async () => [...messages],\n\t\tsetComposerText: async () => undefined,\n\t\tsetDelegate: () => undefined,\n\t\ttrackEvent: async () => undefined,\n\t\tsubscribeEvent: async (key, callback) => {\n\t\t\tconst id = nextSubscriptionId++;\n\t\t\tkeyedSubscriptions.set(id, { key, callback });\n\t\t\treturn id;\n\t\t},\n\t\tunsubscribeEvent: async (id) => {\n\t\t\tkeyedSubscriptions.delete(id);\n\t\t\twildcardSubscriptions.delete(id);\n\t\t},\n\t\tsubscribeAll: async (callback) => {\n\t\t\tconst id = nextSubscriptionId++;\n\t\t\twildcardSubscriptions.set(id, callback);\n\t\t\treturn id;\n\t\t},\n\t\topen: async () => {\n\t\t\tchatOpen = true;\n\t\t},\n\t\tclose: async () => {\n\t\t\tchatOpen = false;\n\t\t},\n\t\tsetLanguage: async () => undefined,\n\t\tsetTheme: async () => undefined,\n\t\tsetDeviceToken: async () => undefined,\n\t\tsendMessage: async (body) => {\n\t\t\tconst id = `mock-message-${nextMessageId++}`;\n\t\t\tconversationId = conversationId ?? \"mock-conversation\";\n\t\t\tmessages.push({\n\t\t\t\tid,\n\t\t\t\trole: \"user\",\n\t\t\t\ttype: \"text\",\n\t\t\t\tbody,\n\t\t\t\tcreatedAt: Math.floor(Date.now() / 1000),\n\t\t\t\torigin: \"programmatic\",\n\t\t\t});\n\t\t\treturn { id };\n\t\t},\n\t\thandleNotification: async () => {\n\t\t\tchatOpen = true;\n\t\t},\n\t\trequestNotifications: async () => \"granted\",\n\t\tcreateProactive: async () => undefined,\n\t\ttriggerCampaign: async () => undefined,\n\t\tevaluateCampaignConditions: async () => undefined,\n\t\tcloseCampaign: async () => undefined,\n\t\ttriggerAnswer: async () => undefined,\n\t\ttriggerProactive: async () => undefined,\n\t\ttriggerGreeting: async () => undefined,\n\t\tdestroy: async () => {\n\t\t\tkeyedSubscriptions.clear();\n\t\t\twildcardSubscriptions.clear();\n\t\t\tchatOpen = false;\n\t\t},\n\t};\n\n\tconst definedOverrides = Object.fromEntries(\n\t\tObject.entries(overrides).filter(([, value]) => value !== undefined),\n\t);\n\tconst implementation = { ...base, ...definedOverrides };\n\tconst recorded = Object.fromEntries(\n\t\tObject.entries(implementation).map(([method, fn]) => [\n\t\t\tmethod,\n\t\t\t(...args: unknown[]) => {\n\t\t\t\tcalls.push({ method, args });\n\t\t\t\treturn (fn as (...callArgs: unknown[]) => unknown)(...args);\n\t\t\t},\n\t\t]),\n\t) as unknown as AdaMessagingInterface;\n\n\treturn { ...recorded, calls, $emit: emit };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AdaMessagingInterface } from "./loader.js" with { "resolution-mode": "import" };
|
|
2
|
+
/** One recorded method invocation on a {@link MockAdaMessaging}. */
|
|
3
|
+
export interface RecordedAdaMessagingCall {
|
|
4
|
+
method: string;
|
|
5
|
+
args: unknown[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The mock returned by {@link createMockAdaMessaging}: the full
|
|
9
|
+
* {@link AdaMessagingInterface} plus test hooks for inspecting calls and
|
|
10
|
+
* simulating SDK events.
|
|
11
|
+
*/
|
|
12
|
+
export interface MockAdaMessaging extends AdaMessagingInterface {
|
|
13
|
+
/** Every method invocation, in call order. */
|
|
14
|
+
calls: RecordedAdaMessagingCall[];
|
|
15
|
+
/**
|
|
16
|
+
* Deliver an event to `subscribeEvent` and `subscribeAll` callbacks, as if
|
|
17
|
+
* the SDK emitted it (e.g. `$emit("ada:ready", { isRolledOut: true })`).
|
|
18
|
+
* Routing matches the real SDK: keyed subscriptions match by prefix
|
|
19
|
+
* (`"ada:campaigns"` catches `"ada:campaigns:shown"`), except the
|
|
20
|
+
* transcript events `ada:message:sent`/`ada:message:received`, which reach
|
|
21
|
+
* exact-key subscribers only and never `subscribeAll`.
|
|
22
|
+
*/
|
|
23
|
+
$emit: (key: string, data?: unknown) => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create an in-memory messaging-interface stand-in for unit-testing an
|
|
27
|
+
* integration without loading the SDK from the CDN.
|
|
28
|
+
*
|
|
29
|
+
* Every method resolves, records itself in `calls`, and keeps just enough
|
|
30
|
+
* state to behave like the real interface: `sendMessage` appends a
|
|
31
|
+
* programmatic user message that `getMessages` returns, `open`/`close`/
|
|
32
|
+
* `toggle` drive `isOpen` and `getInfo`, `setMetaFields` feeds
|
|
33
|
+
* `getMetaFields` (sensitive fields are never returned, matching the real
|
|
34
|
+
* SDK), and `$emit` fans out to `subscribeEvent`/`subscribeAll` callbacks.
|
|
35
|
+
*
|
|
36
|
+
* Pass `overrides` to replace any method (e.g. with `vi.fn()`); overridden
|
|
37
|
+
* methods are still recorded in `calls`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createMockAdaMessaging(overrides?: Partial<AdaMessagingInterface>): MockAdaMessaging;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AdaMessagingInterface } from "./loader.js";
|
|
2
|
+
/** One recorded method invocation on a {@link MockAdaMessaging}. */
|
|
3
|
+
export interface RecordedAdaMessagingCall {
|
|
4
|
+
method: string;
|
|
5
|
+
args: unknown[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The mock returned by {@link createMockAdaMessaging}: the full
|
|
9
|
+
* {@link AdaMessagingInterface} plus test hooks for inspecting calls and
|
|
10
|
+
* simulating SDK events.
|
|
11
|
+
*/
|
|
12
|
+
export interface MockAdaMessaging extends AdaMessagingInterface {
|
|
13
|
+
/** Every method invocation, in call order. */
|
|
14
|
+
calls: RecordedAdaMessagingCall[];
|
|
15
|
+
/**
|
|
16
|
+
* Deliver an event to `subscribeEvent` and `subscribeAll` callbacks, as if
|
|
17
|
+
* the SDK emitted it (e.g. `$emit("ada:ready", { isRolledOut: true })`).
|
|
18
|
+
* Routing matches the real SDK: keyed subscriptions match by prefix
|
|
19
|
+
* (`"ada:campaigns"` catches `"ada:campaigns:shown"`), except the
|
|
20
|
+
* transcript events `ada:message:sent`/`ada:message:received`, which reach
|
|
21
|
+
* exact-key subscribers only and never `subscribeAll`.
|
|
22
|
+
*/
|
|
23
|
+
$emit: (key: string, data?: unknown) => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create an in-memory messaging-interface stand-in for unit-testing an
|
|
27
|
+
* integration without loading the SDK from the CDN.
|
|
28
|
+
*
|
|
29
|
+
* Every method resolves, records itself in `calls`, and keeps just enough
|
|
30
|
+
* state to behave like the real interface: `sendMessage` appends a
|
|
31
|
+
* programmatic user message that `getMessages` returns, `open`/`close`/
|
|
32
|
+
* `toggle` drive `isOpen` and `getInfo`, `setMetaFields` feeds
|
|
33
|
+
* `getMetaFields` (sensitive fields are never returned, matching the real
|
|
34
|
+
* SDK), and `$emit` fans out to `subscribeEvent`/`subscribeAll` callbacks.
|
|
35
|
+
*
|
|
36
|
+
* Pass `overrides` to replace any method (e.g. with `vi.fn()`); overridden
|
|
37
|
+
* methods are still recorded in `calls`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createMockAdaMessaging(overrides?: Partial<AdaMessagingInterface>): MockAdaMessaging;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
//#region src/npm/testing.ts
|
|
2
|
+
var EXACT_MATCH_EVENT_KEYS = new Set(["ada:message:sent", "ada:message:received"]);
|
|
3
|
+
function keyedSubscriptionMatches(subscriptionKey, eventKey) {
|
|
4
|
+
if (EXACT_MATCH_EVENT_KEYS.has(eventKey)) return subscriptionKey === eventKey;
|
|
5
|
+
return subscriptionKey === eventKey || eventKey.startsWith(subscriptionKey);
|
|
6
|
+
}
|
|
7
|
+
function toMetaFieldRecord(fields) {
|
|
8
|
+
const record = {};
|
|
9
|
+
for (const [key, value] of Object.entries(fields)) if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) record[key] = value;
|
|
10
|
+
return record;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Create an in-memory messaging-interface stand-in for unit-testing an
|
|
14
|
+
* integration without loading the SDK from the CDN.
|
|
15
|
+
*
|
|
16
|
+
* Every method resolves, records itself in `calls`, and keeps just enough
|
|
17
|
+
* state to behave like the real interface: `sendMessage` appends a
|
|
18
|
+
* programmatic user message that `getMessages` returns, `open`/`close`/
|
|
19
|
+
* `toggle` drive `isOpen` and `getInfo`, `setMetaFields` feeds
|
|
20
|
+
* `getMetaFields` (sensitive fields are never returned, matching the real
|
|
21
|
+
* SDK), and `$emit` fans out to `subscribeEvent`/`subscribeAll` callbacks.
|
|
22
|
+
*
|
|
23
|
+
* Pass `overrides` to replace any method (e.g. with `vi.fn()`); overridden
|
|
24
|
+
* methods are still recorded in `calls`.
|
|
25
|
+
*/
|
|
26
|
+
function createMockAdaMessaging(overrides = {}) {
|
|
27
|
+
const calls = [];
|
|
28
|
+
let nextSubscriptionId = 1;
|
|
29
|
+
let nextMessageId = 1;
|
|
30
|
+
let chatOpen = false;
|
|
31
|
+
let conversationId = null;
|
|
32
|
+
const metaFields = {};
|
|
33
|
+
const messages = [];
|
|
34
|
+
const keyedSubscriptions = /* @__PURE__ */ new Map();
|
|
35
|
+
const wildcardSubscriptions = /* @__PURE__ */ new Map();
|
|
36
|
+
const emit = (key, data) => {
|
|
37
|
+
for (const subscription of keyedSubscriptions.values()) if (keyedSubscriptionMatches(subscription.key, key)) subscription.callback(data, { eventKey: key });
|
|
38
|
+
if (EXACT_MATCH_EVENT_KEYS.has(key)) return;
|
|
39
|
+
for (const callback of wildcardSubscriptions.values()) callback(key, data);
|
|
40
|
+
};
|
|
41
|
+
const clearTranscript = () => {
|
|
42
|
+
messages.length = 0;
|
|
43
|
+
conversationId = null;
|
|
44
|
+
};
|
|
45
|
+
const base = {
|
|
46
|
+
start: async () => void 0,
|
|
47
|
+
stop: async () => void 0,
|
|
48
|
+
toggle: async () => {
|
|
49
|
+
chatOpen = !chatOpen;
|
|
50
|
+
},
|
|
51
|
+
deleteHistory: async () => {
|
|
52
|
+
clearTranscript();
|
|
53
|
+
},
|
|
54
|
+
reset: async () => {
|
|
55
|
+
clearTranscript();
|
|
56
|
+
},
|
|
57
|
+
setMetaFields: async (fields) => {
|
|
58
|
+
Object.assign(metaFields, toMetaFieldRecord(fields));
|
|
59
|
+
},
|
|
60
|
+
setSensitiveMetaFields: async () => void 0,
|
|
61
|
+
setTestModeBanner: async () => void 0,
|
|
62
|
+
getInfo: async () => ({
|
|
63
|
+
isChatOpen: chatOpen,
|
|
64
|
+
isDrawerOpen: chatOpen,
|
|
65
|
+
hasActiveChatter: messages.length > 0,
|
|
66
|
+
hasClosedChat: false
|
|
67
|
+
}),
|
|
68
|
+
getMetaFields: async () => ({ ...metaFields }),
|
|
69
|
+
isOpen: async () => chatOpen,
|
|
70
|
+
getConversation: async () => ({
|
|
71
|
+
id: conversationId,
|
|
72
|
+
handoff: { inLiveChat: false }
|
|
73
|
+
}),
|
|
74
|
+
getMessages: async () => [...messages],
|
|
75
|
+
setComposerText: async () => void 0,
|
|
76
|
+
setDelegate: () => void 0,
|
|
77
|
+
trackEvent: async () => void 0,
|
|
78
|
+
subscribeEvent: async (key, callback) => {
|
|
79
|
+
const id = nextSubscriptionId++;
|
|
80
|
+
keyedSubscriptions.set(id, {
|
|
81
|
+
key,
|
|
82
|
+
callback
|
|
83
|
+
});
|
|
84
|
+
return id;
|
|
85
|
+
},
|
|
86
|
+
unsubscribeEvent: async (id) => {
|
|
87
|
+
keyedSubscriptions.delete(id);
|
|
88
|
+
wildcardSubscriptions.delete(id);
|
|
89
|
+
},
|
|
90
|
+
subscribeAll: async (callback) => {
|
|
91
|
+
const id = nextSubscriptionId++;
|
|
92
|
+
wildcardSubscriptions.set(id, callback);
|
|
93
|
+
return id;
|
|
94
|
+
},
|
|
95
|
+
open: async () => {
|
|
96
|
+
chatOpen = true;
|
|
97
|
+
},
|
|
98
|
+
close: async () => {
|
|
99
|
+
chatOpen = false;
|
|
100
|
+
},
|
|
101
|
+
setLanguage: async () => void 0,
|
|
102
|
+
setTheme: async () => void 0,
|
|
103
|
+
setDeviceToken: async () => void 0,
|
|
104
|
+
sendMessage: async (body) => {
|
|
105
|
+
const id = `mock-message-${nextMessageId++}`;
|
|
106
|
+
conversationId = conversationId ?? "mock-conversation";
|
|
107
|
+
messages.push({
|
|
108
|
+
id,
|
|
109
|
+
role: "user",
|
|
110
|
+
type: "text",
|
|
111
|
+
body,
|
|
112
|
+
createdAt: Math.floor(Date.now() / 1e3),
|
|
113
|
+
origin: "programmatic"
|
|
114
|
+
});
|
|
115
|
+
return { id };
|
|
116
|
+
},
|
|
117
|
+
handleNotification: async () => {
|
|
118
|
+
chatOpen = true;
|
|
119
|
+
},
|
|
120
|
+
requestNotifications: async () => "granted",
|
|
121
|
+
createProactive: async () => void 0,
|
|
122
|
+
triggerCampaign: async () => void 0,
|
|
123
|
+
evaluateCampaignConditions: async () => void 0,
|
|
124
|
+
closeCampaign: async () => void 0,
|
|
125
|
+
triggerAnswer: async () => void 0,
|
|
126
|
+
triggerProactive: async () => void 0,
|
|
127
|
+
triggerGreeting: async () => void 0,
|
|
128
|
+
destroy: async () => {
|
|
129
|
+
keyedSubscriptions.clear();
|
|
130
|
+
wildcardSubscriptions.clear();
|
|
131
|
+
chatOpen = false;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const definedOverrides = Object.fromEntries(Object.entries(overrides).filter(([, value]) => value !== void 0));
|
|
135
|
+
const implementation = {
|
|
136
|
+
...base,
|
|
137
|
+
...definedOverrides
|
|
138
|
+
};
|
|
139
|
+
return {
|
|
140
|
+
...Object.fromEntries(Object.entries(implementation).map(([method, fn]) => [method, (...args) => {
|
|
141
|
+
calls.push({
|
|
142
|
+
method,
|
|
143
|
+
args
|
|
144
|
+
});
|
|
145
|
+
return fn(...args);
|
|
146
|
+
}])),
|
|
147
|
+
calls,
|
|
148
|
+
$emit: emit
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
152
|
+
export { createMockAdaMessaging };
|
|
153
|
+
|
|
154
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","names":[],"sources":["../../src/npm/testing.ts"],"sourcesContent":["import type {\n\tAdaSdkEventCallback,\n\tMetaFieldValue,\n\tPublicMessage,\n} from \"../client/client-types\";\nimport type { AdaMessagingInterface } from \"./loader\";\n\n/** One recorded method invocation on a {@link MockAdaMessaging}. */\nexport interface RecordedAdaMessagingCall {\n\tmethod: string;\n\targs: unknown[];\n}\n\n/**\n * The mock returned by {@link createMockAdaMessaging}: the full\n * {@link AdaMessagingInterface} plus test hooks for inspecting calls and\n * simulating SDK events.\n */\nexport interface MockAdaMessaging extends AdaMessagingInterface {\n\t/** Every method invocation, in call order. */\n\tcalls: RecordedAdaMessagingCall[];\n\t/**\n\t * Deliver an event to `subscribeEvent` and `subscribeAll` callbacks, as if\n\t * the SDK emitted it (e.g. `$emit(\"ada:ready\", { isRolledOut: true })`).\n\t * Routing matches the real SDK: keyed subscriptions match by prefix\n\t * (`\"ada:campaigns\"` catches `\"ada:campaigns:shown\"`), except the\n\t * transcript events `ada:message:sent`/`ada:message:received`, which reach\n\t * exact-key subscribers only and never `subscribeAll`.\n\t */\n\t$emit: (key: string, data?: unknown) => void;\n}\n\ninterface KeyedSubscription {\n\tkey: string;\n\tcallback: AdaSdkEventCallback;\n}\n\n// Mirrors EXACT_MATCH_EVENT_KEYS in client/client-host-runtime.ts: transcript\n// events reach exact-key subscribers only, never prefix or subscribeAll\n// subscribers. Duplicated (not imported) so the published testing entry stays\n// free of runtime modules; a drift test pins the mock against the real matcher.\nconst EXACT_MATCH_EVENT_KEYS = new Set([\n\t\"ada:message:sent\",\n\t\"ada:message:received\",\n]);\n\nfunction keyedSubscriptionMatches(\n\tsubscriptionKey: string,\n\teventKey: string,\n): boolean {\n\tif (EXACT_MATCH_EVENT_KEYS.has(eventKey)) {\n\t\treturn subscriptionKey === eventKey;\n\t}\n\t// Raw prefix match, same as the real SDK: \"ada:campaigns\" also catches\n\t// \"ada:campaigns:shown\" and underscore-suffixed keys.\n\treturn subscriptionKey === eventKey || eventKey.startsWith(subscriptionKey);\n}\n\nfunction toMetaFieldRecord(\n\tfields: Record<string, unknown>,\n): Record<string, MetaFieldValue> {\n\tconst record: Record<string, MetaFieldValue> = {};\n\tfor (const [key, value] of Object.entries(fields)) {\n\t\tif (\n\t\t\ttypeof value === \"string\" ||\n\t\t\ttypeof value === \"number\" ||\n\t\t\ttypeof value === \"boolean\" ||\n\t\t\tvalue === null\n\t\t) {\n\t\t\trecord[key] = value;\n\t\t}\n\t}\n\treturn record;\n}\n\n/**\n * Create an in-memory messaging-interface stand-in for unit-testing an\n * integration without loading the SDK from the CDN.\n *\n * Every method resolves, records itself in `calls`, and keeps just enough\n * state to behave like the real interface: `sendMessage` appends a\n * programmatic user message that `getMessages` returns, `open`/`close`/\n * `toggle` drive `isOpen` and `getInfo`, `setMetaFields` feeds\n * `getMetaFields` (sensitive fields are never returned, matching the real\n * SDK), and `$emit` fans out to `subscribeEvent`/`subscribeAll` callbacks.\n *\n * Pass `overrides` to replace any method (e.g. with `vi.fn()`); overridden\n * methods are still recorded in `calls`.\n */\nexport function createMockAdaMessaging(\n\toverrides: Partial<AdaMessagingInterface> = {},\n): MockAdaMessaging {\n\tconst calls: RecordedAdaMessagingCall[] = [];\n\tlet nextSubscriptionId = 1;\n\tlet nextMessageId = 1;\n\tlet chatOpen = false;\n\tlet conversationId: string | null = null;\n\tconst metaFields: Record<string, MetaFieldValue> = {};\n\tconst messages: PublicMessage[] = [];\n\tconst keyedSubscriptions = new Map<number, KeyedSubscription>();\n\tconst wildcardSubscriptions = new Map<\n\t\tnumber,\n\t\t(key: string, data: unknown) => void\n\t>();\n\n\tconst emit = (key: string, data?: unknown): void => {\n\t\tfor (const subscription of keyedSubscriptions.values()) {\n\t\t\tif (keyedSubscriptionMatches(subscription.key, key)) {\n\t\t\t\tsubscription.callback(data, { eventKey: key });\n\t\t\t}\n\t\t}\n\t\tif (EXACT_MATCH_EVENT_KEYS.has(key)) {\n\t\t\treturn;\n\t\t}\n\t\tfor (const callback of wildcardSubscriptions.values()) {\n\t\t\tcallback(key, data);\n\t\t}\n\t};\n\n\tconst clearTranscript = (): void => {\n\t\tmessages.length = 0;\n\t\tconversationId = null;\n\t};\n\n\tconst base: AdaMessagingInterface = {\n\t\tstart: async () => undefined,\n\t\tstop: async () => undefined,\n\t\ttoggle: async () => {\n\t\t\tchatOpen = !chatOpen;\n\t\t},\n\t\tdeleteHistory: async () => {\n\t\t\tclearTranscript();\n\t\t},\n\t\treset: async () => {\n\t\t\tclearTranscript();\n\t\t},\n\t\tsetMetaFields: async (fields) => {\n\t\t\tObject.assign(metaFields, toMetaFieldRecord(fields));\n\t\t},\n\t\t// Sensitive fields are accepted but never readable back, matching the\n\t\t// real SDK's getMetaFields contract.\n\t\tsetSensitiveMetaFields: async () => undefined,\n\t\tsetTestModeBanner: async () => undefined,\n\t\tgetInfo: async () => ({\n\t\t\tisChatOpen: chatOpen,\n\t\t\tisDrawerOpen: chatOpen,\n\t\t\thasActiveChatter: messages.length > 0,\n\t\t\thasClosedChat: false,\n\t\t}),\n\t\tgetMetaFields: async () => ({ ...metaFields }),\n\t\tisOpen: async () => chatOpen,\n\t\tgetConversation: async () => ({\n\t\t\tid: conversationId,\n\t\t\thandoff: { inLiveChat: false },\n\t\t}),\n\t\tgetMessages: async () => [...messages],\n\t\tsetComposerText: async () => undefined,\n\t\tsetDelegate: () => undefined,\n\t\ttrackEvent: async () => undefined,\n\t\tsubscribeEvent: async (key, callback) => {\n\t\t\tconst id = nextSubscriptionId++;\n\t\t\tkeyedSubscriptions.set(id, { key, callback });\n\t\t\treturn id;\n\t\t},\n\t\tunsubscribeEvent: async (id) => {\n\t\t\tkeyedSubscriptions.delete(id);\n\t\t\twildcardSubscriptions.delete(id);\n\t\t},\n\t\tsubscribeAll: async (callback) => {\n\t\t\tconst id = nextSubscriptionId++;\n\t\t\twildcardSubscriptions.set(id, callback);\n\t\t\treturn id;\n\t\t},\n\t\topen: async () => {\n\t\t\tchatOpen = true;\n\t\t},\n\t\tclose: async () => {\n\t\t\tchatOpen = false;\n\t\t},\n\t\tsetLanguage: async () => undefined,\n\t\tsetTheme: async () => undefined,\n\t\tsetDeviceToken: async () => undefined,\n\t\tsendMessage: async (body) => {\n\t\t\tconst id = `mock-message-${nextMessageId++}`;\n\t\t\tconversationId = conversationId ?? \"mock-conversation\";\n\t\t\tmessages.push({\n\t\t\t\tid,\n\t\t\t\trole: \"user\",\n\t\t\t\ttype: \"text\",\n\t\t\t\tbody,\n\t\t\t\tcreatedAt: Math.floor(Date.now() / 1000),\n\t\t\t\torigin: \"programmatic\",\n\t\t\t});\n\t\t\treturn { id };\n\t\t},\n\t\thandleNotification: async () => {\n\t\t\tchatOpen = true;\n\t\t},\n\t\trequestNotifications: async () => \"granted\",\n\t\tcreateProactive: async () => undefined,\n\t\ttriggerCampaign: async () => undefined,\n\t\tevaluateCampaignConditions: async () => undefined,\n\t\tcloseCampaign: async () => undefined,\n\t\ttriggerAnswer: async () => undefined,\n\t\ttriggerProactive: async () => undefined,\n\t\ttriggerGreeting: async () => undefined,\n\t\tdestroy: async () => {\n\t\t\tkeyedSubscriptions.clear();\n\t\t\twildcardSubscriptions.clear();\n\t\t\tchatOpen = false;\n\t\t},\n\t};\n\n\tconst definedOverrides = Object.fromEntries(\n\t\tObject.entries(overrides).filter(([, value]) => value !== undefined),\n\t);\n\tconst implementation = { ...base, ...definedOverrides };\n\tconst recorded = Object.fromEntries(\n\t\tObject.entries(implementation).map(([method, fn]) => [\n\t\t\tmethod,\n\t\t\t(...args: unknown[]) => {\n\t\t\t\tcalls.push({ method, args });\n\t\t\t\treturn (fn as (...callArgs: unknown[]) => unknown)(...args);\n\t\t\t},\n\t\t]),\n\t) as unknown as AdaMessagingInterface;\n\n\treturn { ...recorded, calls, $emit: emit };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function loadMessagingSdkModule(scriptUrl: string): Promise<unknown>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export declare const CSAT_INTEGRATION_ID: "csat";
|
|
2
|
+
export declare const CSAT_SUBMIT_ACTION: "survey.submit";
|
|
3
|
+
export declare const CSAT_SUBMITTED_ACTION_ALIAS: "survey.submitted";
|
|
4
|
+
export declare const CSAT_CHANNEL_NAME: "integration.csat";
|
|
5
|
+
export declare const CSAT_CONFIG_SET_TYPE: "integration.config.set";
|
|
6
|
+
export declare const CSAT_RESULT_TYPE: "integration.result";
|
|
7
|
+
export declare const CSAT_SURVEY_TYPES: readonly [
|
|
8
|
+
"answer_flow",
|
|
9
|
+
"proactive",
|
|
10
|
+
"end_chat",
|
|
11
|
+
"live_chat",
|
|
12
|
+
];
|
|
13
|
+
export type CsatSurveyType = (typeof CSAT_SURVEY_TYPES)[number];
|
|
14
|
+
export declare function isCsatSurveyType(
|
|
15
|
+
value: unknown,
|
|
16
|
+
): value is CsatSurveyType;
|
|
17
|
+
export declare const POST_AGENT_CSAT_SURVEY_TYPES: ReadonlySet<CsatSurveyType>;
|
|
18
|
+
export declare function isPostAgentCsatSurveyType(value: string): boolean;
|
|
19
|
+
export declare function isCsatSubmitAction(action: string): boolean;
|
|
20
|
+
export declare function normalizeCsatSubmitAction(action: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* The four `csat_style` values accepted by the Ada API on
|
|
23
|
+
* `/surveys/submit_survey` (see `api/internal_apis/surveys/spec.yml` and
|
|
24
|
+
* `api/core/feedback/surveys/models/csat_styles.py`).
|
|
25
|
+
*/
|
|
26
|
+
export declare const CSAT_STYLE_API_VALUES: readonly [
|
|
27
|
+
"NUMERIC",
|
|
28
|
+
"NUMERIC_TEN",
|
|
29
|
+
"THUMBS",
|
|
30
|
+
"EMOJI",
|
|
31
|
+
];
|
|
32
|
+
export type CsatStyleApiValue = (typeof CSAT_STYLE_API_VALUES)[number];
|
|
33
|
+
export interface CsatApiScoreAndStyle {
|
|
34
|
+
score: number;
|
|
35
|
+
style: CsatStyleApiValue;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Translates a messaging UI scale string (`"1-5"`, `"1-10"`, `"emoji"`) to the
|
|
39
|
+
* corresponding API enum value accepted by `/surveys/submit_survey`
|
|
40
|
+
* (`NUMERIC`, `NUMERIC_TEN`, `EMOJI`).
|
|
41
|
+
*
|
|
42
|
+
* Returns `null` when the scale cannot be represented by the API enum without
|
|
43
|
+
* also transforming the score. Use `toCsatApiScoreAndStyle` for outbound
|
|
44
|
+
* `/surveys/submit_survey` payloads.
|
|
45
|
+
*
|
|
46
|
+
* Intentionally NOT mapped (returns `null`):
|
|
47
|
+
*
|
|
48
|
+
* - `"1-7"` — API has no `NUMERIC_SEVEN`; collapsing to `NUMERIC` would let
|
|
49
|
+
* the UI emit `csat_score=7`, which the API rejects when `csat_style="NUMERIC"`
|
|
50
|
+
* (NUMERIC range is 1–5, see `api/internal_apis/surveys/spec.yml`).
|
|
51
|
+
* - `"0-10"` — API has no `NUMERIC_TEN_WITH_ZERO`; collapsing to `NUMERIC_TEN`
|
|
52
|
+
* would let `csat_score=0` slip through, which `NUMERIC_TEN` (range 1–10)
|
|
53
|
+
* rejects.
|
|
54
|
+
* - `"thumbs"` — messaging's UI emits `csat_score=1` / `csat_score=5` for
|
|
55
|
+
* thumbs-down/thumbs-up, but API `THUMBS` expects `0/1`. This is handled by
|
|
56
|
+
* `toCsatApiScoreAndStyle`.
|
|
57
|
+
*
|
|
58
|
+
* Pass-through: callers that already supply one of the four canonical API
|
|
59
|
+
* values get them back unchanged.
|
|
60
|
+
*/
|
|
61
|
+
export declare function toCsatStyleApiValue(
|
|
62
|
+
uiStyle: string | null | undefined,
|
|
63
|
+
): CsatStyleApiValue | null;
|
|
64
|
+
/**
|
|
65
|
+
* Converts the score/style pair emitted by messaging UI into the raw integer
|
|
66
|
+
* pair accepted by the current `/surveys/submit_survey` API.
|
|
67
|
+
*
|
|
68
|
+
* The API validates scores as native values for the provided `csat_style`:
|
|
69
|
+
* `NUMERIC`/`EMOJI` 1-5, `NUMERIC_TEN` 1-10, `THUMBS` 0-1. Messaging's thumbs
|
|
70
|
+
* UI still emits legacy 5-point values (1 = down, 5 = up), so this helper maps
|
|
71
|
+
* them to API-native 0/1 before the request.
|
|
72
|
+
*
|
|
73
|
+
* Missing, unknown, and unsupported legacy satisfaction scales (`1-7`, `0-10`)
|
|
74
|
+
* return `null` because the current API requires `csat_style` when
|
|
75
|
+
* `csat_score` is provided and has no matching style for those legacy scales.
|
|
76
|
+
*/
|
|
77
|
+
export declare function toCsatApiScoreAndStyle(
|
|
78
|
+
score: number,
|
|
79
|
+
uiStyle: string | null | undefined,
|
|
80
|
+
): CsatApiScoreAndStyle | null;
|
|
81
|
+
/**
|
|
82
|
+
* The inverse of {@link toCsatApiScoreAndStyle}: turns a stored `csat_score` /
|
|
83
|
+
* `csat_style` pair back into the score and scale string the UI renders on.
|
|
84
|
+
*
|
|
85
|
+
* Only `THUMBS` needs the score itself moved — messaging's thumbs UI selects on
|
|
86
|
+
* the legacy 5-point values (1 = down, 5 = up) while the API stores 0/1, so a
|
|
87
|
+
* restored thumbs answer would otherwise select no chip at all.
|
|
88
|
+
*
|
|
89
|
+
* Returns `null` when the pair cannot be rendered, which callers read as "start
|
|
90
|
+
* with no satisfaction answer" rather than as an error.
|
|
91
|
+
*/
|
|
92
|
+
export declare function fromCsatApiScoreAndStyle(
|
|
93
|
+
score: unknown,
|
|
94
|
+
apiStyle: unknown,
|
|
95
|
+
): {
|
|
96
|
+
score: number;
|
|
97
|
+
style: string;
|
|
98
|
+
} | null;
|
|
99
|
+
/**
|
|
100
|
+
* The inverse of {@link toCsatStyleApiValue}: maps an API enum value back to
|
|
101
|
+
* the lowercase UI scale string that messaging's UI renderers (`CsatSurveyForm`,
|
|
102
|
+
* `CsatPromptSheet`, `CsatInlineBlock`) branch on. The `/csat_settings`
|
|
103
|
+
* response and the `csat` log message both serialize `satisfaction_style` /
|
|
104
|
+
* `scale_type` as the API's uppercase enum (`THUMBS`, `EMOJI`, `NUMERIC`,
|
|
105
|
+
* `NUMERIC_TEN`), so without this translation the UI silently falls through
|
|
106
|
+
* to the `"1-5"` default and renders the wrong scale.
|
|
107
|
+
*
|
|
108
|
+
* Strings that are already in the UI's lowercase format (e.g. `"1-7"`,
|
|
109
|
+
* `"0-10"`, `"thumbs"`, `"emoji"`) are returned unchanged so legacy payloads
|
|
110
|
+
* keep working.
|
|
111
|
+
*
|
|
112
|
+
* Returns `null` only when given a non-string or empty input.
|
|
113
|
+
*/
|
|
114
|
+
export declare function fromCsatStyleApiValue(
|
|
115
|
+
apiStyle: string | null | undefined,
|
|
116
|
+
): string | null;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type HostTelemetrySurface = "mobile" | "browser";
|
|
2
|
+
export type HostTelemetryPlatform =
|
|
3
|
+
| "ios"
|
|
4
|
+
| "android"
|
|
5
|
+
| "react-native"
|
|
6
|
+
| "web"
|
|
7
|
+
| "unknown";
|
|
8
|
+
export type HostTelemetryWebSdkOrigin = "legacy" | "messaging";
|
|
9
|
+
export type HostTelemetryMobileShell = "messaging-sdk" | "legacy-sdk";
|
|
10
|
+
export interface HostTelemetryContext {
|
|
11
|
+
surface: HostTelemetrySurface;
|
|
12
|
+
hostPlatform: HostTelemetryPlatform;
|
|
13
|
+
webSdkOrigin: HostTelemetryWebSdkOrigin;
|
|
14
|
+
mobileShell?: HostTelemetryMobileShell;
|
|
15
|
+
mobilePackage?: string;
|
|
16
|
+
mobileVersion?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function sanitizeHostTelemetryContext(
|
|
19
|
+
value: unknown,
|
|
20
|
+
): HostTelemetryContext | undefined;
|
|
21
|
+
export declare function resolveHostTelemetryContext(
|
|
22
|
+
hostTelemetry: HostTelemetryContext | undefined,
|
|
23
|
+
{
|
|
24
|
+
defaultOrigin,
|
|
25
|
+
defaultSurface,
|
|
26
|
+
defaultPlatform,
|
|
27
|
+
}: {
|
|
28
|
+
defaultOrigin: HostTelemetryWebSdkOrigin;
|
|
29
|
+
defaultSurface: HostTelemetrySurface;
|
|
30
|
+
defaultPlatform?: HostTelemetryPlatform;
|
|
31
|
+
},
|
|
32
|
+
): HostTelemetryContext;
|
|
33
|
+
export declare function toHostTelemetryMonitoringContext(
|
|
34
|
+
hostTelemetry: HostTelemetryContext,
|
|
35
|
+
): Record<string, string>;
|