Skip to content

Commit bcdf8f6

Browse files
prepare 3.3.0 release (#35)
1 parent 1912fdc commit bcdf8f6

File tree

8 files changed

+332
-20
lines changed

8 files changed

+332
-20
lines changed

src/EventProcessor.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ export default function EventProcessor(
4747
// Transform an event from its internal format to the format we use when sending a payload.
4848
function makeOutputEvent(e) {
4949
const ret = utils.extend({}, e);
50+
if (e.kind === 'alias') {
51+
// alias events do not require any transformation
52+
return ret;
53+
}
5054
if (inlineUsers || e.kind === 'identify') {
5155
// identify events always have an inline user
5256
ret.user = userFilter.filterUser(e.user);

src/Identity.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ export default function Identity(initialUser, onChange) {
55
let user;
66

77
ident.setUser = function(u) {
8+
const previousUser = user && utils.clone(user);
89
user = utils.sanitizeUser(u);
910
if (user && onChange) {
10-
onChange(utils.clone(user));
11+
onChange(utils.clone(user), previousUser);
1112
}
1213
};
1314

src/__tests__/LDClient-events-test.js

Lines changed: 250 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,36 @@ describe('LDClient events', () => {
5353
expect(e.user).toEqual(user);
5454
}
5555

56-
function expectFeatureEvent(e, key, value, variation, version, defaultVal, trackEvents, debugEventsUntilDate) {
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+
}
73+
}
74+
75+
function expectFeatureEvent({
76+
e,
77+
key,
78+
user,
79+
value,
80+
variation,
81+
version,
82+
defaultVal,
83+
trackEvents,
84+
debugEventsUntilDate,
85+
}) {
5786
expect(e.kind).toEqual('feature');
5887
expect(e.key).toEqual(key);
5988
expect(e.value).toEqual(value);
@@ -62,6 +91,7 @@ describe('LDClient events', () => {
6291
expect(e.default).toEqual(defaultVal);
6392
expect(e.trackEvents).toEqual(trackEvents);
6493
expect(e.debugEventsUntilDate).toEqual(debugEventsUntilDate);
94+
expectContextKindInEvent(e, user);
6595
}
6696

6797
it('sends an identify event at startup', async () => {
@@ -99,6 +129,126 @@ describe('LDClient events', () => {
99129
});
100130
});
101131

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+
102252
it('stringifies user attributes in the identify event when identify() is called', async () => {
103253
// This just verifies that the event is being sent with the sanitized user, not the user that was passed in
104254
await withServer(async server => {
@@ -137,7 +287,39 @@ describe('LDClient events', () => {
137287

138288
expect(ep.events.length).toEqual(2);
139289
expectIdentifyEvent(ep.events[0], user);
140-
expectFeatureEvent(ep.events[1], 'foo', 'a', 1, 2000, 'x');
290+
expectFeatureEvent({
291+
e: ep.events[1],
292+
key: 'foo',
293+
user,
294+
value: 'a',
295+
variation: 1,
296+
version: 2000,
297+
defaultVal: 'x',
298+
});
299+
});
300+
});
301+
302+
it('sends a feature event for variation() when user is anonymous', async () => {
303+
const initData = makeBootstrap({ foo: { value: 'a', variation: 1, version: 2, flagVersion: 2000 } });
304+
await withServer(async server => {
305+
const anonUser = { key: 'anon-user', anonymous: true };
306+
await withClientAndEventProcessor(anonUser, { baseUrl: server.url, bootstrap: initData }, async (client, ep) => {
307+
await client.waitForInitialization();
308+
309+
client.variation('foo', 'x');
310+
311+
expect(ep.events.length).toEqual(2);
312+
expectIdentifyEvent(ep.events[0], anonUser);
313+
expectFeatureEvent({
314+
e: ep.events[1],
315+
key: 'foo',
316+
user: anonUser,
317+
value: 'a',
318+
variation: 1,
319+
version: 2000,
320+
defaultVal: 'x',
321+
});
322+
});
141323
});
142324
});
143325

@@ -151,7 +333,15 @@ describe('LDClient events', () => {
151333

152334
expect(ep.events.length).toEqual(2);
153335
expectIdentifyEvent(ep.events[0], user);
154-
expectFeatureEvent(ep.events[1], 'foo', 'a', 1, 2000, 'x');
336+
expectFeatureEvent({
337+
e: ep.events[1],
338+
key: 'foo',
339+
user,
340+
value: 'a',
341+
variation: 1,
342+
version: 2000,
343+
defaultVal: 'x',
344+
});
155345
expect(ep.events[1].reason).toEqual({ kind: 'OFF' });
156346
});
157347
});
@@ -166,7 +356,15 @@ describe('LDClient events', () => {
166356

167357
expect(ep.events.length).toEqual(2);
168358
expectIdentifyEvent(ep.events[0], user);
169-
expectFeatureEvent(ep.events[1], 'foo', 'a', 1, 2000, 'x');
359+
expectFeatureEvent({
360+
e: ep.events[1],
361+
key: 'foo',
362+
user,
363+
value: 'a',
364+
variation: 1,
365+
version: 2000,
366+
defaultVal: 'x',
367+
});
170368
expect(ep.events[1].reason).toBe(undefined);
171369
});
172370
});
@@ -181,7 +379,15 @@ describe('LDClient events', () => {
181379

182380
expect(ep.events.length).toEqual(2);
183381
expectIdentifyEvent(ep.events[0], user);
184-
expectFeatureEvent(ep.events[1], 'foo', 'a', 1, 2000, 'x');
382+
expectFeatureEvent({
383+
e: ep.events[1],
384+
key: 'foo',
385+
user,
386+
value: 'a',
387+
variation: 1,
388+
version: 2000,
389+
defaultVal: 'x',
390+
});
185391
expect(ep.events[1].reason).toEqual({ kind: 'OFF' });
186392
});
187393
});
@@ -201,7 +407,7 @@ describe('LDClient events', () => {
201407
expect(ep.events.length).toEqual(3);
202408
expectIdentifyEvent(ep.events[0], user);
203409
expectIdentifyEvent(ep.events[1], user1);
204-
expectFeatureEvent(ep.events[2], 'foo', 'b', 2, 2001);
410+
expectFeatureEvent({ e: ep.events[2], key: 'foo', user: user1, value: 'b', variation: 2, version: 2001 });
205411
});
206412
});
207413
});
@@ -255,8 +461,8 @@ describe('LDClient events', () => {
255461

256462
expect(ep.events.length).toEqual(3);
257463
expectIdentifyEvent(ep.events[0], user);
258-
expectFeatureEvent(ep.events[1], 'foo', 'a', 1, 2, null);
259-
expectFeatureEvent(ep.events[2], 'bar', 'b', 1, 3, null);
464+
expectFeatureEvent({ e: ep.events[1], key: 'foo', user, value: 'a', variation: 1, version: 2, defaultVal: null });
465+
expectFeatureEvent({ e: ep.events[2], key: 'bar', user, value: 'b', variation: 1, version: 3, defaultVal: null });
260466
});
261467
});
262468

