feat(auth, learning): password toggle (#591) and return-to-video from quiz (#561) with e2e test#941
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves UX in the frontend auth flows by adding a reusable password visibility toggle and wiring it into login/signup/confirm-password fields, and adds a Playwright E2E test that validates the quiz → “rewatch previous video” navigation flow using full request mocks.
Changes:
- Added
PasswordVisibilityToggleUI component and integrated it into auth password inputs. - Adjusted Google login role resolution (new users default to
student) and some redirect/error handling. - Added a mocked Playwright E2E test for quiz → video “rewatch” navigation.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
frontend/src/components/ui/password-visibility-toggle.tsx |
New reusable toggle button component for password visibility. |
frontend/src/components/Auth/AuthPage.tsx |
Integrates the toggle into auth UI; tweaks Google login role + error handling; disables Google button based on Firebase config. |
frontend/src/app/pages/auth-page.tsx |
Integrates the toggle into the app auth page; adjusts Google login redirect + error parsing; switches image references to public paths. |
e2e/tests/mock-return-to-video.spec.ts |
New Playwright test with full network mocking for quiz → video navigation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -1,4 +1,4 @@ | |||
| import { loginWithGoogle, loginWithEmail } from "@/lib/firebase"; | |||
| import { loginWithGoogle, loginWithEmail, isFirebaseConfigured } from "@/lib/firebase"; | |||
There was a problem hiding this comment.
isFirebaseConfigured is imported from @/lib/firebase but that module doesn't export it, so this file will fail to compile. Either export an isFirebaseConfigured boolean/function from frontend/src/lib/firebase.ts (and call it here if it's a function), or remove this import and adjust the disabled logic accordingly.
| console.error("Google Login Failed", error); | ||
| const message = error instanceof Error ? error.message : "Failed to sign in with Google. Please try again."; | ||
| setFormErrors({ | ||
| ...formErrors, | ||
| auth: "Failed to sign in with Google. Please try again." | ||
| auth: message | ||
| }); |
There was a problem hiding this comment.
This uses error.message directly for the user-facing auth error. For Firebase errors this is typically a technical string (e.g. Firebase: Error (auth/...)) and can regress UX compared to a friendly message. Consider mapping known Firebase error codes/messages to user-friendly copy (similar to sendPasswordResetEmail), and falling back to the generic message.
| size="icon" | ||
| onClick={onToggle} | ||
| data-state={visible ? "visible" : "hidden"} | ||
| aria-label={visible ? `Hide ${label}` : `Show ${label}`} |
There was a problem hiding this comment.
This toggle button controls a binary state (show/hide). For better screen-reader support, add aria-pressed={visible} (and optionally aria-controls pointing at the associated password input) so assistive tech can announce the current toggle state.
| aria-label={visible ? `Hide ${label}` : `Show ${label}`} | |
| aria-label={visible ? `Hide ${label}` : `Show ${label}`} | |
| aria-pressed={visible} |
| } catch (error) { | ||
| console.error("Google Login Failed", error); | ||
| setFormErrors({ | ||
| ...formErrors, | ||
| auth: "Failed to sign in with Google. Please try again." | ||
| auth: error instanceof Error ? error.message : "Failed to sign in with Google. Please try again." | ||
| }); |
There was a problem hiding this comment.
This sets the auth error to error.message directly, which for Firebase errors is usually a technical string (e.g. Firebase: Error (auth/...)) and may not be appropriate for end users. Consider translating known Firebase error codes/messages into friendly copy and falling back to the generic message.
| if (fallbackApiCalls.length > 0) { | ||
| console.log('Unhandled mock API calls:', fallbackApiCalls.join(', ')); | ||
| } |
There was a problem hiding this comment.
The test tracks fallbackApiCalls (unhandled API requests) but only logs them; it still passes even if the UI makes unexpected backend calls, which reduces the value of a “full mocks only” test. Consider asserting fallbackApiCalls is empty (or fulfilling unhandled API calls with a failing status) so the test fails when mocks are incomplete.
| if (fallbackApiCalls.length > 0) { | |
| console.log('Unhandled mock API calls:', fallbackApiCalls.join(', ')); | |
| } | |
| expect( | |
| fallbackApiCalls, | |
| `Unhandled mock API calls: ${fallbackApiCalls.join(', ')}` | |
| ).toEqual([]); |
75927d6 to
d3b3e7f
Compare
Summary
Implements two user experience improvements:
Also includes a mocked Playwright E2E test to validate the quiz-to-video flow.
What Changed
Why
Scope
Files Included
password-visibility-toggle.tsxAuthPage.tsxauth-page.tsxmock-return-to-video.spec.tsValidation