@paypal/checkout-components 5.0.363 → 5.0.365

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,830 @@
1
+ /* @flow */
2
+ import { describe, expect, it, beforeEach, vi } from "vitest";
3
+ import { FUNDING } from "@paypal/sdk-constants";
4
+
5
+ import { BUTTON_COLOR } from "../../constants";
6
+
7
+ import {
8
+ getButtonColor,
9
+ getButtonColorExperience,
10
+ getColorForFullRedesign,
11
+ getColorForABTest,
12
+ getDefaultColorForFundingSource,
13
+ throwErrorForInvalidButtonColor,
14
+ hasInvalidScriptOptionsForFullRedesign,
15
+ determineRandomButtonColor,
16
+ getColorABTestFromStorage,
17
+ } from "./props";
18
+
19
+ describe("getColorABTestFromStorage", () => {
20
+ it("should return null when storage state has no colorABTest value", () => {
21
+ const storageState = {
22
+ get: vi.fn().mockReturnValue(null),
23
+ set: vi.fn(),
24
+ };
25
+
26
+ const result = getColorABTestFromStorage(storageState);
27
+
28
+ expect(result).toBeNull();
29
+ expect(storageState.get).toHaveBeenCalledWith("colorABTest");
30
+ });
31
+
32
+ it("should return null when storage state has colorABTest but no value property", () => {
33
+ const storageState = {
34
+ get: vi.fn().mockReturnValue({ someOtherProperty: "test" }),
35
+ set: vi.fn(),
36
+ };
37
+
38
+ const result = getColorABTestFromStorage(storageState);
39
+
40
+ expect(result).toBeNull();
41
+ expect(storageState.get).toHaveBeenCalledWith("colorABTest");
42
+ });
43
+
44
+ it("should return value when storage state has colorABTest with value property", () => {
45
+ const mockStoredValue = {
46
+ shouldApplyRebrandedStyles: true,
47
+ color: BUTTON_COLOR.REBRAND_BLUE,
48
+ sessionID: "test-session",
49
+ };
50
+
51
+ const storageState = {
52
+ get: vi.fn().mockReturnValue({ value: mockStoredValue }),
53
+ set: vi.fn(),
54
+ };
55
+
56
+ const result = getColorABTestFromStorage(storageState);
57
+
58
+ expect(result).toEqual(mockStoredValue);
59
+ expect(storageState.get).toHaveBeenCalledWith("colorABTest");
60
+ });
61
+ });
62
+
63
+ describe("determineRandomButtonColor", () => {
64
+ let mathRandomSpy;
65
+
66
+ beforeEach(() => {
67
+ mathRandomSpy = vi.spyOn(Math, "random");
68
+ });
69
+
70
+ afterEach(() => {
71
+ mathRandomSpy.mockRestore();
72
+ });
73
+
74
+ it("should return rebrand blue when random value is less than 0.33", () => {
75
+ mathRandomSpy.mockReturnValue(0);
76
+
77
+ const result = determineRandomButtonColor({
78
+ buttonColorInput: BUTTON_COLOR.GOLD,
79
+ });
80
+
81
+ expect(result).toEqual({
82
+ shouldApplyRebrandedStyles: true,
83
+ color: BUTTON_COLOR.REBRAND_BLUE,
84
+ });
85
+ });
86
+
87
+ it("should return rebrand darkblue when random value is between 0.33 and 0.67", () => {
88
+ mathRandomSpy.mockReturnValue(0.4);
89
+
90
+ const result = determineRandomButtonColor({
91
+ buttonColorInput: BUTTON_COLOR.GOLD,
92
+ });
93
+
94
+ expect(result).toEqual({
95
+ shouldApplyRebrandedStyles: true,
96
+ color: BUTTON_COLOR.REBRAND_DARKBLUE,
97
+ });
98
+ });
99
+
100
+ it("should return provided buttonColorInput when random value is above 0.67", () => {
101
+ mathRandomSpy.mockReturnValue(0.8);
102
+
103
+ const result = determineRandomButtonColor({
104
+ buttonColorInput: BUTTON_COLOR.BLACK,
105
+ });
106
+
107
+ expect(result).toEqual({
108
+ shouldApplyRebrandedStyles: false,
109
+ color: BUTTON_COLOR.BLACK,
110
+ });
111
+ });
112
+
113
+ it("should default to GOLD if buttonColorInput is not provided and random value is above 0.67", () => {
114
+ mathRandomSpy.mockReturnValue(0.8);
115
+
116
+ const result = determineRandomButtonColor({
117
+ buttonColorInput: null,
118
+ });
119
+
120
+ expect(result).toEqual({
121
+ shouldApplyRebrandedStyles: false,
122
+ color: BUTTON_COLOR.GOLD,
123
+ });
124
+ });
125
+ });
126
+
127
+ describe("hasInvalidScriptOptionsForFullRedesign", () => {
128
+ const validFundingSources = [FUNDING.PAYPAL];
129
+ const invalidFundingSources = [
130
+ FUNDING.CARD,
131
+ FUNDING.VENMO,
132
+ FUNDING.PAYLATER,
133
+ FUNDING.CREDIT,
134
+ FUNDING.APPLEPAY,
135
+ FUNDING.IDEAL,
136
+ ];
137
+
138
+ // Test valid funding sources
139
+ validFundingSources.forEach((fundingSource) => {
140
+ it(`should return false for fundingSource: ${fundingSource}`, () => {
141
+ const result = hasInvalidScriptOptionsForFullRedesign({
142
+ fundingSource,
143
+ });
144
+
145
+ expect(result).toBe(false);
146
+ });
147
+ });
148
+
149
+ // Test invalid funding sources
150
+ invalidFundingSources.forEach((fundingSource) => {
151
+ it(`should return true for fundingSource: ${fundingSource}`, () => {
152
+ const result = hasInvalidScriptOptionsForFullRedesign({
153
+ fundingSource,
154
+ });
155
+
156
+ expect(result).toBe(true);
157
+ });
158
+ });
159
+
160
+ it("should return true when no funding source is provided", () => {
161
+ const result = hasInvalidScriptOptionsForFullRedesign({});
162
+
163
+ expect(result).toBe(true);
164
+ });
165
+
166
+ it("should return true when funding source is null", () => {
167
+ const result = hasInvalidScriptOptionsForFullRedesign({
168
+ fundingSource: null,
169
+ });
170
+
171
+ expect(result).toBe(true);
172
+ });
173
+ });
174
+
175
+ describe("throwErrorForInvalidButtonColor", () => {
176
+ it("should throw error with appropriate message for invalid color", () => {
177
+ expect(() => {
178
+ throwErrorForInvalidButtonColor({
179
+ fundingSource: FUNDING.PAYPAL,
180
+ fundingSourceColors: [
181
+ BUTTON_COLOR.GOLD,
182
+ BUTTON_COLOR.BLUE,
183
+ BUTTON_COLOR.WHITE,
184
+ ],
185
+ invalidButtonColor: BUTTON_COLOR.BLACK,
186
+ });
187
+ }).toThrow(/Unexpected style.color/);
188
+ });
189
+
190
+ it("should include funding source in error message", () => {
191
+ expect(() => {
192
+ throwErrorForInvalidButtonColor({
193
+ fundingSource: FUNDING.VENMO,
194
+ fundingSourceColors: [BUTTON_COLOR.BLUE, BUTTON_COLOR.WHITE],
195
+ invalidButtonColor: BUTTON_COLOR.GOLD,
196
+ });
197
+ }).toThrow(/venmo/i);
198
+ });
199
+
200
+ it("should list available colors in error message", () => {
201
+ expect(() => {
202
+ throwErrorForInvalidButtonColor({
203
+ fundingSource: FUNDING.PAYPAL,
204
+ fundingSourceColors: [BUTTON_COLOR.GOLD, BUTTON_COLOR.SILVER],
205
+ invalidButtonColor: BUTTON_COLOR.BLUE,
206
+ });
207
+ }).toThrow(/(gold|Gold).*(silver|Silver)/);
208
+ });
209
+
210
+ it("should handle undefined funding source", () => {
211
+ expect(() => {
212
+ throwErrorForInvalidButtonColor({
213
+ fundingSource: undefined,
214
+ fundingSourceColors: [BUTTON_COLOR.GOLD],
215
+ invalidButtonColor: BUTTON_COLOR.BLUE,
216
+ });
217
+ }).toThrow(/paypal/i);
218
+ });
219
+
220
+ it("should filter out rebranded colors from error message", () => {
221
+ // Define a local helper function to capture error message
222
+ function getErrorMessage(fn): string {
223
+ try {
224
+ fn();
225
+ return "";
226
+ } catch (err) {
227
+ return err.message;
228
+ }
229
+ }
230
+
231
+ const errorMessage = getErrorMessage(() => {
232
+ throwErrorForInvalidButtonColor({
233
+ fundingSource: FUNDING.PAYPAL,
234
+ fundingSourceColors: [
235
+ BUTTON_COLOR.GOLD,
236
+ BUTTON_COLOR.BLUE,
237
+ BUTTON_COLOR.REBRAND_BLUE, // This should be filtered out
238
+ ],
239
+ invalidButtonColor: BUTTON_COLOR.BLACK,
240
+ });
241
+ });
242
+
243
+ // Check that the error message contains gold and blue
244
+ expect(errorMessage).toMatch(/gold/i);
245
+ expect(errorMessage).toMatch(/blue/i);
246
+
247
+ // Check that the error message doesn't contain rebrand_blue
248
+ expect(errorMessage).not.toMatch(/rebrand_blue/i);
249
+ });
250
+ });
251
+
252
+ describe("getDefaultColorForFundingSource", () => {
253
+ beforeEach(() => {
254
+ // Mock getFundingConfig to return consistent test data
255
+ vi.mock("../../funding", () => ({
256
+ getFundingConfig: () => ({
257
+ [FUNDING.PAYPAL]: {
258
+ colors: [BUTTON_COLOR.GOLD, BUTTON_COLOR.BLUE, BUTTON_COLOR.WHITE],
259
+ },
260
+ [FUNDING.VENMO]: {
261
+ colors: [BUTTON_COLOR.BLUE],
262
+ },
263
+ [FUNDING.PAYLATER]: {
264
+ colors: [BUTTON_COLOR.WHITE, BUTTON_COLOR.BLACK],
265
+ },
266
+ }),
267
+ }));
268
+ });
269
+
270
+ afterEach(() => {
271
+ vi.resetAllMocks();
272
+ });
273
+
274
+ it("should return the first color in the funding source config when style.color is undefined", () => {
275
+ const result = getDefaultColorForFundingSource({
276
+ fundingSource: FUNDING.PAYPAL,
277
+ // $FlowFixMe
278
+ style: {},
279
+ });
280
+
281
+ expect(result).toBe(BUTTON_COLOR.GOLD);
282
+ });
283
+
284
+ it("should return style.color if it is valid for the funding source", () => {
285
+ const result = getDefaultColorForFundingSource({
286
+ fundingSource: FUNDING.PAYPAL,
287
+ // $FlowFixMe
288
+ style: { color: BUTTON_COLOR.BLUE },
289
+ });
290
+
291
+ expect(result).toBe(BUTTON_COLOR.BLUE);
292
+ });
293
+
294
+ it("should throw an error when provided style.color is invalid for the funding source", () => {
295
+ expect(() => {
296
+ getDefaultColorForFundingSource({
297
+ fundingSource: FUNDING.PAYPAL,
298
+ // $FlowFixMe
299
+ style: { color: BUTTON_COLOR.BLACK },
300
+ });
301
+ }).toThrow();
302
+ });
303
+
304
+ it("should return different default colors for different funding sources", () => {
305
+ const paypalResult = getDefaultColorForFundingSource({
306
+ fundingSource: FUNDING.PAYPAL,
307
+ // $FlowFixMe
308
+ style: {},
309
+ });
310
+
311
+ const venmoResult = getDefaultColorForFundingSource({
312
+ fundingSource: FUNDING.VENMO,
313
+ // $FlowFixMe
314
+ style: {},
315
+ });
316
+
317
+ const paylaterResult = getDefaultColorForFundingSource({
318
+ fundingSource: FUNDING.PAYLATER,
319
+ // $FlowFixMe
320
+ style: {},
321
+ });
322
+
323
+ expect(paypalResult).toBe(BUTTON_COLOR.GOLD);
324
+ expect(venmoResult).toBe(BUTTON_COLOR.BLUE);
325
+ expect(paylaterResult).toBe(BUTTON_COLOR.WHITE);
326
+ });
327
+
328
+ it("should default to GOLD for smart stack (fundingSource is undefined)", () => {
329
+ const result = getDefaultColorForFundingSource({
330
+ fundingSource: FUNDING.IDEAL,
331
+ // $FlowFixMe
332
+ style: {},
333
+ });
334
+
335
+ expect(result).toBe(BUTTON_COLOR.GOLD);
336
+ });
337
+
338
+ it("should return style.color if provided for smart stack (fundingSource is undefined)", () => {
339
+ const result = getDefaultColorForFundingSource({
340
+ fundingSource: FUNDING.IDEAL,
341
+ // $FlowFixMe
342
+ style: { color: BUTTON_COLOR.BLACK },
343
+ });
344
+
345
+ expect(result).toBe(BUTTON_COLOR.BLACK);
346
+ });
347
+
348
+ it("should handle null style", () => {
349
+ const result = getDefaultColorForFundingSource({
350
+ fundingSource: FUNDING.PAYPAL,
351
+ style: null,
352
+ });
353
+
354
+ expect(result).toBe(BUTTON_COLOR.GOLD);
355
+ });
356
+
357
+ it("should handle undefined fundingSource", () => {
358
+ const result = getDefaultColorForFundingSource({
359
+ fundingSource: undefined,
360
+ // $FlowFixMe
361
+ style: {},
362
+ });
363
+
364
+ expect(result).toBe(BUTTON_COLOR.GOLD);
365
+ });
366
+ });
367
+
368
+ describe("getColorForABTest", () => {
369
+ it("should return color from storage if sessionID matches", () => {
370
+ const mockSessionID = "test-session-123";
371
+ const mockStoredValue = {
372
+ color: BUTTON_COLOR.REBRAND_BLUE,
373
+ shouldApplyRebrandedStyles: true,
374
+ sessionID: mockSessionID,
375
+ };
376
+
377
+ const storageState = {
378
+ get: vi.fn().mockReturnValue({ value: mockStoredValue }),
379
+ set: vi.fn(),
380
+ };
381
+
382
+ const result = getColorForABTest({
383
+ storageState,
384
+ sessionID: mockSessionID,
385
+ // $FlowFixMe
386
+ style: { color: BUTTON_COLOR.GOLD },
387
+ });
388
+
389
+ expect(result).toEqual({
390
+ color: BUTTON_COLOR.REBRAND_BLUE,
391
+ shouldApplyRebrandedStyles: true,
392
+ });
393
+ expect(storageState.get).toHaveBeenCalledWith("colorABTest");
394
+ expect(storageState.set).not.toHaveBeenCalled();
395
+ });
396
+
397
+ it("should generate new color and save it if sessionID does not match", () => {
398
+ const mockSessionID = "new-session-456";
399
+ const mockStoredValue = {
400
+ color: BUTTON_COLOR.REBRAND_BLUE,
401
+ shouldApplyRebrandedStyles: true,
402
+ sessionID: "old-session-123",
403
+ };
404
+
405
+ const storageState = {
406
+ get: vi.fn().mockReturnValue({ value: mockStoredValue }),
407
+ set: vi.fn(),
408
+ };
409
+
410
+ const result = getColorForABTest({
411
+ storageState,
412
+ sessionID: mockSessionID,
413
+ // $FlowFixMe
414
+ style: { color: BUTTON_COLOR.GOLD },
415
+ });
416
+
417
+ expect(result).toEqual(
418
+ expect.objectContaining({
419
+ color: expect.any(String),
420
+ shouldApplyRebrandedStyles: expect.any(Boolean),
421
+ })
422
+ );
423
+ expect(storageState.get).toHaveBeenCalledWith("colorABTest");
424
+ expect(storageState.set).toHaveBeenCalledWith("colorABTest", {
425
+ ...result,
426
+ sessionID: mockSessionID,
427
+ });
428
+ });
429
+
430
+ it("should generate new color and save it if no value in storage", () => {
431
+ const mockSessionID = "fresh-session-789";
432
+
433
+ const storageState = {
434
+ get: vi.fn().mockReturnValue(null),
435
+ set: vi.fn(),
436
+ };
437
+
438
+ const result = getColorForABTest({
439
+ storageState,
440
+ sessionID: mockSessionID,
441
+ // $FlowFixMe
442
+ style: { color: BUTTON_COLOR.GOLD },
443
+ });
444
+
445
+ expect(result).toEqual(
446
+ expect.objectContaining({
447
+ color: expect.any(String),
448
+ shouldApplyRebrandedStyles: expect.any(Boolean),
449
+ })
450
+ );
451
+ expect(storageState.get).toHaveBeenCalledWith("colorABTest");
452
+ expect(storageState.set).toHaveBeenCalledWith("colorABTest", {
453
+ ...result,
454
+ sessionID: mockSessionID,
455
+ });
456
+ });
457
+
458
+ it("should handle undefined style by generating a default color", () => {
459
+ const mockSessionID = "test-session-undefined-style";
460
+
461
+ const storageState = {
462
+ get: vi.fn().mockReturnValue(null),
463
+ set: vi.fn(),
464
+ };
465
+
466
+ const result = getColorForABTest({
467
+ storageState,
468
+ sessionID: mockSessionID,
469
+ style: undefined,
470
+ });
471
+
472
+ expect(result).toEqual(
473
+ expect.objectContaining({
474
+ color: expect.any(String),
475
+ shouldApplyRebrandedStyles: expect.any(Boolean),
476
+ })
477
+ );
478
+ expect(storageState.get).toHaveBeenCalledWith("colorABTest");
479
+ expect(storageState.set).toHaveBeenCalledWith("colorABTest", {
480
+ ...result,
481
+ sessionID: mockSessionID,
482
+ });
483
+ });
484
+ });
485
+
486
+ describe("getColorForFullRedesign", () => {
487
+ it("should map BLUE to REBRAND_BLUE", () => {
488
+ const result = getColorForFullRedesign({
489
+ // $FlowFixMe
490
+ style: { color: BUTTON_COLOR.BLUE },
491
+ fundingSource: FUNDING.PAYPAL,
492
+ });
493
+
494
+ expect(result).toEqual({
495
+ color: BUTTON_COLOR.REBRAND_BLUE,
496
+ shouldApplyRebrandedStyles: true,
497
+ });
498
+ });
499
+
500
+ it("should map DARKBLUE to REBRAND_DARKBLUE", () => {
501
+ const result = getColorForFullRedesign({
502
+ // $FlowFixMe
503
+ style: { color: BUTTON_COLOR.DARKBLUE },
504
+ fundingSource: FUNDING.PAYPAL,
505
+ });
506
+
507
+ expect(result).toEqual({
508
+ color: BUTTON_COLOR.REBRAND_DARKBLUE,
509
+ shouldApplyRebrandedStyles: true,
510
+ });
511
+ });
512
+
513
+ it("should map GOLD to REBRAND_BLUE", () => {
514
+ const result = getColorForFullRedesign({
515
+ // $FlowFixMe
516
+ style: { color: BUTTON_COLOR.GOLD },
517
+ fundingSource: FUNDING.PAYPAL,
518
+ });
519
+
520
+ expect(result).toEqual({
521
+ color: BUTTON_COLOR.REBRAND_BLUE,
522
+ shouldApplyRebrandedStyles: true,
523
+ });
524
+ });
525
+
526
+ it("should handle REBRAND colors directly without remapping them", () => {
527
+ const result = getColorForFullRedesign({
528
+ // $FlowFixMe
529
+ style: { color: BUTTON_COLOR.REBRAND_DARKBLUE },
530
+ fundingSource: FUNDING.PAYPAL,
531
+ });
532
+
533
+ expect(result).toEqual({
534
+ color: BUTTON_COLOR.REBRAND_DARKBLUE,
535
+ shouldApplyRebrandedStyles: true,
536
+ });
537
+ });
538
+
539
+ it("should handle unspecified style.color by determining an appropriate color", () => {
540
+ const result = getColorForFullRedesign({
541
+ // $FlowFixMe
542
+ style: {},
543
+ fundingSource: FUNDING.PAYPAL,
544
+ });
545
+
546
+ // Since we're not mocking getDefaultColorForFundingSource, just verify
547
+ // we get a proper structured response
548
+ expect(result).toEqual(
549
+ expect.objectContaining({
550
+ color: expect.any(String),
551
+ shouldApplyRebrandedStyles: true,
552
+ })
553
+ );
554
+ });
555
+
556
+ it("should handle null style by determining an appropriate color", () => {
557
+ const result = getColorForFullRedesign({
558
+ style: null,
559
+ fundingSource: FUNDING.PAYPAL,
560
+ });
561
+
562
+ expect(result).toEqual(
563
+ expect.objectContaining({
564
+ color: expect.any(String),
565
+ shouldApplyRebrandedStyles: true,
566
+ })
567
+ );
568
+ });
569
+
570
+ it("should handle different funding sources", () => {
571
+ const result = getColorForFullRedesign({
572
+ // $FlowFixMe
573
+ style: { color: BUTTON_COLOR.BLUE },
574
+ fundingSource: FUNDING.VENMO,
575
+ });
576
+
577
+ expect(result).toEqual({
578
+ color: BUTTON_COLOR.REBRAND_BLUE,
579
+ shouldApplyRebrandedStyles: true,
580
+ });
581
+ });
582
+
583
+ it("should throw error for invalid colors", () => {
584
+ expect(() => {
585
+ getColorForFullRedesign({
586
+ // $FlowFixMe
587
+ style: { color: "green" },
588
+ fundingSource: FUNDING.PAYPAL,
589
+ });
590
+ }).toThrow();
591
+ });
592
+ });
593
+
594
+ describe("getButtonColorExperience", () => {
595
+ it("should return 'legacy' when PayPal rebrand is not enabled", () => {
596
+ const result = getButtonColorExperience({
597
+ experiment: {
598
+ isPaypalRebrandEnabled: false,
599
+ isPaypalRebrandABTestEnabled: false,
600
+ },
601
+ fundingSource: FUNDING.PAYPAL,
602
+ // $FlowFixMe
603
+ style: { color: BUTTON_COLOR.GOLD },
604
+ });
605
+
606
+ expect(result).toBe("legacy");
607
+ });
608
+
609
+ it("should return 'abTest' when PayPal rebrand AB test is enabled and funding source is valid", () => {
610
+ const result = getButtonColorExperience({
611
+ experiment: {
612
+ isPaypalRebrandEnabled: true,
613
+ isPaypalRebrandABTestEnabled: true,
614
+ },
615
+ fundingSource: FUNDING.PAYPAL,
616
+ // $FlowFixMe
617
+ style: { color: BUTTON_COLOR.GOLD },
618
+ });
619
+
620
+ expect(result).toBe("abTest");
621
+ });
622
+
623
+ it("should return 'legacy' when PayPal rebrand AB test is enabled but funding source is invalid", () => {
624
+ const result = getButtonColorExperience({
625
+ experiment: {
626
+ isPaypalRebrandEnabled: true,
627
+ isPaypalRebrandABTestEnabled: true,
628
+ },
629
+ fundingSource: FUNDING.VENMO,
630
+ // $FlowFixMe
631
+ style: { color: BUTTON_COLOR.BLUE },
632
+ });
633
+
634
+ expect(result).toBe("legacy");
635
+ });
636
+
637
+ it("should return 'fullRebrand' when rebrand is enabled and not in AB test mode", () => {
638
+ const result = getButtonColorExperience({
639
+ experiment: {
640
+ isPaypalRebrandEnabled: true,
641
+ isPaypalRebrandABTestEnabled: false,
642
+ },
643
+ fundingSource: FUNDING.PAYPAL,
644
+ // $FlowFixMe
645
+ style: { color: BUTTON_COLOR.GOLD },
646
+ });
647
+
648
+ expect(result).toBe("fullRebrand");
649
+ });
650
+
651
+ it("should return 'legacy' when rebrand is enabled but style.color is not dev complete", () => {
652
+ const incompleteColors = [
653
+ BUTTON_COLOR.BLACK,
654
+ BUTTON_COLOR.WHITE,
655
+ BUTTON_COLOR.SILVER,
656
+ BUTTON_COLOR.TRANSPARENT,
657
+ BUTTON_COLOR.DEFAULT,
658
+ ];
659
+
660
+ // Test each incomplete color
661
+ incompleteColors.forEach((incompleteColor) => {
662
+ const result = getButtonColorExperience({
663
+ experiment: {
664
+ isPaypalRebrandEnabled: true,
665
+ isPaypalRebrandABTestEnabled: false,
666
+ },
667
+ fundingSource: FUNDING.PAYPAL,
668
+ // $FlowFixMe
669
+ style: { color: incompleteColor },
670
+ });
671
+
672
+ expect(result).toBe("legacy");
673
+ });
674
+ });
675
+
676
+ it("should handle null/undefined experiment values", () => {
677
+ const result = getButtonColorExperience({
678
+ // $FlowFixMe
679
+ experiment: null,
680
+ fundingSource: FUNDING.PAYPAL,
681
+ // $FlowFixMe
682
+ style: { color: BUTTON_COLOR.GOLD },
683
+ });
684
+
685
+ expect(result).toBe("legacy");
686
+ });
687
+
688
+ it("should handle null/undefined style", () => {
689
+ const result = getButtonColorExperience({
690
+ experiment: {
691
+ isPaypalRebrandEnabled: true,
692
+ isPaypalRebrandABTestEnabled: false,
693
+ },
694
+ fundingSource: FUNDING.PAYPAL,
695
+ style: null,
696
+ });
697
+
698
+ expect(result).toBe("fullRebrand");
699
+ });
700
+
701
+ it("should return legacy for smart stack (fundingSource is undefined)", () => {
702
+ const result = getButtonColorExperience({
703
+ experiment: {
704
+ isPaypalRebrandEnabled: true,
705
+ isPaypalRebrandABTestEnabled: false,
706
+ },
707
+ fundingSource: undefined,
708
+ // $FlowFixMe
709
+ style: { color: BUTTON_COLOR.GOLD },
710
+ });
711
+
712
+ expect(result).toBe("legacy");
713
+ });
714
+ });
715
+
716
+ describe("getButtonColor", () => {
717
+ afterEach(() => {
718
+ vi.restoreAllMocks();
719
+ });
720
+
721
+ it("should return legacy styling for non-rebrand-enabled experiments", () => {
722
+ const style = { color: BUTTON_COLOR.GOLD };
723
+ const storageState = { get: vi.fn(), set: vi.fn() };
724
+ const sessionID = "test-session";
725
+ const fundingSource = FUNDING.PAYPAL;
726
+ const experiment = {
727
+ isPaypalRebrandEnabled: false,
728
+ isPaypalRebrandABTestEnabled: false,
729
+ };
730
+
731
+ const result = getButtonColor({
732
+ experiment,
733
+ // $FlowFixMe
734
+ style,
735
+ sessionID,
736
+ storageState,
737
+ fundingSource,
738
+ });
739
+
740
+ expect(result).toEqual({
741
+ color: BUTTON_COLOR.GOLD,
742
+ shouldApplyRebrandedStyles: false,
743
+ });
744
+ });
745
+
746
+ it("should return the rebranded blue color for rebrand-enabled experiments", () => {
747
+ const style = { color: BUTTON_COLOR.GOLD };
748
+ const storageState = { get: vi.fn(), set: vi.fn() };
749
+ const sessionID = "test-session";
750
+ const fundingSource = FUNDING.PAYPAL;
751
+ const experiment = {
752
+ isPaypalRebrandEnabled: true,
753
+ isPaypalRebrandABTestEnabled: false,
754
+ };
755
+
756
+ const result = getButtonColor({
757
+ experiment,
758
+ // $FlowFixMe
759
+ style,
760
+ sessionID,
761
+ storageState,
762
+ fundingSource,
763
+ });
764
+
765
+ expect(result).toEqual({
766
+ color: BUTTON_COLOR.REBRAND_BLUE,
767
+ shouldApplyRebrandedStyles: true,
768
+ });
769
+ });
770
+
771
+ it("should return the default color for non-PayPal funding sources", () => {
772
+ const style = { color: BUTTON_COLOR.BLUE };
773
+ const storageState = { get: vi.fn(), set: vi.fn() };
774
+ const sessionID = "test-session";
775
+ const fundingSource = FUNDING.VENMO;
776
+ const experiment = {
777
+ isPaypalRebrandEnabled: true,
778
+ isPaypalRebrandABTestEnabled: true,
779
+ };
780
+
781
+ const result = getButtonColor({
782
+ experiment,
783
+ // $FlowFixMe
784
+ style,
785
+ sessionID,
786
+ storageState,
787
+ fundingSource,
788
+ });
789
+
790
+ expect(result).toEqual({
791
+ color: BUTTON_COLOR.BLUE,
792
+ shouldApplyRebrandedStyles: false,
793
+ });
794
+ });
795
+
796
+ it("should respect specified colors in legacy mode", () => {
797
+ const style = { color: BUTTON_COLOR.WHITE };
798
+ const storageState = { get: vi.fn(), set: vi.fn() };
799
+ const sessionID = "test-session";
800
+ const fundingSource = FUNDING.PAYPAL;
801
+ const experiment = {
802
+ isPaypalRebrandEnabled: false,
803
+ };
804
+
805
+ const result = getButtonColor({
806
+ experiment,
807
+ // $FlowFixMe
808
+ style,
809
+ sessionID,
810
+ storageState,
811
+ fundingSource,
812
+ });
813
+
814
+ expect(result).toEqual({
815
+ color: BUTTON_COLOR.WHITE,
816
+ shouldApplyRebrandedStyles: false,
817
+ });
818
+ });
819
+
820
+ it("should handle undefined parameters", () => {
821
+ // $FlowFixMe
822
+ const result = getButtonColor({});
823
+
824
+ // The default color should be returned
825
+ expect(result).toEqual({
826
+ color: BUTTON_COLOR.GOLD,
827
+ shouldApplyRebrandedStyles: false,
828
+ });
829
+ });
830
+ });