@thoughtspot/visual-embed-sdk 1.52.2-beta.1 → 1.53.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.
Files changed (237) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/css-variables.d.ts +373 -5
  3. package/cjs/src/css-variables.d.ts.map +1 -1
  4. package/cjs/src/embed/app.d.ts +14 -0
  5. package/cjs/src/embed/app.d.ts.map +1 -1
  6. package/cjs/src/embed/app.js +6 -3
  7. package/cjs/src/embed/app.js.map +1 -1
  8. package/cjs/src/embed/app.spec.js +28 -0
  9. package/cjs/src/embed/app.spec.js.map +1 -1
  10. package/cjs/src/embed/auto-frame-renderer.d.ts.map +1 -1
  11. package/cjs/src/embed/auto-frame-renderer.js +244 -4
  12. package/cjs/src/embed/auto-frame-renderer.js.map +1 -1
  13. package/cjs/src/embed/auto-frame-renderer.spec.js +389 -0
  14. package/cjs/src/embed/auto-frame-renderer.spec.js.map +1 -1
  15. package/cjs/src/embed/bodyless-conversation.js +1 -1
  16. package/cjs/src/embed/bodyless-conversation.js.map +1 -1
  17. package/cjs/src/embed/conversation.d.ts +15 -0
  18. package/cjs/src/embed/conversation.d.ts.map +1 -1
  19. package/cjs/src/embed/conversation.js +7 -3
  20. package/cjs/src/embed/conversation.js.map +1 -1
  21. package/cjs/src/embed/conversation.spec.js +66 -0
  22. package/cjs/src/embed/conversation.spec.js.map +1 -1
  23. package/cjs/src/embed/liveboard-override-utils.d.ts +59 -0
  24. package/cjs/src/embed/liveboard-override-utils.d.ts.map +1 -0
  25. package/cjs/src/embed/liveboard-override-utils.js +19 -0
  26. package/cjs/src/embed/liveboard-override-utils.js.map +1 -0
  27. package/cjs/src/embed/liveboard-override-utils.spec.d.ts +2 -0
  28. package/cjs/src/embed/liveboard-override-utils.spec.d.ts.map +1 -0
  29. package/cjs/src/embed/liveboard-override-utils.spec.js +34 -0
  30. package/cjs/src/embed/liveboard-override-utils.spec.js.map +1 -0
  31. package/cjs/src/embed/liveboard.d.ts +43 -1
  32. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  33. package/cjs/src/embed/liveboard.js +11 -18
  34. package/cjs/src/embed/liveboard.js.map +1 -1
  35. package/cjs/src/embed/liveboard.spec.js +104 -54
  36. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  37. package/cjs/src/embed/search-bar.js +1 -1
  38. package/cjs/src/embed/search-bar.js.map +1 -1
  39. package/cjs/src/embed/search.js +1 -1
  40. package/cjs/src/embed/search.js.map +1 -1
  41. package/cjs/src/embed/search.spec.js +20 -0
  42. package/cjs/src/embed/search.spec.js.map +1 -1
  43. package/cjs/src/embed/spotter-utils.d.ts +11 -0
  44. package/cjs/src/embed/spotter-utils.d.ts.map +1 -1
  45. package/cjs/src/embed/spotter-utils.js +13 -1
  46. package/cjs/src/embed/spotter-utils.js.map +1 -1
  47. package/cjs/src/embed/spotter-viz-utils.d.ts +15 -0
  48. package/cjs/src/embed/spotter-viz-utils.d.ts.map +1 -1
  49. package/cjs/src/embed/spotter-viz-utils.js.map +1 -1
  50. package/cjs/src/embed/spotter-viz-utils.spec.js +11 -0
  51. package/cjs/src/embed/spotter-viz-utils.spec.js.map +1 -1
  52. package/cjs/src/embed/ts-embed.d.ts +27 -34
  53. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  54. package/cjs/src/embed/ts-embed.js +224 -102
  55. package/cjs/src/embed/ts-embed.js.map +1 -1
  56. package/cjs/src/embed/ts-embed.spec.d.ts.map +1 -1
  57. package/cjs/src/embed/ts-embed.spec.js +543 -171
  58. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  59. package/cjs/src/index.d.ts +4 -2
  60. package/cjs/src/index.d.ts.map +1 -1
  61. package/cjs/src/index.js +4 -2
  62. package/cjs/src/index.js.map +1 -1
  63. package/cjs/src/mixpanel-service.d.ts +1 -0
  64. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  65. package/cjs/src/mixpanel-service.js +1 -0
  66. package/cjs/src/mixpanel-service.js.map +1 -1
  67. package/cjs/src/react/all-types-export.d.ts +1 -1
  68. package/cjs/src/react/all-types-export.d.ts.map +1 -1
  69. package/cjs/src/react/all-types-export.js +2 -1
  70. package/cjs/src/react/all-types-export.js.map +1 -1
  71. package/cjs/src/types.d.ts +182 -2
  72. package/cjs/src/types.d.ts.map +1 -1
  73. package/cjs/src/types.js +109 -0
  74. package/cjs/src/types.js.map +1 -1
  75. package/cjs/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  76. package/cjs/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  77. package/cjs/src/utils/graphql/answerService/answer-queries.js +8 -1
  78. package/cjs/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  79. package/cjs/src/utils/graphql/answerService/answerService.d.ts +28 -4
  80. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  81. package/cjs/src/utils/graphql/answerService/answerService.js +39 -4
  82. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  83. package/cjs/src/utils/graphql/answerService/answerService.spec.js +124 -0
  84. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  85. package/dist/{index-Bt56pC82.js → index-CyDR8j_0.js} +1 -1
  86. package/dist/src/css-variables.d.ts +373 -5
  87. package/dist/src/css-variables.d.ts.map +1 -1
  88. package/dist/src/embed/app.d.ts +14 -0
  89. package/dist/src/embed/app.d.ts.map +1 -1
  90. package/dist/src/embed/auto-frame-renderer.d.ts.map +1 -1
  91. package/dist/src/embed/conversation.d.ts +15 -0
  92. package/dist/src/embed/conversation.d.ts.map +1 -1
  93. package/dist/src/embed/liveboard-override-utils.d.ts +59 -0
  94. package/dist/src/embed/liveboard-override-utils.d.ts.map +1 -0
  95. package/dist/src/embed/liveboard-override-utils.spec.d.ts +2 -0
  96. package/dist/src/embed/liveboard-override-utils.spec.d.ts.map +1 -0
  97. package/dist/src/embed/liveboard.d.ts +43 -1
  98. package/dist/src/embed/liveboard.d.ts.map +1 -1
  99. package/dist/src/embed/spotter-utils.d.ts +11 -0
  100. package/dist/src/embed/spotter-utils.d.ts.map +1 -1
  101. package/dist/src/embed/spotter-viz-utils.d.ts +15 -0
  102. package/dist/src/embed/spotter-viz-utils.d.ts.map +1 -1
  103. package/dist/src/embed/ts-embed.d.ts +27 -34
  104. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  105. package/dist/src/embed/ts-embed.spec.d.ts.map +1 -1
  106. package/dist/src/index.d.ts +4 -2
  107. package/dist/src/index.d.ts.map +1 -1
  108. package/dist/src/mixpanel-service.d.ts +1 -0
  109. package/dist/src/mixpanel-service.d.ts.map +1 -1
  110. package/dist/src/react/all-types-export.d.ts +1 -1
  111. package/dist/src/react/all-types-export.d.ts.map +1 -1
  112. package/dist/src/types.d.ts +182 -2
  113. package/dist/src/types.d.ts.map +1 -1
  114. package/dist/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  115. package/dist/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  116. package/dist/src/utils/graphql/answerService/answerService.d.ts +28 -4
  117. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  118. package/dist/tsembed-react.es.js +437 -175
  119. package/dist/tsembed-react.js +436 -174
  120. package/dist/tsembed.es.js +680 -180
  121. package/dist/tsembed.js +678 -178
  122. package/dist/visual-embed-sdk-react-full.d.ts +702 -44
  123. package/dist/visual-embed-sdk-react.d.ts +697 -44
  124. package/dist/visual-embed-sdk.d.ts +729 -45
  125. package/lib/package.json +1 -1
  126. package/lib/src/css-variables.d.ts +373 -5
  127. package/lib/src/css-variables.d.ts.map +1 -1
  128. package/lib/src/embed/app.d.ts +14 -0
  129. package/lib/src/embed/app.d.ts.map +1 -1
  130. package/lib/src/embed/app.js +7 -4
  131. package/lib/src/embed/app.js.map +1 -1
  132. package/lib/src/embed/app.spec.js +28 -0
  133. package/lib/src/embed/app.spec.js.map +1 -1
  134. package/lib/src/embed/auto-frame-renderer.d.ts.map +1 -1
  135. package/lib/src/embed/auto-frame-renderer.js +244 -4
  136. package/lib/src/embed/auto-frame-renderer.js.map +1 -1
  137. package/lib/src/embed/auto-frame-renderer.spec.js +389 -0
  138. package/lib/src/embed/auto-frame-renderer.spec.js.map +1 -1
  139. package/lib/src/embed/bodyless-conversation.js +1 -1
  140. package/lib/src/embed/bodyless-conversation.js.map +1 -1
  141. package/lib/src/embed/conversation.d.ts +15 -0
  142. package/lib/src/embed/conversation.d.ts.map +1 -1
  143. package/lib/src/embed/conversation.js +8 -4
  144. package/lib/src/embed/conversation.js.map +1 -1
  145. package/lib/src/embed/conversation.spec.js +67 -1
  146. package/lib/src/embed/conversation.spec.js.map +1 -1
  147. package/lib/src/embed/liveboard-override-utils.d.ts +59 -0
  148. package/lib/src/embed/liveboard-override-utils.d.ts.map +1 -0
  149. package/lib/src/embed/liveboard-override-utils.js +15 -0
  150. package/lib/src/embed/liveboard-override-utils.js.map +1 -0
  151. package/lib/src/embed/liveboard-override-utils.spec.d.ts +2 -0
  152. package/lib/src/embed/liveboard-override-utils.spec.d.ts.map +1 -0
  153. package/lib/src/embed/liveboard-override-utils.spec.js +32 -0
  154. package/lib/src/embed/liveboard-override-utils.spec.js.map +1 -0
  155. package/lib/src/embed/liveboard.d.ts +43 -1
  156. package/lib/src/embed/liveboard.d.ts.map +1 -1
  157. package/lib/src/embed/liveboard.js +11 -17
  158. package/lib/src/embed/liveboard.js.map +1 -1
  159. package/lib/src/embed/liveboard.spec.js +104 -54
  160. package/lib/src/embed/liveboard.spec.js.map +1 -1
  161. package/lib/src/embed/search-bar.js +1 -1
  162. package/lib/src/embed/search-bar.js.map +1 -1
  163. package/lib/src/embed/search.js +1 -1
  164. package/lib/src/embed/search.js.map +1 -1
  165. package/lib/src/embed/search.spec.js +20 -0
  166. package/lib/src/embed/search.spec.js.map +1 -1
  167. package/lib/src/embed/spotter-utils.d.ts +11 -0
  168. package/lib/src/embed/spotter-utils.d.ts.map +1 -1
  169. package/lib/src/embed/spotter-utils.js +12 -0
  170. package/lib/src/embed/spotter-utils.js.map +1 -1
  171. package/lib/src/embed/spotter-viz-utils.d.ts +15 -0
  172. package/lib/src/embed/spotter-viz-utils.d.ts.map +1 -1
  173. package/lib/src/embed/spotter-viz-utils.js.map +1 -1
  174. package/lib/src/embed/spotter-viz-utils.spec.js +11 -0
  175. package/lib/src/embed/spotter-viz-utils.spec.js.map +1 -1
  176. package/lib/src/embed/ts-embed.d.ts +27 -34
  177. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  178. package/lib/src/embed/ts-embed.js +224 -102
  179. package/lib/src/embed/ts-embed.js.map +1 -1
  180. package/lib/src/embed/ts-embed.spec.d.ts.map +1 -1
  181. package/lib/src/embed/ts-embed.spec.js +544 -172
  182. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  183. package/lib/src/index.d.ts +4 -2
  184. package/lib/src/index.d.ts.map +1 -1
  185. package/lib/src/index.js +3 -2
  186. package/lib/src/index.js.map +1 -1
  187. package/lib/src/mixpanel-service.d.ts +1 -0
  188. package/lib/src/mixpanel-service.d.ts.map +1 -1
  189. package/lib/src/mixpanel-service.js +1 -0
  190. package/lib/src/mixpanel-service.js.map +1 -1
  191. package/lib/src/react/all-types-export.d.ts +1 -1
  192. package/lib/src/react/all-types-export.d.ts.map +1 -1
  193. package/lib/src/react/all-types-export.js +1 -1
  194. package/lib/src/react/all-types-export.js.map +1 -1
  195. package/lib/src/types.d.ts +182 -2
  196. package/lib/src/types.d.ts.map +1 -1
  197. package/lib/src/types.js +109 -0
  198. package/lib/src/types.js.map +1 -1
  199. package/lib/src/utils/graphql/answerService/answer-queries.d.ts +1 -0
  200. package/lib/src/utils/graphql/answerService/answer-queries.d.ts.map +1 -1
  201. package/lib/src/utils/graphql/answerService/answer-queries.js +7 -0
  202. package/lib/src/utils/graphql/answerService/answer-queries.js.map +1 -1
  203. package/lib/src/utils/graphql/answerService/answerService.d.ts +28 -4
  204. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  205. package/lib/src/utils/graphql/answerService/answerService.js +39 -4
  206. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  207. package/lib/src/utils/graphql/answerService/answerService.spec.js +125 -1
  208. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  209. package/lib/src/visual-embed-sdk.d.ts +729 -45
  210. package/package.json +1 -1
  211. package/src/css-variables.ts +475 -26
  212. package/src/embed/app.spec.ts +32 -0
  213. package/src/embed/app.ts +28 -4
  214. package/src/embed/auto-frame-renderer.spec.ts +464 -0
  215. package/src/embed/auto-frame-renderer.ts +305 -6
  216. package/src/embed/bodyless-conversation.ts +1 -1
  217. package/src/embed/conversation.spec.ts +94 -1
  218. package/src/embed/conversation.ts +28 -3
  219. package/src/embed/liveboard-override-utils.spec.ts +38 -0
  220. package/src/embed/liveboard-override-utils.ts +71 -0
  221. package/src/embed/liveboard.spec.ts +119 -62
  222. package/src/embed/liveboard.ts +56 -21
  223. package/src/embed/search-bar.tsx +1 -1
  224. package/src/embed/search.spec.ts +23 -0
  225. package/src/embed/search.ts +1 -1
  226. package/src/embed/spotter-utils.ts +12 -0
  227. package/src/embed/spotter-viz-utils.spec.ts +11 -0
  228. package/src/embed/spotter-viz-utils.ts +15 -0
  229. package/src/embed/ts-embed.spec.ts +684 -213
  230. package/src/embed/ts-embed.ts +227 -97
  231. package/src/index.ts +16 -1
  232. package/src/mixpanel-service.ts +1 -0
  233. package/src/react/all-types-export.ts +6 -0
  234. package/src/types.ts +186 -5
  235. package/src/utils/graphql/answerService/answer-queries.ts +8 -0
  236. package/src/utils/graphql/answerService/answerService.spec.ts +145 -1
  237. package/src/utils/graphql/answerService/answerService.ts +65 -3
