Skip to content

Commit 2fd329f

Browse files
LaunchDarklyReleaseBoteli-darklyLaunchDarklyCIbwoskow-ldmsiadak
authored
prepare 5.2.0 release (#102)
## [5.2.0] - 2024-05-01 ### Added: - Added an optional timeout to the `waitForInitialization` method. When a timeout is specified the returned promise will be rejected after the timeout elapses if the client has not finished initializing within that time. When no timeout is specified the returned promise will not be resolved or rejected until the initialization either completes or fails. ### Changed: - The track method now validates that the provided metricValue is a number. If a metric value is provided, and it is not a number, then a warning will be logged. ### Fixed: - Fixed the documentation for `evaluationReasons` for the `identify` method. --------- Co-authored-by: Eli Bishop <eli@launchdarkly.com> Co-authored-by: LaunchDarklyCI <dev@launchdarkly.com> Co-authored-by: Ben Woskow <48036130+bwoskow-ld@users.noreply.github.com> Co-authored-by: Michael Siadak <mike.siadak@gmail.com> Co-authored-by: Ben Woskow <bwoskow@launchdarkly.com> Co-authored-by: Jeff Wen <sinchangwen@gmail.com> Co-authored-by: Andrey Krasnov <34657799+Doesntmeananything@users.noreply.github.com> Co-authored-by: Gavin Whelan <gwhelan@launchdarkly.com> Co-authored-by: LaunchDarklyReleaseBot <launchdarklyreleasebot@launchdarkly.com> Co-authored-by: Louis Chan <lchan@launchdarkly.com> Co-authored-by: Louis Chan <91093020+louis-launchdarkly@users.noreply.github.com> Co-authored-by: Zach Davis <zach@launchdarkly.com> Co-authored-by: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Co-authored-by: Mateusz Sikora <mateusz.sikora@ramp.network> Co-authored-by: Yusinto Ngadiman <yus@launchdarkly.com> Co-authored-by: Yusinto Ngadiman <yusinto@gmail.com> Co-authored-by: Ember Stevens <ember.stevens@launchdarkly.com> Co-authored-by: Ember Stevens <79482775+ember-stevens@users.noreply.github.com> Co-authored-by: ld-repository-standards[bot] <113625520+ld-repository-standards[bot]@users.noreply.github.com> Co-authored-by: Kane Parkinson <93555788+kparkinson-ld@users.noreply.github.com> Co-authored-by: Matthew M. Keeler <mkeeler@launchdarkly.com> Co-authored-by: Molly <molly.jones@launchdarkly.com>
1 parent 0c4a8c0 commit 2fd329f

17 files changed

+380
-194
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@
3838
"eslint-formatter-pretty": "^1.3.0",
3939
"eslint-plugin-babel": "^5.0.0",
4040
"eslint-plugin-prettier": "^2.6.0",
41-
"jest": "^25.5.4",
41+
"jest": "^26.6.3",
4242
"jsdom": "^11.11.0",
4343
"launchdarkly-js-test-helpers": "1.1.0",
44-
"prettier": "1.11.1",
44+
"prettier": "1.19.1",
4545
"readline-sync": "^1.4.9",
4646
"typescript": "~4.4.4"
4747
},

