@segment/analytics-browser-mixpanel-web-actions 1.0.1-staging-294d81392.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.
Files changed (135) hide show
  1. package/README.md +31 -0
  2. package/dist/cjs/alias/generated-types.d.ts +4 -0
  3. package/dist/cjs/alias/generated-types.js +3 -0
  4. package/dist/cjs/alias/generated-types.js.map +1 -0
  5. package/dist/cjs/alias/index.d.ts +6 -0
  6. package/dist/cjs/alias/index.js +32 -0
  7. package/dist/cjs/alias/index.js.map +1 -0
  8. package/dist/cjs/constants.d.ts +14 -0
  9. package/dist/cjs/constants.js +18 -0
  10. package/dist/cjs/constants.js.map +1 -0
  11. package/dist/cjs/fields.d.ts +11 -0
  12. package/dist/cjs/fields.js +162 -0
  13. package/dist/cjs/fields.js.map +1 -0
  14. package/dist/cjs/functions.d.ts +7 -0
  15. package/dist/cjs/functions.js +39 -0
  16. package/dist/cjs/functions.js.map +1 -0
  17. package/dist/cjs/generated-types.d.ts +30 -0
  18. package/dist/cjs/generated-types.js +3 -0
  19. package/dist/cjs/generated-types.js.map +1 -0
  20. package/dist/cjs/group/generated-types.d.ts +16 -0
  21. package/dist/cjs/group/generated-types.js +3 -0
  22. package/dist/cjs/group/generated-types.js.map +1 -0
  23. package/dist/cjs/group/index.d.ts +6 -0
  24. package/dist/cjs/group/index.js +21 -0
  25. package/dist/cjs/group/index.js.map +1 -0
  26. package/dist/cjs/identify/generated-types.d.ts +19 -0
  27. package/dist/cjs/identify/generated-types.js +3 -0
  28. package/dist/cjs/identify/generated-types.js.map +1 -0
  29. package/dist/cjs/identify/index.d.ts +6 -0
  30. package/dist/cjs/identify/index.js +21 -0
  31. package/dist/cjs/identify/index.js.map +1 -0
  32. package/dist/cjs/index.d.ts +11 -0
  33. package/dist/cjs/index.js +76 -0
  34. package/dist/cjs/index.js.map +1 -0
  35. package/dist/cjs/init-script.d.ts +1 -0
  36. package/dist/cjs/init-script.js +65 -0
  37. package/dist/cjs/init-script.js.map +1 -0
  38. package/dist/cjs/setting-fields.d.ts +2 -0
  39. package/dist/cjs/setting-fields.js +273 -0
  40. package/dist/cjs/setting-fields.js.map +1 -0
  41. package/dist/cjs/track/generated-types.d.ts +37 -0
  42. package/dist/cjs/track/generated-types.js +3 -0
  43. package/dist/cjs/track/generated-types.js.map +1 -0
  44. package/dist/cjs/track/index.d.ts +6 -0
  45. package/dist/cjs/track/index.js +93 -0
  46. package/dist/cjs/track/index.js.map +1 -0
  47. package/dist/cjs/trackPageView/generated-types.d.ts +37 -0
  48. package/dist/cjs/trackPageView/generated-types.js +3 -0
  49. package/dist/cjs/trackPageView/generated-types.js.map +1 -0
  50. package/dist/cjs/trackPageView/index.d.ts +6 -0
  51. package/dist/cjs/trackPageView/index.js +101 -0
  52. package/dist/cjs/trackPageView/index.js.map +1 -0
  53. package/dist/cjs/types.d.ts +68 -0
  54. package/dist/cjs/types.js +3 -0
  55. package/dist/cjs/types.js.map +1 -0
  56. package/dist/esm/alias/generated-types.d.ts +4 -0
  57. package/dist/esm/alias/generated-types.js +2 -0
  58. package/dist/esm/alias/generated-types.js.map +1 -0
  59. package/dist/esm/alias/index.d.ts +6 -0
  60. package/dist/esm/alias/index.js +30 -0
  61. package/dist/esm/alias/index.js.map +1 -0
  62. package/dist/esm/constants.d.ts +14 -0
  63. package/dist/esm/constants.js +15 -0
  64. package/dist/esm/constants.js.map +1 -0
  65. package/dist/esm/fields.d.ts +11 -0
  66. package/dist/esm/fields.js +159 -0
  67. package/dist/esm/fields.js.map +1 -0
  68. package/dist/esm/functions.d.ts +7 -0
  69. package/dist/esm/functions.js +35 -0
  70. package/dist/esm/functions.js.map +1 -0
  71. package/dist/esm/generated-types.d.ts +30 -0
  72. package/dist/esm/generated-types.js +2 -0
  73. package/dist/esm/generated-types.js.map +1 -0
  74. package/dist/esm/group/generated-types.d.ts +16 -0
  75. package/dist/esm/group/generated-types.js +2 -0
  76. package/dist/esm/group/generated-types.js.map +1 -0
  77. package/dist/esm/group/index.d.ts +6 -0
  78. package/dist/esm/group/index.js +19 -0
  79. package/dist/esm/group/index.js.map +1 -0
  80. package/dist/esm/identify/generated-types.d.ts +19 -0
  81. package/dist/esm/identify/generated-types.js +2 -0
  82. package/dist/esm/identify/generated-types.js.map +1 -0
  83. package/dist/esm/identify/index.d.ts +6 -0
  84. package/dist/esm/identify/index.js +19 -0
  85. package/dist/esm/identify/index.js.map +1 -0
  86. package/dist/esm/index.d.ts +11 -0
  87. package/dist/esm/index.js +72 -0
  88. package/dist/esm/index.js.map +1 -0
  89. package/dist/esm/init-script.d.ts +1 -0
  90. package/dist/esm/init-script.js +62 -0
  91. package/dist/esm/init-script.js.map +1 -0
  92. package/dist/esm/setting-fields.d.ts +2 -0
  93. package/dist/esm/setting-fields.js +270 -0
  94. package/dist/esm/setting-fields.js.map +1 -0
  95. package/dist/esm/track/generated-types.d.ts +37 -0
  96. package/dist/esm/track/generated-types.js +2 -0
  97. package/dist/esm/track/generated-types.js.map +1 -0
  98. package/dist/esm/track/index.d.ts +6 -0
  99. package/dist/esm/track/index.js +91 -0
  100. package/dist/esm/track/index.js.map +1 -0
  101. package/dist/esm/trackPageView/generated-types.d.ts +37 -0
  102. package/dist/esm/trackPageView/generated-types.js +2 -0
  103. package/dist/esm/trackPageView/generated-types.js.map +1 -0
  104. package/dist/esm/trackPageView/index.d.ts +6 -0
  105. package/dist/esm/trackPageView/index.js +99 -0
  106. package/dist/esm/trackPageView/index.js.map +1 -0
  107. package/dist/esm/types.d.ts +68 -0
  108. package/dist/esm/types.js +2 -0
  109. package/dist/esm/types.js.map +1 -0
  110. package/dist/tsconfig.tsbuildinfo +1 -0
  111. package/package.json +25 -0
  112. package/src/alias/__tests__/index.test.ts +95 -0
  113. package/src/alias/generated-types.ts +12 -0
  114. package/src/alias/index.ts +35 -0
  115. package/src/constants.ts +16 -0
  116. package/src/fields.ts +173 -0
  117. package/src/functions.ts +57 -0
  118. package/src/generated-types.ts +116 -0
  119. package/src/group/__tests__/index.test.ts +126 -0
  120. package/src/group/generated-types.ts +42 -0
  121. package/src/group/index.ts +29 -0
  122. package/src/identify/__tests__/index.test.ts +135 -0
  123. package/src/identify/generated-types.ts +54 -0
  124. package/src/identify/index.ts +29 -0
  125. package/src/index.ts +99 -0
  126. package/src/init-script.ts +63 -0
  127. package/src/setting-fields.ts +273 -0
  128. package/src/track/__tests__/index.test.ts +196 -0
  129. package/src/track/generated-types.ts +102 -0
  130. package/src/track/index.ts +109 -0
  131. package/src/trackPageView/__tests__/index.test.ts +250 -0
  132. package/src/trackPageView/generated-types.ts +102 -0
  133. package/src/trackPageView/index.ts +116 -0
  134. package/src/types.ts +78 -0
  135. package/tsconfig.json +9 -0