@@ -11,6 +11,7 @@ const test_utils_1 = require("../test/test-utils");
11
11
  const config = tslib_1.__importStar(require("../config"));
12
12
  const embedConfig = tslib_1.__importStar(require("./embedConfig"));
13
13
  const tsEmbedInstance = tslib_1.__importStar(require("./ts-embed"));
14
+ const ts_embed_1 = require("./ts-embed");
14
15
  const mixpanelInstance = tslib_1.__importStar(require("../mixpanel-service"));
15
16
  const authInstance = tslib_1.__importStar(require("../auth"));
16
17
  const baseInstance = tslib_1.__importStar(require("./base"));
@@ -27,9 +28,6 @@ const apiIntercept = tslib_1.__importStar(require("../api-intercept"));
27
28
  const processData = tslib_1.__importStar(require("../utils/processData"));
28
29
  jest.mock('../utils/processTrigger');
29
30
  const mockProcessTrigger = processTrigger_1.processTrigger;
30
- const flushAnimationFrame = () => new Promise((resolve) => {
31
- requestAnimationFrame(() => resolve());
32
- });
33
31
  const mockHandleInterceptEvent = jest.spyOn(apiIntercept, 'handleInterceptEvent');
34
32
  const defaultViewConfig = {
35
33
  frameParams: {
@@ -1098,6 +1096,26 @@ describe('Unit test case for ts embed', () => {
1098
1096
  elHeight: 0,
1099
1097
  }));
1100
1098
  });
