@thoughtspot/visual-embed-sdk 1.42.1-alpha.7 → 1.42.3
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/cjs/package.json +4 -3
- package/cjs/src/css-variables.d.ts +0 -48
- package/cjs/src/css-variables.d.ts.map +1 -1
- package/cjs/src/embed/app.d.ts +20 -0
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +9 -4
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +62 -0
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/base.d.ts.map +1 -1
- package/cjs/src/embed/base.js +2 -0
- package/cjs/src/embed/base.js.map +1 -1
- package/cjs/src/embed/bodyless-conversation.d.ts +1 -1
- package/cjs/src/embed/conversation.d.ts +16 -0
- package/cjs/src/embed/conversation.d.ts.map +1 -1
- package/cjs/src/embed/conversation.js +5 -2
- package/cjs/src/embed/conversation.js.map +1 -1
- package/cjs/src/embed/conversation.spec.js +25 -1
- package/cjs/src/embed/conversation.spec.js.map +1 -1
- package/cjs/src/embed/hostEventClient/contracts.d.ts +1 -11
- package/cjs/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/cjs/src/embed/hostEventClient/contracts.js +0 -1
- package/cjs/src/embed/hostEventClient/contracts.js.map +1 -1
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +5 -1
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +46 -0
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/sage.d.ts +4 -4
- package/cjs/src/embed/search.d.ts.map +1 -1
- package/cjs/src/embed/search.js +1 -3
- package/cjs/src/embed/search.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts +0 -2
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +31 -44
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +134 -43
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/errors.js +1 -1
- package/cjs/src/errors.js.map +1 -1
- package/cjs/src/index.d.ts +3 -3
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +1 -2
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/react/all-types-export.d.ts +1 -2
- package/cjs/src/react/all-types-export.d.ts.map +1 -1
- package/cjs/src/react/all-types-export.js +5 -3
- package/cjs/src/react/all-types-export.js.map +1 -1
- package/cjs/src/react/all-types-export.spec.js +0 -8
- package/cjs/src/react/all-types-export.spec.js.map +1 -1
- package/cjs/src/react/index.d.ts +1 -2
- package/cjs/src/react/index.d.ts.map +1 -1
- package/cjs/src/react/index.js +2 -1
- package/cjs/src/react/index.js.map +1 -1
- package/cjs/src/react/util.d.ts +1 -0
- package/cjs/src/react/util.d.ts.map +1 -1
- package/cjs/src/types.d.ts +80 -94
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +30 -46
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/custom-actions.d.ts.map +1 -1
- package/cjs/src/utils/custom-actions.js +9 -0
- package/cjs/src/utils/custom-actions.js.map +1 -1
- package/cjs/src/utils/custom-actions.spec.js +20 -0
- package/cjs/src/utils/custom-actions.spec.js.map +1 -1
- package/cjs/src/utils/processData.d.ts +1 -1
- package/cjs/src/utils/processData.d.ts.map +1 -1
- package/cjs/src/utils/processData.js +8 -8
- package/cjs/src/utils/processData.js.map +1 -1
- package/cjs/src/utils/processData.spec.js.map +1 -1
- package/dist/{index-DvNA626T.js → index-SVcLgSqi.js} +1 -1
- package/dist/src/css-variables.d.ts +0 -48
- package/dist/src/css-variables.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +20 -0
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts.map +1 -1
- package/dist/src/embed/bodyless-conversation.d.ts +1 -1
- package/dist/src/embed/conversation.d.ts +16 -0
- package/dist/src/embed/conversation.d.ts.map +1 -1
- package/dist/src/embed/hostEventClient/contracts.d.ts +1 -11
- package/dist/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/sage.d.ts +4 -4
- package/dist/src/embed/search.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +0 -2
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/react/all-types-export.d.ts +1 -2
- package/dist/src/react/all-types-export.d.ts.map +1 -1
- package/dist/src/react/index.d.ts +1 -2
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/react/util.d.ts +1 -0
- package/dist/src/react/util.d.ts.map +1 -1
- package/dist/src/types.d.ts +80 -94
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/custom-actions.d.ts.map +1 -1
- package/dist/src/utils/processData.d.ts +1 -1
- package/dist/src/utils/processData.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +114 -224
- package/dist/tsembed-react.js +258 -444
- package/dist/tsembed.es.js +113 -224
- package/dist/tsembed.js +256 -443
- package/dist/visual-embed-sdk-react-full.d.ts +126 -161
- package/dist/visual-embed-sdk-react.d.ts +117 -156
- package/dist/visual-embed-sdk.d.ts +117 -159
- package/lib/package.json +4 -3
- package/lib/src/css-variables.d.ts +0 -48
- package/lib/src/css-variables.d.ts.map +1 -1
- package/lib/src/embed/app.d.ts +20 -0
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +9 -4
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +62 -0
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +2 -0
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/bodyless-conversation.d.ts +1 -1
- package/lib/src/embed/conversation.d.ts +16 -0
- package/lib/src/embed/conversation.d.ts.map +1 -1
- package/lib/src/embed/conversation.js +5 -2
- package/lib/src/embed/conversation.js.map +1 -1
- package/lib/src/embed/conversation.spec.js +25 -1
- package/lib/src/embed/conversation.spec.js.map +1 -1
- package/lib/src/embed/hostEventClient/contracts.d.ts +1 -11
- package/lib/src/embed/hostEventClient/contracts.d.ts.map +1 -1
- package/lib/src/embed/hostEventClient/contracts.js +0 -1
- package/lib/src/embed/hostEventClient/contracts.js.map +1 -1
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +5 -1
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +47 -1
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/sage.d.ts +4 -4
- package/lib/src/embed/search.d.ts.map +1 -1
- package/lib/src/embed/search.js +1 -3
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +0 -2
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +31 -44
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +134 -43
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/errors.js +1 -1
- package/lib/src/errors.js.map +1 -1
- package/lib/src/index.d.ts +3 -3
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +2 -2
- package/lib/src/index.js.map +1 -1
- package/lib/src/react/all-types-export.d.ts +1 -2
- package/lib/src/react/all-types-export.d.ts.map +1 -1
- package/lib/src/react/all-types-export.js +2 -2
- package/lib/src/react/all-types-export.js.map +1 -1
- package/lib/src/react/all-types-export.spec.js +0 -8
- package/lib/src/react/all-types-export.spec.js.map +1 -1
- package/lib/src/react/index.d.ts +1 -2
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +4 -3
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/util.d.ts +1 -0
- package/lib/src/react/util.d.ts.map +1 -1
- package/lib/src/types.d.ts +80 -94
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +29 -45
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/custom-actions.d.ts.map +1 -1
- package/lib/src/utils/custom-actions.js +9 -0
- package/lib/src/utils/custom-actions.js.map +1 -1
- package/lib/src/utils/custom-actions.spec.js +20 -0
- package/lib/src/utils/custom-actions.spec.js.map +1 -1
- package/lib/src/utils/processData.d.ts +1 -1
- package/lib/src/utils/processData.d.ts.map +1 -1
- package/lib/src/utils/processData.js +8 -8
- package/lib/src/utils/processData.js.map +1 -1
- package/lib/src/utils/processData.spec.js.map +1 -1
- package/package.json +4 -3
- package/src/css-variables.ts +0 -58
- package/src/embed/app.spec.ts +87 -0
- package/src/embed/app.ts +35 -4
- package/src/embed/base.ts +2 -0
- package/src/embed/bodyless-conversation.ts +1 -1
- package/src/embed/conversation.spec.ts +35 -1
- package/src/embed/conversation.ts +22 -0
- package/src/embed/hostEventClient/contracts.ts +0 -10
- package/src/embed/liveboard.spec.ts +60 -0
- package/src/embed/liveboard.ts +9 -0
- package/src/embed/sage.ts +4 -4
- package/src/embed/search.ts +1 -3
- package/src/embed/ts-embed.spec.ts +175 -53
- package/src/embed/ts-embed.ts +45 -68
- package/src/errors.ts +1 -1
- package/src/index.ts +3 -4
- package/src/react/all-types-export.spec.ts +1 -9
- package/src/react/all-types-export.ts +8 -10
- package/src/react/index.tsx +130 -155
- package/src/types.ts +78 -94
- package/src/utils/custom-actions.spec.ts +22 -0
- package/src/utils/custom-actions.ts +11 -0
- package/src/utils/processData.spec.ts +1 -0
- package/src/utils/processData.ts +11 -11
- package/cjs/src/api-intercept.d.ts +0 -31
- package/cjs/src/api-intercept.d.ts.map +0 -1
- package/cjs/src/api-intercept.js +0 -119
- package/cjs/src/api-intercept.js.map +0 -1
- package/cjs/src/api-intercept.spec.d.ts +0 -2
- package/cjs/src/api-intercept.spec.d.ts.map +0 -1
- package/cjs/src/api-intercept.spec.js +0 -122
- package/cjs/src/api-intercept.spec.js.map +0 -1
- package/dist/index-BCC3Z072.js +0 -7371
- package/dist/index-BEzW4MDA.js +0 -7371
- package/dist/index-BaESA9rq.js +0 -7371
- package/dist/index-CFNZIcKr.js +0 -7447
- package/dist/index-CqKTa1Fe.js +0 -7447
- package/dist/index-DFnPKcjZ.js +0 -7447
- package/dist/index-DhFH7b7U.js +0 -7447
- package/dist/src/api-intercept.d.ts +0 -31
- package/dist/src/api-intercept.d.ts.map +0 -1
- package/dist/src/api-intercept.spec.d.ts +0 -2
- package/dist/src/api-intercept.spec.d.ts.map +0 -1
- package/lib/src/api-intercept.d.ts +0 -31
- package/lib/src/api-intercept.d.ts.map +0 -1
- package/lib/src/api-intercept.js +0 -112
- package/lib/src/api-intercept.js.map +0 -1
- package/lib/src/api-intercept.spec.d.ts +0 -2
- package/lib/src/api-intercept.spec.d.ts.map +0 -1
- package/lib/src/api-intercept.spec.js +0 -119
- package/lib/src/api-intercept.spec.js.map +0 -1
- package/src/api-intercept.ts +0 -139
|
@@ -90,7 +90,6 @@ beforeAll(() => {
|
|
|
90
90
|
const customisations = {
|
|
91
91
|
style: {
|
|
92
92
|
customCSS: {},
|
|
93
|
-
customCSSUrl: undefined as string | undefined,
|
|
94
93
|
},
|
|
95
94
|
content: {},
|
|
96
95
|
};
|
|
@@ -98,7 +97,6 @@ const customisations = {
|
|
|
98
97
|
const customisationsView = {
|
|
99
98
|
style: {
|
|
100
99
|
customCSS: {},
|
|
101
|
-
customCSSUrl: undefined as string | undefined,
|
|
102
100
|
},
|
|
103
101
|
content: {
|
|
104
102
|
strings: {
|
|
@@ -1047,7 +1045,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
1047
1045
|
type: EmbedEvent.APP_INIT,
|
|
1048
1046
|
data: {},
|
|
1049
1047
|
};
|
|
1050
|
-
|
|
1048
|
+
|
|
1051
1049
|
// Create a SearchEmbed with valid custom actions to test
|
|
1052
1050
|
// CustomActionsValidationResult
|
|
1053
1051
|
const searchEmbed = new SearchEmbed(getRootEl(), {
|
|
@@ -1069,7 +1067,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
1069
1067
|
}
|
|
1070
1068
|
]
|
|
1071
1069
|
});
|
|
1072
|
-
|
|
1070
|
+
|
|
1073
1071
|
searchEmbed.render();
|
|
1074
1072
|
const mockPort: any = {
|
|
1075
1073
|
postMessage: jest.fn(),
|
|
@@ -1118,7 +1116,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
1118
1116
|
customVariablesForThirdPartyTools: {},
|
|
1119
1117
|
},
|
|
1120
1118
|
});
|
|
1121
|
-
|
|
1119
|
+
|
|
1122
1120
|
// Verify that CustomActionsValidationResult structure is
|
|
1123
1121
|
// correct
|
|
1124
1122
|
const appInitData = mockPort.postMessage.mock.calls[0][0].data;
|
|
@@ -1139,7 +1137,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
1139
1137
|
})
|
|
1140
1138
|
])
|
|
1141
1139
|
);
|
|
1142
|
-
|
|
1140
|
+
|
|
1143
1141
|
// Verify actions are sorted by name (alphabetically)
|
|
1144
1142
|
expect(appInitData.customActions[0].name).toBe('Another Valid Action');
|
|
1145
1143
|
expect(appInitData.customActions[1].name).toBe('Valid Action');
|
|
@@ -2430,50 +2428,6 @@ describe('Unit test case for ts embed', () => {
|
|
|
2430
2428
|
});
|
|
2431
2429
|
});
|
|
2432
2430
|
|
|
2433
|
-
describe('When destroyed', () => {
|
|
2434
|
-
it('should remove the iframe', async () => {
|
|
2435
|
-
const appEmbed = new AppEmbed(getRootEl(), {
|
|
2436
|
-
frameParams: {
|
|
2437
|
-
width: '100%',
|
|
2438
|
-
height: '100%',
|
|
2439
|
-
},
|
|
2440
|
-
});
|
|
2441
|
-
await appEmbed.render();
|
|
2442
|
-
expect(getIFrameEl()).toBeTruthy();
|
|
2443
|
-
appEmbed.destroy();
|
|
2444
|
-
expect(getIFrameEl()).toBeFalsy();
|
|
2445
|
-
});
|
|
2446
|
-
|
|
2447
|
-
it('should remove the iframe when insertAsSibling is true', async () => {
|
|
2448
|
-
const appEmbed = new AppEmbed(getRootEl(), {
|
|
2449
|
-
frameParams: {
|
|
2450
|
-
width: '100%',
|
|
2451
|
-
height: '100%',
|
|
2452
|
-
},
|
|
2453
|
-
insertAsSibling: true,
|
|
2454
|
-
});
|
|
2455
|
-
await appEmbed.render();
|
|
2456
|
-
expect(getIFrameEl()).toBeTruthy();
|
|
2457
|
-
appEmbed.destroy();
|
|
2458
|
-
expect(getIFrameEl()).toBeFalsy();
|
|
2459
|
-
});
|
|
2460
|
-
|
|
2461
|
-
it("Should remove the error message on destroy if it's present", async () => {
|
|
2462
|
-
jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValueOnce(false);
|
|
2463
|
-
const appEmbed = new AppEmbed(getRootEl(), {
|
|
2464
|
-
frameParams: {
|
|
2465
|
-
width: '100%',
|
|
2466
|
-
height: '100%',
|
|
2467
|
-
},
|
|
2468
|
-
insertAsSibling: true,
|
|
2469
|
-
});
|
|
2470
|
-
await appEmbed.render();
|
|
2471
|
-
expect(getRootEl().nextElementSibling.innerHTML).toContain('Not logged in');
|
|
2472
|
-
appEmbed.destroy();
|
|
2473
|
-
expect(getRootEl().nextElementSibling.innerHTML).toBe('');
|
|
2474
|
-
});
|
|
2475
|
-
});
|
|
2476
|
-
|
|
2477
2431
|
describe('validate getThoughtSpotPostUrlParams', () => {
|
|
2478
2432
|
const { location } = window;
|
|
2479
2433
|
|
|
@@ -2490,7 +2444,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
2490
2444
|
});
|
|
2491
2445
|
|
|
2492
2446
|
afterAll((): void => {
|
|
2493
|
-
|
|
2447
|
+
window.location = location as any;
|
|
2494
2448
|
});
|
|
2495
2449
|
|
|
2496
2450
|
it('get url params for TS', () => {
|
|
@@ -3408,7 +3362,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
3408
3362
|
new Error('Auth failed'),
|
|
3409
3363
|
);
|
|
3410
3364
|
const searchEmbed = new SearchEmbed(getRootEl(), defaultViewConfig);
|
|
3411
|
-
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {
|
|
3365
|
+
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
3412
3366
|
await searchEmbed.render();
|
|
3413
3367
|
await executeAfterWait(() => {
|
|
3414
3368
|
expect(getRootEl().innerHTML).toContain('Not logged in');
|
|
@@ -3417,7 +3371,7 @@ describe('Unit test case for ts embed', () => {
|
|
|
3417
3371
|
window.dispatchEvent(onlineEvent);
|
|
3418
3372
|
}).not.toThrow();
|
|
3419
3373
|
});
|
|
3420
|
-
|
|
3374
|
+
|
|
3421
3375
|
errorSpy.mockReset();
|
|
3422
3376
|
});
|
|
3423
3377
|
|
|
@@ -3458,4 +3412,172 @@ describe('Unit test case for ts embed', () => {
|
|
|
3458
3412
|
triggerSpy.mockReset();
|
|
3459
3413
|
});
|
|
3460
3414
|
});
|
|
3415
|
+
|
|
3416
|
+
describe('When destroyed', () => {
|
|
3417
|
+
it('should remove the iframe', async () => {
|
|
3418
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
3419
|
+
frameParams: {
|
|
3420
|
+
width: '100%',
|
|
3421
|
+
height: '100%',
|
|
3422
|
+
},
|
|
3423
|
+
});
|
|
3424
|
+
await appEmbed.render();
|
|
3425
|
+
expect(getIFrameEl()).toBeTruthy();
|
|
3426
|
+
appEmbed.destroy();
|
|
3427
|
+
expect(getIFrameEl()).toBeFalsy();
|
|
3428
|
+
});
|
|
3429
|
+
|
|
3430
|
+
it('should remove the iframe when insertAsSibling is true', async () => {
|
|
3431
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
3432
|
+
frameParams: {
|
|
3433
|
+
width: '100%',
|
|
3434
|
+
height: '100%',
|
|
3435
|
+
},
|
|
3436
|
+
insertAsSibling: true,
|
|
3437
|
+
});
|
|
3438
|
+
await appEmbed.render();
|
|
3439
|
+
expect(getIFrameEl()).toBeTruthy();
|
|
3440
|
+
appEmbed.destroy();
|
|
3441
|
+
expect(getIFrameEl()).toBeFalsy();
|
|
3442
|
+
});
|
|
3443
|
+
|
|
3444
|
+
it("Should remove the error message on destroy if it's present", async () => {
|
|
3445
|
+
jest.spyOn(baseInstance, 'getAuthPromise').mockResolvedValueOnce(false);
|
|
3446
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
3447
|
+
frameParams: {
|
|
3448
|
+
width: '100%',
|
|
3449
|
+
height: '100%',
|
|
3450
|
+
},
|
|
3451
|
+
insertAsSibling: true,
|
|
3452
|
+
});
|
|
3453
|
+
await appEmbed.render();
|
|
3454
|
+
expect(getRootEl().nextElementSibling.innerHTML).toContain('Not logged in');
|
|
3455
|
+
appEmbed.destroy();
|
|
3456
|
+
expect(getRootEl().nextElementSibling.innerHTML).toBe('');
|
|
3457
|
+
});
|
|
3458
|
+
|
|
3459
|
+
describe('with waitForCleanupOnDestroy configuration', () => {
|
|
3460
|
+
let originalEmbedConfig: any;
|
|
3461
|
+
|
|
3462
|
+
beforeEach(() => {
|
|
3463
|
+
originalEmbedConfig = embedConfig.getEmbedConfig();
|
|
3464
|
+
});
|
|
3465
|
+
|
|
3466
|
+
afterEach(() => {
|
|
3467
|
+
embedConfig.setEmbedConfig(originalEmbedConfig);
|
|
3468
|
+
});
|
|
3469
|
+
|
|
3470
|
+
it('should trigger DestroyEmbed event immediately when waitForCleanupOnDestroy is false', async () => {
|
|
3471
|
+
embedConfig.setEmbedConfig({
|
|
3472
|
+
...originalEmbedConfig,
|
|
3473
|
+
waitForCleanupOnDestroy: false,
|
|
3474
|
+
});
|
|
3475
|
+
|
|
3476
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
3477
|
+
frameParams: {
|
|
3478
|
+
width: '100%',
|
|
3479
|
+
height: '100%',
|
|
3480
|
+
},
|
|
3481
|
+
});
|
|
3482
|
+
await appEmbed.render();
|
|
3483
|
+
|
|
3484
|
+
const triggerSpy = jest.spyOn(appEmbed, 'trigger').mockResolvedValue(null);
|
|
3485
|
+
const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
|
|
3486
|
+
|
|
3487
|
+
appEmbed.destroy();
|
|
3488
|
+
|
|
3489
|
+
expect(triggerSpy).toHaveBeenCalledWith(HostEvent.DestroyEmbed);
|
|
3490
|
+
expect(removeChildSpy).toHaveBeenCalled();
|
|
3491
|
+
});
|
|
3492
|
+
|
|
3493
|
+
it('should trigger DestroyEmbed event and wait for cleanup when waitForCleanupOnDestroy is true', async () => {
|
|
3494
|
+
embedConfig.setEmbedConfig({
|
|
3495
|
+
...originalEmbedConfig,
|
|
3496
|
+
waitForCleanupOnDestroy: true,
|
|
3497
|
+
cleanupTimeout: 1000,
|
|
3498
|
+
});
|
|
3499
|
+
|
|
3500
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
3501
|
+
frameParams: {
|
|
3502
|
+
width: '100%',
|
|
3503
|
+
height: '100%',
|
|
3504
|
+
},
|
|
3505
|
+
});
|
|
3506
|
+
await appEmbed.render();
|
|
3507
|
+
|
|
3508
|
+
const triggerSpy = jest.spyOn(appEmbed, 'trigger').mockResolvedValue(null);
|
|
3509
|
+
const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
|
|
3510
|
+
|
|
3511
|
+
appEmbed.destroy();
|
|
3512
|
+
|
|
3513
|
+
// Should be called immediately when waitForCleanupOnDestroy is true
|
|
3514
|
+
expect(triggerSpy).toHaveBeenCalledWith(HostEvent.DestroyEmbed);
|
|
3515
|
+
|
|
3516
|
+
// Wait for the timeout to complete
|
|
3517
|
+
await new Promise(resolve => setTimeout(resolve, 1100));
|
|
3518
|
+
|
|
3519
|
+
expect(removeChildSpy).toHaveBeenCalled();
|
|
3520
|
+
});
|
|
3521
|
+
|
|
3522
|
+
it('should handle Promise.race with successful cleanup completion', async () => {
|
|
3523
|
+
embedConfig.setEmbedConfig({
|
|
3524
|
+
...originalEmbedConfig,
|
|
3525
|
+
waitForCleanupOnDestroy: true,
|
|
3526
|
+
cleanupTimeout: 2000,
|
|
3527
|
+
});
|
|
3528
|
+
|
|
3529
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
3530
|
+
frameParams: {
|
|
3531
|
+
width: '100%',
|
|
3532
|
+
height: '100%',
|
|
3533
|
+
},
|
|
3534
|
+
});
|
|
3535
|
+
await appEmbed.render();
|
|
3536
|
+
|
|
3537
|
+
// Mock trigger to resolve quickly (before timeout)
|
|
3538
|
+
const triggerSpy = jest.spyOn(appEmbed, 'trigger').mockImplementation(() =>
|
|
3539
|
+
new Promise(resolve => setTimeout(() => resolve(null), 100))
|
|
3540
|
+
);
|
|
3541
|
+
const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
|
|
3542
|
+
|
|
3543
|
+
appEmbed.destroy();
|
|
3544
|
+
|
|
3545
|
+
// Wait for the trigger to complete
|
|
3546
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
3547
|
+
|
|
3548
|
+
expect(triggerSpy).toHaveBeenCalledWith(HostEvent.DestroyEmbed);
|
|
3549
|
+
expect(removeChildSpy).toHaveBeenCalled();
|
|
3550
|
+
});
|
|
3551
|
+
|
|
3552
|
+
it('should handle Promise.race with timeout when cleanup takes too long', async () => {
|
|
3553
|
+
embedConfig.setEmbedConfig({
|
|
3554
|
+
...originalEmbedConfig,
|
|
3555
|
+
waitForCleanupOnDestroy: true,
|
|
3556
|
+
cleanupTimeout: 100,
|
|
3557
|
+
});
|
|
3558
|
+
|
|
3559
|
+
const appEmbed = new AppEmbed(getRootEl(), {
|
|
3560
|
+
frameParams: {
|
|
3561
|
+
width: '100%',
|
|
3562
|
+
height: '100%',
|
|
3563
|
+
},
|
|
3564
|
+
});
|
|
3565
|
+
await appEmbed.render();
|
|
3566
|
+
|
|
3567
|
+
// Mock trigger to take longer than timeout
|
|
3568
|
+
const triggerSpy = jest.spyOn(appEmbed, 'trigger').mockImplementation(() =>
|
|
3569
|
+
new Promise(resolve => setTimeout(() => resolve(null), 500))
|
|
3570
|
+
);
|
|
3571
|
+
const removeChildSpy = jest.spyOn(Node.prototype, 'removeChild').mockImplementation(() => getRootEl());
|
|
3572
|
+
|
|
3573
|
+
appEmbed.destroy();
|
|
3574
|
+
|
|
3575
|
+
// Wait for the timeout to complete
|
|
3576
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
3577
|
+
|
|
3578
|
+
expect(triggerSpy).toHaveBeenCalledWith(HostEvent.DestroyEmbed);
|
|
3579
|
+
expect(removeChildSpy).toHaveBeenCalled();
|
|
3580
|
+
});
|
|
3581
|
+
});
|
|
3582
|
+
});
|
|
3461
3583
|
});
|
package/src/embed/ts-embed.ts
CHANGED
|
@@ -71,7 +71,6 @@ import { getEmbedConfig } from './embedConfig';
|
|
|
71
71
|
import { ERROR_MESSAGE } from '../errors';
|
|
72
72
|
import { getPreauthInfo } from '../utils/sessionInfoService';
|
|
73
73
|
import { HostEventClient } from './hostEventClient/host-event-client';
|
|
74
|
-
import { getInterceptInitData, handleInterceptEvent, processLegacyInterceptResponse } from '../api-intercept';
|
|
75
74
|
|
|
76
75
|
const { version } = pkgInfo;
|
|
77
76
|
|
|
@@ -202,7 +201,7 @@ export class TsEmbed {
|
|
|
202
201
|
});
|
|
203
202
|
const embedConfig = getEmbedConfig();
|
|
204
203
|
this.embedConfig = embedConfig;
|
|
205
|
-
|
|
204
|
+
|
|
206
205
|
this.hostEventClient = new HostEventClient(this.iFrame);
|
|
207
206
|
this.isReadyForRenderPromise = getInitPromise().then(async () => {
|
|
208
207
|
if (!embedConfig.authTriggerContainer && !embedConfig.useEventForSAMLPopup) {
|
|
@@ -337,50 +336,33 @@ export class TsEmbed {
|
|
|
337
336
|
this.subscribedListeners.offline = offlineEventListener;
|
|
338
337
|
}
|
|
339
338
|
|
|
340
|
-
private messageEventListener = async (event: MessageEvent<any>) => {
|
|
341
|
-
const eventType = this.getEventType(event);
|
|
342
|
-
const eventPort = this.getEventPort(event);
|
|
343
|
-
const eventData = this.formatEventData(event, eventType);
|
|
344
|
-
if (event.source === this.iFrame.contentWindow) {
|
|
345
|
-
const processedEventData = await processEventData(
|
|
346
|
-
eventType,
|
|
347
|
-
eventData,
|
|
348
|
-
this.thoughtSpotHost,
|
|
349
|
-
this.isPreRendered ? this.preRenderWrapper : this.el,
|
|
350
|
-
);
|
|
351
|
-
|
|
352
|
-
const executeEvent = (_eventType: EmbedEvent, data: any) => {
|
|
353
|
-
this.executeCallbacks(_eventType, data, eventPort);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
if (eventType === EmbedEvent.ApiIntercept && this.viewConfig.enableApiIntercept) {
|
|
357
|
-
const getUnsavedAnswerTml = async (props: { sessionId?: string, vizId?: string }) => {
|
|
358
|
-
const response = await this.triggerUIPassThrough(UIPassthroughEvent.GetUnsavedAnswerTML, props);
|
|
359
|
-
return response[0]?.value;
|
|
360
|
-
}
|
|
361
|
-
handleInterceptEvent({ eventData: processedEventData, executeEvent, embedConfig: this.embedConfig, viewConfig: this.viewConfig, getUnsavedAnswerTml });
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
this.executeCallbacks(
|
|
366
|
-
eventType,
|
|
367
|
-
processedEventData,
|
|
368
|
-
eventPort,
|
|
369
|
-
);
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
339
|
/**
|
|
373
340
|
* Subscribe to message events that depend on successful iframe setup
|
|
374
341
|
*/
|
|
375
342
|
private subscribeToMessageEvents() {
|
|
376
343
|
this.unsubscribeToMessageEvents();
|
|
377
344
|
|
|
378
|
-
|
|
345
|
+
const messageEventListener = (event: MessageEvent<any>) => {
|
|
346
|
+
const eventType = this.getEventType(event);
|
|
347
|
+
const eventPort = this.getEventPort(event);
|
|
348
|
+
const eventData = this.formatEventData(event, eventType);
|
|
349
|
+
if (event.source === this.iFrame.contentWindow) {
|
|
350
|
+
this.executeCallbacks(
|
|
351
|
+
eventType,
|
|
352
|
+
processEventData(
|
|
353
|
+
eventType,
|
|
354
|
+
eventData,
|
|
355
|
+
this.thoughtSpotHost,
|
|
356
|
+
this.isPreRendered ? this.preRenderWrapper : this.el,
|
|
357
|
+
),
|
|
358
|
+
eventPort,
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
window.addEventListener('message', messageEventListener);
|
|
379
363
|
|
|
380
|
-
this.subscribedListeners.message =
|
|
364
|
+
this.subscribedListeners.message = messageEventListener;
|
|
381
365
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
366
|
/**
|
|
385
367
|
* Adds event listeners for both network and message events.
|
|
386
368
|
* This maintains backward compatibility with the existing method.
|
|
@@ -394,7 +376,6 @@ export class TsEmbed {
|
|
|
394
376
|
this.subscribeToMessageEvents();
|
|
395
377
|
}
|
|
396
378
|
|
|
397
|
-
|
|
398
379
|
private unsubscribeToNetworkEvents() {
|
|
399
380
|
if (this.subscribedListeners.online) {
|
|
400
381
|
window.removeEventListener('online', this.subscribedListeners.online);
|
|
@@ -445,7 +426,7 @@ export class TsEmbed {
|
|
|
445
426
|
message: customActionsResult.errors,
|
|
446
427
|
});
|
|
447
428
|
}
|
|
448
|
-
|
|
429
|
+
return {
|
|
449
430
|
customisations: getCustomisations(this.embedConfig, this.viewConfig),
|
|
450
431
|
authToken,
|
|
451
432
|
runtimeFilterParams: this.viewConfig.excludeRuntimeFiltersfromURL
|
|
@@ -464,10 +445,7 @@ export class TsEmbed {
|
|
|
464
445
|
this.embedConfig.customVariablesForThirdPartyTools || {},
|
|
465
446
|
hiddenListColumns: this.viewConfig.hiddenListColumns || [],
|
|
466
447
|
customActions: customActionsResult.actions,
|
|
467
|
-
...getInterceptInitData(this.embedConfig, this.viewConfig),
|
|
468
448
|
};
|
|
469
|
-
|
|
470
|
-
return baseInitData;
|
|
471
449
|
}
|
|
472
450
|
|
|
473
451
|
protected async getAppInitData() {
|
|
@@ -1045,21 +1023,6 @@ export class TsEmbed {
|
|
|
1045
1023
|
this.iFrame.style.height = getCssDimension(height);
|
|
1046
1024
|
}
|
|
1047
1025
|
|
|
1048
|
-
protected createEmbedEventResponder = (eventPort: MessagePort | void, eventType: EmbedEvent) => {
|
|
1049
|
-
|
|
1050
|
-
const { enableApiIntercept } = getInterceptInitData(this.embedConfig, this.viewConfig);
|
|
1051
|
-
if (eventType === EmbedEvent.OnBeforeGetVizDataIntercept && enableApiIntercept) {
|
|
1052
|
-
return (payload: any) => {
|
|
1053
|
-
const payloadToSend = processLegacyInterceptResponse(payload);
|
|
1054
|
-
this.triggerEventOnPort(eventPort, payloadToSend);
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
return (payload: any) => {
|
|
1059
|
-
this.triggerEventOnPort(eventPort, payload);
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
1026
|
/**
|
|
1064
1027
|
* Executes all registered event handlers for a particular event type
|
|
1065
1028
|
* @param eventType The event type
|
|
@@ -1084,8 +1047,9 @@ export class TsEmbed {
|
|
|
1084
1047
|
// payload
|
|
1085
1048
|
|| (!callbackObj.options.start && dataStatus === embedEventStatus.END)
|
|
1086
1049
|
) {
|
|
1087
|
-
|
|
1088
|
-
|
|
1050
|
+
callbackObj.callback(data, (payload) => {
|
|
1051
|
+
this.triggerEventOnPort(eventPort, payload);
|
|
1052
|
+
});
|
|
1089
1053
|
}
|
|
1090
1054
|
});
|
|
1091
1055
|
}
|
|
@@ -1227,12 +1191,12 @@ export class TsEmbed {
|
|
|
1227
1191
|
}
|
|
1228
1192
|
}
|
|
1229
1193
|
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1194
|
+
/**
|
|
1195
|
+
* @hidden
|
|
1196
|
+
* Internal state to track if the embed container is loaded.
|
|
1197
|
+
* This is used to trigger events after the embed container is loaded.
|
|
1198
|
+
*/
|
|
1199
|
+
public isEmbedContainerLoaded = false;
|
|
1236
1200
|
|
|
1237
1201
|
/**
|
|
1238
1202
|
* @hidden
|
|
@@ -1384,7 +1348,7 @@ export class TsEmbed {
|
|
|
1384
1348
|
}
|
|
1385
1349
|
this.isPreRendered = true;
|
|
1386
1350
|
this.showPreRenderByDefault = showPreRenderByDefault;
|
|
1387
|
-
|
|
1351
|
+
|
|
1388
1352
|
const isAlreadyRendered = this.connectPreRendered();
|
|
1389
1353
|
if (isAlreadyRendered && !replaceExistingPreRender) {
|
|
1390
1354
|
return this;
|
|
@@ -1432,8 +1396,21 @@ export class TsEmbed {
|
|
|
1432
1396
|
public destroy(): void {
|
|
1433
1397
|
try {
|
|
1434
1398
|
this.removeFullscreenChangeHandler();
|
|
1435
|
-
this.insertedDomEl?.parentNode.removeChild(this.insertedDomEl);
|
|
1436
1399
|
this.unsubscribeToEvents();
|
|
1400
|
+
if (!getEmbedConfig().waitForCleanupOnDestroy) {
|
|
1401
|
+
this.trigger(HostEvent.DestroyEmbed)
|
|
1402
|
+
this.insertedDomEl?.parentNode?.removeChild(this.insertedDomEl);
|
|
1403
|
+
} else {
|
|
1404
|
+
const cleanupTimeout = getEmbedConfig().cleanupTimeout;
|
|
1405
|
+
Promise.race([
|
|
1406
|
+
this.trigger(HostEvent.DestroyEmbed),
|
|
1407
|
+
new Promise((resolve) => setTimeout(resolve, cleanupTimeout)),
|
|
1408
|
+
]).then(() => {
|
|
1409
|
+
this.insertedDomEl?.parentNode?.removeChild(this.insertedDomEl);
|
|
1410
|
+
}).catch((e) => {
|
|
1411
|
+
logger.log('Error destroying TS Embed', e);
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1437
1414
|
} catch (e) {
|
|
1438
1415
|
logger.log('Error destroying TS Embed', e);
|
|
1439
1416
|
}
|
package/src/errors.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const ERROR_MESSAGE = {
|
|
2
2
|
INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
|
|
3
|
-
SPOTTER_EMBED_WORKSHEED_ID_NOT_FOUND: 'Please select a
|
|
3
|
+
SPOTTER_EMBED_WORKSHEED_ID_NOT_FOUND: 'Please select a Model to get started',
|
|
4
4
|
LIVEBOARD_VIZ_ID_VALIDATION: 'Please select a Liveboard to embed.',
|
|
5
5
|
TRIGGER_TIMED_OUT: 'Trigger timed-out in getting a response',
|
|
6
6
|
SEARCHEMBED_BETA_WRANING_MESSAGE: 'SearchEmbed is in Beta in this release.',
|
package/src/index.ts
CHANGED
|
@@ -30,10 +30,10 @@ import {
|
|
|
30
30
|
import { PinboardEmbed, LiveboardViewConfig, LiveboardEmbed } from './embed/liveboard';
|
|
31
31
|
import { SearchEmbed, SearchViewConfig } from './embed/search';
|
|
32
32
|
import { SearchBarEmbed, SearchBarViewConfig } from './embed/search-bar';
|
|
33
|
-
import { SpotterAgentEmbed, SpotterAgentEmbedViewConfig, BodylessConversation, BodylessConversationViewConfig
|
|
33
|
+
import { SpotterAgentEmbed, SpotterAgentEmbedViewConfig, BodylessConversation, BodylessConversationViewConfig} from './embed/bodyless-conversation';
|
|
34
34
|
import { SpotterEmbed, SpotterEmbedViewConfig, ConversationEmbed, ConversationViewConfig } from './embed/conversation';
|
|
35
35
|
import {
|
|
36
|
-
AuthFailureType, AuthStatus, AuthEvent,
|
|
36
|
+
AuthFailureType, AuthStatus, AuthEvent, AuthEventEmitter,
|
|
37
37
|
} from './auth';
|
|
38
38
|
import { getSessionInfo } from './utils/sessionInfoService';
|
|
39
39
|
import {
|
|
@@ -64,7 +64,6 @@ import {
|
|
|
64
64
|
ListPageColumns,
|
|
65
65
|
CustomActionsPosition,
|
|
66
66
|
CustomActionTarget,
|
|
67
|
-
InterceptedApiType,
|
|
68
67
|
} from './types';
|
|
69
68
|
import { CustomCssVariables } from './css-variables';
|
|
70
69
|
import { SageEmbed, SageViewConfig } from './embed/sage';
|
|
@@ -106,6 +105,7 @@ export {
|
|
|
106
105
|
AuthFailureType,
|
|
107
106
|
AuthStatus,
|
|
108
107
|
AuthEvent,
|
|
108
|
+
AuthEventEmitter,
|
|
109
109
|
AnswerService,
|
|
110
110
|
// types
|
|
111
111
|
SessionInterface,
|
|
@@ -152,7 +152,6 @@ export {
|
|
|
152
152
|
DataPanelCustomColumnGroupsAccordionState,
|
|
153
153
|
CustomActionsPosition,
|
|
154
154
|
CustomActionTarget,
|
|
155
|
-
InterceptedApiType,
|
|
156
155
|
};
|
|
157
156
|
|
|
158
157
|
export { resetCachedAuthToken } from './authToken';
|
|
@@ -6,14 +6,6 @@ describe('Exports', () => {
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
it('should not have undefined exports', () => {
|
|
9
|
-
|
|
10
|
-
.filter(([, exportValue]) => !Boolean(exportValue))
|
|
11
|
-
.map(([key]) => key);
|
|
12
|
-
// Helpful log if the expectation fails
|
|
13
|
-
if (undefinedKeys.length) {
|
|
14
|
-
// eslint-disable-next-line no-console
|
|
15
|
-
console.log('Undefined re-exports in all-types-export:', undefinedKeys);
|
|
16
|
-
}
|
|
17
|
-
Object.entries(Exports).forEach(([, exportValue]) => { expect(Boolean(exportValue)).toBe(true); });
|
|
9
|
+
Object.entries(Exports).forEach(([, exportValue]) => {expect(Boolean(exportValue)).toBe(true);});
|
|
18
10
|
});
|
|
19
11
|
});
|
|
@@ -29,29 +29,23 @@ export {
|
|
|
29
29
|
AuthFailureType,
|
|
30
30
|
AuthStatus,
|
|
31
31
|
AuthEvent,
|
|
32
|
-
|
|
32
|
+
AuthEventEmitter,
|
|
33
|
+
// types
|
|
33
34
|
Page,
|
|
34
35
|
AuthType,
|
|
36
|
+
RuntimeFilter,
|
|
35
37
|
RuntimeFilterOp,
|
|
36
38
|
EmbedEvent,
|
|
37
39
|
HostEvent,
|
|
38
40
|
DataSourceVisualMode,
|
|
39
41
|
Action,
|
|
40
|
-
PrefetchFeatures,
|
|
41
|
-
resetCachedAuthToken,
|
|
42
|
-
DataPanelCustomColumnGroupsAccordionState,
|
|
43
|
-
InterceptedApiType,
|
|
44
|
-
} from '../index';
|
|
45
|
-
|
|
46
|
-
export type {
|
|
47
|
-
// type-only exports
|
|
48
|
-
RuntimeFilter,
|
|
49
42
|
EmbedConfig,
|
|
50
43
|
SearchViewConfig,
|
|
51
44
|
SearchBarViewConfig,
|
|
52
45
|
LiveboardViewConfig,
|
|
53
46
|
SageViewConfig,
|
|
54
47
|
AppViewConfig,
|
|
48
|
+
PrefetchFeatures,
|
|
55
49
|
FrameParams,
|
|
56
50
|
DOMSelector,
|
|
57
51
|
MessageOptions,
|
|
@@ -62,5 +56,9 @@ export type {
|
|
|
62
56
|
customCssInterface,
|
|
63
57
|
CustomCssVariables,
|
|
64
58
|
RuntimeParameter,
|
|
59
|
+
resetCachedAuthToken,
|
|
65
60
|
UIPassthroughEvent,
|
|
61
|
+
DataPanelCustomColumnGroupsAccordionState,
|
|
62
|
+
CustomActionsPosition,
|
|
63
|
+
CustomActionTarget,
|
|
66
64
|
} from '../index';
|