posthog-js 1.161.3 → 1.161.4

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.
@@ -0,0 +1,310 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ import { WebExperiments } from './web-experiments';
49
+ import { RequestRouter } from './utils/request-router';
50
+ describe('Web Experimentation', function () {
51
+ var webExperiment;
52
+ var posthog;
53
+ var persistence;
54
+ var experimentsResponse;
55
+ var signupButtonWebExperimentWithFeatureFlag = {
56
+ id: 3,
57
+ name: 'Signup button test',
58
+ feature_flag_key: 'signup-button-test',
59
+ variants: {
60
+ Signup: {
61
+ transforms: [
62
+ {
63
+ selector: '#set-user-properties',
64
+ text: 'Sign me up',
65
+ html: 'Sign me up',
66
+ },
67
+ ],
68
+ },
69
+ 'Send-it': {
70
+ transforms: [
71
+ {
72
+ selector: '#set-user-properties',
73
+ text: 'Send it',
74
+ html: 'Send it',
75
+ },
76
+ ],
77
+ },
78
+ 'css-transform': {
79
+ transforms: [
80
+ {
81
+ selector: '#set-user-properties',
82
+ className: 'primary',
83
+ },
84
+ ],
85
+ },
86
+ 'innerhtml-transform': {
87
+ transforms: [
88
+ {
89
+ selector: '#set-user-properties',
90
+ html: '<h1>hello world</h1>',
91
+ },
92
+ ],
93
+ },
94
+ control: {
95
+ transforms: [
96
+ {
97
+ selector: '#set-user-properties',
98
+ text: 'Sign up',
99
+ html: 'Sign up',
100
+ },
101
+ ],
102
+ },
103
+ },
104
+ };
105
+ var buttonWebExperimentWithUrlConditions = {
106
+ id: 3,
107
+ name: 'Signup button test',
108
+ variants: {
109
+ Signup: {
110
+ conditions: {
111
+ url: 'https://example.com/Signup',
112
+ urlMatchType: 'exact',
113
+ },
114
+ transforms: [
115
+ {
116
+ selector: '#set-user-properties',
117
+ text: 'Sign me up',
118
+ html: 'Sign me up',
119
+ },
120
+ ],
121
+ },
122
+ 'Send-it': {
123
+ conditions: { url: 'regex-url', urlMatchType: 'regex' },
124
+ transforms: [
125
+ {
126
+ selector: '#set-user-properties',
127
+ text: 'Send it',
128
+ html: 'Send it',
129
+ },
130
+ ],
131
+ },
132
+ control: {
133
+ conditions: { url: 'checkout', urlMatchType: 'icontains' },
134
+ transforms: [
135
+ {
136
+ selector: '#set-user-properties',
137
+ text: 'Sign up',
138
+ html: 'Sign up',
139
+ },
140
+ ],
141
+ },
142
+ },
143
+ };
144
+ beforeEach(function () {
145
+ persistence = { props: {}, register: jest.fn() };
146
+ posthog = makePostHog({
147
+ config: {
148
+ disable_web_experiments: false,
149
+ api_host: 'https://test.com',
150
+ token: 'testtoken',
151
+ autocapture: true,
152
+ region: 'us-east-1',
153
+ },
154
+ persistence: persistence,
155
+ get_property: jest.fn(),
156
+ _send_request: jest
157
+ .fn()
158
+ .mockImplementation(function (_a) {
159
+ var callback = _a.callback;
160
+ return callback({ statusCode: 200, json: experimentsResponse });
161
+ }),
162
+ consent: { isOptedOut: function () { return true; } },
163
+ });
164
+ posthog.requestRouter = new RequestRouter(posthog);
165
+ webExperiment = new WebExperiments(posthog);
166
+ });
167
+ function createTestDocument() {
168
+ // eslint-disable-next-line no-restricted-globals
169
+ var elTarget = document.createElement('img');
170
+ elTarget.id = 'primary_button';
171
+ // eslint-disable-next-line no-restricted-globals
172
+ var elParent = document.createElement('span');
173
+ elParent.innerText = 'unassigned';
174
+ elParent.className = 'unassigned';
175
+ elParent.appendChild(elTarget);
176
+ // eslint-disable-next-line no-restricted-globals
177
+ document.querySelectorAll = function () {
178
+ return [elParent];
179
+ };
180
+ return elParent;
181
+ }
182
+ function testUrlMatch(testLocation, expectedText) {
183
+ experimentsResponse = {
184
+ experiments: [buttonWebExperimentWithUrlConditions],
185
+ };
186
+ var webExperiment = new WebExperiments(posthog);
187
+ var elParent = createTestDocument();
188
+ WebExperiments.getWindowLocation = function () {
189
+ // eslint-disable-next-line compat/compat
190
+ return new URL(testLocation);
191
+ };
192
+ webExperiment.getWebExperimentsAndEvaluateDisplayLogic(false);
193
+ expect(elParent.innerText).toEqual(expectedText);
194
+ }
195
+ function assertElementChanged(variant, expectedProperty, value) {
196
+ var elParent = createTestDocument();
197
+ webExperiment = new WebExperiments(posthog);
198
+ webExperiment.afterDecideResponse({
199
+ featureFlags: {
200
+ 'signup-button-test': variant,
201
+ },
202
+ });
203
+ switch (expectedProperty) {
204
+ case 'className':
205
+ expect(elParent.className).toEqual(value);
206
+ break;
207
+ case 'innerText':
208
+ expect(elParent.innerText).toEqual(value);
209
+ break;
210
+ case 'innerHTML':
211
+ expect(elParent.innerHTML).toEqual(value);
212
+ break;
213
+ }
214
+ }
215
+ describe('url match conditions', function () {
216
+ it('exact location match', function () {
217
+ var testLocation = 'https://example.com/Signup';
218
+ var expectedText = 'Sign me up';
219
+ testUrlMatch(testLocation, expectedText);
220
+ });
221
+ it('regex location match', function () {
222
+ var testLocation = 'https://regex-url.com/test';
223
+ var expectedText = 'Send it';
224
+ testUrlMatch(testLocation, expectedText);
225
+ });
226
+ it('icontains location match', function () {
227
+ var testLocation = 'https://example.com/checkout';
228
+ var expectedText = 'Sign up';
229
+ testUrlMatch(testLocation, expectedText);
230
+ });
231
+ });
232
+ describe('utm match conditions', function () {
233
+ it('can disqualify on utm terms', function () {
234
+ var buttonWebExperimentWithUTMConditions = buttonWebExperimentWithUrlConditions;
235
+ buttonWebExperimentWithUTMConditions.variants['Signup'].conditions = {
236
+ utm: {
237
+ utm_campaign: 'marketing',
238
+ utm_medium: 'desktop',
239
+ },
240
+ };
241
+ var testLocation = 'https://example.com/landing-page?utm_campaign=marketing&utm_medium=mobile';
242
+ var expectedText = 'unassigned';
243
+ testUrlMatch(testLocation, expectedText);
244
+ });
245
+ });
246
+ describe('with feature flags', function () {
247
+ it('experiments are disabled by default', function () { return __awaiter(void 0, void 0, void 0, function () {
248
+ var expResponse, disabledPostHog;
249
+ return __generator(this, function (_a) {
250
+ expResponse = {
251
+ experiments: [signupButtonWebExperimentWithFeatureFlag],
252
+ };
253
+ disabledPostHog = makePostHog({
254
+ config: {
255
+ api_host: 'https://test.com',
256
+ token: 'testtoken',
257
+ autocapture: true,
258
+ region: 'us-east-1',
259
+ },
260
+ persistence: persistence,
261
+ get_property: jest.fn(),
262
+ _send_request: jest
263
+ .fn()
264
+ .mockImplementation(function (_a) {
265
+ var callback = _a.callback;
266
+ return callback({ statusCode: 200, json: expResponse });
267
+ }),
268
+ consent: { isOptedOut: function () { return true; } },
269
+ });
270
+ posthog.requestRouter = new RequestRouter(disabledPostHog);
271
+ webExperiment = new WebExperiments(disabledPostHog);
272
+ assertElementChanged('control', 'innerText', 'unassigned');
273
+ return [2 /*return*/];
274
+ });
275
+ }); });
276
+ it('can set text of Span Element', function () { return __awaiter(void 0, void 0, void 0, function () {
277
+ return __generator(this, function (_a) {
278
+ experimentsResponse = {
279
+ experiments: [signupButtonWebExperimentWithFeatureFlag],
280
+ };
281
+ assertElementChanged('control', 'innerText', 'Sign up');
282
+ return [2 /*return*/];
283
+ });
284
+ }); });
285
+ it('can set className of Span Element', function () { return __awaiter(void 0, void 0, void 0, function () {
286
+ return __generator(this, function (_a) {
287
+ experimentsResponse = {
288
+ experiments: [signupButtonWebExperimentWithFeatureFlag],
289
+ };
290
+ assertElementChanged('css-transform', 'className', 'primary');
291
+ return [2 /*return*/];
292
+ });
293
+ }); });
294
+ it('can set innerHtml of Span Element', function () { return __awaiter(void 0, void 0, void 0, function () {
295
+ return __generator(this, function (_a) {
296
+ experimentsResponse = {
297
+ experiments: [signupButtonWebExperimentWithFeatureFlag],
298
+ };
299
+ assertElementChanged('innerhtml-transform', 'innerHTML', '<h1>hello world</h1>');
300
+ return [2 /*return*/];
301
+ });
302
+ }); });
303
+ });
304
+ function makePostHog(ph) {
305
+ return __assign({ get_distinct_id: function () {
306
+ return 'distinctid';
307
+ } }, ph);
308
+ }
309
+ });
310
+ //# sourceMappingURL=web-experiments.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-experiments.test.js","sourceRoot":"","sources":["../../src/web-experiments.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebExperiments } from './web-experiments'\nimport { PostHog } from './posthog-core'\nimport { DecideResponse, PostHogConfig } from './types'\nimport { PostHogPersistence } from './posthog-persistence'\nimport { WebExperiment } from './web-experiments-types'\nimport { RequestRouter } from './utils/request-router'\nimport { ConsentManager } from './consent'\n\ndescribe('Web Experimentation', () => {\n let webExperiment: WebExperiments\n let posthog: PostHog\n let persistence: PostHogPersistence\n let experimentsResponse: { status?: number; experiments?: WebExperiment[] }\n const signupButtonWebExperimentWithFeatureFlag = {\n id: 3,\n name: 'Signup button test',\n feature_flag_key: 'signup-button-test',\n variants: {\n Signup: {\n transforms: [\n {\n selector: '#set-user-properties',\n text: 'Sign me up',\n html: 'Sign me up',\n },\n ],\n },\n 'Send-it': {\n transforms: [\n {\n selector: '#set-user-properties',\n text: 'Send it',\n html: 'Send it',\n },\n ],\n },\n 'css-transform': {\n transforms: [\n {\n selector: '#set-user-properties',\n className: 'primary',\n },\n ],\n },\n 'innerhtml-transform': {\n transforms: [\n {\n selector: '#set-user-properties',\n html: '<h1>hello world</h1>',\n },\n ],\n },\n control: {\n transforms: [\n {\n selector: '#set-user-properties',\n text: 'Sign up',\n html: 'Sign up',\n },\n ],\n },\n },\n } as unknown as WebExperiment\n\n const buttonWebExperimentWithUrlConditions = {\n id: 3,\n name: 'Signup button test',\n variants: {\n Signup: {\n conditions: {\n url: 'https://example.com/Signup',\n urlMatchType: 'exact',\n },\n transforms: [\n {\n selector: '#set-user-properties',\n text: 'Sign me up',\n html: 'Sign me up',\n },\n ],\n },\n 'Send-it': {\n conditions: { url: 'regex-url', urlMatchType: 'regex' },\n transforms: [\n {\n selector: '#set-user-properties',\n text: 'Send it',\n html: 'Send it',\n },\n ],\n },\n control: {\n conditions: { url: 'checkout', urlMatchType: 'icontains' },\n transforms: [\n {\n selector: '#set-user-properties',\n text: 'Sign up',\n html: 'Sign up',\n },\n ],\n },\n },\n } as unknown as WebExperiment\n\n beforeEach(() => {\n persistence = { props: {}, register: jest.fn() } as unknown as PostHogPersistence\n posthog = makePostHog({\n config: {\n disable_web_experiments: false,\n api_host: 'https://test.com',\n token: 'testtoken',\n autocapture: true,\n region: 'us-east-1',\n } as unknown as PostHogConfig,\n persistence: persistence,\n get_property: jest.fn(),\n _send_request: jest\n .fn()\n .mockImplementation(({ callback }) => callback({ statusCode: 200, json: experimentsResponse })),\n consent: { isOptedOut: () => true } as unknown as ConsentManager,\n })\n\n posthog.requestRouter = new RequestRouter(posthog)\n webExperiment = new WebExperiments(posthog)\n })\n\n function createTestDocument() {\n // eslint-disable-next-line no-restricted-globals\n const elTarget = document.createElement('img')\n elTarget.id = 'primary_button'\n // eslint-disable-next-line no-restricted-globals\n const elParent = document.createElement('span')\n elParent.innerText = 'unassigned'\n elParent.className = 'unassigned'\n elParent.appendChild(elTarget)\n // eslint-disable-next-line no-restricted-globals\n document.querySelectorAll = function () {\n return [elParent] as unknown as NodeListOf<Element>\n }\n\n return elParent\n }\n\n function testUrlMatch(testLocation: string, expectedText: string) {\n experimentsResponse = {\n experiments: [buttonWebExperimentWithUrlConditions],\n }\n const webExperiment = new WebExperiments(posthog)\n const elParent = createTestDocument()\n\n WebExperiments.getWindowLocation = () => {\n // eslint-disable-next-line compat/compat\n return new URL(testLocation) as unknown as Location\n }\n\n webExperiment.getWebExperimentsAndEvaluateDisplayLogic(false)\n expect(elParent.innerText).toEqual(expectedText)\n }\n\n function assertElementChanged(variant: string, expectedProperty: string, value: string) {\n const elParent = createTestDocument()\n webExperiment = new WebExperiments(posthog)\n webExperiment.afterDecideResponse({\n featureFlags: {\n 'signup-button-test': variant,\n },\n } as unknown as DecideResponse)\n\n switch (expectedProperty) {\n case 'className':\n expect(elParent.className).toEqual(value)\n break\n\n case 'innerText':\n expect(elParent.innerText).toEqual(value)\n break\n\n case 'innerHTML':\n expect(elParent.innerHTML).toEqual(value)\n break\n }\n }\n\n describe('url match conditions', () => {\n it('exact location match', () => {\n const testLocation = 'https://example.com/Signup'\n const expectedText = 'Sign me up'\n testUrlMatch(testLocation, expectedText)\n })\n\n it('regex location match', () => {\n const testLocation = 'https://regex-url.com/test'\n const expectedText = 'Send it'\n testUrlMatch(testLocation, expectedText)\n })\n\n it('icontains location match', () => {\n const testLocation = 'https://example.com/checkout'\n const expectedText = 'Sign up'\n testUrlMatch(testLocation, expectedText)\n })\n })\n\n describe('utm match conditions', () => {\n it('can disqualify on utm terms', () => {\n const buttonWebExperimentWithUTMConditions = buttonWebExperimentWithUrlConditions\n buttonWebExperimentWithUTMConditions.variants['Signup'].conditions = {\n utm: {\n utm_campaign: 'marketing',\n utm_medium: 'desktop',\n },\n }\n const testLocation = 'https://example.com/landing-page?utm_campaign=marketing&utm_medium=mobile'\n const expectedText = 'unassigned'\n testUrlMatch(testLocation, expectedText)\n })\n })\n\n describe('with feature flags', () => {\n it('experiments are disabled by default', async () => {\n const expResponse = {\n experiments: [signupButtonWebExperimentWithFeatureFlag],\n }\n const disabledPostHog = makePostHog({\n config: {\n api_host: 'https://test.com',\n token: 'testtoken',\n autocapture: true,\n region: 'us-east-1',\n } as unknown as PostHogConfig,\n persistence: persistence,\n get_property: jest.fn(),\n _send_request: jest\n .fn()\n .mockImplementation(({ callback }) => callback({ statusCode: 200, json: expResponse })),\n consent: { isOptedOut: () => true } as unknown as ConsentManager,\n })\n\n posthog.requestRouter = new RequestRouter(disabledPostHog)\n webExperiment = new WebExperiments(disabledPostHog)\n assertElementChanged('control', 'innerText', 'unassigned')\n })\n\n it('can set text of Span Element', async () => {\n experimentsResponse = {\n experiments: [signupButtonWebExperimentWithFeatureFlag],\n }\n\n assertElementChanged('control', 'innerText', 'Sign up')\n })\n\n it('can set className of Span Element', async () => {\n experimentsResponse = {\n experiments: [signupButtonWebExperimentWithFeatureFlag],\n }\n\n assertElementChanged('css-transform', 'className', 'primary')\n })\n\n it('can set innerHtml of Span Element', async () => {\n experimentsResponse = {\n experiments: [signupButtonWebExperimentWithFeatureFlag],\n }\n assertElementChanged('innerhtml-transform', 'innerHTML', '<h1>hello world</h1>')\n })\n })\n\n function makePostHog(ph: Partial<PostHog>): PostHog {\n return {\n get_distinct_id() {\n return 'distinctid'\n },\n ...ph,\n } as unknown as PostHog\n }\n})\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthog-js",
3
- "version": "1.161.3",
3
+ "version": "1.161.4",
4
4
  "description": "Posthog-js allows you to automatically capture usage and send events to PostHog.",
5
5
  "repository": "https://github.com/PostHog/posthog-js",
6
6
  "author": "hey@posthog.com",