1099
+ test('should send visual-sdk-init-actions with configured actions, [] when unused', async () => {
1100
+ await new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), {
1101
+ hiddenActions: [types_1.Action.Download],
1102
+ disabledActions: [types_1.Action.Edit],
1103
+ }).render();
1104
+ expect(mockMixPanelEvent).toHaveBeenCalledWith(mixpanel_service_1.MIXPANEL_EVENT.VISUAL_SDK_INIT_ACTIONS, expect.objectContaining({
1105
+ hiddenActions: [types_1.Action.Download],
1106
+ visibleActions: [],
1107
+ disabledActions: [types_1.Action.Edit],
1108
+ }));
1109
+ mockMixPanelEvent.mockClear();
1110
+ await new index_1.SearchEmbed((0, test_utils_1.getRootEl)(), {
1111
+ visibleActions: [types_1.Action.Save],
1112
+ }).render();
1113
+ expect(mockMixPanelEvent).toHaveBeenCalledWith(mixpanel_service_1.MIXPANEL_EVENT.VISUAL_SDK_INIT_ACTIONS, expect.objectContaining({
1114
+ hiddenActions: [],
1115
+ visibleActions: [types_1.Action.Save],
1116
+ disabledActions: [],
1117
+ }));
1118
+ });
1101
1119
  test('Should remove prefetch iframe', async () => {
1102
1120
  await setup(true);
1103
1121
  const prefetchIframe = document.querySelectorAll('.prefetchIframe');
@@ -2115,6 +2133,71 @@ describe('Unit test case for ts embed', () => {
2115
2133
  });
2116
2134
  });
2117
2135
  });
