@mostly-good-metrics/javascript 0.5.0 → 0.6.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.
@@ -19,12 +19,15 @@
19
19
  * page: '/checkout',
20
20
  * });
21
21
  *
22
- * // Identify users
23
- * MostlyGoodMetrics.identify('user_123');
22
+ * // Identify users with profile data
23
+ * MostlyGoodMetrics.identify('user_123', {
24
+ * email: 'user@example.com',
25
+ * name: 'Jane Doe',
26
+ * });
24
27
  * ```
25
28
  */
26
29
  export { MostlyGoodMetrics } from './client';
27
- export type { MGMConfiguration, ResolvedConfiguration, EventProperties, EventPropertyValue, MGMEvent, MGMEventContext, MGMEventsPayload, Platform, SDK, DeviceType, MGMErrorType, SendResult, IEventStorage, INetworkClient, } from './types';
30
+ export type { MGMConfiguration, ResolvedConfiguration, EventProperties, EventPropertyValue, MGMEvent, MGMEventContext, MGMEventsPayload, Platform, SDK, DeviceType, MGMErrorType, SendResult, IEventStorage, INetworkClient, UserProfile, Experiment, ExperimentsResponse, } from './types';
28
31
  export { MGMError } from './types';
29
32
  export { SystemEvents, SystemProperties, DefaultConfiguration, Constraints, EVENT_NAME_REGEX, } from './types';
30
33
  export { InMemoryEventStorage, LocalStorageEventStorage, createDefaultStorage } from './storage';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,GAAG,EACH,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAGjG,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAG3E,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,GAAG,EACH,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,cAAc,EACd,WAAW,EACX,UAAU,EACV,mBAAmB,GACpB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAGjG,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAG3E,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
@@ -127,6 +127,26 @@ declare class PersistenceManager {
127
127
  */
128
128
  clearSuperProperties(): void;
129
129
  private saveSuperProperties;
130
+ /**
131
+ * Get the stored identify hash (for debouncing).
132
+ */
133
+ getIdentifyHash(): string | null;
134
+ /**
135
+ * Set the identify hash.
136
+ */
137
+ setIdentifyHash(hash: string): void;
138
+ /**
139
+ * Get the timestamp of the last identify event sent.
140
+ */
141
+ getIdentifyLastSentAt(): number | null;
142
+ /**
143
+ * Set the timestamp of the last identify event sent.
144
+ */
145
+ setIdentifyLastSentAt(timestamp: number): void;
146
+ /**
147
+ * Clear identify debounce state (used when resetting identity).
148
+ */
149
+ clearIdentifyState(): void;
130
150
  }
131
151
  export declare const persistence: PersistenceManager;
132
152
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/storage.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,eAAe,EAAE,aAAa,EAAY,QAAQ,EAAE,MAAM,SAAS,CAAC;AA8E1F;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,aAAa;IACxD,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,GAAE,MAAsC;IAIvD,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAI/C,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAI7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAGtC;AAED;;;GAGG;AACH,qBAAa,wBAAyB,YAAW,aAAa;IAC5D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAA2B;gBAE7B,SAAS,GAAE,MAAsC;IAI7D,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,UAAU;IASZ,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAcrC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAK/C,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1C,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAI7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAGtC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAQrE;AAED;;;GAGG;AACH,cAAM,kBAAkB;IACtB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,uBAAuB,CAAuB;IACtD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,cAAc,CAAS;IAE/B;;;;OAIG;IACH,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,GAAG,IAAI;IAKvE;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACH,SAAS,IAAI,MAAM,GAAG,IAAI;IAO1B;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAWtC;;;OAGG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAiB/B;;;OAGG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAczC;;;;;OAKG;IACH,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,MAAM,GAAG,MAAM;IAuBzF;;;OAGG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,MAAM,GAAG,MAAM;IAMpD;;OAEG;IACH,aAAa,IAAI,MAAM,GAAG,IAAI;IAO9B;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAW3C;;;OAGG;IACH,aAAa,IAAI,OAAO;IAexB;;OAEG;IACH,kBAAkB,IAAI,eAAe;IAerC;;OAEG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,GAAG,IAAI;IAMnE;;OAEG;IACH,kBAAkB,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI;IAMrD;;OAEG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMtC;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAI5B,OAAO,CAAC,mBAAmB;CAU5B;AAED,eAAO,MAAM,WAAW,oBAA2B,CAAC"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/storage.ts"],"names":[],"mappings":"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"}
@@ -305,7 +305,40 @@ export declare const SystemEvents: {
305
305
  readonly APP_UPDATED: "$app_updated";
306
306
  readonly APP_OPENED: "$app_opened";
307
307
  readonly APP_BACKGROUNDED: "$app_backgrounded";
308
+ readonly IDENTIFY: "$identify";
308
309
  };
310
+ /**
311
+ * User profile data for the identify() call.
312
+ */
313
+ export interface UserProfile {
314
+ /**
315
+ * The user's email address.
316
+ */
317
+ email?: string;
318
+ /**
319
+ * The user's display name.
320
+ */
321
+ name?: string;
322
+ }
323
+ /**
324
+ * An experiment configuration from the server.
325
+ */
326
+ export interface Experiment {
327
+ /**
328
+ * The experiment identifier (e.g., "button-color").
329
+ */
330
+ id: string;
331
+ /**
332
+ * The variants for this experiment (e.g., ["a", "b"]).
333
+ */
334
+ variants: string[];
335
+ }
336
+ /**
337
+ * Response from the experiments API endpoint.
338
+ */
339
+ export interface ExperimentsResponse {
340
+ experiments: Experiment[];
341
+ }
309
342
  /**
310
343
  * System property keys (prefixed with $).
311
344
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mostly-good-metrics/javascript",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "JavaScript/TypeScript SDK for MostlyGoodMetrics - a lightweight analytics library for web applications",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -266,6 +266,97 @@ describe('MostlyGoodMetrics', () => {
266
266
  MostlyGoodMetrics.identify('');
267
267
  expect(MostlyGoodMetrics.shared?.userId).toBe('user_123');
268
268
  });
269
+
270
+ it('should send $identify event with email', async () => {
271
+ MostlyGoodMetrics.resetIdentity(); // Clear any previous identify state
272
+ MostlyGoodMetrics.identify('user_123', { email: 'test@example.com' });
273
+
274
+ await new Promise((resolve) => setTimeout(resolve, 10));
275
+
276
+ const events = await storage.fetchEvents(10);
277
+ const identifyEvent = events.find((e) => e.name === '$identify');
278
+ expect(identifyEvent).toBeDefined();
279
+ expect(identifyEvent?.properties?.email).toBe('test@example.com');
280
+ expect(identifyEvent?.properties?.name).toBeUndefined();
281
+ });
282
+
283
+ it('should send $identify event with name', async () => {
284
+ MostlyGoodMetrics.resetIdentity(); // Clear any previous identify state
285
+ MostlyGoodMetrics.identify('user_123', { name: 'John Doe' });
286
+
287
+ await new Promise((resolve) => setTimeout(resolve, 10));
288
+
289
+ const events = await storage.fetchEvents(10);
290
+ const identifyEvent = events.find((e) => e.name === '$identify');
291
+ expect(identifyEvent).toBeDefined();
292
+ expect(identifyEvent?.properties?.name).toBe('John Doe');
293
+ expect(identifyEvent?.properties?.email).toBeUndefined();
294
+ });
295
+
296
+ it('should send $identify event with both email and name', async () => {
297
+ MostlyGoodMetrics.resetIdentity(); // Clear any previous identify state
298
+ MostlyGoodMetrics.identify('user_123', { email: 'test@example.com', name: 'John Doe' });
299
+
300
+ await new Promise((resolve) => setTimeout(resolve, 10));
301
+
302
+ const events = await storage.fetchEvents(10);
303
+ const identifyEvent = events.find((e) => e.name === '$identify');
304
+ expect(identifyEvent).toBeDefined();
305
+ expect(identifyEvent?.properties?.email).toBe('test@example.com');
306
+ expect(identifyEvent?.properties?.name).toBe('John Doe');
307
+ });
308
+
309
+ it('should not send $identify event without profile data', async () => {
310
+ MostlyGoodMetrics.resetIdentity(); // Clear any previous identify state
311
+ MostlyGoodMetrics.identify('user_123');
312
+
313
+ await new Promise((resolve) => setTimeout(resolve, 10));
314
+
315
+ const events = await storage.fetchEvents(10);
316
+ const identifyEvent = events.find((e) => e.name === '$identify');
317
+ expect(identifyEvent).toBeUndefined();
318
+ });
319
+
320
+ it('should debounce $identify event with same profile data', async () => {
321
+ MostlyGoodMetrics.resetIdentity(); // Clear any previous identify state
322
+
323
+ MostlyGoodMetrics.identify('user_123', { email: 'debounce-test@example.com' });
324
+ await new Promise((resolve) => setTimeout(resolve, 10));
325
+
326
+ // Call again with same data - should not send another event
327
+ MostlyGoodMetrics.identify('user_123', { email: 'debounce-test@example.com' });
328
+ await new Promise((resolve) => setTimeout(resolve, 10));
329
+
330
+ const events = await storage.fetchEvents(10);
331
+ const identifyEvents = events.filter((e) => e.name === '$identify');
332
+ expect(identifyEvents.length).toBe(1);
333
+ });
334
+
335
+ it('should send new $identify event when profile data changes', async () => {
336
+ MostlyGoodMetrics.resetIdentity(); // Clear any previous identify state
337
+
338
+ MostlyGoodMetrics.identify('user_123', { email: 'change-test@example.com' });
339
+ await new Promise((resolve) => setTimeout(resolve, 10));
340
+
341
+ // Call with different email - should send new event
342
+ MostlyGoodMetrics.identify('user_123', { email: 'changed@example.com' });
343
+ await new Promise((resolve) => setTimeout(resolve, 10));
344
+
345
+ const events = await storage.fetchEvents(10);
346
+ const identifyEvents = events.filter((e) => e.name === '$identify');
347
+ expect(identifyEvents.length).toBe(2);
348
+ });
349
+
350
+ it('should not send $identify event with empty profile', async () => {
351
+ MostlyGoodMetrics.resetIdentity(); // Clear any previous identify state
352
+ MostlyGoodMetrics.identify('user_123', {});
353
+
354
+ await new Promise((resolve) => setTimeout(resolve, 10));
355
+
356
+ const events = await storage.fetchEvents(10);
357
+ const identifyEvent = events.find((e) => e.name === '$identify');
358
+ expect(identifyEvent).toBeUndefined();
359
+ });
269
360
  });
270
361
 
271
362
  describe('resetIdentity', () => {
@@ -702,4 +793,259 @@ describe('MostlyGoodMetrics', () => {
702
793
  expect(events[0].properties?.$device_type).not.toBe('hacked');
703
794
  });
704
795
  });
796
+
797
+ describe('getVariant', () => {
798
+ let originalFetch: typeof global.fetch;
799
+
800
+ beforeEach(() => {
801
+ originalFetch = global.fetch;
802
+ });
803
+
804
+ afterEach(() => {
805
+ global.fetch = originalFetch;
806
+ MostlyGoodMetrics.reset();
807
+ });
808
+
809
+ it('should return null when SDK not configured', () => {
810
+ const variant = MostlyGoodMetrics.getVariant('button-color');
811
+ expect(variant).toBeNull();
812
+ });
813
+
814
+ it('should return null when experiment not found after experiments loaded', async () => {
815
+ global.fetch = jest.fn().mockResolvedValue({
816
+ ok: true,
817
+ json: () => Promise.resolve({ experiments: [] }),
818
+ });
819
+
820
+ MostlyGoodMetrics.configure({
821
+ apiKey: 'test-key',
822
+ storage,
823
+ networkClient,
824
+ trackAppLifecycleEvents: false,
825
+ });
826
+
827
+ await MostlyGoodMetrics.ready();
828
+
829
+ const variant = MostlyGoodMetrics.getVariant('nonexistent-experiment');
830
+ expect(variant).toBeNull();
831
+ });
832
+
833
+ it('should return null when called before experiments are loaded', async () => {
834
+ // Never resolve the fetch
835
+ global.fetch = jest.fn().mockImplementation(() => new Promise(() => {}));
836
+
837
+ MostlyGoodMetrics.configure({
838
+ apiKey: 'test-key',
839
+ storage,
840
+ networkClient,
841
+ trackAppLifecycleEvents: false,
842
+ });
843
+
844
+ // Don't wait for ready - experiments not loaded yet
845
+ const variant = MostlyGoodMetrics.getVariant('button-color');
846
+ expect(variant).toBeNull();
847
+ });
848
+
849
+ it('should return variant when experiment exists', async () => {
850
+ global.fetch = jest.fn().mockResolvedValue({
851
+ ok: true,
852
+ json: () =>
853
+ Promise.resolve({
854
+ experiments: [{ id: 'button-color', variants: ['a', 'b'] }],
855
+ }),
856
+ });
857
+
858
+ MostlyGoodMetrics.configure({
859
+ apiKey: 'test-key',
860
+ storage,
861
+ networkClient,
862
+ trackAppLifecycleEvents: false,
863
+ });
864
+
865
+ await MostlyGoodMetrics.ready();
866
+
867
+ const variant = MostlyGoodMetrics.getVariant('button-color');
868
+ expect(variant).not.toBeNull();
869
+ expect(['a', 'b']).toContain(variant);
870
+ });
871
+
872
+ it('should be deterministic - same user gets same variant', async () => {
873
+ global.fetch = jest.fn().mockResolvedValue({
874
+ ok: true,
875
+ json: () =>
876
+ Promise.resolve({
877
+ experiments: [{ id: 'button-color', variants: ['a', 'b', 'c'] }],
878
+ }),
879
+ });
880
+
881
+ MostlyGoodMetrics.configure({
882
+ apiKey: 'test-key',
883
+ storage,
884
+ networkClient,
885
+ trackAppLifecycleEvents: false,
886
+ });
887
+
888
+ await MostlyGoodMetrics.ready();
889
+
890
+ // Call multiple times - should return same variant
891
+ const variant1 = MostlyGoodMetrics.getVariant('button-color');
892
+ const variant2 = MostlyGoodMetrics.getVariant('button-color');
893
+ const variant3 = MostlyGoodMetrics.getVariant('button-color');
894
+
895
+ expect(variant1).toBe(variant2);
896
+ expect(variant2).toBe(variant3);
897
+ });
898
+
899
+ it('should store variant as super property', async () => {
900
+ global.fetch = jest.fn().mockResolvedValue({
901
+ ok: true,
902
+ json: () =>
903
+ Promise.resolve({
904
+ experiments: [{ id: 'button-color', variants: ['a', 'b'] }],
905
+ }),
906
+ });
907
+
908
+ MostlyGoodMetrics.configure({
909
+ apiKey: 'test-key',
910
+ storage,
911
+ networkClient,
912
+ trackAppLifecycleEvents: false,
913
+ });
914
+
915
+ await MostlyGoodMetrics.ready();
916
+
917
+ const variant = MostlyGoodMetrics.getVariant('button-color');
918
+
919
+ const superProps = MostlyGoodMetrics.getSuperProperties();
920
+ expect(superProps.experiment_button_color).toBe(variant);
921
+ });
922
+
923
+ it('should attach experiment variant to tracked events', async () => {
924
+ global.fetch = jest.fn().mockResolvedValue({
925
+ ok: true,
926
+ json: () =>
927
+ Promise.resolve({
928
+ experiments: [{ id: 'checkout-flow', variants: ['control', 'treatment'] }],
929
+ }),
930
+ });
931
+
932
+ MostlyGoodMetrics.configure({
933
+ apiKey: 'test-key',
934
+ storage,
935
+ networkClient,
936
+ trackAppLifecycleEvents: false,
937
+ });
938
+
939
+ await MostlyGoodMetrics.ready();
940
+
941
+ const variant = MostlyGoodMetrics.getVariant('checkout-flow');
942
+ MostlyGoodMetrics.track('purchase_completed');
943
+
944
+ await new Promise((resolve) => setTimeout(resolve, 10));
945
+
946
+ const events = await storage.fetchEvents(1);
947
+ expect(events[0].properties?.experiment_checkout_flow).toBe(variant);
948
+ });
949
+
950
+ it('should handle fetch failure gracefully', async () => {
951
+ global.fetch = jest.fn().mockRejectedValue(new Error('Network error'));
952
+
953
+ MostlyGoodMetrics.configure({
954
+ apiKey: 'test-key',
955
+ storage,
956
+ networkClient,
957
+ trackAppLifecycleEvents: false,
958
+ });
959
+
960
+ // Should resolve even on fetch failure
961
+ await MostlyGoodMetrics.ready();
962
+
963
+ const variant = MostlyGoodMetrics.getVariant('button-color');
964
+ expect(variant).toBeNull();
965
+ });
966
+
967
+ it('should handle non-ok response gracefully', async () => {
968
+ global.fetch = jest.fn().mockResolvedValue({
969
+ ok: false,
970
+ status: 500,
971
+ });
972
+
973
+ MostlyGoodMetrics.configure({
974
+ apiKey: 'test-key',
975
+ storage,
976
+ networkClient,
977
+ trackAppLifecycleEvents: false,
978
+ });
979
+
980
+ await MostlyGoodMetrics.ready();
981
+
982
+ const variant = MostlyGoodMetrics.getVariant('button-color');
983
+ expect(variant).toBeNull();
984
+ });
985
+
986
+ it('should convert experiment name to snake_case for property', async () => {
987
+ global.fetch = jest.fn().mockResolvedValue({
988
+ ok: true,
989
+ json: () =>
990
+ Promise.resolve({
991
+ experiments: [{ id: 'newOnboardingFlow', variants: ['a', 'b'] }],
992
+ }),
993
+ });
994
+
995
+ MostlyGoodMetrics.configure({
996
+ apiKey: 'test-key',
997
+ storage,
998
+ networkClient,
999
+ trackAppLifecycleEvents: false,
1000
+ });
1001
+
1002
+ await MostlyGoodMetrics.ready();
1003
+
1004
+ MostlyGoodMetrics.getVariant('newOnboardingFlow');
1005
+
1006
+ const superProps = MostlyGoodMetrics.getSuperProperties();
1007
+ expect(superProps.experiment_new_onboarding_flow).toBeDefined();
1008
+ });
1009
+
1010
+ it('should return null for empty experimentName', async () => {
1011
+ global.fetch = jest.fn().mockResolvedValue({
1012
+ ok: true,
1013
+ json: () => Promise.resolve({ experiments: [] }),
1014
+ });
1015
+
1016
+ MostlyGoodMetrics.configure({
1017
+ apiKey: 'test-key',
1018
+ storage,
1019
+ networkClient,
1020
+ trackAppLifecycleEvents: false,
1021
+ });
1022
+
1023
+ await MostlyGoodMetrics.ready();
1024
+
1025
+ const variant = MostlyGoodMetrics.getVariant('');
1026
+ expect(variant).toBeNull();
1027
+ });
1028
+
1029
+ it('should return null for experiment with no variants', async () => {
1030
+ global.fetch = jest.fn().mockResolvedValue({
1031
+ ok: true,
1032
+ json: () =>
1033
+ Promise.resolve({
1034
+ experiments: [{ id: 'empty-experiment', variants: [] }],
1035
+ }),
1036
+ });
1037
+
1038
+ MostlyGoodMetrics.configure({
1039
+ apiKey: 'test-key',
1040
+ storage,
1041
+ networkClient,
1042
+ trackAppLifecycleEvents: false,
1043
+ });
1044
+
1045
+ await MostlyGoodMetrics.ready();
1046
+
1047
+ const variant = MostlyGoodMetrics.getVariant('empty-experiment');
1048
+ expect(variant).toBeNull();
1049
+ });
1050
+ });
705
1051
  });