Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions jest-setup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const fetchMock = require('jest-fetch-mock');
const crypto = require('crypto');

fetchMock.enableMocks();

Expand Down Expand Up @@ -32,3 +33,10 @@ global.MessageChannel = jest.fn().mockImplementation(() => {
},
};
});

Object.defineProperty(global, 'crypto', {
value: {
getRandomValues: (arr) => crypto.randomBytes(arr.length),
randomUUID: () => crypto.randomBytes(16).toString('hex'),
},
});
26,325 changes: 20,770 additions & 5,555 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@thoughtspot/visual-embed-sdk",
"version": "1.33.0",
"version": "1.33.1",
"description": "ThoughtSpot Embed SDK",
"module": "lib/src/index.js",
"main": "dist/tsembed.js",
Expand Down Expand Up @@ -37,8 +37,8 @@
},
"size-limit": [
{
"path": "dist/tsembed.js",
"limit": "49 kB"
"path": "dist/es/index.js",
"limit": "30 kB"
}
],
"scripts": {
Expand Down Expand Up @@ -80,7 +80,8 @@
"mixpanel-browser": "2.47.0",
"ts-deepmerge": "^6.0.2",
"tslib": "^2.5.3",
"use-deep-compare-effect": "^1.8.1"
"use-deep-compare-effect": "^1.8.1",
"yaml": "^2.5.1"
},
"devDependencies": {
"@mdx-js/mdx": "^1.6.22",
Expand All @@ -96,8 +97,8 @@
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^13.1.8",
"@types/jest": "^22.2.3",
"@types/mixpanel-browser": "^2.35.6",
"@types/lodash": "^4.17.0",
"@types/mixpanel-browser": "^2.35.6",
"@types/react-test-renderer": "^17.0.1",
"@typescript-eslint/eslint-plugin": "^4.6.0",
"@typescript-eslint/parser": "^4.6.0",
Expand All @@ -106,6 +107,7 @@
"babel-preset-gatsby": "^1.10.0",
"command-line-args": "^5.1.1",
"coveralls": "^3.1.0",
"crypto": "^1.0.1",
"current-git-branch": "^1.1.0",
"dts-bundle": "^0.7.3",
"eslint": "^7.12.1",
Expand All @@ -132,7 +134,7 @@
"react-resize-detector": "^6.6.0",
"react-test-renderer": "^17.0.2",
"react-use-flexsearch": "^0.1.1",
"rollup": "2.30.0",
"rollup": "4.24.0",
"rollup-plugin-typescript2": "0.27.3",
"ts-jest": "^26.5.5",
"ts-loader": "8.0.4",
Expand Down
33 changes: 17 additions & 16 deletions rollup.config.js → rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* Copyright (c) 2020
*
* Rollup configuration for building ThoughtSpot Embed UI SDK module
*
* @summary Rollup config
* @author Ayon Ghosh <[email protected]>
*/
Expand All @@ -13,31 +12,31 @@ import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import replace from '@rollup/plugin-replace';

import pkg from './package.json';
import pkg from './package.json' assert {type: "json"};

const plugins = [
typescript({
typescript: require('typescript'),
}),
nodeResolve(),
commonjs(),
json({
compact: true
}),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
})
];
typescript(),
nodeResolve(),
commonjs(),
json({
compact: true,
}),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
];