@@ -283,7 +489,7 @@ describe('LDClient events', () => {
283489

284490
expect(ep.events.length).toEqual(2);
285491
expectIdentifyEvent(ep.events[0], user);
286-
expectFeatureEvent(ep.events[1], 'foo', 'a', 1, 2, 'x');
492+
expectFeatureEvent({ e: ep.events[1], key: 'foo', user, value: 'a', variation: 1, version: 2, defaultVal: 'x' });
287493
});
288494
});
289495

@@ -294,7 +500,7 @@ describe('LDClient events', () => {
294500

295501
expect(ep.events.length).toEqual(2);
296502
expectIdentifyEvent(ep.events[0], user);
297-
expectFeatureEvent(ep.events[1], 'foo', 'x', null, undefined, 'x');
503+
expectFeatureEvent({ e: ep.events[1], key: 'foo', user, value: 'x', variation: null, defaultVal: 'x' });
298504
});
299505
});
300506

@@ -315,7 +521,17 @@ describe('LDClient events', () => {
315521

316522
expect(ep.events.length).toEqual(2);
317523
expectIdentifyEvent(ep.events[0], user);
318-
expectFeatureEvent(ep.events[1], 'foo', 'bar', 1, 2, 'x', true, 1000);
524+
expectFeatureEvent({
525+
e: ep.events[1],
526+
key: 'foo',
527+
value: 'bar',
528+
variation: 1,
529+
version: 2,
530+
defaultVal: 'x',
531+
trackEvents: true,
532+
debugEventsUntilDate: 1000,
533+
user,
534+
});
319535
});
320536
});
321537
});
@@ -333,6 +549,27 @@ describe('LDClient events', () => {
333549
expect(trackEvent.user).toEqual(user);
334550
expect(trackEvent.data).toEqual(undefined);
335551
expect(trackEvent.url).toEqual(fakeUrl);
552+
expectContextKindInEvent(trackEvent, user);
553+
});
554+
});
555+
556+
it('sends an event for track() when user is anonymous', async () => {
557+
await withServer(async server => {
558+
const anonUser = { key: 'anon-user', anonymous: true };
559+
await withClientAndEventProcessor(anonUser, { baseUrl: server.url }, async (client, ep) => {
560+
await client.waitForInitialization();
561+
client.track('eventkey');
562+
563+
expect(ep.events.length).toEqual(2);
564+
expectIdentifyEvent(ep.events[0], anonUser);
565+
const trackEvent = ep.events[1];
566+
expect(trackEvent.kind).toEqual('custom');
567+
expect(trackEvent.key).toEqual('eventkey');
568+
expect(trackEvent.user).toEqual(anonUser);
569+
expect(trackEvent.data).toEqual(undefined);
570+
expect(trackEvent.url).toEqual(fakeUrl);
571+
expectContextKindInEvent(trackEvent, anonUser);
572+
});
336573
});
337574
});
338575

@@ -350,6 +587,7 @@ describe('LDClient events', () => {
350587
expect(trackEvent.user).toEqual(user);
351588
expect(trackEvent.data).toEqual(eventData);
352589
expect(trackEvent.url).toEqual(fakeUrl);
590+
expectContextKindInEvent(trackEvent, user);
353591
});
354592
});
355593

@@ -369,6 +607,7 @@ describe('LDClient events', () => {
369607
expect(trackEvent.data).toEqual(eventData);
370608
expect(trackEvent.metricValue).toEqual(metricValue);
371609
expect(trackEvent.url).toEqual(fakeUrl);
610+
expectContextKindInEvent(trackEvent, user);
372611
});
373612
});
374613

0 commit comments

Comments
 (0)