|
1 | 1 | import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; |
| 2 | +import { Socket } from "phoenix"; |
2 | 3 |
|
3 | 4 | import packageJson from "../package.json"; |
4 | 5 | import ApiClient from "../src/api"; |
@@ -609,6 +610,102 @@ describe("API Client", () => { |
609 | 610 | (global as GlobalWithWindow).window = originalWindow; |
610 | 611 | }); |
611 | 612 |
|
| 613 | + test("configures socket with reconnectAfterMs and rejoinAfterMs", () => { |
| 614 | + const originalWindow = (global as GlobalWithWindow).window; |
| 615 | + (global as GlobalWithWindow).window = {}; |
| 616 | + |
| 617 | + vi.mocked(Socket).mockClear(); |
| 618 | + |
| 619 | + new ApiClient({ |
| 620 | + host: "https://api.knock.app", |
| 621 | + apiKey: "pk_test_12345", |
| 622 | + userToken: "user_token_456", |
| 623 | + }); |
| 624 | + |
| 625 | + const socketOpts = vi.mocked(Socket).mock.calls[0]![1] as Record< |
| 626 | + string, |
| 627 | + unknown |
| 628 | + >; |
| 629 | + expect(typeof socketOpts.reconnectAfterMs).toBe("function"); |
| 630 | + expect(typeof socketOpts.rejoinAfterMs).toBe("function"); |
| 631 | + |
| 632 | + (global as GlobalWithWindow).window = originalWindow; |
| 633 | + }); |
| 634 | + |
| 635 | + test("reconnectAfterMs returns values within expected bounds", () => { |
| 636 | + const originalWindow = (global as GlobalWithWindow).window; |
| 637 | + (global as GlobalWithWindow).window = {}; |
| 638 | + |
| 639 | + vi.mocked(Socket).mockClear(); |
| 640 | + |
| 641 | + new ApiClient({ |
| 642 | + host: "https://api.knock.app", |
| 643 | + apiKey: "pk_test_12345", |
| 644 | + userToken: "user_token_456", |
| 645 | + }); |
| 646 | + |
| 647 | + const socketOpts = vi.mocked(Socket).mock.calls[0]![1] as Record< |
| 648 | + string, |
| 649 | + unknown |
| 650 | + >; |
| 651 | + const reconnectAfterMs = socketOpts.reconnectAfterMs as ( |
| 652 | + tries: number, |
| 653 | + ) => number; |
| 654 | + |
| 655 | + // Call it many times to verify the range holds |
| 656 | + for (let i = 0; i < 50; i++) { |
| 657 | + const delay = reconnectAfterMs(1); |
| 658 | + expect(delay).toBeGreaterThanOrEqual(250); |
| 659 | + expect(delay).toBeLessThanOrEqual(1000); |
| 660 | + } |
| 661 | + |
| 662 | + // At high tries, should be capped at 30_000 |
| 663 | + for (let i = 0; i < 50; i++) { |
| 664 | + const delay = reconnectAfterMs(100); |
| 665 | + expect(delay).toBeGreaterThanOrEqual(250); |
| 666 | + expect(delay).toBeLessThanOrEqual(30_000); |
| 667 | + } |
| 668 | + |
| 669 | + (global as GlobalWithWindow).window = originalWindow; |
| 670 | + }); |
| 671 | + |
| 672 | + test("rejoinAfterMs returns values within expected bounds", () => { |
| 673 | + const originalWindow = (global as GlobalWithWindow).window; |
| 674 | + (global as GlobalWithWindow).window = {}; |
| 675 | + |
| 676 | + vi.mocked(Socket).mockClear(); |
| 677 | + |
| 678 | + new ApiClient({ |
| 679 | + host: "https://api.knock.app", |
| 680 | + apiKey: "pk_test_12345", |
| 681 | + userToken: "user_token_456", |
| 682 | + }); |
| 683 | + |
| 684 | + const socketOpts = vi.mocked(Socket).mock.calls[0]![1] as Record< |
| 685 | + string, |
| 686 | + unknown |
| 687 | + >; |
| 688 | + const rejoinAfterMs = socketOpts.rejoinAfterMs as ( |
| 689 | + tries: number, |
| 690 | + ) => number; |
| 691 | + |
| 692 | + // Call it many times to verify the range holds |
| 693 | + for (let i = 0; i < 50; i++) { |
| 694 | + const delay = rejoinAfterMs(1); |
| 695 | + expect(delay).toBeGreaterThanOrEqual(250); |
| 696 | + expect(delay).toBeLessThanOrEqual(1000); |
| 697 | + } |
| 698 | + |
| 699 | + // At high tries, should be capped at 60_000 |
| 700 | + for (let i = 0; i < 50; i++) { |
| 701 | + const delay = rejoinAfterMs(100); |
| 702 | + expect(delay).toBeGreaterThanOrEqual(250); |
| 703 | + expect(delay).toBeLessThanOrEqual(60_000); |
| 704 | + } |
| 705 | + |
| 706 | + (global as GlobalWithWindow).window = originalWindow; |
| 707 | + }); |
| 708 | + |
612 | 709 | test("gracefully handles missing WebSocket in server environment", () => { |
613 | 710 | // Store original window value |
614 | 711 | const originalWindow = (global as GlobalWithWindow).window; |
|
0 commit comments