Skip to content

feat: implement UI side of google auth#6

Merged
sjlangley merged 8 commits intomainfrom
ui/auth
Apr 7, 2026
Merged

feat: implement UI side of google auth#6
sjlangley merged 8 commits intomainfrom
ui/auth

Conversation

@sjlangley
Copy link
Copy Markdown
Owner

No description provided.

- Add GoogleSignInButton component with Google Identity Services integration
- Add LoggedInScreen component to display authenticated user info
- Implement auth state management with AuthProvider and useAuth hook
- Add API client functions (login, logout, getCurrentUser)
- Update App.tsx with auth flow: loading -> unauthenticated -> authenticated
- Fix CORS configuration to allow credentials for session cookies
- Add comprehensive test coverage for all new components (20 tests)
- Add environment variable examples for both UI and API
- Update HTML to include Google Identity Services script

Users can now sign in with Google, and the app displays their user
information fetched from the /user/current API endpoint, validating
the end-to-end authentication flow.
- Add 'Completed' section showing Google authentication is live
- Add 'Getting Started' guide for backend and frontend setup
- Include prerequisites, setup steps, and test running instructions
- Document required environment configuration
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 7, 2026

Codecov Report

❌ Patch coverage is 93.15068% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
apps/ui/src/components/GoogleSignInButton.tsx 78.72% 8 Missing and 2 partials ⚠️
Flag Coverage Δ
api 93.66% <ø> (ø)
ui 93.15% <93.15%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
apps/api/src/api/app.py 93.33% <ø> (ø)
apps/ui/src/App.tsx 100.00% <100.00%> (ø)
apps/ui/src/components/LoggedInScreen.tsx 100.00% <100.00%> (ø)
apps/ui/src/lib/api.ts 100.00% <100.00%> (ø)
apps/ui/src/lib/auth.tsx 100.00% <100.00%> (ø)
apps/ui/src/components/GoogleSignInButton.tsx 78.72% <78.72%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements the UI flow for Google OAuth sign-in, including an auth context/provider, API client wiring for session cookies, and basic authenticated/unauthenticated screens.

Changes:

  • Added UI auth state management (AuthProvider/useAuth) plus API helpers to login/logout and fetch the current user.
  • Introduced Google Identity Services sign-in button + logged-in screen, and updated App to render based on auth state.
  • Added frontend tests and updated docs/env examples; enabled credentialed CORS on the API.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
README.md Updates project status and adds local setup + test commands.
apps/ui/tests/App.test.tsx Updates App tests to cover loading/authenticated/unauthenticated rendering.
apps/ui/tests/GoogleSignInButton.test.tsx Adds tests for GIS loading/config/errors and login callback behavior.
apps/ui/tests/LoggedInScreen.test.tsx Adds tests for displaying user info and logout behavior.
apps/ui/src/types/google.d.ts Adds global typings for window.google Google Identity Services API surface.
apps/ui/src/types/api.ts Defines shared UI User type matching backend responses.
apps/ui/src/main.tsx Wraps the app in AuthProvider so auth state is available globally.
apps/ui/src/lib/auth.tsx Implements auth state machine (loading/authenticated/unauthenticated) and actions.
apps/ui/src/lib/api.ts Adds API client functions for login/logout/current-user with cookie credentials.
apps/ui/src/components/LoggedInScreen.tsx Adds a logged-in view with user details and logout button.
apps/ui/src/components/GoogleSignInButton.tsx Renders Google GIS button and triggers login via ID token callback.
apps/ui/src/App.tsx Switches UI to auth-gated screens (loading / sign-in / logged-in).
apps/ui/src/App.css Adds styling for the login and logged-in screens.
apps/ui/index.html Sets the app title and loads the Google Identity Services script.
apps/ui/.env.example Documents required UI env vars (client ID, API base URL).
apps/api/src/api/app.py Enables allow_credentials=True for CORS to support session cookies.
apps/api/.env.example Documents API env vars for OAuth, CORS origins, and session secret.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/ui/src/components/GoogleSignInButton.tsx Outdated
Comment thread apps/ui/src/components/GoogleSignInButton.tsx Outdated
Comment thread apps/ui/src/components/GoogleSignInButton.tsx
Comment thread apps/ui/src/components/LoggedInScreen.tsx Outdated
Comment thread apps/api/.env.example Outdated
sjlangley and others added 6 commits April 7, 2026 18:48
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
- Move GOOGLE_CLIENT_ID inside component for better testability
- Add upfront env var validation with immediate error feedback
- Add 10s timeout to SDK polling to prevent infinite checks
- Add initialization guard to prevent double-rendering in React StrictMode
- Clear container HTML before rendering to prevent duplicates
- Remove dead error handling test in LoggedInScreen (now in AuthProvider)

