forked from segmentio/action-destinations
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding bucket web Integration (segmentio#1755)
* adding bucket web Integration * updating yarn.lock
- Loading branch information
1 parent
6ae4522
commit 84f33ca
Showing
18 changed files
with
975 additions
and
1 deletion.
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
packages/browser-destinations/destinations/bucket/package.json
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,25 @@ | ||
{ | ||
"name": "@segment/analytics-browser-actions-bucket", | ||
"version": "1.0.0", | ||
"license": "MIT", | ||
"publishConfig": { | ||
"access": "public", | ||
"registry": "https://registry.npmjs.org" | ||
}, | ||
"main": "./dist/cjs", | ||
"module": "./dist/esm", | ||
"scripts": { | ||
"build": "yarn build:esm && yarn build:cjs", | ||
"build:cjs": "tsc --module commonjs --outDir ./dist/cjs", | ||
"build:esm": "tsc --outDir ./dist/esm" | ||
}, | ||
"typings": "./dist/esm", | ||
"dependencies": { | ||
"@bucketco/tracking-sdk": "^2.0.0", | ||
"@segment/actions-core": "^3.90.0", | ||
"@segment/browser-destination-runtime": "^1.20.0" | ||
}, | ||
"peerDependencies": { | ||
"@segment/analytics-next": ">=1.55.0" | ||
} | ||
} |
116 changes: 116 additions & 0 deletions
116
packages/browser-destinations/destinations/bucket/src/__tests__/index.test.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,116 @@ | ||
import { Analytics, Context, User } from '@segment/analytics-next' | ||
import bucketWebDestination, { destination } from '../index' | ||
import { Subscription } from '@segment/browser-destination-runtime/types' | ||
import { JSONArray } from '@segment/actions-core/*' | ||
import { bucketTestHooks, getBucketCallLog } from '../test-utils' | ||
|
||
const subscriptions: Subscription[] = [ | ||
{ | ||
partnerAction: 'trackEvent', | ||
name: 'Track Event', | ||
enabled: true, | ||
subscribe: 'type = "track"', | ||
mapping: { | ||
name: { | ||
'@path': '$.name' | ||
} | ||
} | ||
} | ||
] | ||
|
||
describe('Bucket', () => { | ||
bucketTestHooks() | ||
|
||
it('loads the Bucket SDK', async () => { | ||
const [instance] = await bucketWebDestination({ | ||
trackingKey: 'testTrackingKey', | ||
subscriptions: subscriptions as unknown as JSONArray | ||
}) | ||
|
||
jest.spyOn(destination, 'initialize') | ||
|
||
const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) | ||
|
||
await instance.load(Context.system(), analyticsInstance) | ||
expect(destination.initialize).toHaveBeenCalled() | ||
|
||
const scripts = Array.from(window.document.querySelectorAll('script')) | ||
expect(scripts).toMatchInlineSnapshot(` | ||
Array [ | ||
<script | ||
src="https://cdn.jsdelivr.net/npm/@bucketco/tracking-sdk@2" | ||
status="loaded" | ||
type="text/javascript" | ||
/>, | ||
<script> | ||
// the emptiness | ||
</script>, | ||
] | ||
`) | ||
|
||
expect(window.bucket).toMatchObject({ | ||
init: expect.any(Function), | ||
user: expect.any(Function), | ||
company: expect.any(Function), | ||
track: expect.any(Function), | ||
reset: expect.any(Function) | ||
}) | ||
}) | ||
|
||
it('resets the Bucket SDK', async () => { | ||
const [instance] = await bucketWebDestination({ | ||
trackingKey: 'testTrackingKey', | ||
subscriptions: subscriptions as unknown as JSONArray | ||
}) | ||
|
||
const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) | ||
|
||
await instance.load(Context.system(), analyticsInstance) | ||
|
||
analyticsInstance.reset() | ||
|
||
expect(getBucketCallLog()).toStrictEqual([ | ||
{ method: 'init', args: ['testTrackingKey'] }, | ||
{ method: 'reset', args: [] } | ||
]) | ||
}) | ||
|
||
describe('when not logged in', () => { | ||
it('initializes Bucket SDK', async () => { | ||
const [instance] = await bucketWebDestination({ | ||
trackingKey: 'testTrackingKey', | ||
subscriptions: subscriptions as unknown as JSONArray | ||
}) | ||
|
||
const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) | ||
|
||
await instance.load(Context.system(), analyticsInstance) | ||
|
||
expect(getBucketCallLog()).toStrictEqual([{ method: 'init', args: ['testTrackingKey'] }]) | ||
}) | ||
}) | ||
|
||
describe('when logged in', () => { | ||
it('initializes Bucket SDK and registers user', async () => { | ||
const [instance] = await bucketWebDestination({ | ||
trackingKey: 'testTrackingKey', | ||
subscriptions: subscriptions as unknown as JSONArray | ||
}) | ||
|
||
const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) | ||
jest.spyOn(analyticsInstance, 'user').mockImplementation( | ||
() => | ||
({ | ||
id: () => 'test-user-id-1' | ||
} as User) | ||
) | ||
|
||
await instance.load(Context.system(), analyticsInstance) | ||
|
||
expect(getBucketCallLog()).toStrictEqual([ | ||
{ method: 'init', args: ['testTrackingKey'] }, | ||
{ method: 'user', args: ['test-user-id-1', {}, { active: false }] } | ||
]) | ||
}) | ||
}) | ||
}) |
8 changes: 8 additions & 0 deletions
8
packages/browser-destinations/destinations/bucket/src/generated-types.ts
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
186 changes: 186 additions & 0 deletions
186
packages/browser-destinations/destinations/bucket/src/group/__tests__/index.test.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,186 @@ | ||
import { Analytics, Context, User } from '@segment/analytics-next' | ||
import bucketWebDestination, { destination } from '../../index' | ||
import { Subscription } from '@segment/browser-destination-runtime/types' | ||
import { JSONArray } from '@segment/actions-core/*' | ||
import { bucketTestHooks, getBucketCallLog } from '../../test-utils' | ||
|
||
const subscriptions: Subscription[] = [ | ||
{ | ||
partnerAction: 'group', | ||
name: 'Identify Company', | ||
enabled: true, | ||
subscribe: 'type = "group"', | ||
mapping: { | ||
groupId: { | ||
'@path': '$.groupId' | ||
}, | ||
userId: { | ||
'@path': '$.userId' | ||
}, | ||
traits: { | ||
'@path': '$.traits' | ||
} | ||
} | ||
} | ||
] | ||
|
||
describe('Bucket.company', () => { | ||
bucketTestHooks() | ||
|
||
describe('when logged in', () => { | ||
describe('from analytics.js previous session', () => { | ||
it('maps parameters correctly to Bucket', async () => { | ||
const [bucketPlugin] = await bucketWebDestination({ | ||
trackingKey: 'testTrackingKey', | ||
subscriptions: subscriptions as unknown as JSONArray | ||
}) | ||
|
||
const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) | ||
jest.spyOn(analyticsInstance, 'user').mockImplementation( | ||
() => | ||
({ | ||
id: () => 'user-id-1' | ||
} as User) | ||
) | ||
await bucketPlugin.load(Context.system(), analyticsInstance) | ||
|
||
jest.spyOn(destination.actions.group, 'perform') | ||
|
||
await bucketPlugin.group?.( | ||
new Context({ | ||
type: 'group', | ||
userId: 'user-id-1', | ||
groupId: 'group-id-1', | ||
traits: { | ||
name: 'ACME INC' | ||
} | ||
}) | ||
) | ||
|
||
expect(destination.actions.group.perform).toHaveBeenCalledWith( | ||
expect.anything(), | ||
expect.objectContaining({ | ||
payload: { | ||
userId: 'user-id-1', | ||
groupId: 'group-id-1', | ||
traits: { | ||
name: 'ACME INC' | ||
} | ||
} | ||
}) | ||
) | ||
|
||
expect(getBucketCallLog()).toStrictEqual([ | ||
{ method: 'init', args: ['testTrackingKey'] }, | ||
{ | ||
method: 'user', | ||
args: ['user-id-1', {}, { active: false }] | ||
}, | ||
{ | ||
method: 'company', | ||
args: [ | ||
'group-id-1', | ||
{ | ||
name: 'ACME INC' | ||
}, | ||
'user-id-1' | ||
] | ||
} | ||
]) | ||
}) | ||
}) | ||
|
||
describe('from am identify call', () => { | ||
it('maps parameters correctly to Bucket', async () => { | ||
const [bucketPlugin] = await bucketWebDestination({ | ||
trackingKey: 'testTrackingKey', | ||
subscriptions: subscriptions as unknown as JSONArray | ||
}) | ||
|
||
await bucketPlugin.load(Context.system(), new Analytics({ writeKey: 'test-writekey' })) | ||
|
||
jest.spyOn(destination.actions.group, 'perform') | ||
|
||
// Bucket rejects group calls without previous identify calls | ||
await window.bucket.user('user-id-1') | ||
|
||
await bucketPlugin.group?.( | ||
new Context({ | ||
type: 'group', | ||
userId: 'user-id-1', | ||
groupId: 'group-id-1', | ||
traits: { | ||
name: 'ACME INC' | ||
} | ||
}) | ||
) | ||
|
||
expect(destination.actions.group.perform).toHaveBeenCalledWith( | ||
expect.anything(), | ||
expect.objectContaining({ | ||
payload: { | ||
userId: 'user-id-1', | ||
groupId: 'group-id-1', | ||
traits: { | ||
name: 'ACME INC' | ||
} | ||
} | ||
}) | ||
) | ||
|
||
expect(getBucketCallLog()).toStrictEqual([ | ||
{ method: 'init', args: ['testTrackingKey'] }, | ||
{ | ||
method: 'user', | ||
args: ['user-id-1'] | ||
}, | ||
{ | ||
method: 'company', | ||
args: [ | ||
'group-id-1', | ||
{ | ||
name: 'ACME INC' | ||
}, | ||
'user-id-1' | ||
] | ||
} | ||
]) | ||
}) | ||
}) | ||
}) | ||
|
||
describe('when not logged in', () => { | ||
it('should not call Bucket.group', async () => { | ||
const [bucketPlugin] = await bucketWebDestination({ | ||
trackingKey: 'testTrackingKey', | ||
subscriptions: subscriptions as unknown as JSONArray | ||
}) | ||
|
||
const analyticsInstance = new Analytics({ writeKey: 'test-writekey' }) | ||
await bucketPlugin.load(Context.system(), analyticsInstance) | ||
|
||
jest.spyOn(destination.actions.group, 'perform') | ||
|
||
// Manually mimicking a group call without a userId. | ||
// The analytics client will probably never do this if | ||
// userId doesn't exist, since the subscription marks it as required | ||
await bucketPlugin.group?.( | ||
new Context({ | ||
type: 'group', | ||
anonymousId: 'anonymous-id-1', | ||
groupId: 'group-id-1', | ||
traits: { | ||
name: 'ACME INC' | ||
} | ||
}) | ||
) | ||
|
||
// TODO: Ideally we should be able to assert that the destination action was never | ||
// called, but couldn't figure out how to create an anlytics instance with the plugin | ||
// and then trigger the full flow trhough analytics.group() with only an anonymous ID | ||
// expect(destination.actions.group.perform).not.toHaveBeenCalled() | ||
|
||
expect(getBucketCallLog()).toStrictEqual([{ method: 'init', args: ['testTrackingKey'] }]) | ||
}) | ||
}) | ||
}) |
18 changes: 18 additions & 0 deletions
18
packages/browser-destinations/destinations/bucket/src/group/generated-types.ts
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.