src/ContextFilter.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ function ContextFilter(config) {
118118
filtered._meta = filtered._meta || {};
119119
// If any private attributes started with '/' we need to convert them to references, otherwise the '/' will
120120
// cause the literal to incorrectly be treated as a reference.
121-
filtered._meta.privateAttributes = user.privateAttributeNames.map(
122-
literal => (literal.startsWith('/') ? AttributeReference.literalToReference(literal) : literal)
121+
filtered._meta.privateAttributes = user.privateAttributeNames.map(literal =>
122+
literal.startsWith('/') ? AttributeReference.literalToReference(literal) : literal
123123
);
124124
}
125125

src/__tests__/EventProcessor-test.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import { MockEventSender } from './testUtils';
1010
// tests; here, we use a mock EventSender.
1111

1212
describe.each([
13-
[{ key: 'userKey', name: 'Red' }, { key: 'userKey', kind: 'user', _meta: { redactedAttributes: ['/name'] } }],
13+
[
14+
{ key: 'userKey', name: 'Red' },
15+
{ key: 'userKey', kind: 'user', _meta: { redactedAttributes: ['/name'] } },
16+
],
1417
[
1518
{ kind: 'user', key: 'userKey', name: 'Red' },
1619
{ key: 'userKey', kind: 'user', _meta: { redactedAttributes: ['/name'] } },

src/__tests__/EventSummarizer-test.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ describe('EventSummarizer', () => {
9999
key1: {
100100
contextKinds: ['user'],
101101
default: 111,
102-
counters: [{ variation: 0, value: 100, version: 11, count: 1 }, { value: 111, version: 11, count: 2 }],
102+
counters: [
103+
{ variation: 0, value: 100, version: 11, count: 1 },
104+
{ value: 111, version: 11, count: 2 },
105+
],
103106
},
104107
};
105108
expect(data.features).toEqual(expectedFeatures);

src/__tests__/LDClient-events-test.js

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ describe('LDClient events', () => {
7777

7878
it('sends an identify event at startup', async () => {
7979
await withClientAndEventProcessor(user, {}, async (client, ep) => {
80-
await client.waitForInitialization();
80+
await client.waitForInitialization(5);
8181

8282
expect(ep.events.length).toEqual(1);
8383
expectIdentifyEvent(ep.events[0], user);
@@ -87,7 +87,7 @@ describe('LDClient events', () => {
8787
it('stringifies user attributes in the identify event at startup', async () => {
8888
// This just verifies that the event is being sent with the sanitized user, not the user that was passed in
8989
await withClientAndEventProcessor(numericUser, {}, async (client, ep) => {
90-
await client.waitForInitialization();
90+
await client.waitForInitialization(5);
9191

9292
expect(ep.events.length).toEqual(1);
9393
expectIdentifyEvent(ep.events[0], stringifiedNumericUser);
@@ -99,7 +99,7 @@ describe('LDClient events', () => {
9999
await withServer(async server => {
100100
await withClientAndEventProcessor(user, { baseUrl: server.url }, async (client, ep) => {
101101
const user1 = { key: 'user1' };
102-
await client.waitForInitialization();
102+
await client.waitForInitialization(5);
103103

104104
expect(ep.events.length).toEqual(1);
105105
await client.identify(user1);
@@ -114,7 +114,7 @@ describe('LDClient events', () => {
114114
// This just verifies that the event is being sent with the sanitized user, not the user that was passed in
115115
await withServer(async server => {
116116
await withClientAndEventProcessor(user, { baseUrl: server.url }, async (client, ep) => {
117-
await client.waitForInitialization();
117+
await client.waitForInitialization(5);
118118

119119
expect(ep.events.length).toEqual(1);
120120
await client.identify(numericUser);
@@ -131,7 +131,7 @@ describe('LDClient events', () => {
131131
await withClientAndEventProcessor(user, { baseUrl: server.url }, async (client, ep) => {
132132
const user1 = { key: 'user1' };
133133

134-
await client.waitForInitialization();
134+
await client.waitForInitialization(5);
135135
await client.identify(user1);
136136

137137
expect(ep.events.length).toEqual(0);
@@ -142,7 +142,7 @@ describe('LDClient events', () => {
142142
it('sends a feature event for variation()', async () => {
143143
const initData = makeBootstrap({ foo: { value: 'a', variation: 1, version: 2, flagVersion: 2000 } });
144144
await withClientAndEventProcessor(user, { bootstrap: initData }, async (client, ep) => {
145-
await client.waitForInitialization();
145+
await client.waitForInitialization(5);
146146

147147
client.variation('foo', 'x');
148148

@@ -165,7 +165,7 @@ describe('LDClient events', () => {
165165
await withServer(async server => {
166166
const anonUser = { key: 'anon-user', anonymous: true };
167167
await withClientAndEventProcessor(anonUser, { baseUrl: server.url, bootstrap: initData }, async (client, ep) => {
168-
await client.waitForInitialization();
168+
await client.waitForInitialization(5);
169169

170170
client.variation('foo', 'x');
171171

@@ -189,7 +189,7 @@ describe('LDClient events', () => {
189189
foo: { value: 'a', variation: 1, version: 2, flagVersion: 2000, reason: { kind: 'OFF' } },
190190
});
191191
await withClientAndEventProcessor(user, { bootstrap: initData }, async (client, ep) => {
192-
await client.waitForInitialization();
192+
await client.waitForInitialization(5);
193193
client.variationDetail('foo', 'x');
194194

195195
expect(ep.events.length).toEqual(2);
@@ -212,7 +212,7 @@ describe('LDClient events', () => {
212212
foo: { value: 'a', variation: 1, version: 2, flagVersion: 2000, reason: { kind: 'OFF' } },
213213
});
214214
await withClientAndEventProcessor(user, { bootstrap: initData }, async (client, ep) => {
215-
await client.waitForInitialization();
215+
await client.waitForInitialization(5);
216216
client.variation('foo', 'x');
217217

218218
expect(ep.events.length).toEqual(2);
@@ -235,7 +235,7 @@ describe('LDClient events', () => {
235235
foo: { value: 'a', variation: 1, version: 2, flagVersion: 2000, reason: { kind: 'OFF' }, trackReason: true },
236236
});
237237
await withClientAndEventProcessor(user, { bootstrap: initData }, async (client, ep) => {
238-
await client.waitForInitialization();
238+
await client.waitForInitialization(5);
239239
client.variation('foo', 'x');
240240

241241
expect(ep.events.length).toEqual(2);
@@ -260,7 +260,7 @@ describe('LDClient events', () => {
260260
await withServer(async server => {
261261
server.byDefault(respondJson(newFlags));
262262
await withClientAndEventProcessor(user, { baseUrl: server.url, bootstrap: initData }, async (client, ep) => {
263-
await client.waitForInitialization();
263+
await client.waitForInitialization(5);
264264

265265
const user1 = { key: 'user1' };
266266
await client.identify(user1);
@@ -281,7 +281,7 @@ describe('LDClient events', () => {
281281
server.byDefault(respondJson(newFlags));
282282
const extraConfig = { sendEventsOnlyForVariation: true, baseUrl: server.url, bootstrap: initData };
283283
await withClientAndEventProcessor(user, extraConfig, async (client, ep) => {
284-
await client.waitForInitialization();
284+
await client.waitForInitialization(5);
285285

286286
const user1 = { key: 'user1' };
287287
await client.identify(user1);
@@ -301,7 +301,7 @@ describe('LDClient events', () => {
301301
server.byDefault(respondJson(newFlags));
302302
const extraConfig = { stateProvider: sp, baseUrl: server.url };
303303
await withClientAndEventProcessor(user, extraConfig, async (client, ep) => {
304-
await client.waitForInitialization();
304+
await client.waitForInitialization(5);
305305

306306
sp.emit('update', { flags: newFlags });
307307

@@ -317,7 +317,7 @@ describe('LDClient events', () => {
317317
bar: { value: 'b', variation: 1, version: 3 },
318318
});
319319
await withClientAndEventProcessor(user, { bootstrap: initData }, async (client, ep) => {
320-
await client.waitForInitialization();
320+
await client.waitForInitialization(5);
321321
client.allFlags();
322322

323323
expect(ep.events.length).toEqual(3);
@@ -334,7 +334,7 @@ describe('LDClient events', () => {
334334
});
335335
const extraConfig = { sendEventsOnlyForVariation: true, bootstrap: initData };
336336
await withClientAndEventProcessor(user, extraConfig, async (client, ep) => {
337-
await client.waitForInitialization();
337+
await client.waitForInitialization(5);
338338
client.allFlags();
339339

340340
expect(ep.events.length).toEqual(1);
@@ -345,7 +345,7 @@ describe('LDClient events', () => {
345345
it('uses "version" instead of "flagVersion" in event if "flagVersion" is absent', async () => {
346346
const initData = makeBootstrap({ foo: { value: 'a', variation: 1, version: 2 } });
347347
await withClientAndEventProcessor(user, { bootstrap: initData }, async (client, ep) => {
348-
await client.waitForInitialization();
348+
await client.waitForInitialization(5);
349349
client.variation('foo', 'x');
350350

351351
expect(ep.events.length).toEqual(2);
@@ -356,7 +356,7 @@ describe('LDClient events', () => {
356356

357357
it('omits event version if flag does not exist', async () => {
358358
await withClientAndEventProcessor(user, {}, async (client, ep) => {
359-
await client.waitForInitialization();
359+
await client.waitForInitialization(5);
360360
client.variation('foo', 'x');
361361

362362
expect(ep.events.length).toEqual(2);
@@ -377,7 +377,7 @@ describe('LDClient events', () => {
377377
});
378378
await withClientAndEventProcessor(user, { bootstrap: initData }, async (client, ep) => {
379379
await withCloseable(client, async () => {
380-
await client.waitForInitialization();
380+
await client.waitForInitialization(5);
381381
client.variation('foo', 'x');
382382

383383
expect(ep.events.length).toEqual(2);
@@ -399,7 +399,7 @@ describe('LDClient events', () => {
399399

400400
it('sends an event for track()', async () => {
401401
await withClientAndEventProcessor(user, {}, async (client, ep) => {
402-
await client.waitForInitialization();
402+
await client.waitForInitialization(5);
403403
client.track('eventkey');
404404

405405
expect(ep.events.length).toEqual(2);
@@ -417,7 +417,7 @@ describe('LDClient events', () => {
417417
await withServer(async server => {
418418
const anonUser = { key: 'anon-user', anonymous: true };
419419
await withClientAndEventProcessor(anonUser, { baseUrl: server.url }, async (client, ep) => {
420-
await client.waitForInitialization();
420+
await client.waitForInitialization(5);
421421
client.track('eventkey');
422422

423423
expect(ep.events.length).toEqual(2);
@@ -435,7 +435,7 @@ describe('LDClient events', () => {
435435
it('sends an event for track() with data', async () => {
436436
await withClientAndEventProcessor(user, {}, async (client, ep) => {
437437
const eventData = { thing: 'stuff' };
438-
await client.waitForInitialization();
438+
await client.waitForInitialization(5);
439439
client.track('eventkey', eventData);
440440

441441
expect(ep.events.length).toEqual(2);
@@ -453,7 +453,7 @@ describe('LDClient events', () => {
453453
await withClientAndEventProcessor(user, {}, async (client, ep) => {
454454
const eventData = { thing: 'stuff' };
455455
const metricValue = 1.5;
456-
await client.waitForInitialization();
456+
await client.waitForInitialization(5);
457457
client.track('eventkey', eventData, metricValue);
458458

459459
expect(ep.events.length).toEqual(2);
@@ -472,24 +472,36 @@ describe('LDClient events', () => {
472472
platform.testing.setDoNotTrack(true);
473473
await withClientAndEventProcessor(user, {}, async (client, ep) => {
474474
const eventData = { thing: 'stuff' };
475-
await client.waitForInitialization();
475+
await client.waitForInitialization(5);
476476
client.track('eventkey', eventData);
477477
expect(ep.events.length).toEqual(0);
478478
});
479479
});
480480

481481
it('does not warn by default when tracking a custom event', async () => {
482482
await withClientAndEventProcessor(user, {}, async client => {
483-
await client.waitForInitialization();
483+
await client.waitForInitialization(5);
484484

485485
client.track('known');
486486
expect(platform.testing.logger.output.warn).toEqual([]);
487487
});
488488
});
489489

490+
it('does warn when a metric value is non-numeric', async () => {
491+
await withClientAndEventProcessor(user, {}, async client => {
492+
await client.waitForInitialization(5);
493+
494+
client.track('known', undefined, '12');
495+
expect(platform.testing.logger.output.warn).toEqual([
496+
'The track function was called with a non-numeric "metricValue" (string), ' +
497+
'only numeric metric values are supported.',
498+
]);
499+
});
500+
});
501+
490502
it('emits an error when tracking a non-string custom event', async () => {
491503
await withClientAndEventProcessor(user, {}, async client => {
492-
await client.waitForInitialization();
504+
await client.waitForInitialization(5);
493505

494506
const badCustomEventKeys = [123, [], {}, null, undefined];
495507
badCustomEventKeys.forEach(key => {
@@ -513,7 +525,7 @@ describe('LDClient events', () => {
513525
sp.enqueueEvent = event => divertedEvents.push(event);
514526

515527
await withClientAndEventProcessor(user, { stateProvider: sp }, async (client, ep) => {
516-
await client.waitForInitialization();
528+
await client.waitForInitialization(5);
517529

518530
client.track('eventkey');
519531
expect(ep.events.length).toEqual(0);
@@ -555,7 +567,7 @@ describe('LDClient events', () => {
555567
};
556568
const client = platform.testing.makeClient(envName, user, config);
557569
await withCloseable(client, async () => {
558-
await client.waitForInitialization();
570+
await client.waitForInitialization(5);
559571
await client.flush();
560572
const data = await expectDiagnosticEventAndDiscardRegularEvent(server);
561573
expect(data.kind).toEqual('diagnostic-init');
@@ -579,7 +591,7 @@ describe('LDClient events', () => {
579591
};
580592
const client = platform1.testing.makeClient(envName, user, config);
581593
await withCloseable(client, async () => {
582-
await client.waitForInitialization();
594+
await client.waitForInitialization(5);
583595
await client.flush();
584596
const data = await expectDiagnosticEventAndDiscardRegularEvent(server);
585597
expect(data.kind).toEqual('diagnostic-combined');
@@ -602,7 +614,7 @@ describe('LDClient events', () => {
602614
};
603615
const client = platform.testing.makeClient(envName, user, config);
604616
await withCloseable(client, async () => {
605-
await client.waitForInitialization();
617+
await client.waitForInitialization(5);
606618
await client.flush();
607619
expect(server.requests.length()).toEqual(1);
608620
const req = await server.nextRequest();

src/__tests__/LDClient-localstorage-test.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ describe('LDClient local storage', () => {
3838

3939
await withServer(async server => {
4040
await withClient(user, { baseUrl: server.url }, async client => {
41-
await client.waitForInitialization();
41+
await client.waitForInitialization(5);
4242

4343
// should see a flag request to the server right away, as if bootstrap was not specified
4444
expect(server.requests.length()).toEqual(1);
@@ -58,7 +58,7 @@ describe('LDClient local storage', () => {
5858
server.byDefault(() => {});
5959

6060
await withClient(user, { baseUrl: server.url }, async client => {
61-
await client.waitForInitialization();
61+
await client.waitForInitialization(5);
6262

6363
expect(client.variation('flag-key')).toEqual(1);
6464

@@ -79,7 +79,7 @@ describe('LDClient local storage', () => {
7979
expect(client.variation('flag-key', 0)).toEqual(0);
8080

8181
// verify that the flags get requested from LD
82-
await client.waitForInitialization();
82+
await client.waitForInitialization(5);
8383
expect(client.variation('flag-key')).toEqual(1);
8484
});
8585
});
@@ -93,7 +93,7 @@ describe('LDClient local storage', () => {
9393
await withServer(async server => {
9494
server.byDefault(respondJson(flags));
9595
await withClient(user, { baseUrl: server.url }, async client => {
96-
await client.waitForInitialization();
96+
await client.waitForInitialization(5);
9797
expect(platform.testing.logger.output.warn).toEqual([messages.localStorageUnavailable(myError)]);
9898
});
9999
});
@@ -107,7 +107,7 @@ describe('LDClient local storage', () => {
107107
await withServer(async server => {
108108
server.byDefault(respondJson(flags));
109109
await withClient(user, { baseUrl: server.url }, async client => {
110-
await client.waitForInitialization();
110+
await client.waitForInitialization(5);
111111

112112
await sleepAsync(0); // allow any pending async tasks to complete
113113

@@ -123,7 +123,7 @@ describe('LDClient local storage', () => {
123123
await withServer(async server => {
124124
server.byDefault(respond(503));
125125
await withClient(user, { baseUrl: server.url }, async client => {
126-
await client.waitForInitialization();
126+
await client.waitForInitialization(5);
127127

128128
await sleepAsync(0); // allow any pending async tasks to complete
129129

@@ -141,7 +141,7 @@ describe('LDClient local storage', () => {
141141
await withServer(async server => {
142142
server.byDefault(respondJson(flags));
143143
await withClient(user, { baseUrl: server.url, hash }, async client => {
144-
await client.waitForInitialization();
144+
await client.waitForInitialization(5);
145145
const value = platform.testing.getLocalStorageImmediately(lsKeyHash);
146146
expect(JSON.parse(value)).toEqual({
147147
$schema: 1,
@@ -159,7 +159,7 @@ describe('LDClient local storage', () => {
159159
await withServer(async server => {
160160
server.byDefault(respondJson(flags));
161161
await withClient(user, { baseUrl: server.url }, async client => {
162-
await client.waitForInitialization();
162+
await client.waitForInitialization(5);
163163

164164
await sleepAsync(0); // allow any pending async tasks to complete
165165

0 commit comments

Comments
 (0)