From f655585cc81ab4af5d27cebb1fa9390e93e0a4bf Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Sat, 6 Dec 2025 18:55:57 +0900
Subject: feat(client): add protected route handling with login redirect
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Unauthenticated users accessing protected pages (like HomePage) are
now redirected to the login page. Includes ProtectedRoute component
with loading state support.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
---
 src/client/App.test.tsx | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

(limited to 'src/client/App.test.tsx')

diff --git a/src/client/App.test.tsx b/src/client/App.test.tsx
index f4e3541..321f073 100644
--- a/src/client/App.test.tsx
+++ b/src/client/App.test.tsx
@@ -52,10 +52,33 @@ afterEach(() => {
 });
 
 describe("App routing", () => {
-	it("renders home page at /", () => {
-		renderWithRouter("/");
-		expect(screen.getByRole("heading", { name: "Kioku" })).toBeDefined();
-		expect(screen.getByText("Spaced repetition learning app")).toBeDefined();
+	describe("when authenticated", () => {
+		beforeEach(() => {
+			vi.mocked(apiClient.getTokens).mockReturnValue({
+				accessToken: "access-token",
+				refreshToken: "refresh-token",
+			});
+			vi.mocked(apiClient.isAuthenticated).mockReturnValue(true);
+		});
+
+		it("renders home page at /", () => {
+			renderWithRouter("/");
+			expect(screen.getByRole("heading", { name: "Kioku" })).toBeDefined();
+			expect(screen.getByText("Spaced repetition learning app")).toBeDefined();
+		});
+	});
+
+	describe("when not authenticated", () => {
+		beforeEach(() => {
+			vi.mocked(apiClient.getTokens).mockReturnValue(null);
+			vi.mocked(apiClient.isAuthenticated).mockReturnValue(false);
+		});
+
+		it("redirects to login when accessing / without authentication", () => {
+			renderWithRouter("/");
+			// Should not render home page content
+			expect(screen.queryByRole("heading", { name: "Kioku" })).toBeNull();
+		});
 	});
 
 	it("renders login page at /login", () => {
-- 
cgit v1.2.3-70-g09d2