@@ -0,0 +1,196 @@
1
+ import { Analytics, Context } from '@segment/analytics-next'
2
+ import { Subscription } from '@segment/browser-destination-runtime'
3
+ import MixpanelDestination, { destination } from '../../index'
4
+ import { Mixpanel } from '../../types'
5
+ import { AUTOCAPTURE_OPTIONS, PERSISTENCE_OPTIONS } from '../../constants'
6
+ import { Group } from '../../types'
7
+
8
+ describe('Mixpanel.track', () => {
9
+ const settings = {
10
+ projectToken: 'projectToken1',
11
+ name: 'name1',
12
+ default: 'https://api-js.mixpanel.com',
13
+ autocapture: AUTOCAPTURE_OPTIONS.ENABLED,
14
+ cross_subdomain_cookie: true,
15
+ persistence: PERSISTENCE_OPTIONS.COOKIE,
16
+ track_marketing: true,
17
+ cookie_expiration: 365,
18
+ disable_persistence: false,
19
+ ip: true,
20
+ record_block_class: 'mp-block',
21
+ record_block_selector: 'img, video, audio',
22
+ record_canvas: false,
23
+ record_heatmap_data: false,
24
+ record_idle_timeout_ms: 180_000,
25
+ record_mask_text_class: 'mp-mask',
26
+ record_mask_text_selector: '*',
27
+ record_max_ms: 86_400_000,
28
+ record_min_ms: 8_000,
29
+ record_sessions_percent: 0
30
+ }
31
+
32
+ let mockMPP: Mixpanel
33
+ let mockGroup: Group
34
+ let event: any
35
+
36
+ beforeEach(async () => {
37
+ jest.restoreAllMocks()
38
+ jest.spyOn(destination, 'initialize').mockImplementation(() => {
39
+ mockGroup = {
40
+ set: jest.fn(),
41
+ set_once: jest.fn(),
42
+ union: jest.fn()
43
+ }
44
+
45
+ mockMPP = {
46
+ init: jest.fn(),
47
+ track_pageview: jest.fn(),
48
+ track: jest.fn(),
49
+ identify: jest.fn(),
50
+ alias: jest.fn(),
51
+ get_group: jest.fn().mockReturnValue(mockGroup),
52
+ set_group: jest.fn(),
53
+ people: {
54
+ set: jest.fn(),
55
+ set_once: jest.fn(),
56
+ increment: jest.fn()
57
+ }
58
+ }
59
+ return Promise.resolve(mockMPP)
60
+ })
61
+ })
62
+
63
+ test('track() handled correctly', async () => {
64
+ const subscriptions: Subscription[] = [
65
+ {
66
+ partnerAction: 'track',
67
+ name: 'Track',
68
+ enabled: true,
69
+ subscribe: 'type = "track"',
70
+ mapping: {
71
+ event_name: { '@path': '$.event' },
72
+ properties: { '@path': '$.properties' },
73
+ unique_id: { '@path': '$.userId' },
74
+ user_profile_properties_to_set: {
75
+ name: { '@path': '$.context.traits.user.name' },
76
+ first_name: { '@path': '$.context.traits.user.first_name' },
77
+ last_name: { '@path': '$.context.traits.user.last_name' },
78
+ email: { '@path': '$.context.traits.user.email' },
79
+ phone: { '@path': '$.context.traits.user.phone' },
80
+ avatar: { '@path': '$.context.traits.user.avatar' },
81
+ created: { '@path': '$.context.traits.user.created' }
82
+ },
83
+ user_profile_properties_to_set_once: {
84
+ set_once_trait: { '@path': '$.context.traits.user.set_once_trait_1' }
85
+ },
86
+ user_profile_properties_to_increment: {
87
+ increment_property: { '@path': '$.context.traits.user.increment_property_1' }
88
+ },
89
+ group_details: {
90
+ group_key: { '@path': '$.context.traits.company.group_key' },
91
+ group_id: { '@path': '$.context.groupId' }
92
+ },
93
+ group_profile_properties_to_set: {
94
+ company_name: { '@path': '$.context.traits.company.company_name' },
95
+ number_employees: { '@path': '$.context.traits.company.number_employees' }
96
+ },
97
+ group_profile_properties_to_set_once: {
98
+ set_once_trait: { '@path': '$.context.traits.company.set_once_trait_1' }
99
+ },
100
+ group_profile_properties_to_union: { '@path': '$.context.traits.company.union_properties' }
101
+ }
102
+ }
103
+ ]
104
+
105
+ const context = new Context({
106
+ messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
107
+ type: 'track',
108
+ event: 'Big Fat Test Event',
109
+ anonymousId: 'anonymousId',
110
+ userId: 'userId1',
111
+ properties: {
112
+ prop1: 'value1',
113
+ prop2: 2,
114
+ prop3: true,
115
+ prop4: [1, 2, 3],
116
+ prop5: { subprop1: 'subvalue1', subprop2: 22 }
117
+ },
118
+ context: {
119
+ groupId: 'groupId1',
120
+ traits: {
121
+ user: {
122
+ name: 'User Name',
123
+ first_name: 'First',
124
+ last_name: 'Last',
125
+ email: 'user@example.com',
126
+ phone: '123-456-7890',
127
+ avatar: 'https://example.com/avatar.jpg',
128
+ created: '2020-01-01T00:00:000Z',
129
+ set_once_trait_1: 'set_once_value_1',
130
+ increment_property_1: 5
131
+ },
132
+ company: {
133
+ group_key: 'company',
134
+ company_name: 'MicroMegaCorpSoftware',
135
+ number_employees: 1000,
136
+ set_once_trait_1: 'set_once_value_1',
137
+ union_properties: [
138
+ { list_name: 'Interests', string_values: ['sports', 'music'] },
139
+ { list_name: 'Regions', string_values: ['north-america', 'europe'] }
140
+ ]
141
+ }
142
+ }
143
+ }
144
+ })
145
+
146
+ const [trackEvent] = await MixpanelDestination({
147
+ ...settings,
148
+ subscriptions
149
+ })
150
+ event = trackEvent
151
+
152
+ await event.load(Context.system(), {} as Analytics)
153
+ await event.group?.(context)
154
+
155
+ // Identify related calls
156
+ expect(mockMPP.identify).toHaveBeenCalledWith('userId1')
157
+ expect(mockMPP.people.set).toHaveBeenCalledWith({
158
+ name: 'User Name',
159
+ last_name: 'Last',
160
+ first_name: 'First',
161
+ email: 'user@example.com',
162
+ phone: '123-456-7890',
163
+ avatar: 'https://example.com/avatar.jpg',
164
+ created: '2020-01-01T00:00:000Z'
165
+ })
166
+ expect(mockMPP.people.set_once).toHaveBeenCalledWith({
167
+ set_once_trait: 'set_once_value_1'
168
+ })
169
+ expect(mockMPP.people.increment).toHaveBeenCalledWith({
170
+ increment_property: 5
171
+ })
172
+
173
+ // Group related calls
174
+ expect(mockMPP.set_group).toHaveBeenCalledWith('company', 'groupId1')
175
+ expect(mockMPP.get_group).toHaveBeenCalledWith('company', 'groupId1')
176
+ expect(mockGroup.set).toHaveBeenCalledWith({
177
+ company_name: 'MicroMegaCorpSoftware',
178
+ number_employees: 1000
179
+ })
180
+ expect(mockGroup.set_once).toHaveBeenCalledWith({
181
+ set_once_trait: 'set_once_value_1'
182
+ })
183
+ expect(mockGroup.union).toHaveBeenCalledTimes(2)
184
+ expect(mockGroup.union).toHaveBeenNthCalledWith(1, 'Interests', ['sports', 'music'])
185
+ expect(mockGroup.union).toHaveBeenNthCalledWith(2, 'Regions', ['north-america', 'europe'])
186
+
187
+ // Track related calls
188
+ expect(mockMPP.track).toHaveBeenCalledWith('Big Fat Test Event', {
189
+ prop1: 'value1',
190
+ prop2: 2,
191
+ prop3: true,
192
+ prop4: [1, 2, 3],
193
+ prop5: { subprop1: 'subvalue1', subprop2: 22 }
194
+ })
195
+ })
196
+ })
@@ -0,0 +1,102 @@
1
+ // Generated file. DO NOT MODIFY IT BY HAND.
2
+
3
+ export interface Payload {
4
+ /**
5
+ * The name of the event to track in Mixpanel.
6
+ */
7
+ event_name: string
8
+ /**
9
+ * Properties to associate with the event.
10
+ */
11
+ properties?: {
12
+ [k: string]: unknown
13
+ }
14
+ /**
15
+ * The unique ID to associate with the user. Settings this value will trigger a Mixpanel identify call before immediately the track event is sent.
16
+ */
17
+ unique_id?: string
18
+ /**
19
+ * User Profile Properties to set on the user profile in Mixpanel.
20
+ */
21
+ user_profile_properties_to_set?: {
22
+ /**
23
+ * The name of the user.
24
+ */
25
+ name?: string
26
+ /**
27
+ * The first name of the user.
28
+ */
29
+ first_name?: string
30
+ /**
31
+ * The last name of the user.
32
+ */
33
+ last_name?: string
34
+ /**
35
+ * The email of the user.
36
+ */
37
+ email?: string
38
+ /**
39
+ * The phone number of the user.
40
+ */
41
+ phone?: string
42
+ /**
43
+ * The avatar URL of the user.
44
+ */
45
+ avatar?: string
46
+ /**
47
+ * The creation date of the user profile.
48
+ */
49
+ created?: string
50
+ [k: string]: unknown
51
+ }
52
+ /**
53
+ * User Profile Properties to set once on the user profile in Mixpanel. Values which get set once cannot be overwritten later.
54
+ */
55
+ user_profile_properties_to_set_once?: {
56
+ [k: string]: unknown
57
+ }
58
+ /**
59
+ * User Profile Properties to increment on the user profile in Mixpanel. Values must be numeric.
60
+ */
61
+ user_profile_properties_to_increment?: {
62
+ [k: string]: unknown
63
+ }
64
+ /**
65
+ * Details for the group to be created or updated in Mixpanel. Setting this value will trigger a Mixpanel set_group call before the track event is sent.
66
+ */
67
+ group_details?: {
68
+ /**
69
+ * The Group Key / type of group to associate with the user. This group key should already be defined in your Mixpanel project.
70
+ */
71
+ group_key: string
72
+ /**
73
+ * The unique ID to associate with the group.
74
+ */
75
+ group_id: string
76
+ }
77
+ /**
78
+ * Group Profile Properties to set on the group in Mixpanel.
79
+ */
80
+ group_profile_properties_to_set?: {
81
+ [k: string]: unknown
82
+ }
83
+ /**
84
+ * Group Profile Properties to set once on the group profile in Mixpanel. Values which get set once cannot be overwritten later.
85
+ */
86
+ group_profile_properties_to_set_once?: {
87
+ [k: string]: unknown
88
+ }
89
+ /**
90
+ * Merge a list into a list group property. Duplicates will be removed.
91
+ */
92
+ group_profile_properties_to_union?: {
93
+ /**
94
+ * The name of the list property to union values into.
95
+ */
96
+ list_name: string
97
+ /**
98
+ * An array of string values to merge into the list. Non string lists cannot be updated. Duplicates will be removed.
99
+ */
100
+ string_values: string[]
101
+ }[]
102
+ }
@@ -0,0 +1,109 @@
1
+ import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
2
+ import type { Settings } from '../generated-types'
3
+ import type { Payload } from './generated-types'
4
+ import type { Mixpanel } from '../types'
5
+ import { sendIdentify, sendGroup } from '../functions'
6
+ import {
7
+ event_name,
8
+ properties,
9
+ unique_id,
10
+ user_profile_properties_to_set,
11
+ user_profile_properties_to_set_once,
12
+ user_profile_properties_to_increment,
13
+ group_details,
14
+ group_profile_properties_to_set,
15
+ group_profile_properties_to_set_once,
16
+ group_profile_properties_to_union
17
+ } from '../fields'
18
+
19
+ const action: BrowserActionDefinition<Settings, Mixpanel, Payload> = {
20
+ title: 'Track',
21
+ description: 'Sync Segment track events to Mixpanel.',
22
+ platform: 'web',
23
+ fields: {
24
+ event_name,
25
+ properties,
26
+ unique_id: {
27
+ ...unique_id,
28
+ description:
29
+ 'The unique ID to associate with the user. Settings this value will trigger a Mixpanel identify call before immediately the track event is sent.',
30
+ default: undefined,
31
+ required: false
32
+ },
33
+ user_profile_properties_to_set: {
34
+ ...user_profile_properties_to_set,
35
+ default: {
36
+ name: {
37
+ '@if': {
38
+ exists: { '@path': '$.context.traits.name' },
39
+ then: { '@path': '$.context.traits.name' },
40
+ else: { '@path': '$.properties.name' }
41
+ }
42
+ },
43
+ first_name: {
44
+ '@if': {
45
+ exists: { '@path': '$.context.traits.first_name' },
46
+ then: { '@path': '$.context.traits.first_name' },
47
+ else: { '@path': '$.properties.first_name' }
48
+ }
49
+ },
50
+ last_name: {
51
+ '@if': {
52
+ exists: { '@path': '$.context.traits.last_name' },
53
+ then: { '@path': '$.context.traits.last_name' },
54
+ else: { '@path': '$.properties.last_name' }
55
+ }
56
+ },
57
+ email: {
58
+ '@if': {
59
+ exists: { '@path': '$.context.traits.email' },
60
+ then: { '@path': '$.context.traits.email' },
61
+ else: { '@path': '$.properties.email' }
62
+ }
63
+ },
64
+ phone: {
65
+ '@if': {
66
+ exists: { '@path': '$.context.traits.phone' },
67
+ then: { '@path': '$.context.traits.phone' },
68
+ else: { '@path': '$.properties.phone' }
69
+ }
70
+ },
71
+ avatar: {
72
+ '@if': {
73
+ exists: { '@path': '$.context.traits.avatar' },
74
+ then: { '@path': '$.context.traits.avatar' },
75
+ else: { '@path': '$.properties.avatar' }
76
+ }
77
+ },
78
+ created: {
79
+ '@if': {
80
+ exists: { '@path': '$.context.traits.created_at' },
81
+ then: { '@path': '$.context.traits.created_at' },
82
+ else: { '@path': '$.properties.created_at' }
83
+ }
84
+ }
85
+ }
86
+ },
87
+ user_profile_properties_to_set_once,
88
+ user_profile_properties_to_increment,
89
+ group_details: {
90
+ ...group_details,
91
+ required: false,
92
+ description:
93
+ 'Details for the group to be created or updated in Mixpanel. Setting this value will trigger a Mixpanel set_group call before the track event is sent.',
94
+ default: undefined
95
+ },
96
+ group_profile_properties_to_set,
97
+ group_profile_properties_to_set_once,
98
+ group_profile_properties_to_union
99
+ },
100
+ defaultSubscription: 'type = "track"',
101
+ perform: (mixpanel, { payload }) => {
102
+ sendIdentify(mixpanel, payload)
103
+ sendGroup(mixpanel, payload)
104
+ const { event_name, properties = {} } = payload
105
+ mixpanel.track(event_name, properties)
106
+ }
107
+ }
108
+
109
+ export default action
@@ -0,0 +1,250 @@
1
+ import { Analytics, Context } from '@segment/analytics-next'
2
+ import { Subscription } from '@segment/browser-destination-runtime'
3
+ import MixpanelDestination, { destination } from '../../index'
4
+ import { Mixpanel } from '../../types'
5
+ import { AUTOCAPTURE_OPTIONS, PERSISTENCE_OPTIONS } from '../../constants'
6
+ import { Group } from '../../types'
7
+
8
+ describe('Mixpanel.trackPageView', () => {
9
+ const settings = {
10
+ projectToken: 'projectToken1',
11
+ name: 'name1',
12
+ default: 'https://api-js.mixpanel.com',
13
+ autocapture: AUTOCAPTURE_OPTIONS.ENABLED,
14
+ cross_subdomain_cookie: true,
15
+ persistence: PERSISTENCE_OPTIONS.COOKIE,
16
+ track_marketing: true,
17
+ cookie_expiration: 365,
18
+ disable_persistence: false,
19
+ ip: true,
20
+ record_block_class: 'mp-block',
21
+ record_block_selector: 'img, video, audio',
22
+ record_canvas: false,
23
+ record_heatmap_data: false,
24
+ record_idle_timeout_ms: 180_000,
25
+ record_mask_text_class: 'mp-mask',
26
+ record_mask_text_selector: '*',
27
+ record_max_ms: 86_400_000,
28
+ record_min_ms: 8_000,
29
+ record_sessions_percent: 0
30
+ }
31
+
32
+ let mockMPP: Mixpanel
33
+ let mockGroup: Group
34
+ let event: any
35
+
36
+ beforeEach(async () => {
37
+ jest.restoreAllMocks()
38
+ jest.spyOn(destination, 'initialize').mockImplementation(() => {
39
+ mockGroup = {
40
+ set: jest.fn(),
41
+ set_once: jest.fn(),
42
+ union: jest.fn()
43
+ }
44
+
45
+ mockMPP = {
46
+ init: jest.fn(),
47
+ track_pageview: jest.fn(),
48
+ track: jest.fn(),
49
+ identify: jest.fn(),
50
+ alias: jest.fn(),
51
+ get_group: jest.fn().mockReturnValue(mockGroup),
52
+ set_group: jest.fn(),
53
+ people: {
54
+ set: jest.fn(),
55
+ set_once: jest.fn(),
56
+ increment: jest.fn()
57
+ }
58
+ }
59
+ return Promise.resolve(mockMPP)
60
+ })
61
+ })
62
+
63
+ test('trackPageView() handled correctly', async () => {
64
+ const subscriptions: Subscription[] = [
65
+ {
66
+ partnerAction: 'trackPageView',
67
+ name: 'Track Page View',
68
+ enabled: true,
69
+ subscribe: 'type = "page"',
70
+ mapping: {
71
+ event_name: undefined,
72
+ properties: { '@path': '$.properties' },
73
+ unique_id: { '@path': '$.userId' },
74
+ user_profile_properties_to_set: {
75
+ name: { '@path': '$.context.traits.user.name' },
76
+ first_name: { '@path': '$.context.traits.user.first_name' },
77
+ last_name: { '@path': '$.context.traits.user.last_name' },
78
+ email: { '@path': '$.context.traits.user.email' },
79
+ phone: { '@path': '$.context.traits.user.phone' },
80
+ avatar: { '@path': '$.context.traits.user.avatar' },
81
+ created: { '@path': '$.context.traits.user.created' }
82
+ },
83
+ user_profile_properties_to_set_once: {
84
+ set_once_trait: { '@path': '$.context.traits.user.set_once_trait_1' }
85
+ },
86
+ user_profile_properties_to_increment: {
87
+ increment_property: { '@path': '$.context.traits.user.increment_property_1' }
88
+ },
89
+ group_details: {
90
+ group_key: { '@path': '$.context.traits.company.group_key' },
91
+ group_id: { '@path': '$.context.groupId' }
92
+ },
93
+ group_profile_properties_to_set: {
94
+ company_name: { '@path': '$.context.traits.company.company_name' },
95
+ number_employees: { '@path': '$.context.traits.company.number_employees' }
96
+ },
97
+ group_profile_properties_to_set_once: {
98
+ set_once_trait: { '@path': '$.context.traits.company.set_once_trait_1' }
99
+ },
100
+ group_profile_properties_to_union: { '@path': '$.context.traits.company.union_properties' }
101
+ }
102
+ }
103
+ ]
104
+
105
+ const context = new Context({
106
+ messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
107
+ type: 'page',
108
+ anonymousId: 'anonymousId',
109
+ userId: 'userId1',
110
+ properties: {
111
+ prop1: 'value1',
112
+ prop2: 2,
113
+ prop3: true,
114
+ prop4: [1, 2, 3],
115
+ prop5: { subprop1: 'subvalue1', subprop2: 22 }
116
+ },
117
+ context: {
118
+ groupId: 'groupId1',
119
+ traits: {
120
+ user: {
121
+ name: 'User Name',
122
+ first_name: 'First',
123
+ last_name: 'Last',
124
+ email: 'user@example.com',
125
+ phone: '123-456-7890',
126
+ avatar: 'https://example.com/avatar.jpg',
127
+ created: '2020-01-01T00:00:000Z',
128
+ set_once_trait_1: 'set_once_value_1',
129
+ increment_property_1: 5
130
+ },
131
+ company: {
132
+ group_key: 'company',
133
+ company_name: 'MicroMegaCorpSoftware',
134
+ number_employees: 1000,
135
+ set_once_trait_1: 'set_once_value_1',
136
+ union_properties: [
137
+ { list_name: 'Interests', string_values: ['sports', 'music'] },
138
+ { list_name: 'Regions', string_values: ['north-america', 'europe'] }
139
+ ]
140
+ }
141
+ }
142
+ }
143
+ })
144
+
145
+ const [trackEvent] = await MixpanelDestination({
146
+ ...settings,
147
+ subscriptions
148
+ })
149
+ event = trackEvent
150
+
151
+ await event.load(Context.system(), {} as Analytics)
152
+ await event.group?.(context)
153
+
154
+ // Identify related calls
155
+ expect(mockMPP.identify).toHaveBeenCalledWith('userId1')
156
+ expect(mockMPP.people.set).toHaveBeenCalledWith({
157
+ name: 'User Name',
158
+ last_name: 'Last',
159
+ first_name: 'First',
160
+ email: 'user@example.com',
161
+ phone: '123-456-7890',
162
+ avatar: 'https://example.com/avatar.jpg',
163
+ created: '2020-01-01T00:00:000Z'
164
+ })
165
+ expect(mockMPP.people.set_once).toHaveBeenCalledWith({
166
+ set_once_trait: 'set_once_value_1'
167
+ })
168
+ expect(mockMPP.people.increment).toHaveBeenCalledWith({
169
+ increment_property: 5
170
+ })
171
+
172
+ // Group related calls
173
+ expect(mockMPP.set_group).toHaveBeenCalledWith('company', 'groupId1')
174
+ expect(mockMPP.get_group).toHaveBeenCalledWith('company', 'groupId1')
175
+ expect(mockGroup.set).toHaveBeenCalledWith({
176
+ company_name: 'MicroMegaCorpSoftware',
177
+ number_employees: 1000
178
+ })
179
+ expect(mockGroup.set_once).toHaveBeenCalledWith({
180
+ set_once_trait: 'set_once_value_1'
181
+ })
182
+ expect(mockGroup.union).toHaveBeenCalledTimes(2)
183
+ expect(mockGroup.union).toHaveBeenNthCalledWith(1, 'Interests', ['sports', 'music'])
184
+ expect(mockGroup.union).toHaveBeenNthCalledWith(2, 'Regions', ['north-america', 'europe'])
185
+
186
+ // Track Page View related calls
187
+ expect(mockMPP.track_pageview).toHaveBeenCalledWith({
188
+ prop1: 'value1',
189
+ prop2: 2,
190
+ prop3: true,
191
+ prop4: [1, 2, 3],
192
+ prop5: { subprop1: 'subvalue1', subprop2: 22 }
193
+ })
194
+ })
195
+
196
+ test('trackPageView() handled correctly, with event name', async () => {
197
+ const subscriptions: Subscription[] = [
198
+ {
199
+ partnerAction: 'trackPageView',
200
+ name: 'Track Page View',
201
+ enabled: true,
202
+ subscribe: 'type = "page"',
203
+ mapping: {
204
+ event_name: { '@path': '$.properties.event_name' },
205
+ properties: { '@path': '$.properties.other_props' }
206
+ }
207
+ }
208
+ ]
209
+
210
+ const context = new Context({
211
+ messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
212
+ type: 'page',
213
+ anonymousId: 'anonymousId',
214
+ userId: 'userId1',
215
+ properties: {
216
+ event_name: 'Dis be an event name',
217
+ other_props: {
218
+ prop1: 'value1',
219
+ prop2: 2,
220
+ prop3: true,
221
+ prop4: [1, 2, 3],
222
+ prop5: { subprop1: 'subvalue1', subprop2: 22 }
223
+ }
224
+ }
225
+ })
226
+
227
+ const [trackEvent] = await MixpanelDestination({
228
+ ...settings,
229
+ subscriptions
230
+ })
231
+ event = trackEvent
232
+
233
+ await event.load(Context.system(), {} as Analytics)
234
+ await event.group?.(context)
235
+
236
+ // Track Page View related calls
237
+ expect(mockMPP.track_pageview).toHaveBeenCalledWith(
238
+ {
239
+ prop1: 'value1',
240
+ prop2: 2,
241
+ prop3: true,
242
+ prop4: [1, 2, 3],
243
+ prop5: { subprop1: 'subvalue1', subprop2: 22 }
244
+ },
245
+ {
246
+ event_name: 'Dis be an event name'
247
+ }
248
+ )
249
+ })
250
+ })