Addresses PR comments from copilot-pull-request-reviewer
- Move env var validation after all hooks (hooks must be unconditional)
- Add GOOGLE_CLIENT_ID check in useEffect to prevent init if missing
- Add eslint-disable comment for GOOGLE_CLIENT_ID dependency
- All hooks now called unconditionally at component top level
- Run prettier --write to fix formatting in GoogleSignInButton and tests
- Update CLAUDE.md PR guidelines to include format:check validation
- Add format:check step to both UI and API pre-submission checklists

This prevents CI failures from formatting issues.
Add 19 new tests to increase UI code coverage from 46.66% to 85%:

- api.test.ts (9 tests): Complete coverage of login, logout, getCurrentUser
  - Success and error scenarios for all API functions
  - Abort signal handling
  - Relative vs absolute URL paths

- auth.test.tsx (10 tests): Complete coverage of AuthProvider and useAuth
  - Initial auth check and state transitions
  - Login flow with Google token
  - Logout flow with error handling
  - Abort error handling on unmount
  - Context usage validation

Coverage breakdown:
- src/lib/api.ts: 0% → 100%
- src/lib/auth.tsx: 1.72% → 96.55%
- Overall: 46.66% → 85% (exceeds 80% target)

All 38 tests passing with no warnings.
@sjlangley
Copy link
Copy Markdown
Owner Author

PR Review Comments Addressed

All review comments from @copilot-pull-request-reviewer have been addressed in commits 9815d29, d86127c, and 2361b81:

✅ Comment 1: Environment Variable Validation

Issue: Client ID validated inside effect but loading state renders first. Missing config shows "Loading..." until SDK loads, then error logs.

Fixed:

  • Moved GOOGLE_CLIENT_ID read inside component for better testability
  • Validation now occurs after hooks (fixes Rules of Hooks violation) but still shows immediate error
  • Added upfront check in second useEffect to prevent initialization if missing
  • Error surfaces immediately when component renders

Code: GoogleSignInButton.tsx#L18-L27


✅ Comment 2: Polling Timeout

Issue: setInterval polls every 100ms indefinitely if Google SDK fails to load (network error, blocked scripts). Causes unnecessary CPU wakeups.

Fixed:

  • Added GOOGLE_SDK_TIMEOUT_MS = 10000 (10 seconds)
  • Implemented poll count tracking with maxPolls calculation
  • Added sdkLoadError state to handle timeout
  • Shows clear error message: "Failed to load Google Sign-In. Please check your internet connection and ensure third-party scripts are not blocked."

Code: GoogleSignInButton.tsx#L31-L53


✅ Comment 3: Double Initialization

Issue: initialize/renderButton runs in effect with no cleanup. React StrictMode triggers effects twice in dev mode. Causes duplicate button rendering.

Fixed:

  • Added initializationRef to guard against double-initialization
  • Clear container innerHTML before rendering to prevent duplicates
  • Cleanup function resets initializationRef on unmount
  • Now idempotent and StrictMode-safe

Code: GoogleSignInButton.tsx#L61-L102


✅ Comment 4: LoggedInScreen Dead Code (RESOLVED)

Issue: try/catch in LoggedInScreen is dead code since AuthProvider.logout doesn't rethrow.

Fixed:

  • Removed try/catch from handleLogout in LoggedInScreen
  • Removed corresponding test that expected component-level error handling
  • Error handling now centralized in AuthProvider as intended

Code: LoggedInScreen.tsx#L16-L18


✅ Comment 5: ALLOWED_HOSTED_DOMAINS Documentation (RESOLVED)

Issue: Comments suggested comma-separated values but Pydantic expects JSON array format.

Fixed: Already correctly documented as JSON array format in .env.example


Additional Improvements

Code Quality

  • Fixed ESLint Rules of Hooks violation by moving all hooks to component top level
  • Applied Prettier formatting to all modified files
  • Updated CLAUDE.md with format:check in pre-push checklist to prevent future CI failures

Test Coverage

  • Added comprehensive tests for api.ts (9 tests) - 0% → 100% coverage
  • Added comprehensive tests for auth.tsx (10 tests) - 1.72% → 96.55% coverage
  • Overall UI coverage: 46.66% → 85% (exceeds 80% target)
  • All 38 tests passing with no warnings

Verification

npm run lint - 0 errors
npm run format:check - All files formatted
npm run test:ci - 38/38 tests passing, 85% coverage
npm run build - TypeScript compilation successful

All commits follow conventional commits format and are ready for review.

@sjlangley sjlangley merged commit 031e37d into main Apr 7, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants