|
1 | 1 | import '@testing-library/jest-dom';
|
2 |
| -import React from 'react'; |
| 2 | +import React, { PropsWithChildren } from 'react'; |
3 | 3 | import { render, fireEvent, screen } from '@testing-library/react';
|
4 | 4 | import App from './App';
|
| 5 | +import packageJson from '../package.json'; |
| 6 | + |
| 7 | +const mockDescope = jest.fn(); |
| 8 | +const mockAuthProvider = jest.fn(); |
5 | 9 |
|
6 | 10 | jest.mock('@descope/react-sdk', () => ({
|
7 | 11 | ...jest.requireActual('@descope/react-sdk'),
|
8 |
| - Descope: jest.fn(() => <div />) |
| 12 | + Descope: (props: unknown) => { |
| 13 | + mockDescope(props); |
| 14 | + return <div />; |
| 15 | + }, |
| 16 | + AuthProvider: (props: PropsWithChildren<{ [key: string]: string }>) => { |
| 17 | + const { children } = props; |
| 18 | + mockAuthProvider(props); |
| 19 | + return <div>{children}</div>; |
| 20 | + } |
9 | 21 | }));
|
10 | 22 |
|
11 |
| -describe('App component', () => { |
12 |
| - beforeEach(() => { |
13 |
| - jest.resetModules(); |
14 |
| - process.env.DESCOPE_PROJECT_ID = ''; |
15 |
| - }); |
| 23 | +const validProjectId = 'P2Sn0gttY5sY4Zu6WDGAAEJ4VTrv'; |
| 24 | +const invalidProjectId = 'P2Qbs5l8F1kD1g2inbBktiCDumm'; |
| 25 | +const baseUrl = 'https://api.descope.test'; |
| 26 | +const flowId = 'test'; |
| 27 | +const debug = true; |
16 | 28 |
|
17 |
| - test('displays Welcome component when projectId is missing', async () => { |
| 29 | +describe('App component', () => { |
| 30 | + beforeAll(() => { |
18 | 31 | Object.defineProperty(window, 'location', {
|
19 | 32 | value: {
|
20 |
| - pathname: '/invalid-project-id' |
| 33 | + href: 'http://localhost:3000/', |
| 34 | + pathname: '', |
| 35 | + origin: 'http://localhost:3000', |
| 36 | + replace: jest.fn((href: string) => { |
| 37 | + window.location.href = href; |
| 38 | + }) |
21 | 39 | },
|
22 |
| - writable: true // possibility to override |
| 40 | + writable: true |
23 | 41 | });
|
24 |
| - Object.assign(navigator, { |
25 |
| - clipboard: { |
26 |
| - writeText: () => undefined |
| 42 | + Object.defineProperty(navigator, 'clipboard', { |
| 43 | + value: { |
| 44 | + writeText: jest.fn() |
27 | 45 | }
|
28 | 46 | });
|
| 47 | + }); |
| 48 | + |
| 49 | + beforeEach(() => { |
| 50 | + jest.resetModules(); |
| 51 | + process.env.DESCOPE_PROJECT_ID = ''; |
| 52 | + window.location.pathname = ''; |
| 53 | + window.localStorage.clear(); |
| 54 | + }); |
| 55 | + |
| 56 | + test('displays Welcome component when projectId is missing', async () => { |
| 57 | + window.location.pathname = `/${packageJson.homepage}/${invalidProjectId}`; |
29 | 58 |
|
30 | 59 | render(<App />);
|
31 | 60 | expect(screen.getByTestId('welcome-component')).toBeInTheDocument();
|
32 | 61 | expect(screen.getByTestId('welcome-copy-component')).toBeInTheDocument();
|
33 | 62 | expect(screen.getByTestId('welcome-copy-icon')).toBeInTheDocument();
|
34 | 63 | fireEvent.click(screen.getByTestId('welcome-copy-component'));
|
35 | 64 | await screen.findByTestId('welcome-copied-icon');
|
| 65 | + expect(screen.getByTestId('welcome-component')).toHaveTextContent( |
| 66 | + `/${packageJson.homepage}/` |
| 67 | + ); |
36 | 68 | });
|
37 | 69 |
|
38 | 70 | test('displays Descope component when projectId is valid and part of the location', async () => {
|
39 |
| - Object.defineProperty(window, 'location', { |
40 |
| - value: { |
41 |
| - pathname: '/P2Qbs5l8F1kD1g2inbBktiCDummy' |
42 |
| - }, |
43 |
| - writable: true // possibility to override |
44 |
| - }); |
| 71 | + window.location.pathname = `/${packageJson.homepage}/${validProjectId}`; |
45 | 72 | render(<App />);
|
46 | 73 | expect(screen.getByTestId('descope-component')).toBeInTheDocument();
|
47 | 74 | });
|
48 | 75 |
|
49 |
| - test('displays Descope component when projectId is invalid and part of the location', async () => { |
50 |
| - Object.defineProperty(window, 'location', { |
51 |
| - value: { |
52 |
| - pathname: '/P2Qbs5l8F1kD1g2inbBktiCDumm' |
53 |
| - }, |
54 |
| - writable: true // possibility to override |
55 |
| - }); |
| 76 | + test('displays welcome component when projectId is invalid and part of the location', async () => { |
| 77 | + window.location.pathname = `/${packageJson.homepage}/${invalidProjectId}`; |
56 | 78 | render(<App />);
|
57 | 79 | expect(screen.getByTestId('welcome-component')).toBeInTheDocument();
|
58 | 80 | });
|
59 | 81 |
|
60 | 82 | test('displays Descope component when projectId is valid and as an env var', async () => {
|
61 |
| - process.env.DESCOPE_PROJECT_ID = 'P2Qbs5l8F1kD1g2inbBktiCDummy'; |
| 83 | + process.env.DESCOPE_PROJECT_ID = validProjectId; |
62 | 84 | render(<App />);
|
63 | 85 | expect(screen.getByTestId('descope-component')).toBeInTheDocument();
|
64 | 86 | });
|
65 | 87 |
|
66 |
| - test('displays Descope component when projectId is invalid and as an env var', async () => { |
67 |
| - process.env.DESCOPE_PROJECT_ID = 'P2Qbs5l8F1kD1g2inbBktiCDumm'; |
| 88 | + test('displays welcome component when projectId is invalid and as an env var', async () => { |
| 89 | + process.env.DESCOPE_PROJECT_ID = invalidProjectId; |
68 | 90 | render(<App />);
|
69 | 91 | expect(screen.getByTestId('welcome-component')).toBeInTheDocument();
|
70 | 92 | });
|
71 | 93 |
|
72 | 94 | test('displays Descope component when projectId is valid and part of the location and env', async () => {
|
73 |
| - process.env.DESCOPE_PROJECT_ID = 'P2Qbs5l8F1kD1g2inbBktiCDummk'; |
74 |
| - Object.defineProperty(window, 'location', { |
75 |
| - value: { |
76 |
| - pathname: '/P2Qbs5l8F1kD1g2inbBktiCDummy' |
77 |
| - }, |
78 |
| - writable: true // possibility to override |
79 |
| - }); |
| 95 | + process.env.DESCOPE_PROJECT_ID = validProjectId; |
| 96 | + window.location.pathname = `/${packageJson.homepage}/${validProjectId}`; |
| 97 | + render(<App />); |
| 98 | + expect(screen.getByTestId('descope-component')).toBeInTheDocument(); |
| 99 | + }); |
| 100 | + |
| 101 | + test('that the projectid is removed from the url', async () => { |
| 102 | + window.location.pathname = `/${packageJson.homepage}/${validProjectId}`; |
80 | 103 | render(<App />);
|
81 | 104 | expect(screen.getByTestId('descope-component')).toBeInTheDocument();
|
| 105 | + expect(window.location.pathname).toBe(`/${packageJson.homepage}/`); |
| 106 | + }); |
| 107 | + |
| 108 | + test('that the baseUrl is the same as the origin', async () => { |
| 109 | + Object.defineProperty(window.location, 'origin', { |
| 110 | + value: baseUrl |
| 111 | + }); |
| 112 | + window.location.pathname = `/${packageJson.homepage}/${validProjectId}`; |
| 113 | + render(<App />); |
| 114 | + expect(mockAuthProvider).toHaveBeenCalledWith( |
| 115 | + expect.objectContaining({ baseUrl }) |
| 116 | + ); |
| 117 | + }); |
| 118 | + |
| 119 | + test('that the flow can be customized with env', async () => { |
| 120 | + process.env.REACT_APP_DESCOPE_BASE_URL = baseUrl; |
| 121 | + process.env.DESCOPE_FLOW_ID = flowId; |
| 122 | + process.env.DESCOPE_FLOW_DEBUG = debug.toString(); |
| 123 | + |
| 124 | + window.location.pathname = `/${packageJson.homepage}/${validProjectId}`; |
| 125 | + render(<App />); |
| 126 | + expect(mockAuthProvider).toHaveBeenCalledWith( |
| 127 | + expect.objectContaining({ baseUrl }) |
| 128 | + ); |
| 129 | + expect(mockDescope).toHaveBeenCalledWith( |
| 130 | + expect.objectContaining({ debug, flowId }) |
| 131 | + ); |
| 132 | + }); |
| 133 | + |
| 134 | + test('that the flow can be customized with search params', async () => { |
| 135 | + window.location.pathname = `/${packageJson.homepage}/${validProjectId}`; |
| 136 | + window.location.search = `?debug=${debug}&flow=${flowId}`; |
| 137 | + render(<App />); |
| 138 | + expect(mockDescope).toHaveBeenCalledWith( |
| 139 | + expect.objectContaining({ debug, flowId }) |
| 140 | + ); |
82 | 141 | });
|
83 | 142 | });
|
0 commit comments