-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* feat: gainsight PX destination (#1852) * feat: gainsight PX destination * feat: Gainsight PX destination PR Feedback - changed name to use existing name * feat: gainsight PX destination PR feedback - Switched to use integration options instead of extra config object. Cleaned up identify * feat: gainsight PX destination PR feedback - Use integration config * feat: gainsight PX destination fixed typo on us2 datacenter URL * fix: updating config name to productTagKey and adding test cases * fix: added new test case * fix: added new test case * fix: fix imports * fix: fix destination name * fix: fix size limits * fix: fix build size * fix: fix build size --------- Co-authored-by: Nick Wolfe <[email protected]>
- Loading branch information
1 parent
bfa9d0a
commit 3a705f0
Showing
13 changed files
with
431 additions
and
2 deletions.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
packages/analytics-js-common/src/constants/integrations/Gainsight_PX/constants.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
const DIR_NAME = 'Gainsight_PX'; | ||
const NAME = 'GAINSIGHT_PX'; | ||
const DISPLAY_NAME = 'Gainsight PX'; | ||
|
||
const DISPLAY_NAME_TO_DIR_NAME_MAP = { [DISPLAY_NAME]: DIR_NAME }; | ||
const CNameMapping = { | ||
[NAME]: NAME, | ||
Gainsight_PX: NAME, | ||
}; | ||
|
||
export { NAME, CNameMapping, DISPLAY_NAME_TO_DIR_NAME_MAP, DISPLAY_NAME, DIR_NAME }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
239 changes: 239 additions & 0 deletions
239
packages/analytics-js-integrations/__tests__/integrations/Gainsight_PX/browser.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
import Gainsight_PX from '../../../src/integrations/Gainsight_PX/browser'; | ||
import { loadNativeSdk } from '../../../src/integrations/Gainsight_PX/nativeSdkLoader'; | ||
import { getDestinationOptions } from '../../../src/integrations/Gainsight_PX/utils'; | ||
|
||
// Mock the external dependencies | ||
jest.mock('../../../src/integrations/Gainsight_PX/nativeSdkLoader'); | ||
jest.mock('../../../src/integrations/Gainsight_PX/utils'); | ||
|
||
describe('Gainsight_PX', () => { | ||
let gainsightPX; | ||
let mockAnalytics; | ||
let mockConfig; | ||
|
||
beforeEach(() => { | ||
// Reset mocks | ||
jest.clearAllMocks(); | ||
|
||
// Mock window.aptrinsic | ||
window.aptrinsic = jest.fn(); | ||
|
||
// Mock analytics object | ||
mockAnalytics = { | ||
logLevel: 'debug', | ||
getUserId: jest.fn(), | ||
getUserTraits: jest.fn(), | ||
getGroupId: jest.fn(), | ||
getGroupTraits: jest.fn(), | ||
loadOnlyIntegrations: {}, | ||
}; | ||
|
||
// Mock config | ||
mockConfig = { | ||
productTagKey: 'test-product-key', | ||
dataCenter: 'US', | ||
}; | ||
|
||
gainsightPX = new Gainsight_PX(mockConfig, mockAnalytics); | ||
}); | ||
|
||
describe('init', () => { | ||
it('should load native SDK and initialize', () => { | ||
getDestinationOptions.mockReturnValue({ someOption: 'value' }); | ||
mockAnalytics.getUserId.mockReturnValue('test-user-id'); | ||
mockAnalytics.getUserTraits.mockReturnValue({ name: 'Test User' }); | ||
mockAnalytics.getGroupId.mockReturnValue('test-group-id'); | ||
mockAnalytics.getGroupTraits.mockReturnValue({ plan: 'premium' }); | ||
|
||
gainsightPX.init(); | ||
|
||
expect(loadNativeSdk).toHaveBeenCalledWith('test-product-key', 'US', { someOption: 'value' }); | ||
expect(window.aptrinsic).toHaveBeenCalledWith( | ||
'identify', | ||
{ id: 'test-user-id', name: 'Test User' }, | ||
{ id: 'test-group-id', plan: 'premium' } | ||
); | ||
}); | ||
|
||
it('should not call identify if user ID is not present', () => { | ||
mockAnalytics.getUserId.mockReturnValue(null); | ||
|
||
gainsightPX.init(); | ||
|
||
expect(loadNativeSdk).toHaveBeenCalled(); | ||
expect(window.aptrinsic).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
describe('isLoaded', () => { | ||
it('should return true when window.aptrinsic and window.aptrinsic.init exist', () => { | ||
window.aptrinsic = { init: jest.fn() }; | ||
expect(gainsightPX.isLoaded()).toBe(true); | ||
}); | ||
|
||
it('should return false when window.aptrinsic does not exist', () => { | ||
delete window.aptrinsic; | ||
expect(gainsightPX.isLoaded()).toBe(false); | ||
}); | ||
|
||
it('should return false when window.aptrinsic exists but init is missing', () => { | ||
window.aptrinsic = {}; | ||
expect(gainsightPX.isLoaded()).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('isReady', () => { | ||
it('should return the same value as isLoaded', () => { | ||
window.aptrinsic = { init: jest.fn() }; | ||
expect(gainsightPX.isReady()).toBe(gainsightPX.isLoaded()); | ||
|
||
delete window.aptrinsic; | ||
expect(gainsightPX.isReady()).toBe(gainsightPX.isLoaded()); | ||
}); | ||
}); | ||
|
||
describe('identify', () => { | ||
it('should call aptrinsic identify with user data', () => { | ||
const rudderElement = { | ||
message: { | ||
userId: 'test-user-id', | ||
context: { | ||
traits: { name: 'Test User', email: '[email protected]' }, | ||
}, | ||
}, | ||
}; | ||
|
||
gainsightPX.identify(rudderElement); | ||
|
||
expect(window.aptrinsic).toHaveBeenCalledWith( | ||
'identify', | ||
{ id: 'test-user-id', name: 'Test User', email: '[email protected]' }, | ||
{} | ||
); | ||
}); | ||
|
||
it('should not call aptrinsic identify if userId is missing', () => { | ||
const rudderElement = { | ||
message: { | ||
context: { | ||
traits: { name: 'Test User' }, | ||
}, | ||
}, | ||
}; | ||
|
||
gainsightPX.identify(rudderElement); | ||
|
||
expect(window.aptrinsic).not.toHaveBeenCalled(); | ||
}); | ||
|
||
test('Testing identify call with ID only', () => { | ||
// call RudderStack function | ||
gainsightPX.identify({ | ||
message: { | ||
userId: 'rudder01', | ||
context: {} | ||
} | ||
}); | ||
|
||
// Confirm that it was translated to the appropriate PX call | ||
expect(window.aptrinsic.mock.calls[0]).toEqual([ | ||
'identify', | ||
{ | ||
id: 'rudder01' | ||
}, | ||
{} | ||
]); | ||
}); | ||
|
||
}); | ||
|
||
describe('group', () => { | ||
it('should call aptrinsic identify with group data', () => { | ||
const rudderElement = { | ||
message: { | ||
userId: 'test-user-id', | ||
groupId: 'test-group-id', | ||
traits: { plan: 'premium' }, | ||
context: { | ||
traits: { name: 'Test User' }, | ||
}, | ||
}, | ||
}; | ||
|
||
gainsightPX.group(rudderElement); | ||
|
||
expect(window.aptrinsic).toHaveBeenCalledWith( | ||
'identify', | ||
{ id: 'test-user-id', name: 'Test User' }, | ||
{ id: 'test-group-id', plan: 'premium' } | ||
); | ||
}); | ||
|
||
it('should use anonymousId if groupId is not present', () => { | ||
const rudderElement = { | ||
message: { | ||
anonymousId: 'anon-id', | ||
traits: { plan: 'basic' }, | ||
}, | ||
}; | ||
|
||
gainsightPX.group(rudderElement); | ||
|
||
expect(window.aptrinsic).toHaveBeenCalledWith( | ||
'identify', | ||
{}, | ||
{ id: 'anon-id', plan: 'basic' } | ||
); | ||
}); | ||
}); | ||
|
||
describe('track', () => { | ||
it('should call aptrinsic track with event data', () => { | ||
const rudderElement = { | ||
message: { | ||
event: 'Test Event', | ||
properties: { category: 'test', value: 10 }, | ||
}, | ||
}; | ||
|
||
gainsightPX.track(rudderElement); | ||
|
||
expect(window.aptrinsic).toHaveBeenCalledWith( | ||
'track', | ||
'Test Event', | ||
{ category: 'test', value: 10 } | ||
); | ||
}); | ||
|
||
it('should not call aptrinsic track if event name is missing', () => { | ||
const rudderElement = { | ||
message: { | ||
properties: { category: 'test' }, | ||
}, | ||
}; | ||
|
||
gainsightPX.track(rudderElement); | ||
|
||
expect(window.aptrinsic).not.toHaveBeenCalled(); | ||
}); | ||
|
||
test('Test for empty properties', () => { | ||
// call RudderStack function | ||
gainsightPX.track({ | ||
message: { | ||
context: {}, | ||
event: 'event-name', | ||
properties: {} | ||
} | ||
}); | ||
|
||
// Confirm that it was translated to the appropriate PX call | ||
expect(window.aptrinsic.mock.calls[0]).toEqual([ | ||
'track', | ||
'event-name', | ||
{} | ||
]); | ||
}); | ||
|
||
}); | ||
}); |
Oops, something went wrong.