launchdarkly-js-sdk-common 4.3.2 → 5.0.0-alpha.1
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 +3 -1
- package/src/AnonymousContextProcessor.js +95 -0
- package/src/ContextFilter.js +147 -0
- package/src/EventProcessor.js +30 -13
- package/src/EventSender.js +1 -1
- package/src/Identity.js +10 -11
- package/src/PersistentFlagStore.js +3 -3
- package/src/Requestor.js +4 -4
- package/src/Stream.js +5 -5
- package/src/__tests__/ContextFilter-test.js +470 -0
- package/src/__tests__/EventProcessor-test.js +50 -121
- package/src/__tests__/LDClient-events-test.js +9 -152
- package/src/__tests__/LDClient-inspectors-test.js +1 -1
- package/src/__tests__/LDClient-test.js +18 -15
- package/src/__tests__/TransientContextProcessor-test.js +115 -0
- package/src/__tests__/attributeReference-test.js +400 -0
- package/src/__tests__/configuration-test.js +20 -21
- package/src/__tests__/context-test.js +93 -0
- package/src/__tests__/diagnosticEvents-test.js +0 -4
- package/src/__tests__/utils-test.js +3 -9
- package/src/attributeReference.js +143 -0
- package/src/configuration.js +4 -8
- package/src/context.js +96 -0
- package/src/diagnosticEvents.js +0 -2
- package/src/index.js +76 -89
- package/src/messages.js +8 -8
- package/src/utils.js +18 -15
- package/test-types.ts +3 -7
- package/typings.d.ts +140 -76
- package/src/UserFilter.js +0 -75
- package/src/UserValidator.js +0 -56
- package/src/__tests__/UserFilter-test.js +0 -93
- package/src/__tests__/UserValidator-test.js +0 -57
|
@@ -9,9 +9,20 @@ import { MockEventSender } from './testUtils';
|
|
|
9
9
|
// various inputs. The actual delivery of data is done by EventSender, which has its own
|
|
10
10
|
// tests; here, we use a mock EventSender.
|
|
11
11
|
|
|
12
|
-
describe(
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
describe.each([
|
|
13
|
+
[{ key: 'userKey', name: 'Red' }, { key: 'userKey', kind: 'user', _meta: { redactedAttributes: ['/name'] } }],
|
|
14
|
+
[
|
|
15
|
+
{ kind: 'user', key: 'userKey', name: 'Red' },
|
|
16
|
+
{ key: 'userKey', kind: 'user', _meta: { redactedAttributes: ['/name'] } },
|
|
17
|
+
],
|
|
18
|
+
[
|
|
19
|
+
{ kind: 'multi', user: { key: 'userKey', name: 'Red' } },
|
|
20
|
+
{ kind: 'multi', user: { key: 'userKey', _meta: { redactedAttributes: ['/name'] } } },
|
|
21
|
+
],
|
|
22
|
+
])('EventProcessor', (context, filteredContext) => {
|
|
23
|
+
// const user = { key: 'userKey', name: 'Red' };
|
|
24
|
+
const eventContext = { ...context, kind: context.kind || 'user' };
|
|
25
|
+
// const filteredUser = { key: 'userKey', kind: 'user', _meta: { redactedAttributes: ['/name'] } };
|
|
15
26
|
const eventsUrl = '/fake-url';
|
|
16
27
|
const envId = 'env';
|
|
17
28
|
const logger = stubPlatform.logger();
|
|
@@ -47,11 +58,11 @@ describe('EventProcessor', () => {
|
|
|
47
58
|
|
|
48
59
|
function checkUserInline(e, source, inlineUser) {
|
|
49
60
|
if (inlineUser) {
|
|
50
|
-
expect(e.
|
|
51
|
-
expect(e.
|
|
61
|
+
expect(e.context).toEqual(inlineUser);
|
|
62
|
+
expect(e.contextKeys).toBeUndefined();
|
|
52
63
|
} else {
|
|
53
|
-
expect(e.
|
|
54
|
-
expect(e.
|
|
64
|
+
expect(e.contextKeys).toEqual({ user: source.context.key || source.context.user.key });
|
|
65
|
+
expect(e.context).toBeUndefined();
|
|
55
66
|
}
|
|
56
67
|
}
|
|
57
68
|
|
|
@@ -67,13 +78,13 @@ describe('EventProcessor', () => {
|
|
|
67
78
|
checkUserInline(e, source, inlineUser);
|
|
68
79
|
}
|
|
69
80
|
|
|
70
|
-
function checkCustomEvent(e, source
|
|
81
|
+
function checkCustomEvent(e, source) {
|
|
71
82
|
expect(e.kind).toEqual('custom');
|
|
72
83
|
expect(e.creationDate).toEqual(source.creationDate);
|
|
73
84
|
expect(e.key).toEqual(source.key);
|
|
74
85
|
expect(e.data).toEqual(source.data);
|
|
75
86
|
expect(e.metricValue).toEqual(source.metricValue);
|
|
76
|
-
checkUserInline(e, source
|
|
87
|
+
checkUserInline(e, source);
|
|
77
88
|
}
|
|
78
89
|
|
|
79
90
|
function checkSummaryEvent(e) {
|
|
@@ -82,7 +93,7 @@ describe('EventProcessor', () => {
|
|
|
82
93
|
|
|
83
94
|
it('should enqueue identify event', async () => {
|
|
84
95
|
await withProcessorAndSender(defaultConfig, async (ep, mockEventSender) => {
|
|
85
|
-
const event = { kind: 'identify', creationDate: 1000,
|
|
96
|
+
const event = { kind: 'identify', creationDate: 1000, context: eventContext };
|
|
86
97
|
ep.enqueue(event);
|
|
87
98
|
await ep.flush();
|
|
88
99
|
|
|
@@ -94,7 +105,7 @@ describe('EventProcessor', () => {
|
|
|
94
105
|
it('filters user in identify event', async () => {
|
|
95
106
|
const config = { ...defaultConfig, allAttributesPrivate: true };
|
|
96
107
|
await withProcessorAndSender(config, async (ep, mockEventSender) => {
|
|
97
|
-
const event = { kind: 'identify', creationDate: 1000,
|
|
108
|
+
const event = { kind: 'identify', creationDate: 1000, context: eventContext };
|
|
98
109
|
ep.enqueue(event);
|
|
99
110
|
await ep.flush();
|
|
100
111
|
|
|
@@ -103,8 +114,8 @@ describe('EventProcessor', () => {
|
|
|
103
114
|
{
|
|
104
115
|
kind: 'identify',
|
|
105
116
|
creationDate: event.creationDate,
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
|
|
118
|
+
context: filteredContext,
|
|
108
119
|
},
|
|
109
120
|
]);
|
|
110
121
|
});
|
|
@@ -116,7 +127,7 @@ describe('EventProcessor', () => {
|
|
|
116
127
|
kind: 'feature',
|
|
117
128
|
creationDate: 1000,
|
|
118
129
|
key: 'flagkey',
|
|
119
|
-
|
|
130
|
+
context: eventContext,
|
|
120
131
|
trackEvents: true,
|
|
121
132
|
};
|
|
122
133
|
ep.enqueue(event);
|
|
@@ -130,36 +141,15 @@ describe('EventProcessor', () => {
|
|
|
130
141
|
});
|
|
131
142
|
});
|
|
132
143
|
|
|
133
|
-
it('can include inline user in feature event', async () => {
|
|
134
|
-
const config = { ...defaultConfig, inlineUsersInEvents: true };
|
|
135
|
-
await withProcessorAndSender(config, async (ep, mockEventSender) => {
|
|
136
|
-
const event = {
|
|
137
|
-
kind: 'feature',
|
|
138
|
-
creationDate: 1000,
|
|
139
|
-
key: 'flagkey',
|
|
140
|
-
user: user,
|
|
141
|
-
trackEvents: true,
|
|
142
|
-
};
|
|
143
|
-
ep.enqueue(event);
|
|
144
|
-
await ep.flush();
|
|
145
|
-
|
|
146
|
-
expect(mockEventSender.calls.length()).toEqual(1);
|
|
147
|
-
const output = (await mockEventSender.calls.take()).events;
|
|
148
|
-
expect(output.length).toEqual(2);
|
|
149
|
-
checkFeatureEvent(output[0], event, false, user);
|
|
150
|
-
checkSummaryEvent(output[1]);
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
144
|
it('can include reason in feature event', async () => {
|
|
155
|
-
const config = { ...defaultConfig
|
|
145
|
+
const config = { ...defaultConfig };
|
|
156
146
|
const reason = { kind: 'FALLTHROUGH' };
|
|
157
147
|
await withProcessorAndSender(config, async (ep, mockEventSender) => {
|
|
158
148
|
const event = {
|
|
159
149
|
kind: 'feature',
|
|
160
150
|
creationDate: 1000,
|
|
161
151
|
key: 'flagkey',
|
|
162
|
-
|
|
152
|
+
context: eventContext,
|
|
163
153
|
trackEvents: true,
|
|
164
154
|
reason: reason,
|
|
165
155
|
};
|
|
@@ -169,28 +159,7 @@ describe('EventProcessor', () => {
|
|
|
169
159
|
expect(mockEventSender.calls.length()).toEqual(1);
|
|
170
160
|
const output = (await mockEventSender.calls.take()).events;
|
|
171
161
|
expect(output.length).toEqual(2);
|
|
172
|
-
checkFeatureEvent(output[0], event, false
|
|
173
|
-
checkSummaryEvent(output[1]);
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('filters user in feature event', async () => {
|
|
178
|
-
const config = { ...defaultConfig, allAttributesPrivate: true, inlineUsersInEvents: true };
|
|
179
|
-
await withProcessorAndSender(config, async (ep, mockEventSender) => {
|
|
180
|
-
const event = {
|
|
181
|
-
kind: 'feature',
|
|
182
|
-
creationDate: 1000,
|
|
183
|
-
key: 'flagkey',
|
|
184
|
-
user: user,
|
|
185
|
-
trackEvents: true,
|
|
186
|
-
};
|
|
187
|
-
ep.enqueue(event);
|
|
188
|
-
await ep.flush();
|
|
189
|
-
|
|
190
|
-
expect(mockEventSender.calls.length()).toEqual(1);
|
|
191
|
-
const output = (await mockEventSender.calls.take()).events;
|
|
192
|
-
expect(output.length).toEqual(2);
|
|
193
|
-
checkFeatureEvent(output[0], event, false, filteredUser);
|
|
162
|
+
checkFeatureEvent(output[0], event, false);
|
|
194
163
|
checkSummaryEvent(output[1]);
|
|
195
164
|
});
|
|
196
165
|
});
|
|
@@ -201,7 +170,7 @@ describe('EventProcessor', () => {
|
|
|
201
170
|
const e = {
|
|
202
171
|
kind: 'feature',
|
|
203
172
|
creationDate: 1000,
|
|
204
|
-
|
|
173
|
+
context: eventContext,
|
|
205
174
|
key: 'flagkey',
|
|
206
175
|
version: 11,
|
|
207
176
|
variation: 1,
|
|
@@ -215,7 +184,7 @@ describe('EventProcessor', () => {
|
|
|
215
184
|
expect(mockEventSender.calls.length()).toEqual(1);
|
|
216
185
|
const output = (await mockEventSender.calls.take()).events;
|
|
217
186
|
expect(output.length).toEqual(2);
|
|
218
|
-
checkFeatureEvent(output[0], e, true, user);
|
|
187
|
+
checkFeatureEvent(output[0], e, true, { ...context, kind: context.kind || 'user' });
|
|
219
188
|
checkSummaryEvent(output[1]);
|
|
220
189
|
});
|
|
221
190
|
});
|
|
@@ -227,7 +196,7 @@ describe('EventProcessor', () => {
|
|
|
227
196
|
const e = {
|
|
228
197
|
kind: 'feature',
|
|
229
198
|
creationDate: 1000,
|
|
230
|
-
|
|
199
|
+
context: eventContext,
|
|
231
200
|
key: 'flagkey',
|
|
232
201
|
version: 11,
|
|
233
202
|
variation: 1,
|
|
@@ -242,7 +211,7 @@ describe('EventProcessor', () => {
|
|
|
242
211
|
expect(mockEventSender.calls.length()).toEqual(1);
|
|
243
212
|
const output = (await mockEventSender.calls.take()).events;
|
|
244
213
|
expect(output.length).toEqual(2);
|
|
245
|
-
checkFeatureEvent(output[0], e, true,
|
|
214
|
+
checkFeatureEvent(output[0], e, true, filteredContext);
|
|
246
215
|
checkSummaryEvent(output[1]);
|
|
247
216
|
});
|
|
248
217
|
});
|
|
@@ -253,7 +222,7 @@ describe('EventProcessor', () => {
|
|
|
253
222
|
const e = {
|
|
254
223
|
kind: 'feature',
|
|
255
224
|
creationDate: 1000,
|
|
256
|
-
|
|
225
|
+
context: eventContext,
|
|
257
226
|
key: 'flagkey',
|
|
258
227
|
version: 11,
|
|
259
228
|
variation: 1,
|
|
@@ -268,7 +237,7 @@ describe('EventProcessor', () => {
|
|
|
268
237
|
const output = (await mockEventSender.calls.take()).events;
|
|
269
238
|
expect(output.length).toEqual(3);
|
|
270
239
|
checkFeatureEvent(output[0], e, false);
|
|
271
|
-
checkFeatureEvent(output[1], e, true, user);
|
|
240
|
+
checkFeatureEvent(output[1], e, true, { ...context, kind: context.kind || 'user' });
|
|
272
241
|
checkSummaryEvent(output[2]);
|
|
273
242
|
});
|
|
274
243
|
});
|
|
@@ -280,7 +249,7 @@ describe('EventProcessor', () => {
|
|
|
280
249
|
mockEventSender.setServerTime(serverTime);
|
|
281
250
|
|
|
282
251
|
// Send and flush an event we don't care about, just to set the last server time
|
|
283
|
-
ep.enqueue({ kind: 'identify',
|
|
252
|
+
ep.enqueue({ kind: 'identify', context: { key: 'otherUser' } });
|
|
284
253
|
await ep.flush();
|
|
285
254
|
|
|
286
255
|
// Now send an event with debug mode on, with a "debug until" time that is further in
|
|
@@ -289,7 +258,7 @@ describe('EventProcessor', () => {
|
|
|
289
258
|
const e = {
|
|
290
259
|
kind: 'feature',
|
|
291
260
|
creationDate: 1000,
|
|
292
|
-
|
|
261
|
+
context: eventContext,
|
|
293
262
|
key: 'flagkey',
|
|
294
263
|
version: 11,
|
|
295
264
|
variation: 1,
|
|
@@ -316,7 +285,7 @@ describe('EventProcessor', () => {
|
|
|
316
285
|
mockEventSender.setServerTime(serverTime);
|
|
317
286
|
|
|
318
287
|
// Send and flush an event we don't care about, just to set the last server time
|
|
319
|
-
ep.enqueue({ kind: 'identify',
|
|
288
|
+
ep.enqueue({ kind: 'identify', context: { key: 'otherUser' } });
|
|
320
289
|
await ep.flush();
|
|
321
290
|
|
|
322
291
|
// Now send an event with debug mode on, with a "debug until" time that is further in
|
|
@@ -325,7 +294,7 @@ describe('EventProcessor', () => {
|
|
|
325
294
|
const e = {
|
|
326
295
|
kind: 'feature',
|
|
327
296
|
creationDate: 1000,
|
|
328
|
-
|
|
297
|
+
context: eventContext,
|
|
329
298
|
key: 'flagkey',
|
|
330
299
|
version: 11,
|
|
331
300
|
variation: 1,
|
|
@@ -351,7 +320,7 @@ describe('EventProcessor', () => {
|
|
|
351
320
|
return {
|
|
352
321
|
kind: 'feature',
|
|
353
322
|
creationDate: date,
|
|
354
|
-
|
|
323
|
+
context: eventContext,
|
|
355
324
|
key: key,
|
|
356
325
|
version: version,
|
|
357
326
|
variation: variation,
|
|
@@ -391,7 +360,7 @@ describe('EventProcessor', () => {
|
|
|
391
360
|
const e = {
|
|
392
361
|
kind: 'custom',
|
|
393
362
|
creationDate: 1000,
|
|
394
|
-
|
|
363
|
+
context: eventContext,
|
|
395
364
|
key: 'eventkey',
|
|
396
365
|
data: { thing: 'stuff' },
|
|
397
366
|
metricValue: 1.5,
|
|
@@ -406,51 +375,11 @@ describe('EventProcessor', () => {
|
|
|
406
375
|
});
|
|
407
376
|
});
|
|
408
377
|
|
|
409
|
-
it('can include inline user in custom event', async () => {
|
|
410
|
-
const config = { ...defaultConfig, inlineUsersInEvents: true };
|
|
411
|
-
await withProcessorAndSender(config, async (ep, mockEventSender) => {
|
|
412
|
-
const e = {
|
|
413
|
-
kind: 'custom',
|
|
414
|
-
creationDate: 1000,
|
|
415
|
-
user: user,
|
|
416
|
-
key: 'eventkey',
|
|
417
|
-
data: { thing: 'stuff' },
|
|
418
|
-
};
|
|
419
|
-
ep.enqueue(e);
|
|
420
|
-
await ep.flush();
|
|
421
|
-
|
|
422
|
-
expect(mockEventSender.calls.length()).toEqual(1);
|
|
423
|
-
const output = (await mockEventSender.calls.take()).events;
|
|
424
|
-
expect(output.length).toEqual(1);
|
|
425
|
-
checkCustomEvent(output[0], e, user);
|
|
426
|
-
});
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
it('filters user in custom event', async () => {
|
|
430
|
-
const config = { ...defaultConfig, allAttributesPrivate: true, inlineUsersInEvents: true };
|
|
431
|
-
await withProcessorAndSender(config, async (ep, mockEventSender) => {
|
|
432
|
-
const e = {
|
|
433
|
-
kind: 'custom',
|
|
434
|
-
creationDate: 1000,
|
|
435
|
-
user: user,
|
|
436
|
-
key: 'eventkey',
|
|
437
|
-
data: { thing: 'stuff' },
|
|
438
|
-
};
|
|
439
|
-
ep.enqueue(e);
|
|
440
|
-
await ep.flush();
|
|
441
|
-
|
|
442
|
-
expect(mockEventSender.calls.length()).toEqual(1);
|
|
443
|
-
const output = (await mockEventSender.calls.take()).events;
|
|
444
|
-
expect(output.length).toEqual(1);
|
|
445
|
-
checkCustomEvent(output[0], e, filteredUser);
|
|
446
|
-
});
|
|
447
|
-
});
|
|
448
|
-
|
|
449
378
|
it('enforces event capacity', async () => {
|
|
450
379
|
const config = { ...defaultConfig, eventCapacity: 1, logger: stubPlatform.logger() };
|
|
451
|
-
const e0 = { kind: 'custom', creationDate: 1000,
|
|
452
|
-
const e1 = { kind: 'custom', creationDate: 1001,
|
|
453
|
-
const e2 = { kind: 'custom', creationDate: 1002,
|
|
380
|
+
const e0 = { kind: 'custom', creationDate: 1000, context: eventContext, key: 'key0' };
|
|
381
|
+
const e1 = { kind: 'custom', creationDate: 1001, context: eventContext, key: 'key1' };
|
|
382
|
+
const e2 = { kind: 'custom', creationDate: 1002, context: eventContext, key: 'key2' };
|
|
454
383
|
await withProcessorAndSender(config, async (ep, mockEventSender) => {
|
|
455
384
|
ep.enqueue(e0);
|
|
456
385
|
ep.enqueue(e1);
|
|
@@ -475,7 +404,7 @@ describe('EventProcessor', () => {
|
|
|
475
404
|
|
|
476
405
|
async function verifyUnrecoverableHttpError(status) {
|
|
477
406
|
await withProcessorAndSender(defaultConfig, async (ep, mockEventSender) => {
|
|
478
|
-
const e = { kind: 'identify', creationDate: 1000,
|
|
407
|
+
const e = { kind: 'identify', creationDate: 1000, context: eventContext };
|
|
479
408
|
ep.enqueue(e);
|
|
480
409
|
mockEventSender.setStatus(status);
|
|
481
410
|
await ep.flush();
|
|
@@ -490,7 +419,7 @@ describe('EventProcessor', () => {
|
|
|
490
419
|
|
|
491
420
|
async function verifyRecoverableHttpError(status) {
|
|
492
421
|
await withProcessorAndSender(defaultConfig, async (ep, mockEventSender) => {
|
|
493
|
-
const e = { kind: 'identify', creationDate: 1000,
|
|
422
|
+
const e = { kind: 'identify', creationDate: 1000, context: eventContext };
|
|
494
423
|
ep.enqueue(e);
|
|
495
424
|
mockEventSender.setStatus(status);
|
|
496
425
|
await ep.flush();
|
|
@@ -517,8 +446,8 @@ describe('EventProcessor', () => {
|
|
|
517
446
|
|
|
518
447
|
describe('interaction with diagnostic events', () => {
|
|
519
448
|
it('sets eventsInLastBatch on flush', async () => {
|
|
520
|
-
const e0 = { kind: 'custom', creationDate: 1000,
|
|
521
|
-
const e1 = { kind: 'custom', creationDate: 1001,
|
|
449
|
+
const e0 = { kind: 'custom', creationDate: 1000, context: eventContext, key: 'key0' };
|
|
450
|
+
const e1 = { kind: 'custom', creationDate: 1001, context: eventContext, key: 'key1' };
|
|
522
451
|
await withDiagnosticProcessorAndSender(defaultConfig, async (ep, mockEventSender, diagnosticAccumulator) => {
|
|
523
452
|
expect(diagnosticAccumulator.getProps().eventsInLastBatch).toEqual(0);
|
|
524
453
|
|
|
@@ -536,9 +465,9 @@ describe('EventProcessor', () => {
|
|
|
536
465
|
|
|
537
466
|
it('increments droppedEvents when capacity is exceeded', async () => {
|
|
538
467
|
const config = { ...defaultConfig, eventCapacity: 1, logger: stubPlatform.logger() };
|
|
539
|
-
const e0 = { kind: 'custom', creationDate: 1000,
|
|
540
|
-
const e1 = { kind: 'custom', creationDate: 1001,
|
|
541
|
-
const e2 = { kind: 'custom', creationDate: 1002,
|
|
468
|
+
const e0 = { kind: 'custom', creationDate: 1000, context: eventContext, key: 'key0' };
|
|
469
|
+
const e1 = { kind: 'custom', creationDate: 1001, context: eventContext, key: 'key1' };
|
|
470
|
+
const e2 = { kind: 'custom', creationDate: 1002, context: eventContext, key: 'key2' };
|
|
542
471
|
await withDiagnosticProcessorAndSender(config, async (ep, mockEventSender, diagnosticAccumulator) => {
|
|
543
472
|
ep.enqueue(e0);
|
|
544
473
|
ep.enqueue(e1);
|
|
@@ -50,26 +50,7 @@ describe('LDClient events', () => {
|
|
|
50
50
|
|
|
51
51
|
function expectIdentifyEvent(e, user) {
|
|
52
52
|
expect(e.kind).toEqual('identify');
|
|
53
|
-
expect(e.
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function expectAliasEvent(e, user, previousUser) {
|
|
57
|
-
function userContextKind(user) {
|
|
58
|
-
return user.anonymous ? 'anonymousUser' : 'user';
|
|
59
|
-
}
|
|
60
|
-
expect(e.kind).toEqual('alias');
|
|
61
|
-
expect(e.key).toEqual(user.key);
|
|
62
|
-
expect(e.previousKey).toEqual(previousUser.key);
|
|
63
|
-
expect(e.contextKind).toEqual(userContextKind(user));
|
|
64
|
-
expect(e.previousContextKind).toEqual(userContextKind(previousUser));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function expectContextKindInEvent(e, user) {
|
|
68
|
-
if (user.anonymous) {
|
|
69
|
-
expect(e.contextKind).toEqual('anonymousUser');
|
|
70
|
-
} else {
|
|
71
|
-
expect(e.contextKind).toBe(undefined);
|
|
72
|
-
}
|
|
53
|
+
expect(e.context).toEqual(user);
|
|
73
54
|
}
|
|
74
55
|
|
|
75
56
|
function expectFeatureEvent({
|
|
@@ -91,7 +72,7 @@ describe('LDClient events', () => {
|
|
|
91
72
|
expect(e.default).toEqual(defaultVal);
|
|
92
73
|
expect(e.trackEvents).toEqual(trackEvents);
|
|
93
74
|
expect(e.debugEventsUntilDate).toEqual(debugEventsUntilDate);
|
|
94
|
-
|
|
75
|
+
expect(e.context).toEqual(user);
|
|
95
76
|
}
|
|
96
77
|
|
|
97
78
|
it('sends an identify event at startup', async () => {
|
|
@@ -129,126 +110,6 @@ describe('LDClient events', () => {
|
|
|
129
110
|
});
|
|
130
111
|
});
|
|
131
112
|
|
|
132
|
-
it('sends an alias event when alias() is called', async () => {
|
|
133
|
-
await withClientAndEventProcessor(user, {}, async (client, ep) => {
|
|
134
|
-
const anon1 = { key: 'user1', anonymous: true };
|
|
135
|
-
const anon2 = { key: 'user2', anonymous: true };
|
|
136
|
-
const known1 = { key: 'user3' };
|
|
137
|
-
const known2 = { key: 'user4' };
|
|
138
|
-
await client.waitForInitialization();
|
|
139
|
-
expect(ep.events.length).toEqual(1);
|
|
140
|
-
|
|
141
|
-
await client.alias(anon2, anon1);
|
|
142
|
-
expectAliasEvent(ep.events[1], anon2, anon1);
|
|
143
|
-
|
|
144
|
-
await client.alias(known1, anon1);
|
|
145
|
-
expectAliasEvent(ep.events[2], known1, anon1);
|
|
146
|
-
|
|
147
|
-
await client.alias(known2, known1);
|
|
148
|
-
expectAliasEvent(ep.events[3], known2, known1);
|
|
149
|
-
|
|
150
|
-
await client.alias(anon1, known1);
|
|
151
|
-
expectAliasEvent(ep.events[4], anon1, known1);
|
|
152
|
-
|
|
153
|
-
expect(ep.events.length).toEqual(5);
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('sends an alias event when identify() is called for anon to known', async () => {
|
|
158
|
-
// need a server because it'll do a polling request when we call identify
|
|
159
|
-
await withServer(async server => {
|
|
160
|
-
const anonUser = { key: 'anon-user', anonymous: true };
|
|
161
|
-
const knownUser = { key: 'known-user' };
|
|
162
|
-
await withClientAndEventProcessor(anonUser, { baseUrl: server.url }, async (client, ep) => {
|
|
163
|
-
await client.waitForInitialization();
|
|
164
|
-
|
|
165
|
-
expect(ep.events.length).toEqual(1);
|
|
166
|
-
expectIdentifyEvent(ep.events[0], anonUser);
|
|
167
|
-
|
|
168
|
-
await client.identify(knownUser);
|
|
169
|
-
expect(ep.events.length).toEqual(3);
|
|
170
|
-
expectIdentifyEvent(ep.events[1], knownUser);
|
|
171
|
-
expectAliasEvent(ep.events[2], knownUser, anonUser);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('does not send an alias event when identify() is called if auto-aliasing is disabled', async () => {
|
|
177
|
-
// need a server because it'll do a polling request when we call identify
|
|
178
|
-
await withServer(async server => {
|
|
179
|
-
const anonUser = { key: 'anon-user', anonymous: true };
|
|
180
|
-
const knownUser = { key: 'known-user' };
|
|
181
|
-
await withClientAndEventProcessor(
|
|
182
|
-
anonUser,
|
|
183
|
-
{ baseUrl: server.url, autoAliasingOptOut: true },
|
|
184
|
-
async (client, ep) => {
|
|
185
|
-
await client.waitForInitialization();
|
|
186
|
-
|
|
187
|
-
expect(ep.events.length).toEqual(1);
|
|
188
|
-
expectIdentifyEvent(ep.events[0], anonUser);
|
|
189
|
-
|
|
190
|
-
await client.identify(knownUser);
|
|
191
|
-
expect(ep.events.length).toEqual(2); //no additional alias events
|
|
192
|
-
expectIdentifyEvent(ep.events[1], knownUser);
|
|
193
|
-
}
|
|
194
|
-
);
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('does not send an alias event when identify() is called for known to anon', async () => {
|
|
199
|
-
// need a server because it'll do a polling request when we call identify
|
|
200
|
-
await withServer(async server => {
|
|
201
|
-
const knownUser = { key: 'known-user' };
|
|
202
|
-
const anonUser = { key: 'anon-user', anonymous: true };
|
|
203
|
-
await withClientAndEventProcessor(knownUser, { baseUrl: server.url }, async (client, ep) => {
|
|
204
|
-
await client.waitForInitialization();
|
|
205
|
-
|
|
206
|
-
expect(ep.events.length).toEqual(1);
|
|
207
|
-
expectIdentifyEvent(ep.events[0], knownUser);
|
|
208
|
-
|
|
209
|
-
await client.identify(anonUser);
|
|
210
|
-
expect(ep.events.length).toEqual(2); //no additional alias events
|
|
211
|
-
expectIdentifyEvent(ep.events[1], anonUser);
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('does not send an alias event when identify() is called for anon to anon', async () => {
|
|
217
|
-
// need a server because it'll do a polling request when we call identify
|
|
218
|
-
await withServer(async server => {
|
|
219
|
-
const anonUser1 = { key: 'anon-user1', anonymous: true };
|
|
220
|
-
const anonUser2 = { key: 'anon-user2', anonymous: true };
|
|
221
|
-
await withClientAndEventProcessor(anonUser1, { baseUrl: server.url }, async (client, ep) => {
|
|
222
|
-
await client.waitForInitialization();
|
|
223
|
-
|
|
224
|
-
expect(ep.events.length).toEqual(1);
|
|
225
|
-
expectIdentifyEvent(ep.events[0], anonUser1);
|
|
226
|
-
|
|
227
|
-
await client.identify(anonUser2);
|
|
228
|
-
expect(ep.events.length).toEqual(2); //no additional alias events
|
|
229
|
-
expectIdentifyEvent(ep.events[1], anonUser2);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it('does not send an alias event when identify() is called for known to known', async () => {
|
|
235
|
-
// need a server because it'll do a polling request when we call identify
|
|
236
|
-
await withServer(async server => {
|
|
237
|
-
const knownUser1 = { key: 'known-user1' };
|
|
238
|
-
const knownUser2 = { key: 'known-user2' };
|
|
239
|
-
await withClientAndEventProcessor(knownUser1, { baseUrl: server.url }, async (client, ep) => {
|
|
240
|
-
await client.waitForInitialization();
|
|
241
|
-
|
|
242
|
-
expect(ep.events.length).toEqual(1);
|
|
243
|
-
expectIdentifyEvent(ep.events[0], knownUser1);
|
|
244
|
-
|
|
245
|
-
await client.identify(knownUser2);
|
|
246
|
-
expect(ep.events.length).toEqual(2); //no additional alias events
|
|
247
|
-
expectIdentifyEvent(ep.events[1], knownUser2);
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
|
|
252
113
|
it('stringifies user attributes in the identify event when identify() is called', async () => {
|
|
253
114
|
// This just verifies that the event is being sent with the sanitized user, not the user that was passed in
|
|
254
115
|
await withServer(async server => {
|
|
@@ -435,7 +296,7 @@ describe('LDClient events', () => {
|
|
|
435
296
|
it('does not send a feature event for a new flag value if there is a state provider', async () => {
|
|
436
297
|
const oldFlags = { foo: { value: 'a', variation: 1, version: 2, flagVersion: 2000 } };
|
|
437
298
|
const newFlags = { foo: { value: 'b', variation: 2, version: 3, flagVersion: 2001 } };
|
|
438
|
-
const sp = stubPlatform.mockStateProvider({ environment: envName,
|
|
299
|
+
const sp = stubPlatform.mockStateProvider({ environment: envName, context: user, flags: oldFlags });
|
|
439
300
|
await withServer(async server => {
|
|
440
301
|
server.byDefault(respondJson(newFlags));
|
|
441
302
|
const extraConfig = { stateProvider: sp, baseUrl: server.url };
|
|
@@ -546,10 +407,9 @@ describe('LDClient events', () => {
|
|
|
546
407
|
const trackEvent = ep.events[1];
|
|
547
408
|
expect(trackEvent.kind).toEqual('custom');
|
|
548
409
|
expect(trackEvent.key).toEqual('eventkey');
|
|
549
|
-
expect(trackEvent.
|
|
410
|
+
expect(trackEvent.context).toEqual(user);
|
|
550
411
|
expect(trackEvent.data).toEqual(undefined);
|
|
551
412
|
expect(trackEvent.url).toEqual(fakeUrl);
|
|
552
|
-
expectContextKindInEvent(trackEvent, user);
|
|
553
413
|
});
|
|
554
414
|
});
|
|
555
415
|
|
|
@@ -565,10 +425,9 @@ describe('LDClient events', () => {
|
|
|
565
425
|
const trackEvent = ep.events[1];
|
|
566
426
|
expect(trackEvent.kind).toEqual('custom');
|
|
567
427
|
expect(trackEvent.key).toEqual('eventkey');
|
|
568
|
-
expect(trackEvent.
|
|
428
|
+
expect(trackEvent.context).toEqual(anonUser);
|
|
569
429
|
expect(trackEvent.data).toEqual(undefined);
|
|
570
430
|
expect(trackEvent.url).toEqual(fakeUrl);
|
|
571
|
-
expectContextKindInEvent(trackEvent, anonUser);
|
|
572
431
|
});
|
|
573
432
|
});
|
|
574
433
|
});
|
|
@@ -584,10 +443,9 @@ describe('LDClient events', () => {
|
|
|
584
443
|
const trackEvent = ep.events[1];
|
|
585
444
|
expect(trackEvent.kind).toEqual('custom');
|
|
586
445
|
expect(trackEvent.key).toEqual('eventkey');
|
|
587
|
-
expect(trackEvent.
|
|
446
|
+
expect(trackEvent.context).toEqual(user);
|
|
588
447
|
expect(trackEvent.data).toEqual(eventData);
|
|
589
448
|
expect(trackEvent.url).toEqual(fakeUrl);
|
|
590
|
-
expectContextKindInEvent(trackEvent, user);
|
|
591
449
|
});
|
|
592
450
|
});
|
|
593
451
|
|
|
@@ -603,11 +461,10 @@ describe('LDClient events', () => {
|
|
|
603
461
|
const trackEvent = ep.events[1];
|
|
604
462
|
expect(trackEvent.kind).toEqual('custom');
|
|
605
463
|
expect(trackEvent.key).toEqual('eventkey');
|
|
606
|
-
expect(trackEvent.
|
|
464
|
+
expect(trackEvent.context).toEqual(user);
|
|
607
465
|
expect(trackEvent.data).toEqual(eventData);
|
|
608
466
|
expect(trackEvent.metricValue).toEqual(metricValue);
|
|
609
467
|
expect(trackEvent.url).toEqual(fakeUrl);
|
|
610
|
-
expectContextKindInEvent(trackEvent, user);
|
|
611
468
|
});
|
|
612
469
|
});
|
|
613
470
|
|
|
@@ -646,12 +503,12 @@ describe('LDClient events', () => {
|
|
|
646
503
|
it('should warn about missing user on first event', async () => {
|
|
647
504
|
await withClientAndEventProcessor(null, {}, async client => {
|
|
648
505
|
client.track('eventkey', null);
|
|
649
|
-
expect(platform.testing.logger.output.warn).toEqual([messages.
|
|
506
|
+
expect(platform.testing.logger.output.warn).toEqual([messages.eventWithoutContext()]);
|
|
650
507
|
});
|
|
651
508
|
});
|
|
652
509
|
|
|
653
510
|
it('allows stateProvider to take over sending an event', async () => {
|
|
654
|
-
const sp = stubPlatform.mockStateProvider({ environment: envName,
|
|
511
|
+
const sp = stubPlatform.mockStateProvider({ environment: envName, context: user, flags: {} });
|
|
655
512
|
const divertedEvents = [];
|
|
656
513
|
sp.enqueueEvent = event => divertedEvents.push(event);
|
|
657
514
|
|
|
@@ -59,7 +59,7 @@ describe('given a streaming client with registered inspectors', () => {
|
|
|
59
59
|
platform = stubPlatform.defaults();
|
|
60
60
|
const server = platform.testing.http.newServer();
|
|
61
61
|
server.byDefault(respondJson({}));
|
|
62
|
-
const config = { streaming: true, baseUrl: server.url, inspectors };
|
|
62
|
+
const config = { streaming: true, baseUrl: server.url, inspectors, sendEvents: false };
|
|
63
63
|
client = platform.testing.makeClient(envName, user, config);
|
|
64
64
|
await client.waitUntilReady();
|
|
65
65
|
});
|