2136
+ describe('isDarkMode', () => {
2137
+ const renderAppEmbed = async (viewConfig = {}) => {
2138
+ const appEmbed = new index_1.AppEmbed((0, test_utils_1.getRootEl)(), {
2139
+ frameParams: {
2140
+ width: '100%',
2141
+ height: '100%',
2142
+ },
2143
+ ...viewConfig,
2144
+ });
2145
+ appEmbed.render();
2146
+ await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
2147
+ return (0, test_utils_1.getIFrameSrc)();
2148
+ };
2149
+ it('sends the appearance the host asked for in init, with the radiant theme', async () => {
2150
+ (0, index_1.init)({
2151
+ thoughtSpotHost: 'tshost',
2152
+ authType: index_1.AuthType.None,
2153
+ isDarkMode: true,
2154
+ });
2155
+ (0, test_utils_1.expectUrlToHaveParamsWithValues)(await renderAppEmbed(), {
2156
+ isDarkMode: true,
2157
+ radiantThemeEnabled: true,
2158
+ });
2159
+ });
2160
+ it('sends an explicit false', async () => {
2161
+ (0, index_1.init)({
2162
+ thoughtSpotHost: 'tshost',
2163
+ authType: index_1.AuthType.None,
2164
+ isDarkMode: false,
2165
+ });
2166
+ const src = await renderAppEmbed();
2167
+ (0, test_utils_1.expectUrlToHaveParamsWithValues)(src, { isDarkMode: false });
2168
+ // `false` leaves the radiant theme to the cluster.
2169
+ expect(src).not.toContain('radiantThemeEnabled=');
2170
+ });
2171
+ it('omits the param when the host says nothing', async () => {
2172
+ (0, index_1.init)({
2173
+ thoughtSpotHost: 'tshost',
2174
+ authType: index_1.AuthType.None,
2175
+ });
2176
+ // Absent rather than `isDarkMode=false`: an omitted param keeps the
2177
+ // URL short, and the app treats a missing param like `false`.
2178
+ const src = await renderAppEmbed();
2179
+ expect(src).not.toContain('isDarkMode=');
2180
+ expect(src).not.toContain('radiantThemeEnabled=');
2181
+ });
2182
+ it('lets the view config override the value set in init', async () => {
2183
+ (0, index_1.init)({
2184
+ thoughtSpotHost: 'tshost',
2185
+ authType: index_1.AuthType.None,
2186
+ isDarkMode: true,
2187
+ });
2188
+ const src = await renderAppEmbed({ isDarkMode: false });
2189
+ (0, test_utils_1.expectUrlToHaveParamsWithValues)(src, { isDarkMode: false });
2190
+ expect(src).not.toContain('radiantThemeEnabled=');
2191
+ });
2192
+ it('lets additionalFlags override the radiant theme it turns on', async () => {
2193
+ (0, index_1.init)({
2194
+ thoughtSpotHost: 'tshost',
2195
+ authType: index_1.AuthType.None,
2196
+ isDarkMode: true,
2197
+ });
2198
+ (0, test_utils_1.expectUrlToHaveParamsWithValues)(await renderAppEmbed({ additionalFlags: { radiantThemeEnabled: false } }), { isDarkMode: true, radiantThemeEnabled: false });
2199
+ });
2200
+ });
2118
2201
  describe('validate preRender flow', () => {
2119
2202
  beforeAll(() => {
2120
2203
  (0, index_1.init)({
@@ -2175,12 +2258,10 @@ describe('Unit test case for ts embed', () => {
2175
2258
  contentRect: { height: 297, width: 987 },
2176
2259
  },
2177
2260
  ]);
2178
- // Syncs are coalesced to one per frame.
2179
- await flushAnimationFrame();
2180
2261
  expect(preRenderWrapper.style.height).toEqual(`${297}px`);
2181
2262
  expect(preRenderWrapper.style.width).toEqual(`${987}px`);
2182
2263
  expect(preRenderWrapper.style.opacity).toBe('');
2183
- expect(preRenderWrapper.style.pointerEvents).toBe('auto');
2264
+ expect(preRenderWrapper.style.pointerEvents).toBe('');
2184
2265
  expect(preRenderWrapper.style.zIndex).toBe('');
2185
2266
  libEmbed.hidePreRender();
2186
2267
  expect(preRenderWrapper.style.opacity).toBe('0');
@@ -2209,7 +2290,7 @@ describe('Unit test case for ts embed', () => {
2209
2290
  await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
2210
2291
  const preRenderWrapper = document.getElementById(preRenderIds.wrapper);
2211
2292
  expect(preRenderWrapper.style.opacity).toBe('');
2212
- expect(preRenderWrapper.style.pointerEvents).toBe('auto');
2293
+ expect(preRenderWrapper.style.pointerEvents).toBe('');
2213
2294
  expect(preRenderWrapper.style.zIndex).toBe('');
2214
2295
  });
2215
2296
  it('hidePreRender should not preRender if not available', async () => {
@@ -2349,170 +2430,6 @@ describe('Unit test case for ts embed', () => {
2349
2430
  libEmbed.destroy();
2350
2431
  logger_1.logger.debug.mockRestore();
2351
2432
  });
2352
- describe('position tracking (SCAL-338563)', () => {
2353
- /**
2354
- * A host app whose page scrolls in an inner element rather than the
2355
- * document — the shape both reported cases have. The placeholder's
2356
- * rect is driven off that element's scrollTop, the way a real
2357
- * layout would move it.
2358
- */
2359
- const mountInNestedScroller = () => {
2360
- (0, test_utils_1.createRootEleForEmbed)();
2361
- const scroller = document.createElement('div');
2362
- scroller.id = 'inner-scroller';
2363
- document.body.appendChild(scroller);
2364
- scroller.appendChild(document.getElementById('tsEmbedDiv'));
2365
- let scrollTop = 0;
2366
- Object.defineProperty(scroller, 'scrollTop', {
2367
- configurable: true,
2368
- get: () => scrollTop,
2369
- set: (value) => {
2370
- scrollTop = value;
2371
- },
2372
- });
2373
- scroller.getBoundingClientRect = () => ({
2374
- x: 0, y: 0, width: 800, height: 600,
2375
- top: 0, left: 0, bottom: 600, right: 800,
2376
- });
2377
- const placeholderTopAtRest = 400;
2378
- const readPlaceholderTop = () => placeholderTopAtRest - scroller.scrollTop;
2379
- return { scroller, readPlaceholderTop };
2380
- };
2381
- const stubPlaceholderRect = (embed, readTop) => {
2382
- const placeholder = embed.getPreRenderPlaceHolderElement();
2383
- placeholder.getBoundingClientRect = () => {
2384
- const top = readTop();
2385
- return {
2386
- x: 0, y: top, width: 800, height: 300,
2387
- top, left: 0, bottom: top + 300, right: 800,
2388
- };
2389
- };
2390
- return placeholder;
2391
- };
2392
- it('should stop tracking once the frame is hidden', async () => {
2393
- const { scroller, readPlaceholderTop } = mountInNestedScroller();
2394
- const libEmbed = new index_1.LiveboardEmbed('#tsEmbedDiv', {
2395
- preRenderId: 'scroll-stops-on-hide',
2396
- liveboardId: 'myLiveboardId',
2397
- });
2398
- libEmbed.preRender();
2399
- await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
2400
- await libEmbed.showPreRender();
2401
- stubPlaceholderRect(libEmbed, readPlaceholderTop);
2402
- libEmbed.hidePreRender();
2403
- const syncSpy = jest.spyOn(libEmbed, 'syncPreRenderStyle');
2404
- scroller.scrollTop = 250;
2405
- scroller.dispatchEvent(new Event('scroll'));
2406
- await flushAnimationFrame();
2407
- expect(syncSpy).not.toHaveBeenCalled();
2408
- syncSpy.mockRestore();
2409
- libEmbed.destroy();
2410
- scroller.remove();
2411
- });
2412
- it('should default the container to the host scrolling ancestor', async () => {
2413
- const { scroller } = mountInNestedScroller();
2414
- scroller.style.overflowY = 'auto';
2415
- const libEmbed = new index_1.LiveboardEmbed('#tsEmbedDiv', {
2416
- preRenderId: 'auto-scroll-container',
2417
- liveboardId: 'myLiveboardId',
2418
- });
2419
- libEmbed.preRender();
2420
- await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
2421
- await libEmbed.showPreRender();
2422
- const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
2423
- // In the scroller, so the browser moves it — no repositioning.
2424
- expect(wrapper.parentElement).toBe(scroller);
2425
- expect(libEmbed.preRenderContainerEl).toBe(scroller);
2426
- libEmbed.destroy();
2427
- scroller.remove();
2428
- });
2429
- it('should still use document.body when nothing scrolls', async () => {
2430
- (0, test_utils_1.createRootEleForEmbed)();
2431
- const libEmbed = new index_1.LiveboardEmbed('#tsEmbedDiv', {
2432
- preRenderId: 'no-scroller-body',
2433
- liveboardId: 'myLiveboardId',
2434
- });
2435
- libEmbed.preRender();
2436
- await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
2437
- await libEmbed.showPreRender();
2438
- const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
2439
- expect(wrapper.parentElement).toBe(document.body);
2440
- libEmbed.destroy();
2441
- });
2442
- it('should set pointer-events on show rather than dropping the property', async () => {
2443
- (0, test_utils_1.createRootEleForEmbed)();
2444
- const container = document.createElement('div');
2445
- container.id = 'parking-root';
2446
- // Usual styling for a parking root: no swallowed clicks.
2447
- container.style.pointerEvents = 'none';
2448
- document.body.appendChild(container);
2449
- const libEmbed = new index_1.LiveboardEmbed('#tsEmbedDiv', {
2450
- preRenderId: 'pointer-events-restored',
2451
- liveboardId: 'myLiveboardId',
2452
- preRenderContainer: '#parking-root',
2453
- });
2454
- libEmbed.preRender();
2455
- await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
2456
- await libEmbed.showPreRender();
2457
- const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
2458
- // Merely removing the property would leave the container's
2459
- // inherited `none` in force, and the frame dead to input.
2460
- expect(wrapper.style.pointerEvents).toBe('auto');
2461
- libEmbed.destroy();
2462
- container.remove();
2463
- });
2464
- it('should park a hidden wrapper out of the scrollable area', async () => {
2465
- (0, test_utils_1.createRootEleForEmbed)();
2466
- const libEmbed = new index_1.LiveboardEmbed('#tsEmbedDiv', {
2467
- preRenderId: 'hidden-parked',
2468
- liveboardId: 'myLiveboardId',
2469
- });
2470
- libEmbed.preRender();
2471
- await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
2472
- await libEmbed.showPreRender();
2473
- const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
2474
- expect(wrapper.style.transform).toBe('');
2475
- libEmbed.hidePreRender();
2476
- expect(wrapper.style.transform).toBe('translateY(-100%)');
2477
- await libEmbed.showPreRender();
2478
- expect(wrapper.style.transform).toBe('');
2479
- libEmbed.destroy();
2480
- });
2481
- it('should not seed the placeholder with the unmeasured wrapper height', async () => {
2482
- (0, test_utils_1.createRootEleForEmbed)();
2483
- const libEmbed = new index_1.LiveboardEmbed('#tsEmbedDiv', {
2484
- preRenderId: 'unmeasured-height',
2485
- liveboardId: 'myLiveboardId',
2486
- fullHeight: true,
2487
- frameParams: { height: 420 },
2488
- });
2489
- libEmbed.preRender();
2490
- await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
2491
- const wrapper = document.getElementById(libEmbed.getPreRenderIds().wrapper);
2492
- // createPreRenderWrapper() seeds 100vh, not a measurement.
2493
- expect(wrapper.style.height).toBe('100vh');
2494
- await libEmbed.showPreRender();
2495
- const placeholder = libEmbed.getPreRenderPlaceHolderElement();
2496
- expect(placeholder.style.height).toBe('420px');
2497
- libEmbed.destroy();
2498
- });
2499
- it('should seed the placeholder with a height fullHeight has measured', async () => {
2500
- (0, test_utils_1.createRootEleForEmbed)();
2501
- const libEmbed = new index_1.LiveboardEmbed('#tsEmbedDiv', {
2502
- preRenderId: 'measured-height',
2503
- liveboardId: 'myLiveboardId',
2504
- fullHeight: true,
2505
- frameParams: { height: 420 },
2506
- });
2507
- libEmbed.preRender();
2508
- await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
2509
- libEmbed.setIFrameHeight(1180);
2510
- await libEmbed.showPreRender();
2511
- const placeholder = libEmbed.getPreRenderPlaceHolderElement();
2512
- expect(placeholder.style.height).toBe('1180px');
2513
- libEmbed.destroy();
2514
- });
2515
- });
2516
2433
  describe('preRenderContainer', () => {
2517
2434
  it('should append preRenderWrapper to document.body when preRenderContainer is not set', async () => {
2518
2435
  (0, test_utils_1.createRootEleForEmbed)();
@@ -2731,14 +2648,19 @@ describe('Unit test case for ts embed', () => {
2731
2648
  expect(oldContainer.contains(wrapper)).toBe(true);
2732
2649
  // Simulate React remounting the container: the old node (with
2733
2650
  // our wrapper) is detached and a fresh node takes its place.
2651
+ const removeSpy = jest.spyOn(oldContainer, 'removeEventListener');
2734
2652
  oldContainer.remove();
2735
2653
  const newContainer = document.createElement('div');
2736
2654
  newContainer.id = 'remount-container';
2737
2655
  document.body.appendChild(newContainer);
2656
+ const addSpy = jest.spyOn(newContainer, 'addEventListener');
2738
2657
  // A reposition (scroll/resize/re-show) heals the stale ref.
2739
2658
  libEmbed.syncPreRenderStyle();
2740
2659
  expect(newContainer.contains(wrapper)).toBe(true);
2741
2660
  expect(oldContainer.contains(wrapper)).toBe(false);
2661
+ // The scroll listener is migrated to the live container.
2662
+ expect(removeSpy).toHaveBeenCalledWith('scroll', expect.any(Function));
2663
+ expect(addSpy).toHaveBeenCalledWith('scroll', expect.any(Function));
2742
2664
  libEmbed.destroy();
2743
2665
  newContainer.remove();
2744
2666
  });
@@ -5500,4 +5422,454 @@ describe('ShowPreRender with UpdateEmbedParams', () => {
5500
5422
  });
5501
5423
  });
5502
5424
  });
5425
+ describe('excludeConfigFromURL', () => {
5426
+ const lbConfig = {
5427
+ liveboardId,
5428
+ hiddenActions: [types_1.Action.Download],
5429
+ additionalFlags: { internalBlinkFlag: true },
5430
+ liveboardV2: true,
5431
+ };
5432
+ const withPostMessage = (viewConfig) => ({
5433
+ ...viewConfig,
5434
+ additionalFlags: { ...viewConfig.additionalFlags, excludeConfigFromURL: true },
5435
+ });
5436
+ const renderAndGetSrc = async (viewConfig) => {
5437
+ const embed = new index_1.LiveboardEmbed((0, test_utils_1.getRootEl)(), { ...defaultViewConfig, ...viewConfig });
5438
+ await embed.render();
5439
+ await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
5440
+ return { embed, src: (0, test_utils_1.getIFrameSrc)() };
5441
+ };
5442
+ const signalFrameReady = () => {
5443
+ (0, test_utils_1.postMessageToParent)((0, test_utils_1.getIFrameEl)().contentWindow, {
5444
+ type: index_1.EmbedEvent.EmbedListenerReady,
5445
+ });
5446
+ };
5447
+ beforeEach(() => {
5448
+ document.body.innerHTML = (0, test_utils_1.getDocumentBody)();
5449
+ mockProcessTrigger.mockReset();
5450
+ mockProcessTrigger.mockResolvedValue({});
5451
+ (0, index_1.init)({
5452
+ thoughtSpotHost,
5453
+ authType: index_1.AuthType.None,
5454
+ });
5455
+ });
5456
+ test('leaves the URL untouched when the flag is not set', async () => {
5457
+ const { src } = await renderAndGetSrc(lbConfig);
5458
+ expect(src).toContain('hideAction=');
5459
+ expect(src).toContain('internalBlinkFlag=true');
5460
+ expect(src).toContain('isPinboardV2Enabled=true');
5461
+ });
5462
+ test('keeps only the bootstrap params on the URL when the flag is set', async () => {
5463
+ const { src } = await renderAndGetSrc(withPostMessage(lbConfig));
5464
+ // Boot and auth handshake stays on the URL.
5465
+ expect(src).toContain('hostAppUrl=');
5466
+ expect(src).toContain(`authType=${index_1.AuthType.None}`);
5467
+ expect(src).toContain(`sdkVersion=${package_json_1.version}`);
5468
+ expect(src).toContain('blockNonEmbedFullAppAccess=true');
5469
+ expect(src).toContain('viewPortHeight=');
5470
+ // View configuration and internal flags do not.
5471
+ expect(src).not.toContain('hideAction=');
5472
+ expect(src).not.toContain('internalBlinkFlag');
5473
+ });
5474
+ describe('BOOTSTRAP_URL_PARAMS', () => {
5475
+ test('keeps the auth and origin params', () => {
5476
+ [types_1.Param.EmbedApp, types_1.Param.HostAppUrl, types_1.Param.Version, types_1.Param.AuthType].forEach((param) => {
5477
+ expect(ts_embed_1.BOOTSTRAP_URL_PARAMS.has(param)).toBe(true);
5478
+ });
5479
+ });
5480
+ test('leaves the layout flags to the APP_INIT payload', () => {
5481
+ [
5482
+ types_1.Param.LiveboardV2Enabled,
5483
+ types_1.Param.PrimaryNavHidden,
5484
+ types_1.Param.HideSearchBar,
5485
+ types_1.Param.SpotterExperienceVersion,
5486
+ ].forEach((param) => {
5487
+ expect(ts_embed_1.BOOTSTRAP_URL_PARAMS.has(param)).toBe(false);
5488
+ });
5489
+ });
5490
+ });
5491
+ describe('params held back from the URL go in the APP_INIT payload', () => {
5492
+ const renderEmbed = async (EmbedClass, viewConfig, excludeConfig = true) => {
5493
+ const embed = new EmbedClass((0, test_utils_1.getRootEl)(), {
5494
+ ...defaultViewConfig,
5495
+ ...viewConfig,
5496
+ additionalFlags: {
5497
+ ...viewConfig.additionalFlags,
5498
+ ...(excludeConfig && { excludeConfigFromURL: true }),
5499
+ },
5500
+ });
5501
+ await embed.render();
5502
+ await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
5503
+ return embed;
5504
+ };
5505
+ const requestAppInit = async () => {
5506
+ const mockPort = { postMessage: jest.fn() };
5507
+ (0, test_utils_1.postMessageToParent)((0, test_utils_1.getIFrameEl)().contentWindow, { type: index_1.EmbedEvent.APP_INIT, data: {} }, mockPort);
5508
+ await (0, test_utils_1.waitFor)(() => mockPort.postMessage.mock.calls.length > 0);
5509
+ return mockPort.postMessage.mock.calls[0][0].data;
5510
+ };
5511
+ const getAppInitFor = async (EmbedClass, viewConfig) => {
5512
+ await renderEmbed(EmbedClass, viewConfig);
5513
+ return requestAppInit();
5514
+ };
5515
+ test('sends the app navigation and page version flags', async () => {
5516
+ const { embedParams } = await getAppInitFor(index_1.AppEmbed, {
5517
+ showPrimaryNavbar: false,
5518
+ hideHamburger: true,
5519
+ hideNotification: true,
5520
+ hideObjectSearch: true,
5521
+ hideOrgSwitcher: true,
5522
+ hideApplicationSwitcher: true,
5523
+ disableProfileAndHelp: true,
5524
+ hideHomepageLeftNav: true,
5525
+ hideTagFilterChips: true,
5526
+ modularHomeExperience: true,
5527
+ liveboardV2: true,
5528
+ });
5529
+ expect(embedParams).toEqual(expect.objectContaining({
5530
+ [types_1.Param.PrimaryNavHidden]: true,
5531
+ [types_1.Param.HideHamburger]: true,
5532
+ [types_1.Param.HideNotification]: true,
5533
+ [types_1.Param.HideObjectSearch]: true,
5534
+ [types_1.Param.HideOrgSwitcher]: true,
5535
+ [types_1.Param.HideApplicationSwitcher]: true,
5536
+ [types_1.Param.HideProfleAndHelp]: true,
5537
+ [types_1.Param.HideHomepageLeftNav]: true,
5538
+ [types_1.Param.HideTagFilterChips]: true,
5539
+ [types_1.Param.ModularHomeExperienceEnabled]: true,
5540
+ [types_1.Param.LiveboardV2Enabled]: true,
5541
+ [types_1.Param.NavigationVersion]: expect.any(String),
5542
+ [types_1.Param.HomepageVersion]: expect.any(String),
5543
+ }));
5544
+ });
5545
+ test('sends the Liveboard layout flags', async () => {
5546
+ const { embedParams } = await getAppInitFor(index_1.LiveboardEmbed, {
5547
+ liveboardId,
5548
+ visibleVizs: ['viz-1'],
5549
+ hideLiveboardHeader: true,
5550
+ showLiveboardTitle: true,
5551
+ showLiveboardDescription: true,
5552
+ hideTabPanel: true,
5553
+ enable2ColumnLayout: true,
5554
+ isLiveboardHeaderSticky: true,
5555
+ showLiveboardVerifiedBadge: true,
5556
+ });
5557
+ expect(embedParams).toEqual(expect.objectContaining({
5558
+ [types_1.Param.visibleVizs]: ['viz-1'],
5559
+ [types_1.Param.HideLiveboardHeader]: true,
5560
+ [types_1.Param.ShowLiveboardTitle]: true,
5561
+ [types_1.Param.ShowLiveboardDescription]: true,
5562
+ [types_1.Param.HideTabPanel]: true,
5563
+ [types_1.Param.Enable2ColumnLayout]: true,
5564
+ [types_1.Param.LiveboardHeaderSticky]: true,
5565
+ [types_1.Param.ShowLiveboardVerifiedBadge]: true,
5566
+ }));
5567
+ });
5568
+ test('sends the search layout flags and the initial query', async () => {
5569
+ const { embedParams } = await getAppInitFor(index_1.SearchEmbed, {
5570
+ dataSource: 'ds-1',
5571
+ searchOptions: {
5572
+ searchTokenString: '[revenue]',
5573
+ executeSearch: true,
5574
+ },
5575
+ hideResults: true,
5576
+ hideSearchBar: true,
5577
+ collapseSearchBarInitially: true,
5578
+ enableSearchAssist: true,
5579
+ });
5580
+ expect(embedParams).toEqual(expect.objectContaining({
5581
+ [types_1.Param.HideResult]: true,
5582
+ [types_1.Param.HideSearchBar]: true,
5583
+ [types_1.Param.CollapseSearchBarInitially]: true,
5584
+ [types_1.Param.EnableSearchAssist]: true,
5585
+ [types_1.Param.executeSearch]: true,
5586
+ [types_1.Param.DataSourceMode]: expect.anything(),
5587
+ }));
5588
+ expect(embedParams).not.toHaveProperty(types_1.Param.searchTokenString);
5589
+ });
5590
+ test('sends the Spotter empty-screen flags', async () => {
5591
+ const { embedParams } = await getAppInitFor(index_1.SpotterEmbed, {
5592
+ worksheetId: 'worksheet-1',
5593
+ hideSampleQuestions: true,
5594
+ hideSourceSelection: true,
5595
+ disableSourceSelection: true,
5596
+ showSpotterLimitations: true,
5597
+ showSpotterRadiance: true,
5598
+ updatedSpotterChatPrompt: true,
5599
+ spotterChatConfig: { enableStarterPrompts: true },
5600
+ });
5601
+ expect(embedParams).toEqual(expect.objectContaining({
5602
+ [types_1.Param.HideSampleQuestions]: true,
5603
+ [types_1.Param.HideSourceSelection]: true,
5604
+ [types_1.Param.DisableSourceSelection]: true,
5605
+ [types_1.Param.ShowSpotterLimitations]: true,
5606
+ [types_1.Param.ShowSpotterRadiance]: true,
5607
+ [types_1.Param.UpdatedSpotterChatPrompt]: true,
5608
+ [types_1.Param.IsStarterPromptsEnabled]: true,
5609
+ }));
5610
+ });
5611
+ test('sends the action and tab lists and the additionalFlags', async () => {
5612
+ await renderEmbed(index_1.LiveboardEmbed, {
5613
+ liveboardId,
5614
+ visibleActions: [types_1.Action.Download],
5615
+ visibleTabs: ['tab-1'],
5616
+ additionalFlags: { internalBlinkFlag: true },
5617
+ });
5618
+ const src = (0, test_utils_1.getIFrameSrc)();
5619
+ const { embedParams } = await requestAppInit();
5620
+ expect(src).not.toContain(`${types_1.Param.VisibleActions}=`);
5621
+ expect(src).not.toContain(`${types_1.Param.VisibleTabs}=`);
5622
+ expect(embedParams).toEqual(expect.objectContaining({
5623
+ [types_1.Param.VisibleActions]: [types_1.Action.Download],
5624
+ [types_1.Param.VisibleTabs]: ['tab-1'],
5625
+ internalBlinkFlag: true,
5626
+ }));
5627
+ });
5628
+ test('sends the feature flags only in embedParams', async () => {
5629
+ const appInitData = await getAppInitFor(index_1.AppEmbed, {
5630
+ showPrimaryNavbar: false,
5631
+ liveboardV2: true,
5632
+ dataPanelV2: true,
5633
+ });
5634
+ const featureFlags = {
5635
+ [types_1.Param.PrimaryNavHidden]: true,
5636
+ [types_1.Param.LiveboardV2Enabled]: true,
5637
+ [types_1.Param.DataPanelV2Enabled]: true,
5638
+ };
5639
+ // The app overrides its feature flags from embedParams.
5640
+ expect(appInitData.embedParams).toEqual(expect.objectContaining(featureFlags));
5641
+ Object.keys(featureFlags).forEach((flag) => {
5642
+ expect(appInitData).not.toHaveProperty(flag);
5643
+ });
5644
+ });
5645
+ test("lets the embed's own embedParams win over a param of the same name", async () => {
5646
+ const { embedParams } = await getAppInitFor(index_1.SpotterEmbed, {
5647
+ worksheetId: 'worksheet-1',
5648
+ spotterSidebarConfig: { enablePastConversationsSidebar: true },
5649
+ additionalFlags: { spotterSidebarConfig: 'from-flags' },
5650
+ });
5651
+ expect(embedParams.spotterSidebarConfig).toEqual(expect.objectContaining({ enablePastConversationsSidebar: true }));
5652
+ });
5653
+ test("keeps the embed's own embedParams alongside the params", async () => {
5654
+ const { embedParams } = await getAppInitFor(index_1.SpotterEmbed, {
5655
+ worksheetId: 'worksheet-1',
5656
+ hideSampleQuestions: true,
5657
+ spotterSidebarConfig: { enablePastConversationsSidebar: true },
5658
+ });
5659
+ expect(embedParams).toEqual(expect.objectContaining({
5660
+ [types_1.Param.HideSampleQuestions]: true,
5661
+ spotterSidebarConfig: expect.objectContaining({
5662
+ enablePastConversationsSidebar: true,
5663
+ }),
5664
+ }));
5665
+ });
5666
+ test('keeps the search token on the URL', async () => {
5667
+ const { embedParams } = await getAppInitFor(index_1.SearchEmbed, {
5668
+ dataSource: 'ds-1',
5669
+ searchOptions: { searchTokenString: '[revenue] [region]' },
5670
+ });
5671
+ expect(new URL((0, test_utils_1.getIFrameSrc)()).searchParams.get(types_1.Param.searchTokenString)).toBe('[revenue] [region]');
5672
+ expect(embedParams).not.toHaveProperty(types_1.Param.searchTokenString);
5673
+ });
5674
+ test('sends the token in searchOptions when it is excluded from the URL', async () => {
5675
+ const appInitData = await getAppInitFor(index_1.SearchEmbed, {
5676
+ dataSource: 'ds-1',
5677
+ excludeSearchTokenStringFromURL: true,
5678
+ searchOptions: { searchTokenString: '[revenue]' },
5679
+ });
5680
+ expect((0, test_utils_1.getIFrameSrc)()).not.toContain(types_1.Param.searchTokenString);
5681
+ // The app merges searchOptions.searchTokenString into embedParams.
5682
+ expect(appInitData.searchOptions).toEqual({ searchTokenString: '[revenue]' });
5683
+ expect(appInitData.embedParams).not.toHaveProperty(types_1.Param.searchTokenString);
5684
+ });
5685
+ test('sends a flag the caller set to false', async () => {
5686
+ const { embedParams } = await getAppInitFor(index_1.AppEmbed, {
5687
+ showPrimaryNavbar: true,
5688
+ liveboardV2: false,
5689
+ modularHomeExperience: false,
5690
+ });
5691
+ expect(embedParams).toEqual(expect.objectContaining({
5692
+ [types_1.Param.PrimaryNavHidden]: false,
5693
+ [types_1.Param.LiveboardV2Enabled]: false,
5694
+ [types_1.Param.ModularHomeExperienceEnabled]: false,
5695
+ }));
5696
+ });
5697
+ test('sends a flag only when the caller sets it', async () => {
5698
+ const { embedParams } = await getAppInitFor(index_1.AppEmbed, {});
5699
+ expect(embedParams).not.toHaveProperty(types_1.Param.HideHamburger);
5700
+ expect(embedParams).not.toHaveProperty(types_1.Param.HideNotification);
5701
+ expect(embedParams).not.toHaveProperty(types_1.Param.ModularHomeExperienceEnabled);
5702
+ });
5703
+ test('does not repeat the params that stay on the URL', async () => {
5704
+ const { embedParams } = await getAppInitFor(index_1.LiveboardEmbed, { liveboardId });
5705
+ Object.keys(embedParams).forEach((key) => {
5706
+ expect(ts_embed_1.BOOTSTRAP_URL_PARAMS.has(key)).toBe(false);
5707
+ });
5708
+ });
5709
+ test('leaves the APP_INIT payload unchanged when the flag is not set', async () => {
5710
+ await renderEmbed(index_1.LiveboardEmbed, { liveboardId, hideLiveboardHeader: true }, false);
5711
+ const appInitData = await requestAppInit();
5712
+ expect(appInitData).not.toHaveProperty('embedParams');
5713
+ expect(appInitData).not.toHaveProperty(types_1.Param.HideLiveboardHeader);
5714
+ });
5715
+ test('sends no embedParams when every param stays on the URL', async () => {
5716
+ const getParams = jest
5717
+ .spyOn(index_1.LiveboardEmbed.prototype, 'getEmbedParamsObject')
5718
+ .mockReturnValue({
5719
+ [types_1.Param.EmbedApp]: true,
5720
+ [types_1.Param.AuthType]: index_1.AuthType.None,
5721
+ });
5722
+ await renderEmbed(index_1.LiveboardEmbed, { liveboardId });
5723
+ const appInitData = await requestAppInit();
5724
+ getParams.mockRestore();
5725
+ expect(appInitData).not.toHaveProperty('embedParams');
5726
+ });
5727
+ test('sends the params when excludeConfigFromURL is set in init', async () => {
5728
+ (0, index_1.init)({
5729
+ thoughtSpotHost,
5730
+ authType: index_1.AuthType.None,
5731
+ additionalFlags: { excludeConfigFromURL: true },
5732
+ });
5733
+ await renderEmbed(index_1.LiveboardEmbed, { liveboardId, hideLiveboardHeader: true }, false);
5734
+ const { embedParams } = await requestAppInit();
5735
+ expect((0, test_utils_1.getIFrameSrc)()).not.toContain(`${types_1.Param.HideLiveboardHeader}=`);
5736
+ expect(embedParams).toEqual(expect.objectContaining({ [types_1.Param.HideLiveboardHeader]: true }));
5737
+ });
5738
+ test('sends the params for a pre-rendered embed', async () => {
5739
+ window.ResizeObserver =
5740
+ window.ResizeObserver ||
5741
+ jest.fn().mockImplementation(() => ({
5742
+ disconnect: jest.fn(),
5743
+ observe: jest.fn(),
5744
+ unobserve: jest.fn(),
5745
+ }));
5746
+ const embed = new index_1.LiveboardEmbed((0, test_utils_1.getRootEl)(), {
5747
+ ...defaultViewConfig,
5748
+ ...withPostMessage({ liveboardId, hideLiveboardHeader: true }),
5749
+ preRenderId: 'app-init-pre-render',
5750
+ });
5751
+ await embed.preRender();
5752
+ await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
5753
+ const { embedParams } = await requestAppInit();
5754
+ expect(embedParams).toEqual(expect.objectContaining({ [types_1.Param.HideLiveboardHeader]: true }));
5755
+ });
5756
+ test('does not add the APP_INIT copy to UpdateEmbedParams', async () => {
5757
+ (0, test_utils_1.mockMessageChannel)();
5758
+ window.ResizeObserver =
5759
+ window.ResizeObserver ||
5760
+ jest.fn().mockImplementation(() => ({
5761
+ disconnect: jest.fn(),
5762
+ observe: jest.fn(),
5763
+ unobserve: jest.fn(),
5764
+ }));
5765
+ const embed = new index_1.LiveboardEmbed((0, test_utils_1.getRootEl)(), {
5766
+ ...defaultViewConfig,
5767
+ ...withPostMessage({ liveboardId, hideLiveboardHeader: true }),
5768
+ preRenderId: 'app-init-copy-pre-render',
5769
+ });
5770
+ await embed.preRender();
5771
+ await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
5772
+ signalFrameReady();
5773
+ await (0, test_utils_1.executeAfterWait)(() => {
5774
+ expect(embed.isEmbedContainerLoaded).toBe(true);
5775
+ });
5776
+ // The show cycle is what sends UpdateEmbedParams.
5777
+ await embed.showPreRender();
5778
+ await (0, test_utils_1.executeAfterWait)(() => {
5779
+ const updateCall = mockProcessTrigger.mock.calls.find((call) => call[1] === types_1.HostEvent.UpdateEmbedParams);
5780
+ expect(updateCall[3]).toEqual(expect.objectContaining({ [types_1.Param.HideLiveboardHeader]: true }));
5781
+ expect(updateCall[3]).not.toHaveProperty('embedParams');
5782
+ });
5783
+ });
5784
+ // BOOTSTRAP_URL_PARAMS is the source of truth. Each param goes
5785
+ // through additionalFlags so it is checked on its own.
5786
+ test.each([...ts_embed_1.BOOTSTRAP_URL_PARAMS])('keeps %s on the URL', async (param) => {
5787
+ await renderEmbed(index_1.LiveboardEmbed, {
5788
+ liveboardId,
5789
+ additionalFlags: { [param]: 'bootstrap-value' },
5790
+ });
5791
+ expect(new URL((0, test_utils_1.getIFrameSrc)()).searchParams.has(param)).toBe(true);
5792
+ });
5793
+ });
5794
+ test('strips a non-bootstrap additionalFlag from the URL when the flag is set', async () => {
5795
+ const { src } = await renderAndGetSrc({
5796
+ ...lbConfig,
5797
+ additionalFlags: {
5798
+ internalBlinkFlag: true,
5799
+ someCustomFlag: 'abc',
5800
+ excludeConfigFromURL: true,
5801
+ },
5802
+ });
5803
+ expect(src).not.toContain('internalBlinkFlag');
5804
+ expect(src).not.toContain('someCustomFlag');
5805
+ });
5806
+ test('keeps an additionalFlag that overrides a bootstrap param on the URL', async () => {
5807
+ const { src } = await renderAndGetSrc({
5808
+ ...lbConfig,
5809
+ additionalFlags: { [types_1.Param.OverrideOrgId]: 42, excludeConfigFromURL: true },
5810
+ });
5811
+ expect(src).toContain(`${types_1.Param.OverrideOrgId}=42`);
5812
+ });
5813
+ test('keeps the dark mode params on the URL when the flag is set', async () => {
5814
+ const { src } = await renderAndGetSrc(withPostMessage({ ...lbConfig, isDarkMode: true }));
5815
+ expect(src).toContain(`${types_1.Param.IsDarkMode}=true`);
5816
+ expect(src).toContain(`${types_1.Param.RadiantThemeEnabled}=true`);
5817
+ });
5818
+ test('keeps the deep-link route on the URL when the flag is set', async () => {
5819
+ const { src } = await renderAndGetSrc(withPostMessage(lbConfig));
5820
+ expect(src).toContain(`/embed/viz/${liveboardId}`);
5821
+ });
5822
+ test('sends the config in APP_INIT, not UpdateEmbedParams, on the first load', async () => {
5823
+ await renderAndGetSrc(withPostMessage(lbConfig));
5824
+ const mockPort = { postMessage: jest.fn() };
5825
+ (0, test_utils_1.postMessageToParent)((0, test_utils_1.getIFrameEl)().contentWindow, { type: index_1.EmbedEvent.APP_INIT, data: {} }, mockPort);
5826
+ await (0, test_utils_1.waitFor)(() => mockPort.postMessage.mock.calls.length > 0);
5827
+ signalFrameReady();
5828
+ expect(mockPort.postMessage.mock.calls[0][0].data.embedParams).toEqual(expect.objectContaining({
5829
+ internalBlinkFlag: true,
5830
+ [types_1.Param.HideActions]: expect.arrayContaining([types_1.Action.Download]),
5831
+ }));
5832
+ await (0, test_utils_1.executeAfterWait)(() => {
5833
+ const updateCalls = mockProcessTrigger.mock.calls.filter((call) => call[1] === types_1.HostEvent.UpdateEmbedParams);
5834
+ expect(updateCalls).toHaveLength(0);
5835
+ });
5836
+ });
5837
+ test('does not send UpdateEmbedParams when the flag is not set', async () => {
5838
+ await renderAndGetSrc(lbConfig);
5839
+ signalFrameReady();
5840
+ await (0, test_utils_1.executeAfterWait)(() => {
5841
+ const updateCalls = mockProcessTrigger.mock.calls.filter((call) => call[1] === types_1.HostEvent.UpdateEmbedParams);
5842
+ expect(updateCalls).toHaveLength(0);
5843
+ });
5844
+ });
5845
+ test('does not double-send for a pre-rendered embed that is shown', async () => {
5846
+ (0, test_utils_1.mockMessageChannel)();
5847
+ window.ResizeObserver =
5848
+ window.ResizeObserver ||
5849
+ jest.fn().mockImplementation(() => ({
5850
+ disconnect: jest.fn(),
5851
+ observe: jest.fn(),
5852
+ unobserve: jest.fn(),
5853
+ }));
5854
+ const embed = new index_1.LiveboardEmbed((0, test_utils_1.getRootEl)(), {
5855
+ ...defaultViewConfig,
5856
+ ...withPostMessage(lbConfig),
5857
+ preRenderId: 'send-config-post-message',
5858
+ });
5859
+ await embed.preRender();
5860
+ await (0, test_utils_1.waitFor)(() => !!(0, test_utils_1.getIFrameEl)());
5861
+ signalFrameReady();
5862
+ await (0, test_utils_1.executeAfterWait)(() => {
5863
+ expect(embed.isEmbedContainerLoaded).toBe(true);
5864
+ });
5865
+ // The frame being ready sends nothing; the config went in APP_INIT.
5866
+ expect(mockProcessTrigger.mock.calls.filter((call) => call[1] === types_1.HostEvent.UpdateEmbedParams)).toHaveLength(0);
5867
+ mockProcessTrigger.mockClear();
5868
+ await embed.showPreRender();
5869
+ await (0, test_utils_1.executeAfterWait)(() => {
5870
+ const updateCalls = mockProcessTrigger.mock.calls.filter((call) => call[1] === types_1.HostEvent.UpdateEmbedParams);
5871
+ expect(updateCalls).toHaveLength(1);
5872
+ });
5873
+ });
5874
+ });
5503
5875
  //# sourceMappingURL=ts-embed.spec.js.map