Skip to content

Commit 9909602

Browse files
committed
Add tests for ProtectedRoute component
Introduces a comprehensive test suite for the ProtectedRoute component, covering scenarios for authentication, loading state, fallback and redirect behavior, and error handling. This improves test coverage and ensures correct behavior under various conditions.
1 parent e15f3cc commit 9909602

File tree

2 files changed

+170
-1
lines changed

2 files changed

+170
-1
lines changed

packages/tanstack-router/esbuild.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ await build({
5050
format: 'cjs',
5151
outfile: 'dist/cjs/index.js',
5252
sourcemap: true,
53-
});
53+
});
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/**
2+
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
import { describe, it, expect, vi, beforeEach } from 'vitest';
20+
import { render, screen } from '@testing-library/react';
21+
import ProtectedRoute from '../ProtectedRoute';
22+
import { useAsgardeo } from '@asgardeo/react';
23+
24+
// Mock the dependencies
25+
vi.mock('@asgardeo/react', () => ({
26+
useAsgardeo: vi.fn(),
27+
AsgardeoRuntimeError: class AsgardeoRuntimeError extends Error {
28+
code: string;
29+
component: string;
30+
traceId: string | undefined;
31+
32+
constructor(message: string, code: string, component: string, traceId?: string) {
33+
super(message);
34+
this.name = 'AsgardeoRuntimeError';
35+
this.code = code;
36+
this.component = component;
37+
this.traceId = traceId;
38+
}
39+
},
40+
}));
41+
42+
vi.mock('@tanstack/react-router', () => ({
43+
Navigate: ({ to }: { to: string }) => <div data-testid="navigate">Navigate to: {to}</div>,
44+
}));
45+
46+
describe('ProtectedRoute', () => {
47+
beforeEach(() => {
48+
vi.clearAllMocks();
49+
});
50+
51+
it('should render loader when isLoading is true', () => {
52+
vi.mocked(useAsgardeo).mockReturnValue({
53+
isSignedIn: false,
54+
isLoading: true,
55+
} as any);
56+
57+
render(
58+
<ProtectedRoute redirectTo="/signin" loader={<div data-testid="loader">Loading...</div>}>
59+
<div data-testid="protected-content">Protected Content</div>
60+
</ProtectedRoute>
61+
);
62+
63+
expect(screen.getByTestId('loader')).toBeDefined();
64+
expect(screen.queryByTestId('protected-content')).toBeNull();
65+
});
66+
67+
it('should render children when user is authenticated', () => {
68+
vi.mocked(useAsgardeo).mockReturnValue({
69+
isSignedIn: true,
70+
isLoading: false,
71+
} as any);
72+
73+
render(
74+
<ProtectedRoute redirectTo="/signin">
75+
<div data-testid="protected-content">Protected Content</div>
76+
</ProtectedRoute>
77+
);
78+
79+
expect(screen.getByTestId('protected-content')).toBeDefined();
80+
});
81+
82+
it('should render fallback when user is not authenticated and fallback is provided', () => {
83+
vi.mocked(useAsgardeo).mockReturnValue({
84+
isSignedIn: false,
85+
isLoading: false,
86+
} as any);
87+
88+
render(
89+
<ProtectedRoute
90+
redirectTo="/signin"
91+
fallback={<div data-testid="fallback">Access Denied</div>}
92+
>
93+
<div data-testid="protected-content">Protected Content</div>
94+
</ProtectedRoute>
95+
);
96+
97+
expect(screen.getByTestId('fallback')).toBeDefined();
98+
expect(screen.queryByTestId('protected-content')).toBeNull();
99+
});
100+
101+
it('should navigate to redirectTo when user is not authenticated and no fallback is provided', () => {
102+
vi.mocked(useAsgardeo).mockReturnValue({
103+
isSignedIn: false,
104+
isLoading: false,
105+
} as any);
106+
107+
render(
108+
<ProtectedRoute redirectTo="/signin">
109+
<div data-testid="protected-content">Protected Content</div>
110+
</ProtectedRoute>
111+
);
112+
113+
const navigate = screen.getByTestId('navigate');
114+
expect(navigate).toBeDefined();
115+
expect(navigate.textContent).toBe('Navigate to: /signin');
116+
expect(screen.queryByTestId('protected-content')).toBeNull();
117+
});
118+
119+
it('should throw error when neither fallback nor redirectTo is provided', () => {
120+
vi.mocked(useAsgardeo).mockReturnValue({
121+
isSignedIn: false,
122+
isLoading: false,
123+
} as any);
124+
125+
expect(() => {
126+
render(
127+
<ProtectedRoute>
128+
<div data-testid="protected-content">Protected Content</div>
129+
</ProtectedRoute>
130+
);
131+
}).toThrow('"fallback" or "redirectTo" prop is required.');
132+
});
133+
134+
it('should render null loader by default when isLoading is true and no loader is provided', () => {
135+
vi.mocked(useAsgardeo).mockReturnValue({
136+
isSignedIn: false,
137+
isLoading: true,
138+
} as any);
139+
140+
const { container } = render(
141+
<ProtectedRoute redirectTo="/signin">
142+
<div data-testid="protected-content">Protected Content</div>
143+
</ProtectedRoute>
144+
);
145+
146+
expect(container.textContent).toBe('');
147+
expect(screen.queryByTestId('protected-content')).toBeNull();
148+
});
149+
150+
it('should prioritize fallback over redirectTo when both are provided', () => {
151+
vi.mocked(useAsgardeo).mockReturnValue({
152+
isSignedIn: false,
153+
isLoading: false,
154+
} as any);
155+
156+
render(
157+
<ProtectedRoute
158+
redirectTo="/signin"
159+
fallback={<div data-testid="fallback">Custom Fallback</div>}
160+
>
161+
<div data-testid="protected-content">Protected Content</div>
162+
</ProtectedRoute>
163+
);
164+
165+
expect(screen.getByTestId('fallback')).toBeDefined();
166+
expect(screen.queryByTestId('navigate')).toBeNull();
167+
expect(screen.queryByTestId('protected-content')).toBeNull();
168+
});
169+
});

0 commit comments

Comments
 (0)