Compare commits
6 Commits
worktree-p
...
e652e4b7b3
| Author | SHA1 | Date | |
|---|---|---|---|
| e652e4b7b3 | |||
| 9b45ece68f | |||
| be83262644 | |||
| cd1dd8ddff | |||
| b6ff4923e4 | |||
| 055ef051ca |
72
AGENTS.md
72
AGENTS.md
@@ -12,17 +12,87 @@
|
||||
## Code Quality
|
||||
- Keep cyclomatic complexity under 10 per function
|
||||
- Aim for files under 300 lines
|
||||
- All files must follow single responsibility principle (one clear purpose per module)
|
||||
- Extract complex logic into reusable utilities/services
|
||||
|
||||
## Testing
|
||||
|
||||
### Standard Testing (Ongoing)
|
||||
- Write unit tests for all utility functions
|
||||
- Minimum 80% coverage on new code
|
||||
- Use Vitest for unit tests
|
||||
|
||||
### AI-Friendly Refactoring Testing Strategy (v1.10.16+)
|
||||
**Scope:** Full test coverage before refactoring to prevent UI/functionality regression.
|
||||
|
||||
**Backend Testing (Pytest)**
|
||||
- Target: 85%+ coverage (unit + integration tests)
|
||||
- Structure: `backend/tests/` with suites for routers, models, auth, AI pipeline
|
||||
- Coverage tools: `pytest backend/tests/ --cov=backend --cov-report=html`
|
||||
- Test types: Unit (functions), Integration (full API workflows), Fixtures (mocked auth, in-memory DB)
|
||||
|
||||
**Frontend Testing (Vitest)**
|
||||
- Target: 80%+ coverage (components, hooks, snapshots)
|
||||
- Structure: `frontend/tests/` with component tests, hook tests, integration workflows
|
||||
- Coverage tools: `npm test -- --coverage`
|
||||
- Test types: Component rendering, Hook state/side effects, Snapshot tests for UI layouts
|
||||
|
||||
**E2E Testing (Playwright)**
|
||||
- Target: Critical user workflows automated
|
||||
- Workflows: Login, Scan → Match → Stock adjustment, New Item (AI), Admin config, Offline sync
|
||||
- Runtime: ~30 min total
|
||||
- Command: `npx playwright test`
|
||||
|
||||
**Test-First Approach**
|
||||
- All tests written and passing BEFORE refactoring any code
|
||||
- Tests serve as gating condition: no code changes if tests fail
|
||||
- Functional preservation: Zero behavior changes post-refactor
|
||||
- Regression prevention: Manual checklist + automated tests catch UI breakage
|
||||
|
||||
## Security
|
||||
- Store all secrets in inventory.env — never hardcode credentials
|
||||
- Never log API keys, tokens or passwords
|
||||
- Validate all user input before processing
|
||||
|
||||
## Git Conventions
|
||||
- Use conventional commits (feat:, fix:, docs:, etc.)
|
||||
- Use conventional commits (feat:, fix:, docs:, refactor:, test:, etc.)
|
||||
- Keep PRs under 400 lines of diff when possible
|
||||
- Refactoring commits: `refactor: split {module} into smaller modules`
|
||||
- Testing commits: `test: add {suite} coverage for {module}`
|
||||
- All commits must have passing test suite before merge
|
||||
|
||||
## Refactoring Guidelines (AI-Friendly Modularity)
|
||||
|
||||
### Refactoring Principles
|
||||
- **Target:** Break monolithic files into focused modules (<300 lines each)
|
||||
- **Priority Order:** Backend routers → Components → Pages
|
||||
- **No Behavior Changes:** Every refactor must pass 100% of existing tests
|
||||
- **Gating Rule:** No refactor commit unless all tests pass (pre + post)
|
||||
- **Regression Prevention:** Manual checklist + automated tests validate UI integrity
|
||||
|
||||
### Refactoring Process
|
||||
1. Ensure full test coverage exists (backend 85%, frontend 80%)
|
||||
2. Run complete test suite (all tests PASS)
|
||||
3. Refactor module: split into smaller files/services
|
||||
4. Run test suite again (all tests PASS)
|
||||
5. Manual browser validation: UI unchanged, all buttons/features work
|
||||
6. Commit with test results in message body
|
||||
7. Move to next module
|
||||
|
||||
### Module Extraction Patterns
|
||||
- **Backend Routers:** Split into router (endpoints only) + service (business logic) + validators (input validation)
|
||||
- **Components:** Split into orchestrator component + sub-components + custom hooks for state/logic
|
||||
- **Pages:** Extract page logic into custom hooks, move forms into separate components
|
||||
- **Utilities:** Consolidate repeated logic into `lib/` or `services/` modules
|
||||
|
||||
### Validation Checklist (Post-Refactor)
|
||||
- [ ] All pytest tests passing (backend coverage 85%+)
|
||||
- [ ] All vitest tests passing (frontend coverage 80%+)
|
||||
- [ ] All e2e workflows passing (Playwright)
|
||||
- [ ] Login works (LDAP + local)
|
||||
- [ ] Scanner functional (scan → match → stock adjustment)
|
||||
- [ ] AI extraction working (new item → AI popup → validation)
|
||||
- [ ] Admin page responsive and functional
|
||||
- [ ] No console errors in browser
|
||||
- [ ] Mobile responsive (320px, 768px, 1024px+ viewports)
|
||||
- [ ] Keyboard navigation works (focus indicators visible)
|
||||
|
||||
244
REFACTORING_PROGRESS.md
Normal file
244
REFACTORING_PROGRESS.md
Normal file
@@ -0,0 +1,244 @@
|
||||
# AI-Friendly Refactoring Progress Tracker
|
||||
|
||||
**Branch:** `refactor/ai-friendly`
|
||||
**Started:** 2026-04-18
|
||||
**Status:** IN PROGRESS — Phase 1 Starting
|
||||
|
||||
---
|
||||
|
||||
## Phase Completion Summary
|
||||
|
||||
| Phase | Status | Completion | Last Updated | Commits |
|
||||
|-------|--------|------------|--------------|---------|
|
||||
| **Phase 1: Backend Tests** | ⏳ STARTING | 0% | 2026-04-18 | 0 |
|
||||
| **Phase 2: Frontend Tests** | ⏳ PENDING | 0% | — | — |
|
||||
| **Phase 3: E2E Tests** | ⏳ PENDING | 0% | — | — |
|
||||
| **Phase 4: Backend Refactor** | ⏳ PENDING | 0% | — | — |
|
||||
| **Phase 5: Component Refactor** | ⏳ PENDING | 0% | — | — |
|
||||
| **Phase 6: Page Refactor** | ⏳ PENDING | 0% | — | — |
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Backend Tests (Pytest)
|
||||
|
||||
**Target:** 85%+ coverage for `backend/routers/`, `backend/models.py`, `backend/auth.py`, `backend/ai/`
|
||||
|
||||
**Test Files to Create:**
|
||||
- [ ] `backend/tests/conftest.py` (shared fixtures)
|
||||
- [ ] `backend/tests/test_users.py` (auth, CRUD, LDAP)
|
||||
- [ ] `backend/tests/test_items.py` (item ops)
|
||||
- [ ] `backend/tests/test_operations.py` (check-in/out)
|
||||
- [ ] `backend/tests/test_categories.py` (category mgmt)
|
||||
- [ ] `backend/tests/test_ai_extraction.py` (AI pipeline)
|
||||
- [ ] `backend/tests/test_offline_sync.py` (UUID idempotency)
|
||||
|
||||
**Completion Criteria:**
|
||||
- ✅ All 7 test files created
|
||||
- ✅ `pytest backend/tests/ --cov=backend` shows **85%+ coverage**
|
||||
- ✅ All tests PASS (0 failures, 0 errors)
|
||||
- ✅ Coverage report: `pytest backend/tests/ --cov=backend --cov-report=html`
|
||||
- ✅ Git tag: `phase-1-complete` created
|
||||
- ✅ SESSION_STATE.md updated with Phase 1 status
|
||||
|
||||
**Next Steps (If Interrupted):**
|
||||
Read REFACTORING_PROGRESS.md and SESSION_STATE.md. Resume from next unchecked task.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Frontend Tests (Vitest)
|
||||
|
||||
**Target:** 80%+ coverage for components, hooks, utilities
|
||||
|
||||
**Test Files to Create:**
|
||||
- [ ] `frontend/tests/components/Scanner.test.tsx`
|
||||
- [ ] `frontend/tests/components/AIOnboarding.test.tsx`
|
||||
- [ ] `frontend/tests/components/AdminOverlay.test.tsx`
|
||||
- [ ] `frontend/tests/components/IdentityCheckOverlay.test.tsx`
|
||||
- [ ] `frontend/tests/hooks/useAdmin.test.ts`
|
||||
- [ ] `frontend/tests/lib/api.test.ts`
|
||||
- [ ] `frontend/tests/lib/labels.test.ts`
|
||||
- [ ] `frontend/tests/integration/scanner-workflow.test.tsx`
|
||||
- [ ] `frontend/tests/integration/inventory-workflow.test.tsx`
|
||||
|
||||
**Completion Criteria:**
|
||||
- ✅ All 9 test files created
|
||||
- ✅ `npm test -- --coverage` shows **80%+ coverage**
|
||||
- ✅ All tests PASS (0 failures, 0 errors)
|
||||
- ✅ Git tag: `phase-2-complete` created
|
||||
- ✅ SESSION_STATE.md updated with Phase 2 status
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: E2E Tests (Playwright)
|
||||
|
||||
**Target:** 5+ critical workflows automated
|
||||
|
||||
**E2E Workflows:**
|
||||
- [ ] Login workflow (LDAP + local)
|
||||
- [ ] Scan item → match inventory
|
||||
- [ ] Create new item (AI extraction)
|
||||
- [ ] Admin settings change
|
||||
- [ ] Offline sync (simulate network loss)
|
||||
|
||||
**Test File:**
|
||||
- [ ] `frontend/e2e/critical-workflows.spec.ts`
|
||||
|
||||
**Completion Criteria:**
|
||||
- ✅ 5+ workflows automated
|
||||
- ✅ `npx playwright test` — all passing
|
||||
- ✅ Runtime <30 min
|
||||
- ✅ Git tag: `phase-3-complete` created
|
||||
- ✅ SESSION_STATE.md updated with Phase 3 status
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Backend Refactoring
|
||||
|
||||
**Target:** Split 3 routers into smaller, focused modules
|
||||
|
||||
**Routers to Refactor:**
|
||||
1. `backend/routers/users.py` (443 lines) → Split into:
|
||||
- `backend/routers/users.py` (endpoints, <150 lines)
|
||||
- `backend/services/user_service.py` (CRUD logic)
|
||||
- `backend/validators/user_validator.py` (input validation)
|
||||
|
||||
2. `backend/routers/operations.py` (298 lines) → Split into:
|
||||
- `backend/routers/operations.py` (endpoints, <150 lines)
|
||||
- `backend/services/operation_service.py` (business logic)
|
||||
|
||||
3. `backend/routers/items.py` (240 lines) → Split into:
|
||||
- `backend/routers/items.py` (endpoints, <150 lines)
|
||||
- `backend/services/item_service.py` (business logic)
|
||||
|
||||
**Completion Criteria:**
|
||||
- ✅ All 3 routers split into service modules
|
||||
- ✅ `pytest backend/tests/ --cov=backend` — 85%+ coverage, all tests PASS
|
||||
- ✅ Zero files >300 lines
|
||||
- ✅ All functions <10 complexity
|
||||
- ✅ Git tag: `phase-4-complete` created
|
||||
- ✅ SESSION_STATE.md updated with Phase 4 status
|
||||
|
||||
**Note:** No behavior changes. Tests validate before/after refactor.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Component Refactoring
|
||||
|
||||
**Target:** Split 3 large components into sub-components + hooks
|
||||
|
||||
**Components to Refactor:**
|
||||
1. `frontend/components/AIOnboarding.tsx` (641 lines) → Split into:
|
||||
- `frontend/components/AIOnboarding.tsx` (orchestrator, <150 lines)
|
||||
- `frontend/components/AIOnboarding/StepValidator.tsx`
|
||||
- `frontend/components/AIOnboarding/ImageCapture.tsx`
|
||||
- `frontend/hooks/useAIExtraction.ts` (AI logic)
|
||||
|
||||
2. `frontend/components/Scanner.tsx` (367 lines) → Split into:
|
||||
- `frontend/components/Scanner.tsx` (container, <200 lines)
|
||||
- `frontend/components/Scanner/Viewport.tsx`
|
||||
- `frontend/components/Scanner/Controls.tsx`
|
||||
- `frontend/hooks/useScannerZoom.ts`
|
||||
|
||||
3. `frontend/components/AdminOverlay.tsx` (253 lines) → Split into:
|
||||
- `frontend/components/AdminOverlay.tsx` (orchestrator, <180 lines)
|
||||
- `frontend/components/AdminOverlay/FormFields.tsx`
|
||||
- `frontend/components/AdminOverlay/SubmitButton.tsx`
|
||||
|
||||
**Completion Criteria:**
|
||||
- ✅ All 3 components decomposed into sub-components + hooks
|
||||
- ✅ `npm test -- --coverage` — 80%+ coverage, all tests PASS
|
||||
- ✅ Manual browser test: All components render, buttons clickable
|
||||
- ✅ Git tag: `phase-5-complete` created
|
||||
- ✅ SESSION_STATE.md updated with Phase 5 status
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Page Refactoring
|
||||
|
||||
**Target:** Extract page logic into hooks, reduce file sizes
|
||||
|
||||
**Pages to Refactor:**
|
||||
1. `frontend/app/page.tsx` (979 lines) → Split into:
|
||||
- `frontend/app/page.tsx` (layout only, <100 lines)
|
||||
- `frontend/components/InventoryDashboard.tsx` (dashboard logic)
|
||||
- `frontend/hooks/useDashboardData.ts` (data fetching + state)
|
||||
|
||||
2. `frontend/app/inventory/page.tsx` (857 lines) → Split into:
|
||||
- `frontend/app/inventory/page.tsx` (layout only, <100 lines)
|
||||
- `frontend/components/InventoryManager.tsx`
|
||||
- `frontend/hooks/useInventoryManager.ts`
|
||||
|
||||
3. `frontend/app/logs/page.tsx` (341 lines) → Split into:
|
||||
- `frontend/app/logs/page.tsx` (layout, <150 lines)
|
||||
- `frontend/components/LogsView.tsx`
|
||||
- `frontend/hooks/useLogsData.ts`
|
||||
|
||||
**Completion Criteria:**
|
||||
- ✅ All 3 pages refactored into smaller modules
|
||||
- ✅ `npm test -- --coverage` — 80%+ coverage, all tests PASS
|
||||
- ✅ `npx playwright test` — all e2e tests still PASS
|
||||
- ✅ Manual browser test: All pages load, all features work
|
||||
- ✅ Git tag: `phase-6-complete` created
|
||||
- ✅ SESSION_STATE.md updated with Phase 6 status (REFACTORING COMPLETE)
|
||||
|
||||
---
|
||||
|
||||
## Multi-Session Continuity
|
||||
|
||||
**To Resume Work:**
|
||||
1. Read `REFACTORING_PROGRESS.md` (this file) — see which phase is current
|
||||
2. Read `docs/superpowers/plans/YYYY-MM-DD-phase-N.md` — see which tasks remain
|
||||
3. Read `SESSION_STATE.md` — see AI context from last session
|
||||
4. Start from next unchecked task in the plan
|
||||
5. After each task, update this file and SESSION_STATE.md
|
||||
|
||||
**Git Markers for Phase Completion:**
|
||||
```bash
|
||||
# After Phase 1 complete:
|
||||
git tag phase-1-complete
|
||||
|
||||
# After Phase 2 complete:
|
||||
git tag phase-2-complete
|
||||
|
||||
# etc.
|
||||
|
||||
# View all tags:
|
||||
git tag -l
|
||||
```
|
||||
|
||||
**Rollback Capability:**
|
||||
If a phase breaks the codebase, roll back:
|
||||
```bash
|
||||
git reset --hard phase-N-1-complete
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Session Handover Template
|
||||
|
||||
**To be updated after each session:**
|
||||
|
||||
```
|
||||
**Session End: [DATE]**
|
||||
- Phase: N
|
||||
- Completed: [Task list]
|
||||
- In Progress: [Current task]
|
||||
- Blocked: [Any blockers]
|
||||
- Next Steps: [Resume from task X in Phase N plan]
|
||||
- Git Status: [Latest commit hash, tags]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Validation Checklist (All Phases Complete)
|
||||
|
||||
After Phase 6 is done:
|
||||
- [ ] All 6 test suites passing (85%+ backend, 80%+ frontend, e2e all green)
|
||||
- [ ] All 8 large files refactored (<300 lines each)
|
||||
- [ ] All functions <10 complexity
|
||||
- [ ] Manual validation: Login, Scan, AI extraction, Admin, Offline sync — ALL WORK
|
||||
- [ ] No console errors in browser
|
||||
- [ ] Mobile responsive (320px, 768px, 1024px+ viewports)
|
||||
- [ ] Keyboard navigation works
|
||||
- [ ] Merge `refactor/ai-friendly` → `dev`
|
||||
- [ ] Create version v1.10.17 with refactoring changes
|
||||
@@ -15,4 +15,5 @@ slowapi>=0.1.9
|
||||
apscheduler>=3.10.1
|
||||
pytest>=8.0.0
|
||||
pytest-asyncio>=0.23.0
|
||||
pytest-cov>=4.1.0
|
||||
httpx>=0.27.0
|
||||
|
||||
@@ -1,14 +1,31 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
import json
|
||||
from typing import Generator, Callable, Optional
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.orm import sessionmaker, Session
|
||||
from sqlalchemy.pool import StaticPool
|
||||
from fastapi.testclient import TestClient
|
||||
from unittest.mock import patch, MagicMock
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from backend.database import Base, get_db
|
||||
from backend.main import app
|
||||
from backend.database import Base, get_db
|
||||
from backend.models import User
|
||||
from backend.config_manager import ConfigManager
|
||||
from backend.auth import get_current_admin, TokenData
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
# Test data constants
|
||||
TEST_ADMIN_USERNAME = "admin"
|
||||
TEST_USER_USERNAME = "user"
|
||||
TEST_HASHED_PASSWORD = "hashed_password"
|
||||
TEST_LDAP_DN = "uid=testuser,ou=people,dc=example,dc=com"
|
||||
TEST_AI_RESPONSE = {
|
||||
"name": "Test Item",
|
||||
"part_number": "PN-12345",
|
||||
"category": "Electronics",
|
||||
"quantity": 5
|
||||
}
|
||||
|
||||
# Use in-memory SQLite for tests
|
||||
SQLALCHEMY_DATABASE_URL = "sqlite://"
|
||||
@@ -20,8 +37,10 @@ engine = create_engine(
|
||||
)
|
||||
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def mock_scheduler():
|
||||
def mock_scheduler() -> Generator[None, None, None]:
|
||||
"""Shutdown scheduler before and after each test to avoid conflicts."""
|
||||
from backend.scheduler import scheduler
|
||||
if scheduler.running:
|
||||
scheduler.shutdown()
|
||||
@@ -29,37 +48,158 @@ def mock_scheduler():
|
||||
if scheduler.running:
|
||||
scheduler.shutdown()
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def db():
|
||||
def test_db() -> Generator[Session, None, None]:
|
||||
"""Create in-memory SQLite database for tests."""
|
||||
Base.metadata.create_all(bind=engine)
|
||||
session = TestingSessionLocal()
|
||||
try:
|
||||
yield session
|
||||
finally:
|
||||
session.close()
|
||||
Base.metadata.drop_all(bind=engine)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def client(db):
|
||||
def override_get_db():
|
||||
def test_client(test_db: Session) -> Generator[TestClient, None, None]:
|
||||
"""Create FastAPI test client with mocked database."""
|
||||
|
||||
def override_get_db() -> Generator[Session, None, None]:
|
||||
try:
|
||||
yield db
|
||||
yield test_db
|
||||
finally:
|
||||
pass
|
||||
|
||||
# Mock admin user with valid TokenData
|
||||
def override_get_current_admin():
|
||||
return TokenData(
|
||||
sub=1,
|
||||
username="admin",
|
||||
app.dependency_overrides[get_db] = override_get_db
|
||||
|
||||
client = TestClient(app)
|
||||
yield client
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def mock_ldap() -> Generator[MagicMock, None, None]:
|
||||
"""Mock LDAP authentication."""
|
||||
with patch("backend.auth.ldap3.Server") as mock_server, \
|
||||
patch("backend.auth.ldap3.Connection") as mock_conn_class:
|
||||
|
||||
mock_conn = MagicMock()
|
||||
mock_conn.bind.return_value = True
|
||||
mock_conn.search.return_value = True
|
||||
mock_conn.entries = [
|
||||
MagicMock(entry_dn=TEST_LDAP_DN,
|
||||
uid=["testuser"])
|
||||
]
|
||||
mock_conn_class.return_value = mock_conn
|
||||
|
||||
yield mock_conn
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def mock_gemini() -> Generator[MagicMock, None, None]:
|
||||
"""Mock Google Gemini AI extraction."""
|
||||
with patch("backend.ai.gemini_extractor.generate_content") as mock_gen:
|
||||
mock_response = MagicMock()
|
||||
mock_response.text = json.dumps(TEST_AI_RESPONSE)
|
||||
mock_gen.return_value = mock_response
|
||||
yield mock_gen
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def mock_claude() -> Generator[MagicMock, None, None]:
|
||||
"""Mock Anthropic Claude AI extraction."""
|
||||
with patch("backend.ai.claude_extractor.generate_content") as mock_gen:
|
||||
mock_content = MagicMock()
|
||||
mock_content.text = json.dumps(TEST_AI_RESPONSE)
|
||||
mock_response = MagicMock()
|
||||
mock_response.content = [mock_content]
|
||||
mock_gen.return_value = mock_response
|
||||
yield mock_gen
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def mock_config() -> Generator[MagicMock, None, None]:
|
||||
"""Mock ConfigManager."""
|
||||
with patch.object(ConfigManager, "get_config") as mock_get:
|
||||
mock_get.return_value = {
|
||||
"ai_provider": "gemini",
|
||||
"api_key": "test-key"
|
||||
}
|
||||
yield mock_get
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def create_test_user(test_db: Session) -> Callable[[str, str], str]:
|
||||
"""Factory fixture to create test users with tokens."""
|
||||
def _create_user(username: str, role: str) -> str:
|
||||
from backend.auth import create_access_token
|
||||
|
||||
user = User(
|
||||
username=username,
|
||||
hashed_password=TEST_HASHED_PASSWORD,
|
||||
role=role,
|
||||
origin="local"
|
||||
)
|
||||
test_db.add(user)
|
||||
test_db.commit()
|
||||
test_db.refresh(user)
|
||||
return create_access_token(user_id=user.id, username=username, role=role)
|
||||
|
||||
return _create_user
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def admin_token(create_test_user: Callable[[str, str], str]) -> str:
|
||||
"""Create test admin user and return JWT token."""
|
||||
return create_test_user(TEST_ADMIN_USERNAME, "admin")
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def user_token(create_test_user: Callable[[str, str], str]) -> str:
|
||||
"""Create test regular user and return JWT token."""
|
||||
return create_test_user(TEST_USER_USERNAME, "user")
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def admin_client(test_client: TestClient, test_db: Session, admin_token: str) -> Generator[TestClient, None, None]:
|
||||
"""Create a test client authenticated as admin."""
|
||||
from backend.auth import get_current_user
|
||||
|
||||
# Create TokenData from the JWT token's user info
|
||||
admin_token_data = TokenData(
|
||||
sub=1, # First admin user created has id=1
|
||||
username=TEST_ADMIN_USERNAME,
|
||||
role="admin",
|
||||
exp=datetime.now(timezone.utc)
|
||||
)
|
||||
|
||||
app.dependency_overrides[get_db] = override_get_db
|
||||
app.dependency_overrides[get_current_admin] = override_get_current_admin
|
||||
def override_get_current_user() -> TokenData:
|
||||
return admin_token_data
|
||||
|
||||
with TestClient(app) as c:
|
||||
yield c
|
||||
app.dependency_overrides[get_current_user] = override_get_current_user
|
||||
|
||||
app.dependency_overrides.clear()
|
||||
yield test_client
|
||||
|
||||
app.dependency_overrides.pop(get_current_user, None)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def user_client(test_client: TestClient, test_db: Session, user_token: str) -> Generator[TestClient, None, None]:
|
||||
"""Create a test client authenticated as regular user."""
|
||||
from backend.auth import get_current_user
|
||||
|
||||
# Create TokenData from the JWT token's user info
|
||||
user_token_data = TokenData(
|
||||
sub=2, # Second user created has id=2
|
||||
username=TEST_USER_USERNAME,
|
||||
role="user",
|
||||
exp=datetime.now(timezone.utc)
|
||||
)
|
||||
|
||||
def override_get_current_user() -> TokenData:
|
||||
return user_token_data
|
||||
|
||||
app.dependency_overrides[get_current_user] = override_get_current_user
|
||||
|
||||
yield test_client
|
||||
|
||||
app.dependency_overrides.pop(get_current_user, None)
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
**Active AI:** Claude Haiku 4.5
|
||||
**Last Updated:** 2026-04-18
|
||||
**Current Version:** v1.10.11 (audit fixes applied)
|
||||
**Current Version:** v1.10.16 (version saved and merged to master)
|
||||
**Branch:** dev
|
||||
|
||||
---
|
||||
|
||||
## STATUS: 🟢 STABLE — FRONTEND AUDIT COMPLETE & FIXED
|
||||
## STATUS: 🟢 STABLE — VERSION SAVED & MERGED TO MASTER
|
||||
|
||||
**MAJOR ACCOMPLISHMENTS:**
|
||||
1. ✅ Completed comprehensive frontend audit (14/20 → 17+/20 target)
|
||||
@@ -16,6 +16,8 @@
|
||||
4. ✅ Corrected animation accessibility (P3 animate)
|
||||
5. ✅ Added semantic HTML + focus indicators (P3 polish)
|
||||
6. ✅ Fixed server startup issues (previous session)
|
||||
7. ✅ Saved version v1.10.16 and merged to master
|
||||
8. ✅ Created snapshot branch v1.10.16
|
||||
|
||||
**Commits this session:**
|
||||
- `fix: add npm install and expose pip install errors in start_server.sh`
|
||||
@@ -25,6 +27,7 @@
|
||||
- `refactor: make scanner viewport responsive with fluid sizing`
|
||||
- `fix: correct prefers-reduced-motion animation handling`
|
||||
- `polish: add focus indicators and semantic HTML to admin page`
|
||||
- `Build [v1.10.16]` (version bump with merged changes to master)
|
||||
|
||||
### Frontend Audit (Post v1.10.11) - COMPLETED
|
||||
|
||||
@@ -60,57 +63,61 @@
|
||||
6. **[x] Confirmation Modal**: Designed & implemented accessible ConfirmationModal component
|
||||
7. **[x] AdminOverlay Integration**: Replaced window.confirm() with ConfirmationModal for delete operations
|
||||
8. **[x] Build Verification**: npm run build passes with zero errors
|
||||
9. **[x] Version Save & Release**: Committed all changes, created v1.10.16 branch, merged to master, returned to dev
|
||||
|
||||
**Audit Score Path:** 13/20 → 14/20 → 17/20 (+4 points, +31% improvement)
|
||||
**Status:** Production-ready with confirmation modal safety feature
|
||||
**Version Path:** v1.10.15 → v1.10.16 (audit fixes + server startup improvements)
|
||||
**Status:** Production-ready, all work committed and version saved
|
||||
|
||||
---
|
||||
|
||||
## WHAT THE NEXT AI MUST DO
|
||||
|
||||
### 1. Verify Server Startup Works
|
||||
### 1. Verify Server Startup Works (CRITICAL)
|
||||
- Run `./start_server.sh` in terminal (requires: python3.12-venv installed via `sudo apt install python3.12-venv`)
|
||||
- Verify:
|
||||
- Backend uvicorn starts on port 8000 (fixed this session)
|
||||
- Backend uvicorn starts on port 8000
|
||||
- Frontend npm installs and runs on port 3001
|
||||
- HTTPS proxies start (ports 3002-3003)
|
||||
- Can access https://192.168.84.131:8919 in browser
|
||||
- **MUST TEST**: The start_server.sh fixes are now committed in v1.10.16
|
||||
|
||||
### 2. Run Audit Again & Test UX
|
||||
- Run `/audit` to confirm improvements (target: 17+/20)
|
||||
- Manual testing in browser:
|
||||
### 2. Run Full Audit & Test UX
|
||||
- Run `/audit` to confirm improvements (expected: 17+/20)
|
||||
- Manual browser testing:
|
||||
- Verify removed gradients (Scanner, AIOnboarding, IdentityCheckOverlay)
|
||||
- Test scanner responsive behavior (320px, 768px, 1024px+ viewports)
|
||||
- Test admin page keyboard navigation (focus indicators on logout button)
|
||||
- Verify reduced-motion works: Settings → Accessibility → prefers-reduced-motion
|
||||
- Test ConfirmationModal, CreateUserModal keyboard access
|
||||
|
||||
### 3. Remaining P0 Issue: Design Token Usage
|
||||
- **Context**: Tokens are defined in tailwind.config.ts but not used in components
|
||||
### 3. Production Bundle Generation
|
||||
- **Note**: export_prod.sh may have had issues in the automated run
|
||||
- Manually run `./export_prod.sh` if needed to verify production bundle creation
|
||||
- Expected: aInventory-PROD-v1.10.16.zip in root directory
|
||||
|
||||
### 4. Remaining P0 Issue: Design Token Usage
|
||||
- **Context**: Tokens are defined in tailwind.config.ts but 0 `var(--primary)` references in components
|
||||
- **Task**: Manually audit components and replace hard-coded Tailwind classes with CSS variables
|
||||
- **Impact**: Would improve design consistency and maintainability
|
||||
- **Priority**: Can be deferred to v1.10.13 if time-constrained
|
||||
- **Priority**: P0 but can be deferred to v1.10.17 if other priorities emerge
|
||||
|
||||
### 4. Optional Enhancements
|
||||
### 5. Optional Enhancements
|
||||
- **P2**: `/optimize` — Lazy-load tesseract.js (500KB) only when OCR mode activated
|
||||
- **P3**: Light mode support (extend tailwind, create toggle)
|
||||
- **P3**: More semantic HTML landmarks in other pages (currently only admin has <main>)
|
||||
|
||||
### 5. Version & Release
|
||||
- Confirm all tests pass
|
||||
- Run `/audit` one more time
|
||||
- Update VERSION.json (currently v1.10.11 → v1.10.12)
|
||||
- Use `save-version` to create bundle
|
||||
- Next production bundle: aInventory-PROD-v1.10.12.zip
|
||||
|
||||
---
|
||||
|
||||
## SYSTEM STATE
|
||||
|
||||
**Current Version:** `v1.10.11`
|
||||
**Production Bundle:** `aInventory-PROD-v1.10.10.zip` (Next: 1.10.11)
|
||||
**Git Branch:** `master`
|
||||
**Current Version:** `v1.10.16`
|
||||
**Latest Branch:** `v1.10.16` (snapshot, matches master)
|
||||
**Active Branch:** `dev` (3 commits ahead of origin/dev)
|
||||
**Master Branch:** Updated with all changes from dev
|
||||
**Production Bundle:** aInventory-PROD-v1.10.16.zip (verify generation status)
|
||||
|
||||
**Active AI Tools:**
|
||||
- **Git Binary:** `git` (system PATH, Linux native)
|
||||
- **Environment:** Use `./backend/venv/` for python tasks.
|
||||
- **Environment:** Use `./backend/venv/` for python tasks
|
||||
- **Version Management:** python3 scripts/save_version.py (increments patch by default, use --minor/--major flags)
|
||||
|
||||
1270
docs/superpowers/plans/2026-04-18-phase-1-backend-tests.md
Normal file
1270
docs/superpowers/plans/2026-04-18-phase-1-backend-tests.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user