Added a dark/light theme toggle button to the UI, allowing users to switch between the existing dark theme and a new light theme.
-
Light theme CSS variables — Added a
[data-theme="light"]block after:rootwith a full set of overrides:- Background:
#f8fafc(near-white) - Surface:
#ffffff - Surface hover:
#f1f5f9 - Text primary:
#0f172a(near-black for high contrast) - Text secondary:
#64748b - Border color:
#e2e8f0 - Assistant message bg:
#f1f5f9 - Shadow: lighter
rgba(0,0,0,0.1)drop shadow - Welcome background:
#dbeafe - Primary/accent colors unchanged (
#2563eb)
- Background:
-
Body transition — Added
transition: background-color 0.3s ease, color 0.3s easetobodyso theme switches animate smoothly. -
.theme-togglebutton styles — New styles for a fixed, circular button positioned attop: 1rem; right: 1rem:- 40x40px circle with border and surface background
- Hover: scales up 10%, highlights with primary color border
- Focus ring using
--focus-ringvariable for accessibility - Active state: slight scale-down press effect
- Sun/moon SVG icons absolutely positioned within the button, animated with opacity and rotation transitions
- In dark mode (default): sun icon visible, moon icon hidden
- In light mode (
[data-theme="light"]): moon icon visible, sun icon hidden
- Added a
<button class="theme-toggle" id="themeToggle">element just before the closing</body>tag - Contains two inline SVGs:
.icon-sun— rays + circle sun, shown in dark mode (click to switch to light).icon-moon— crescent moon path, shown in light mode (click to switch to dark)
aria-label="Toggle theme"andtitleattribute for accessibility and tooltip
-
initTheme()— ReadslocalStorage.getItem('theme'); if'light', setsdata-theme="light"on<html>so the chosen theme persists across page reloads. -
toggleTheme()— Checks currentdata-themeon<html>:- If light: removes attribute (reverts to default dark), saves
'dark'tolocalStorage - If dark: sets
data-theme="light", saves'light'tolocalStorage
- If light: removes attribute (reverts to default dark), saves
-
setupEventListeners()— WiresthemeToggle.addEventListener('click', toggleTheme). -
DOMContentLoadedhandler — GrabsthemeToggleelement and callsinitTheme()before session setup.
No frontend changes were made for the testing feature. This enhancement targeted the backend testing infrastructure only.
- Added shared test data constants:
SAMPLE_ANSWER,SAMPLE_SOURCES,SAMPLE_SESSION_ID,SAMPLE_COURSES - Added
mock_ragfixture — a fully mockedRAGSystemwith pre-configured return values - Added
make_test_app(rag_system)helper — builds a minimal FastAPI app with the same/api/query,/api/courses, and/api/session/{id}endpoints but without the static file mount, avoiding file-system dependency on../frontend/ - Added
test_appandclientfixtures that composemake_test_app+starlette.testclient.TestClient
16 tests across three classes:
TestQueryEndpoint—POST /api/query: status codes, response shape, session creation vs reuse, RAG delegation, 500 on error, 422 on missing fieldTestCoursesEndpoint—GET /api/courses: status code, response shape, mocked data, 500 on errorTestSessionEndpoint—DELETE /api/session/{id}: status code, response body, correct ID forwarded tosession_manager.clear_session
- Added
httpx>=0.27.0to[dependency-groups] dev(required bystarlette.testclient.TestClient) - Added
[tool.pytest.ini_options]section:testpaths = ["backend/tests"]— pytest discovers tests without specifying the path manuallypythonpath = ["backend"]— backend modules importable withoutsys.pathhacks in each test fileaddopts = "-v"— verbose output by default