@segment/analytics-browser-actions-commandbar 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +20 -0
- package/src/__tests__/index.test.ts +46 -0
- package/src/generated-types.ts +12 -0
- package/src/identifyUser/__tests__/index.test.ts +153 -0
- package/src/identifyUser/generated-types.ts +24 -0
- package/src/identifyUser/index.ts +66 -0
- package/src/index.ts +75 -0
- package/src/init-script.ts +86 -0
- package/src/trackEvent/__tests__/index.test.ts +63 -0
- package/src/trackEvent/generated-types.ts +14 -0
- package/src/trackEvent/index.ts +40 -0
- package/src/types.ts +24 -0
- package/tsconfig.json +9 -0
package/package.json
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
{
|
2
|
+
"name": "@segment/analytics-browser-actions-commandbar",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"license": "MIT",
|
5
|
+
"main": "./dist/cjs",
|
6
|
+
"module": "./dist/esm",
|
7
|
+
"scripts": {
|
8
|
+
"build": "yarn build:esm && yarn build:cjs",
|
9
|
+
"build:cjs": "tsc --module commonjs --outDir ./dist/cjs",
|
10
|
+
"build:esm": "tsc --outDir ./dist/esm"
|
11
|
+
},
|
12
|
+
"typings": "./dist/esm",
|
13
|
+
"dependencies": {
|
14
|
+
"@segment/actions-core": "^3.71.0",
|
15
|
+
"@segment/browser-destination-runtime": "^1.0.0"
|
16
|
+
},
|
17
|
+
"peerDependencies": {
|
18
|
+
"@segment/analytics-next": "*"
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import { Subscription } from '@segment/browser-destination-runtime/types'
|
2
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
3
|
+
import commandBarDestination, { destination } from '../index'
|
4
|
+
|
5
|
+
const subscriptions: Subscription[] = [
|
6
|
+
{
|
7
|
+
partnerAction: 'trackEvent',
|
8
|
+
name: 'Show',
|
9
|
+
enabled: true,
|
10
|
+
subscribe: 'type = "track"',
|
11
|
+
mapping: {
|
12
|
+
event_name: {
|
13
|
+
'@path': '$.event'
|
14
|
+
},
|
15
|
+
event_metadata: {
|
16
|
+
'@path': '$.properties'
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
]
|
21
|
+
|
22
|
+
describe('CommandBar initialization', () => {
|
23
|
+
test('can load CommandBar with just orgId', async () => {
|
24
|
+
const [event] = await commandBarDestination({
|
25
|
+
orgId: '05f077f2',
|
26
|
+
subscriptions
|
27
|
+
})
|
28
|
+
jest.spyOn(destination, 'initialize')
|
29
|
+
|
30
|
+
await event.load(Context.system(), {} as Analytics)
|
31
|
+
expect(destination.initialize).toHaveBeenCalled()
|
32
|
+
|
33
|
+
const scripts = window.document.querySelectorAll('script')
|
34
|
+
expect(scripts).toMatchInlineSnapshot(`
|
35
|
+
NodeList [
|
36
|
+
<script>
|
37
|
+
// the emptiness
|
38
|
+
</script>,
|
39
|
+
<script
|
40
|
+
src="https://api.commandbar.com/latest/05f077f2?version=2"
|
41
|
+
type="text/javascript"
|
42
|
+
/>,
|
43
|
+
]
|
44
|
+
`)
|
45
|
+
})
|
46
|
+
})
|
@@ -0,0 +1,12 @@
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
2
|
+
|
3
|
+
export interface Settings {
|
4
|
+
/**
|
5
|
+
* The ID of your CommandBar organization.
|
6
|
+
*/
|
7
|
+
orgId: string
|
8
|
+
/**
|
9
|
+
* If enabled, CommandBar will be deployed to your site automatically and you can remove the snippet from your source code.
|
10
|
+
*/
|
11
|
+
deploy?: boolean
|
12
|
+
}
|
@@ -0,0 +1,153 @@
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
2
|
+
import { Subscription } from '@segment/browser-destination-runtime'
|
3
|
+
import commandBarDestination, { destination } from '../../index'
|
4
|
+
|
5
|
+
const subscriptions: Subscription[] = [
|
6
|
+
{
|
7
|
+
partnerAction: 'identifyUser',
|
8
|
+
name: 'Identify User',
|
9
|
+
enabled: true,
|
10
|
+
subscribe: 'type = "identify"',
|
11
|
+
mapping: {
|
12
|
+
userId: {
|
13
|
+
'@path': '$.userId'
|
14
|
+
},
|
15
|
+
traits: {
|
16
|
+
'@path': '$.traits'
|
17
|
+
},
|
18
|
+
hmac: {
|
19
|
+
'@path': '$.context.CommandBar.hmac'
|
20
|
+
},
|
21
|
+
formFactor: {
|
22
|
+
'@path': '$.context.CommandBar.formFactor'
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
]
|
27
|
+
|
28
|
+
describe('CommandBar.boot when with deploy enabled', () => {
|
29
|
+
const settings = {
|
30
|
+
orgId: 'xxxxxxxx'
|
31
|
+
}
|
32
|
+
let mockCommandBarBoot: jest.Mock<any, any>
|
33
|
+
let mockCommandBarMetadataBatch: jest.Mock<any, any>
|
34
|
+
|
35
|
+
let identifyUser: any
|
36
|
+
|
37
|
+
beforeEach(async () => {
|
38
|
+
const [identifyUserPlugin] = await commandBarDestination({
|
39
|
+
...settings,
|
40
|
+
subscriptions
|
41
|
+
})
|
42
|
+
|
43
|
+
identifyUser = identifyUserPlugin
|
44
|
+
|
45
|
+
mockCommandBarBoot = jest.fn()
|
46
|
+
mockCommandBarMetadataBatch = jest.fn()
|
47
|
+
jest.spyOn(destination, 'initialize').mockImplementation(() => {
|
48
|
+
const mockedWithBoot = {
|
49
|
+
boot: mockCommandBarBoot,
|
50
|
+
addMetadataBatch: mockCommandBarMetadataBatch,
|
51
|
+
trackEvent: jest.fn()
|
52
|
+
}
|
53
|
+
return Promise.resolve(mockedWithBoot)
|
54
|
+
})
|
55
|
+
await identifyUser.load(Context.system(), {} as Analytics)
|
56
|
+
})
|
57
|
+
|
58
|
+
it('Can add metadata via identify', async () => {
|
59
|
+
await identifyUser.identify?.(
|
60
|
+
new Context({
|
61
|
+
type: 'identify',
|
62
|
+
userId: 'test-user',
|
63
|
+
traits: {
|
64
|
+
foo: 'bar'
|
65
|
+
}
|
66
|
+
})
|
67
|
+
)
|
68
|
+
|
69
|
+
expect(mockCommandBarMetadataBatch).toHaveBeenCalledWith({ foo: 'bar' }, true)
|
70
|
+
expect(mockCommandBarBoot).not.toHaveBeenCalled()
|
71
|
+
})
|
72
|
+
})
|
73
|
+
|
74
|
+
describe('CommandBar.addMetadataBatch with deploy disabled', () => {
|
75
|
+
const settings = {
|
76
|
+
orgId: 'xxxxxxxx',
|
77
|
+
deploy: true
|
78
|
+
}
|
79
|
+
let mockCommandBarBoot: jest.Mock<any, any>
|
80
|
+
let mockCommandBarMetadataBatch: jest.Mock<any, any>
|
81
|
+
|
82
|
+
let identifyUser: any
|
83
|
+
|
84
|
+
beforeEach(async () => {
|
85
|
+
const [identifyUserPlugin] = await commandBarDestination({
|
86
|
+
...settings,
|
87
|
+
subscriptions
|
88
|
+
})
|
89
|
+
|
90
|
+
identifyUser = identifyUserPlugin
|
91
|
+
|
92
|
+
mockCommandBarBoot = jest.fn()
|
93
|
+
mockCommandBarMetadataBatch = jest.fn()
|
94
|
+
jest.spyOn(destination, 'initialize').mockImplementation(() => {
|
95
|
+
const mockedWithBoot = {
|
96
|
+
boot: mockCommandBarBoot,
|
97
|
+
addMetadataBatch: mockCommandBarMetadataBatch,
|
98
|
+
trackEvent: jest.fn()
|
99
|
+
}
|
100
|
+
return Promise.resolve(mockedWithBoot)
|
101
|
+
})
|
102
|
+
await identifyUser.load(Context.system(), {} as Analytics)
|
103
|
+
})
|
104
|
+
|
105
|
+
it('Can boot via identify', async () => {
|
106
|
+
await identifyUser.identify?.(
|
107
|
+
new Context({
|
108
|
+
type: 'identify',
|
109
|
+
userId: 'test-user',
|
110
|
+
traits: {
|
111
|
+
foo: 'bar'
|
112
|
+
}
|
113
|
+
})
|
114
|
+
)
|
115
|
+
|
116
|
+
expect(mockCommandBarBoot).toHaveBeenCalledWith('test-user', { foo: 'bar' }, {})
|
117
|
+
expect(mockCommandBarMetadataBatch).not.toHaveBeenCalled()
|
118
|
+
})
|
119
|
+
|
120
|
+
it('Can pass instanceAttributes to boot', async () => {
|
121
|
+
await identifyUser.identify?.(
|
122
|
+
new Context({
|
123
|
+
type: 'identify',
|
124
|
+
userId: 'test-user',
|
125
|
+
traits: {
|
126
|
+
foo: 'bar'
|
127
|
+
},
|
128
|
+
context: {
|
129
|
+
CommandBar: {
|
130
|
+
hmac: 'x',
|
131
|
+
formFactor: {
|
132
|
+
type: 'inline',
|
133
|
+
rootElement: 'commandbar-inline-root'
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
137
|
+
})
|
138
|
+
)
|
139
|
+
|
140
|
+
expect(mockCommandBarBoot).toHaveBeenCalledWith(
|
141
|
+
'test-user',
|
142
|
+
{ foo: 'bar' },
|
143
|
+
{
|
144
|
+
hmac: 'x',
|
145
|
+
formFactor: {
|
146
|
+
type: 'inline',
|
147
|
+
rootElement: 'commandbar-inline-root'
|
148
|
+
}
|
149
|
+
}
|
150
|
+
)
|
151
|
+
expect(mockCommandBarMetadataBatch).not.toHaveBeenCalled()
|
152
|
+
})
|
153
|
+
})
|
@@ -0,0 +1,24 @@
|
|
1
|
+
// Generated file. DO NOT MODIFY IT BY HAND.
|
2
|
+
|
3
|
+
export interface Payload {
|
4
|
+
/**
|
5
|
+
* The user's id
|
6
|
+
*/
|
7
|
+
userId: string
|
8
|
+
/**
|
9
|
+
* Identify users with an HMAC of their user ID; this enables end user customizable shortcuts and other features. [Learn about identity verification](https://app.commandbar.com/identity-verification).
|
10
|
+
*/
|
11
|
+
hmac?: string
|
12
|
+
/**
|
13
|
+
* Configures the way the bar is displayed. An 'inline' bar is always visible and hosted within an element on your page. A 'modal' bar will display in a modal dialog when open.
|
14
|
+
*/
|
15
|
+
formFactor?: {
|
16
|
+
[k: string]: unknown
|
17
|
+
}
|
18
|
+
/**
|
19
|
+
* The Segment traits to be forwarded to CommandBar
|
20
|
+
*/
|
21
|
+
traits?: {
|
22
|
+
[k: string]: unknown
|
23
|
+
}
|
24
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
|
2
|
+
import type { Settings } from '../generated-types'
|
3
|
+
import { CommandBarClientSDK, FormFactorConfig } from '../types'
|
4
|
+
import type { Payload } from './generated-types'
|
5
|
+
|
6
|
+
const action: BrowserActionDefinition<Settings, CommandBarClientSDK, Payload> = {
|
7
|
+
title: 'Identify User',
|
8
|
+
description:
|
9
|
+
'Set attributes for the user in CommandBar. If "Deploy via Segment" is enabled, then also boot CommandBar for the user, which makes CommandBar available to the user.',
|
10
|
+
platform: 'web',
|
11
|
+
defaultSubscription: 'type = "identify"',
|
12
|
+
fields: {
|
13
|
+
userId: {
|
14
|
+
type: 'string',
|
15
|
+
required: true,
|
16
|
+
description: "The user's id",
|
17
|
+
label: 'User ID',
|
18
|
+
default: {
|
19
|
+
'@path': '$.userId'
|
20
|
+
}
|
21
|
+
},
|
22
|
+
hmac: {
|
23
|
+
description:
|
24
|
+
'Identify users with an HMAC of their user ID; this enables end user customizable shortcuts and other features. [Learn about identity verification](https://app.commandbar.com/identity-verification).',
|
25
|
+
label: 'HMAC',
|
26
|
+
type: 'string',
|
27
|
+
required: false,
|
28
|
+
default: {
|
29
|
+
'@path': '$.context.CommandBar.hmac'
|
30
|
+
}
|
31
|
+
},
|
32
|
+
formFactor: {
|
33
|
+
description:
|
34
|
+
"Configures the way the bar is displayed. An 'inline' bar is always visible and hosted within an element on your page. A 'modal' bar will display in a modal dialog when open.",
|
35
|
+
label: 'Event Metadata',
|
36
|
+
type: 'object',
|
37
|
+
required: false,
|
38
|
+
default: {
|
39
|
+
'@path': '$.context.CommandBar.formFactor'
|
40
|
+
}
|
41
|
+
},
|
42
|
+
traits: {
|
43
|
+
type: 'object',
|
44
|
+
required: false,
|
45
|
+
description: 'The Segment traits to be forwarded to CommandBar',
|
46
|
+
label: 'Traits',
|
47
|
+
default: {
|
48
|
+
'@path': '$.traits'
|
49
|
+
}
|
50
|
+
}
|
51
|
+
},
|
52
|
+
perform: (CommandBar, event) => {
|
53
|
+
const traits = event.payload.traits || {}
|
54
|
+
|
55
|
+
if (event.settings.deploy) {
|
56
|
+
void CommandBar.boot(event.payload.userId, traits, {
|
57
|
+
...(!!event.payload.hmac && { hmac: event.payload.hmac }),
|
58
|
+
...(!!event.payload.formFactor && { formFactor: event.payload.formFactor as FormFactorConfig })
|
59
|
+
})
|
60
|
+
} else {
|
61
|
+
CommandBar.addMetadataBatch(traits, true)
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
export default action
|
package/src/index.ts
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
import type { Settings } from './generated-types'
|
2
|
+
import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types'
|
3
|
+
import { browserDestination } from '@segment/browser-destination-runtime/shim'
|
4
|
+
import { initScript } from './init-script'
|
5
|
+
import { CommandBarClientSDK } from './types'
|
6
|
+
|
7
|
+
import identifyUser from './identifyUser'
|
8
|
+
import { defaultValues } from '@segment/actions-core'
|
9
|
+
|
10
|
+
import trackEvent from './trackEvent'
|
11
|
+
|
12
|
+
declare global {
|
13
|
+
interface Window {
|
14
|
+
CommandBar: CommandBarClientSDK
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
export const destination: BrowserDestinationDefinition<Settings, CommandBarClientSDK> = {
|
19
|
+
name: 'CommandBar',
|
20
|
+
slug: 'actions-commandbar',
|
21
|
+
mode: 'device',
|
22
|
+
|
23
|
+
settings: {
|
24
|
+
orgId: {
|
25
|
+
description: 'The ID of your CommandBar organization.',
|
26
|
+
label: 'Organization ID',
|
27
|
+
type: 'string',
|
28
|
+
required: true
|
29
|
+
},
|
30
|
+
deploy: {
|
31
|
+
description:
|
32
|
+
'If enabled, CommandBar will be deployed to your site automatically and you can remove the snippet from your source code.',
|
33
|
+
label: 'Deploy via Segment',
|
34
|
+
type: 'boolean',
|
35
|
+
required: false
|
36
|
+
}
|
37
|
+
},
|
38
|
+
|
39
|
+
presets: [
|
40
|
+
{
|
41
|
+
name: 'Track Event',
|
42
|
+
subscribe: 'type = "track"',
|
43
|
+
partnerAction: 'trackEvent',
|
44
|
+
mapping: defaultValues(trackEvent.fields)
|
45
|
+
},
|
46
|
+
{
|
47
|
+
name: 'Identify User',
|
48
|
+
subscribe: 'type = "identify"',
|
49
|
+
partnerAction: 'identifyUser',
|
50
|
+
mapping: defaultValues(identifyUser.fields)
|
51
|
+
}
|
52
|
+
],
|
53
|
+
|
54
|
+
initialize: async ({ settings }, deps) => {
|
55
|
+
if (!window.CommandBar) {
|
56
|
+
initScript(settings.orgId)
|
57
|
+
}
|
58
|
+
|
59
|
+
await deps.resolveWhen(() => Object.prototype.hasOwnProperty.call(window, 'CommandBar'), 100)
|
60
|
+
|
61
|
+
// Older CommandBar snippets initialize a proxy that traps all field access including `then`
|
62
|
+
// `then` is called implicitly on the return value of an async function on await
|
63
|
+
// So, we need to remove that behavior for the promise to resolve
|
64
|
+
Object.assign(window.CommandBar, { then: undefined })
|
65
|
+
|
66
|
+
return window.CommandBar
|
67
|
+
},
|
68
|
+
|
69
|
+
actions: {
|
70
|
+
identifyUser,
|
71
|
+
trackEvent
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
export default browserDestination(destination)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
/* eslint-disable */
|
2
|
+
// @ts-nocheck
|
3
|
+
|
4
|
+
export function initScript(orgId) {
|
5
|
+
var o = orgId,
|
6
|
+
n = ['Object.assign', 'Symbol', 'Symbol.for'].join('%2C'),
|
7
|
+
a = window
|
8
|
+
function t(o, n) {
|
9
|
+
void 0 === n && (n = !1),
|
10
|
+
'complete' !== document.readyState &&
|
11
|
+
window.addEventListener('load', t.bind(null, o, n), { capture: !1, once: !0 })
|
12
|
+
var a = document.createElement('script')
|
13
|
+
;(a.type = 'text/javascript'), (a.async = n), (a.src = o), document.head.appendChild(a)
|
14
|
+
}
|
15
|
+
function r() {
|
16
|
+
var n
|
17
|
+
if (void 0 === a.CommandBar) {
|
18
|
+
delete a.__CommandBarBootstrap__
|
19
|
+
var r = Symbol.for('CommandBar::configuration'),
|
20
|
+
e = Symbol.for('CommandBar::orgConfig'),
|
21
|
+
c = Symbol.for('CommandBar::disposed'),
|
22
|
+
i = Symbol.for('CommandBar::isProxy'),
|
23
|
+
m = Symbol.for('CommandBar::queue'),
|
24
|
+
l = Symbol.for('CommandBar::unwrap'),
|
25
|
+
d = [],
|
26
|
+
s = localStorage.getItem('commandbar.lc'),
|
27
|
+
u = s && s.includes('local') ? 'http://localhost:8000' : 'https://api.commandbar.com',
|
28
|
+
f = Object.assign(
|
29
|
+
(((n = {})[r] = { uuid: o }),
|
30
|
+
(n[e] = {}),
|
31
|
+
(n[c] = !1),
|
32
|
+
(n[i] = !0),
|
33
|
+
(n[m] = new Array()),
|
34
|
+
(n[l] = function () {
|
35
|
+
return f
|
36
|
+
}),
|
37
|
+
n),
|
38
|
+
a.CommandBar
|
39
|
+
),
|
40
|
+
p = ['addCommand', 'boot'],
|
41
|
+
y = f
|
42
|
+
Object.assign(f, {
|
43
|
+
shareCallbacks: function () {
|
44
|
+
return {}
|
45
|
+
},
|
46
|
+
shareContext: function () {
|
47
|
+
return {}
|
48
|
+
}
|
49
|
+
}),
|
50
|
+
(a.CommandBar = new Proxy(f, {
|
51
|
+
get: function (o, n) {
|
52
|
+
if (
|
53
|
+
n === 'then' ||
|
54
|
+
n === 'toJSON' ||
|
55
|
+
n === '$$typeof' ||
|
56
|
+
n === '@@__IMMUTABLE_RECORD__@@' ||
|
57
|
+
n === 'hasAttribute' ||
|
58
|
+
n === 'asymmetricMatch'
|
59
|
+
) {
|
60
|
+
return Reflect.get(...arguments)
|
61
|
+
}
|
62
|
+
return n in y
|
63
|
+
? f[n]
|
64
|
+
: p.includes(n)
|
65
|
+
? function () {
|
66
|
+
var o = Array.prototype.slice.call(arguments)
|
67
|
+
return new Promise(function (a, t) {
|
68
|
+
o.unshift(n, a, t), f[m].push(o)
|
69
|
+
})
|
70
|
+
}
|
71
|
+
: function () {
|
72
|
+
var o = Array.prototype.slice.call(arguments)
|
73
|
+
o.unshift(n), f[m].push(o)
|
74
|
+
}
|
75
|
+
}
|
76
|
+
})),
|
77
|
+
null !== s && d.push('lc='.concat(s)),
|
78
|
+
d.push('version=2'),
|
79
|
+
t(''.concat(u, '/latest/').concat(o, '?').concat(d.join('&')), !0)
|
80
|
+
}
|
81
|
+
}
|
82
|
+
void 0 === Object.assign || 'undefined' == typeof Symbol || void 0 === Symbol.for
|
83
|
+
? ((a.__CommandBarBootstrap__ = r),
|
84
|
+
t('https://polyfill.io/v3/polyfill.min.js?version=3.101.0&callback=__CommandBarBootstrap__&features=' + n))
|
85
|
+
: r()
|
86
|
+
}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import { Analytics, Context } from '@segment/analytics-next'
|
2
|
+
import { Subscription } from '@segment/browser-destination-runtime'
|
3
|
+
import commandBarDestination, { destination } from '../../index'
|
4
|
+
|
5
|
+
const subscriptions: Subscription[] = [
|
6
|
+
{
|
7
|
+
partnerAction: 'trackEvent',
|
8
|
+
name: 'Track Event',
|
9
|
+
enabled: true,
|
10
|
+
subscribe: 'type = "track"',
|
11
|
+
mapping: {
|
12
|
+
event_name: {
|
13
|
+
'@path': '$.event'
|
14
|
+
},
|
15
|
+
event_metadata: {
|
16
|
+
'@path': '$.properties'
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
]
|
21
|
+
|
22
|
+
describe('CommandBar.trackEvent', () => {
|
23
|
+
const settings = {
|
24
|
+
orgId: 'xxxxxxxx'
|
25
|
+
}
|
26
|
+
let mockCommandBarTrackEvent: jest.Mock<any, any>
|
27
|
+
|
28
|
+
let plugin: any
|
29
|
+
|
30
|
+
beforeEach(async () => {
|
31
|
+
const [commandBarPlugin] = await commandBarDestination({
|
32
|
+
...settings,
|
33
|
+
subscriptions
|
34
|
+
})
|
35
|
+
|
36
|
+
plugin = commandBarPlugin
|
37
|
+
|
38
|
+
mockCommandBarTrackEvent = jest.fn()
|
39
|
+
jest.spyOn(destination, 'initialize').mockImplementation(() => {
|
40
|
+
const mockedWithTrack = {
|
41
|
+
boot: jest.fn(),
|
42
|
+
addMetadataBatch: jest.fn(),
|
43
|
+
trackEvent: mockCommandBarTrackEvent
|
44
|
+
}
|
45
|
+
return Promise.resolve(mockedWithTrack)
|
46
|
+
})
|
47
|
+
await plugin.load(Context.system(), {} as Analytics)
|
48
|
+
})
|
49
|
+
|
50
|
+
it('Sends events to CommandBar', async () => {
|
51
|
+
await plugin.track?.(
|
52
|
+
new Context({
|
53
|
+
type: 'track',
|
54
|
+
event: 'example-event',
|
55
|
+
properties: {
|
56
|
+
foo: 'bar'
|
57
|
+
}
|
58
|
+
})
|
59
|
+
)
|
60
|
+
|
61
|
+
expect(mockCommandBarTrackEvent).toHaveBeenCalledWith('example-event', { foo: 'bar' })
|
62
|
+
})
|
63
|
+
})
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
|
2
|
+
import type { Settings } from '../generated-types'
|
3
|
+
import { CommandBarClientSDK } from '../types'
|
4
|
+
import type { Payload } from './generated-types'
|
5
|
+
|
6
|
+
const action: BrowserActionDefinition<Settings, CommandBarClientSDK, Payload> = {
|
7
|
+
title: 'Track Event',
|
8
|
+
description: "Submit an event's properties as CommandBar metaData.",
|
9
|
+
platform: 'web',
|
10
|
+
defaultSubscription: 'type = "track"',
|
11
|
+
|
12
|
+
fields: {
|
13
|
+
event_name: {
|
14
|
+
description: 'The name of the event.',
|
15
|
+
label: 'Event Name',
|
16
|
+
type: 'string',
|
17
|
+
required: true,
|
18
|
+
default: {
|
19
|
+
'@path': '$.event'
|
20
|
+
}
|
21
|
+
},
|
22
|
+
event_metadata: {
|
23
|
+
description: 'Optional metadata describing the event.',
|
24
|
+
label: 'Event Metadata',
|
25
|
+
type: 'object',
|
26
|
+
required: false,
|
27
|
+
default: {
|
28
|
+
'@path': '$.properties'
|
29
|
+
}
|
30
|
+
}
|
31
|
+
},
|
32
|
+
|
33
|
+
perform: (CommandBar, event) => {
|
34
|
+
if (event.payload.event_name) {
|
35
|
+
CommandBar.trackEvent(event.payload.event_name, event.payload.event_metadata || {})
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
export default action
|
package/src/types.ts
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
export type ModalFormFactor = { type: 'modal' }
|
2
|
+
export type InlineFormFactor = { type: 'inline'; rootElement: string | HTMLElement }
|
3
|
+
|
4
|
+
export type FormFactorConfig = ModalFormFactor | InlineFormFactor
|
5
|
+
|
6
|
+
export type UserAttributes = Record<string, unknown>
|
7
|
+
|
8
|
+
export type InstanceAttributes = {
|
9
|
+
canOpenEditor: boolean
|
10
|
+
hmac?: string
|
11
|
+
formFactor: FormFactorConfig
|
12
|
+
}
|
13
|
+
|
14
|
+
export type ContextLoader = (chosenValues?: undefined | Record<string, unknown[]>) => unknown
|
15
|
+
|
16
|
+
export type Metadata = Record<string, unknown>
|
17
|
+
|
18
|
+
export type CommandBarClientSDK = {
|
19
|
+
boot(id: string, userAttributes?: UserAttributes, instanceAttributes?: Partial<InstanceAttributes>): Promise<void>
|
20
|
+
|
21
|
+
addMetadataBatch(data: Metadata, addToUserProperties?: boolean): void
|
22
|
+
|
23
|
+
trackEvent(key: string, properties: Metadata): void
|
24
|
+
}
|