Skip to content

Commit

Permalink
adding bucket web Integration (segmentio#1755)
Browse files Browse the repository at this point in the history
* adding bucket web Integration

* updating yarn.lock
  • Loading branch information
joe-ayoub-segment authored Dec 4, 2023
1 parent 6ae4522 commit 84f33ca
Show file tree
Hide file tree
Showing 18 changed files with 975 additions and 1 deletion.
25 changes: 25 additions & 0 deletions packages/browser-destinations/destinations/bucket/package.json
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"
}
}
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 }] }
])
})
})
})

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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'] }])
})
})
})

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 84f33ca

Please sign in to comment.