@thoughtspot/visual-embed-sdk
Version:
ThoughtSpot Embed SDK
399 lines • 19.1 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const custom_actions_1 = require("./custom-actions");
const types_1 = require("../types");
// Mock logger
jest.mock('./logger', () => ({
logger: {
warn: jest.fn(),
error: jest.fn(),
},
}));
describe('getCustomActions function', () => {
describe('Static getCustomActions method', () => {
test('should return empty result for empty array', () => {
const result = (0, custom_actions_1.getCustomActions)([]);
expect(result.actions).toEqual([]);
expect(result.errors).toEqual([]);
});
test('should return empty result for null/undefined input', () => {
const result1 = (0, custom_actions_1.getCustomActions)(null);
expect(result1.actions).toEqual([]);
expect(result1.errors).toEqual([]);
const result2 = (0, custom_actions_1.getCustomActions)(undefined);
expect(result2.actions).toEqual([]);
expect(result2.errors).toEqual([]);
});
test('should validate and return valid actions', () => {
const actions = [
{
name: 'Test Action',
id: 'test-id',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
},
];
const result = (0, custom_actions_1.getCustomActions)(actions);
expect(result.actions).toEqual(actions);
expect(result.errors).toEqual([]);
});
test('should reject invalid actions and collect errors', () => {
const actions = [
{
name: 'Valid Action',
id: 'valid-id',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
},
{
name: 'Invalid Action',
id: 'invalid-id',
target: types_1.CustomActionTarget.SPOTTER,
position: types_1.CustomActionsPosition.PRIMARY, // Invalid for SPOTTER
},
];
const result = (0, custom_actions_1.getCustomActions)(actions);
expect(result.actions).toEqual([actions[0]]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Position 'PRIMARY' is not supported for spotter-level custom actions. Supported positions: MENU, CONTEXTMENU");
});
test('should sort actions by name', () => {
const actions = [
{
name: 'Zebra Action',
id: 'zebra-id',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
},
{
name: 'Alpha Action',
id: 'alpha-id',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.MENU,
},
];
const result = (0, custom_actions_1.getCustomActions)(actions);
expect(result.actions).toHaveLength(2);
expect(result.actions[0].name).toBe('Alpha Action');
expect(result.actions[1].name).toBe('Zebra Action');
});
});
describe('Input Validation', () => {
test('should return false for null action', () => {
const result = (0, custom_actions_1.getCustomActions)([null]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain('Custom Action Validation Error: Invalid action object provided');
});
test('should return false for undefined action', () => {
const result = (0, custom_actions_1.getCustomActions)([undefined]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain('Custom Action Validation Error: Invalid action object provided');
});
test('should return false for non-object action', () => {
const result = (0, custom_actions_1.getCustomActions)(['string']);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain('Custom Action Validation Error: Invalid action object provided');
});
test('should return false for action missing id', () => {
const action = {
name: 'Test Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Missing required fields: id");
});
test('should return false for action missing name', () => {
const action = {
id: 'test-id',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Missing required fields: name");
});
test('should return false for action missing target', () => {
const action = {
id: 'test-id',
name: 'Test Action',
position: types_1.CustomActionsPosition.PRIMARY,
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Missing required fields: target");
});
test('should return false for action missing position', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.LIVEBOARD,
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Missing required fields: position");
});
});
describe('Target Type Validation', () => {
test('should reject unsupported target type', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: 'UNSUPPORTED',
position: types_1.CustomActionsPosition.PRIMARY,
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Target type 'UNSUPPORTED' is not supported");
});
test('should accept LIVEBOARD target type', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([action]);
expect(result.errors).toEqual([]);
});
test('should accept VIZ target type', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.VIZ,
position: types_1.CustomActionsPosition.MENU,
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([action]);
expect(result.errors).toEqual([]);
});
test('should accept ANSWER target type', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.ANSWER,
position: types_1.CustomActionsPosition.MENU,
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([action]);
expect(result.errors).toEqual([]);
});
test('should accept SPOTTER target type', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.SPOTTER,
position: types_1.CustomActionsPosition.MENU,
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([action]);
expect(result.errors).toEqual([]);
});
});
describe('Position Validation', () => {
test('should reject invalid position for LIVEBOARD', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.CONTEXTMENU, // Invalid for LIVEBOARD
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors).toContain("Position 'CONTEXTMENU' is not supported for liveboard-level custom actions. Supported positions: PRIMARY, MENU");
});
test('should reject invalid position for SPOTTER', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.SPOTTER,
position: types_1.CustomActionsPosition.PRIMARY, // Invalid for SPOTTER
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Position 'PRIMARY' is not supported for spotter-level custom actions. Supported positions: MENU, CONTEXTMENU");
});
test('should accept valid positions for LIVEBOARD', () => {
const primaryAction = {
id: 'primary-id',
name: 'Primary Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
};
const menuAction = {
id: 'menu-id',
name: 'Menu Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.MENU,
};
const result = (0, custom_actions_1.getCustomActions)([primaryAction, menuAction]);
expect(result.actions).toHaveLength(2);
expect(result.errors).toEqual([]);
});
});
describe('Metadata IDs Validation', () => {
test('should reject invalid metadata IDs for LIVEBOARD', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
metadataIds: {
invalidId: 'some-value',
},
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Invalid metadata IDs for liveboard-level custom actions: invalidId. Supported metadata IDs: liveboardIds");
});
test('should accept valid metadata IDs for LIVEBOARD', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
metadataIds: {
liveboardIds: ['lb-1', 'lb-2'],
},
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([action]);
expect(result.errors).toEqual([]);
});
});
describe('Data Model IDs Validation', () => {
test('should reject invalid data model IDs for VIZ', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.VIZ,
position: types_1.CustomActionsPosition.MENU,
dataModelIds: {
invalidId: 'some-value',
},
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Invalid data model IDs for viz-level custom actions: invalidId. Supported data model IDs: modelIds, modelColumnNames");
});
test('should accept valid data model IDs for VIZ', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.VIZ,
position: types_1.CustomActionsPosition.MENU,
dataModelIds: {
modelIds: ['model-1'],
modelColumnNames: ['col-1'],
},
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([action]);
expect(result.errors).toEqual([]);
});
});
describe('Field Validation', () => {
test('should reject invalid fields for LIVEBOARD', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
invalidField: 'some-value',
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Invalid fields for liveboard-level custom actions: invalidField. Supported fields: name, id, position, target, metadataIds, orgIds, groupIds");
});
test('should accept valid fields for LIVEBOARD', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
orgIds: ['org-1'],
groupIds: ['group-1'],
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([action]);
expect(result.errors).toEqual([]);
});
});
describe('Duplicate ID Handling', () => {
test('should keep only the first action when duplicate IDs are found and report duplicate errors', () => {
const action1 = {
id: 'duplicate-id',
name: 'First Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
};
const action2 = {
id: 'duplicate-id',
name: 'Second Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.MENU,
};
const result = (0, custom_actions_1.getCustomActions)([action1, action2]);
expect(result.actions).toHaveLength(1);
expect(result.actions[0]).toEqual(action1);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Duplicate custom action ID 'duplicate-id' found");
expect(result.errors[0]).toContain("Actions with names 'Second Action' will be ignored");
expect(result.errors[0]).toContain("Keeping 'First Action'");
});
});
describe('Complex Validation Scenarios', () => {
test('should handle multiple validation errors for a single action', () => {
const action = {
id: 'test-id',
name: 'Test Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.CONTEXTMENU,
metadataIds: {
invalidId: 'some-value', // Invalid metadata ID
},
invalidField: 'some-value', // Invalid field
};
const result = (0, custom_actions_1.getCustomActions)([action]);
expect(result.actions).toEqual([]);
expect(result.errors).toHaveLength(3);
expect(result.errors).toContain("Position 'CONTEXTMENU' is not supported for liveboard-level custom actions. Supported positions: PRIMARY, MENU");
expect(result.errors).toContain("Invalid metadata IDs for liveboard-level custom actions: invalidId. Supported metadata IDs: liveboardIds");
expect(result.errors).toContain("Invalid fields for liveboard-level custom actions: invalidField. Supported fields: name, id, position, target, metadataIds, orgIds, groupIds");
});
test('should handle mix of valid and invalid actions', () => {
const validAction = {
id: 'valid-id',
name: 'Valid Action',
target: types_1.CustomActionTarget.LIVEBOARD,
position: types_1.CustomActionsPosition.PRIMARY,
};
const invalidAction = {
id: 'invalid-id',
name: 'Invalid Action',
target: types_1.CustomActionTarget.SPOTTER,
position: types_1.CustomActionsPosition.PRIMARY, // Invalid for SPOTTER
};
const result = (0, custom_actions_1.getCustomActions)([validAction, invalidAction]);
expect(result.actions).toEqual([validAction]);
expect(result.errors).toHaveLength(1);
expect(result.errors[0]).toContain("Position 'PRIMARY' is not supported for spotter-level custom actions. Supported positions: MENU, CONTEXTMENU");
});
});
});
//# sourceMappingURL=custom-actions.spec.js.map
;