export default [{
input: 'src/index.ts',
output: [
{
file: 'dist/tsembed.js',
format: 'umd',
inlineDynamicImports: true,
name: 'tsembed',
},
{
file: 'dist/tsembed.es.js',
dir: 'dist/es',
format: 'es',
},
],
Expand All @@ -51,10 +50,12 @@ export default [{
{
file: 'dist/tsembed-react.js',
format: 'umd',
inlineDynamicImports: true,
name: 'tsembed',
},
{
file: 'dist/tsembed-react.es.js',
dir: 'dist/es/react',
inlineDynamicImports: true,
format: 'es',
},
],
Expand Down
15 changes: 3 additions & 12 deletions src/auth.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import 'jest-fetch-mock';
import * as authInstance from './auth';
import * as authTokenService from './authToken';
import * as EmbedConfig from './embed/embedConfig';
import * as mixPanelService from './mixpanel-service';
import { executeAfterWait } from './test/test-utils';
import { executeAfterWait, mockSessionInfo } from './test/test-utils';
import { AuthType, EmbedEvent } from './types';
import * as checkReleaseVersionInBetaInstance from './utils';
import * as authService from './utils/authService/authService';
Expand Down Expand Up @@ -102,17 +103,6 @@ export const embedConfig: any = {
};

const originalWindow = window;
export const mockSessionInfo = {
userGUID: '1234',
mixpanelToken: 'abc123',
isPublicUser: false,
sessionId: '6588e7d9-710c-453e-a7b4-535fb3a8cbb2',
genNo: 3,
acSession: {
sessionId: 'cb202c48-b14b-4466-8a70-899ea666d46q',
genNo: 5,
},
};

export const mockSessionInfoApiResponse = {
userGUID: '1234',
Expand Down Expand Up @@ -205,6 +195,7 @@ describe('Unit test for auth', () => {
});

test('doTokenAuth: when user is not loggedIn & getAuthToken not present, isLoggedIn should called', async () => {
fetchMock.mockResponse(JSON.stringify({ mixpanelAccessToken: '' }));
jest.spyOn(tokenAuthService, 'isActiveService').mockImplementation(async () => false);
jest.spyOn(authService, 'fetchAuthTokenService').mockImplementation(() => ({
text: () => Promise.resolve('abc'),
Expand Down
3 changes: 1 addition & 2 deletions src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
}

/**
* Enum for auth status emitted by the emitter returned from {@link init}.

Check warning on line 45 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

The type 'init' is undefined
* @group Authentication / Init
*/
export enum AuthStatus {
Expand All @@ -66,13 +66,13 @@
* Emitted when inPopup is true in the SAMLRedirect flow and the
* popup is waiting to be triggered either programmatically
* or by the trigger button.
* @version SDK: 1.19.0

Check warning on line 69 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Invalid JSDoc @Version: "SDK: 1.19.0"
*/
WAITING_FOR_POPUP = 'WAITING_FOR_POPUP',
}

/**
* Event emitter returned from {@link init}.

Check warning on line 75 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

The type 'init' is undefined
* @group Authentication / Init
*/
export interface AuthEventEmitter {
Expand Down Expand Up @@ -100,7 +100,7 @@
once(event: AuthStatus.SUCCESS, listener: (sessionInfo: any) => void): this;
/**
* Trigger an event on the emitter returned from init.
* @param {@link AuthEvent}

Check warning on line 103 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Syntax error in type: @link AuthEvent
*/
emit(event: AuthEvent, ...args: any[]): boolean;
/**
Expand All @@ -119,7 +119,7 @@
}

/**
* Events which can be triggered on the emitter returned from {@link init}.

Check warning on line 122 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

The type 'init' is undefined
* @group Authentication / Init
*/
export enum AuthEvent {
Expand All @@ -132,7 +132,7 @@

let authEE: EventEmitter<AuthStatus | AuthEvent>;

/**

Check warning on line 135 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @returns declaration
*
*/
export function getAuthEE(): EventEmitter<AuthStatus | AuthEvent> {
Expand All @@ -141,7 +141,7 @@

/**
*
* @param eventEmitter

Check warning on line 144 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @param "eventEmitter" description

Check warning on line 144 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @param "eventEmitter" type
*/
export function setAuthEE(eventEmitter: EventEmitter<AuthStatus | AuthEvent>): void {
authEE = eventEmitter;
Expand Down Expand Up @@ -176,7 +176,7 @@

/**
*
* @param failureType

Check warning on line 179 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @param "failureType" description

Check warning on line 179 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @param "failureType" type
*/
export function notifyAuthFailure(failureType: AuthFailureType): void {
if (!authEE) {
Expand Down Expand Up @@ -214,7 +214,6 @@
* Services to be called after the login is successful,
* This should be called after the cookie is set for cookie auth or
* after the token is set for cookieless.
*
* @return {Promise<void>}
* @example
* ```js
Expand All @@ -231,7 +230,7 @@
initMixpanel(sessionInfo);
}
} catch (e) {
logger.error('Post login services failed.', e.message);
logger.error('Post login services failed.', e.message, e);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/authToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { logger } from './utils/logger';
let cachedAuthToken: string | null = null;

// This method can be used to get the authToken using the embedConfig
/**
*
* @param embedConfig
*/
export async function getAuthenticationToken(embedConfig: EmbedConfig): Promise<string> {
// Since we don't have token validation enabled , we cannot tell if the
// cached token is valid or not. So we will always fetch a new token.
Expand Down
141 changes: 141 additions & 0 deletions src/embed/bodyless-conversation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import 'jest-fetch-mock';
import { BodylessConversation, BodylessConversationViewConfig } from './bodyless-conversation';
import * as authInstance from '../auth';
import { init } from '../index';
import { Action, AuthType, RuntimeFilterOp } from '../types';
import {
executeAfterWait,
getDocumentBody,
getIFrameSrc,
getRootEl,
fixedEncodeURI,
defaultParamsWithoutHiddenActions as defaultParams,
expectUrlMatchesWithParams,
expectUrlToHaveParamsWithValues,
} from '../test/test-utils';

describe('BodylessConversation', () => {
const thoughtSpotHost = 'tshost';

beforeAll(() => {
init({
thoughtSpotHost,
authType: AuthType.None,
});
jest.spyOn(authInstance, 'postLoginService').mockImplementation(() => Promise.resolve({}));
spyOn(window, 'alert');
document.body.innerHTML = getDocumentBody();
});

beforeEach(() => {
fetchMock.resetMocks();
});

test('should render the bodyless conversation embed', async () => {
fetchMock.mockResponses(
JSON.stringify({
data: {
ConvAssist__createConversation: {
convId: 'conversationId',
initialCtx: {
type: 'TS_ANSWER',
tsAnsCtx: {
sessionId: 'sessionId',
genNo: 1,
stateKey: {
transactionId: 'transactionId',
generationNumber: 1,
},
worksheet: {
worksheetId: 'worksheetId',
worksheetName: 'GTM',
},
},
},
},
},
}),
JSON.stringify({
data: {
ConvAssist__sendMessage: {
responses: [
{
msgId: 'msgId',
data: {
asstRespData: {
tool: 'TS_NLS',
asstRespText: '',
nlsAnsData: {
sageQuerySuggestions: [
{
llmReasoning: {
assumptions: 'You want the total [COL|sales] for [COL|item_type] [VAL|jackets] for [VAL|this year].',
clarifications: '',
interpretation: '',
__typename: 'eureka_SageQuerySuggestion_LLMReasoning',
},
tokens: [
'sum sales',
"item type = 'jackets'",
"date = 'this year'",
],
tmlTokens: [
'sum [sales]',
"[date] = [date].'this year'",
"[item type] = [item type].'jackets'",
],
worksheetId: 'worksheetId',
description: '',
title: '',
cached: false,
sqlQuery: "SELECT SUM(sales) FROM __Sample_Retail_Apparel WHERE item_type = 'jackets' AND date = _this_year();",
sessionId: 'sessionId',
genNo: 2,
formulaInfo: [],
tmlPhrases: [],
stateKey: {
transactionId: 'transactionId',
generationNumber: 1,
__typename: 'sage_auto_complete_v2_ACStateKey',
},
__typename: 'eureka_SageQuerySuggestion',
},
],
responseType: 'ANSWER',
__typename: 'convassist_nls_tool_NLSToolAsstRespData',
},
__typename: 'convassist_AsstResponseData',
},
__typename: 'convassist_MessageData',
},
type: 'ASST_RESPONSE',
__typename: 'convassist_MessagePayload',
},
],
__typename: 'convassist_SendMessageResponse',
},
},
}),
);
const viewConfig: BodylessConversationViewConfig = {
worksheetId: 'worksheetId',
};

const conversationEmbed = new BodylessConversation(viewConfig);
const result = await conversationEmbed.sendMessage('userMessage');
console.log(result.container);
const iframeSrc = getIFrameSrc(result.container);
expectUrlToHaveParamsWithValues(iframeSrc, {
sessionId: 'sessionId',
genNo: 2,
acSessionId: 'transactionId',
acGenNo: 1,
});

fetchMock.mockRejectOnce(
new Error('error'),
);
const errorResult = await conversationEmbed.sendMessage('userMessage');
expect(errorResult.error instanceof Error).toBeTruthy();
});
});
Loading
Loading