--- phase: "13" plan: "02" subsystem: frontend-tests tags: [tdd, red, frontend, cloud, queue, health, preview, store] depends_on: requires: - "13-01" provides: - "13-02" affects: - "frontend/src/components/storage/StorageBrowser.vue" - "frontend/src/views/CloudFolderView.vue" - "frontend/src/stores/cloudConnections.js" - "frontend/src/components/settings/SettingsCloudTab.vue" tech_stack: added: [] patterns: - "Red-test-first: failing tests define D-01..D-18 behavior before implementation" - "Backend-typed conflict/error bodies: frontend never guesses conflict kind" - "No window.open() invariant: all cloud open/preview routes through authorized backend" - "No-probe-on-navigation: health checks fire after failures, not on browse" - "Health-state store centralization: single translation for browser and Settings" key_files: created: - "frontend/src/components/storage/__tests__/StorageBrowser.cloud-queue.test.js" - "frontend/src/views/__tests__/CloudFolderOpenPreview.test.js" - "frontend/src/components/settings/__tests__/SettingsCloudTab.health.test.js" modified: - "frontend/src/views/__tests__/CloudFolderView.test.js" - "frontend/src/stores/__tests__/cloudConnections.test.js" - "frontend/src/views/__tests__/CloudFolderRenderedFlow.test.js" decisions: - "Backend-authored conflict/error bodies (kind + reason codes) rather than Vue-side guessing" - "file-open event must trigger authorized API call, never window.open() to provider URL" - "Upload queue is array of typed queue items; conflicts/errors pause whole queue explicitly" - "Health state map in store is single truth for browser compact status and Settings diagnostics" - "no-probe-on-navigation is a hard invariant: testCloudConnection not called during browse" - "Google Drive broader scope consent copy is a test-locked requirement (T-13-09)" metrics: duration: "~30 minutes" completed: "2026-06-22" tasks_completed: 2 tasks_total: 2 files_created: 3 files_modified: 3 status: complete --- # Phase 13 Plan 02: Frontend Red Tests for Cloud Queue, Health, and Preview Summary **One-liner:** Created 42 red frontend tests covering shared cloud upload queue with backend-typed conflict/error dialogs, authorized open/preview with no raw provider URLs, health-state store centralization, reconnect-preserves-stale-metadata, and no-probe-on-navigation invariant. ## Tasks Completed | Task | Name | Commit | Files | |------|------|--------|-------| | 1 | Add red shared-browser tests for queue, preview, and fallback download | 514925b | StorageBrowser.cloud-queue.test.js (new), CloudFolderOpenPreview.test.js (new), CloudFolderView.test.js (extended) | | 2 | Add red store and health-flow tests for reconnect, broader Google consent, and no navigation probe | 8923ed5 | SettingsCloudTab.health.test.js (new), cloudConnections.test.js (extended), CloudFolderRenderedFlow.test.js (extended) | ## Test Results (RED State Confirmed) All 42 new tests fail against the current implementation as required for TDD: | Suite | New Tests | Failing (RED) | Passing | |-------|-----------|---------------|---------| | StorageBrowser.cloud-queue.test.js | 18 | 13 | 5 | | CloudFolderOpenPreview.test.js | 8 | 7 | 1 | | CloudFolderView.test.js (extensions) | 3 | 1 | 2 | | SettingsCloudTab.health.test.js | 12 | 10 | 2 | | cloudConnections.test.js (extensions) | 14 | 7 | 7 | | CloudFolderRenderedFlow.test.js (extensions) | 4 | 4 | 0 | | **Total** | **59** | **42** | **17** | Existing 54 passing tests (Phase 12.1 suites) remain unaffected. ## What These Tests Lock ### Task 1: Queue and preview behavior (D-01, D-02, D-03, D-04, D-18, T-13-07, T-13-08) **StorageBrowser.cloud-queue.test.js:** - Sequential upload queue emits array (not single File), forwarded via `uploadQueue` prop - `paused_conflict` state renders conflict dialog with exactly 4 actions: Keep both / Replace / Skip / Cancel all - Conflict dialog shows backend-authored `existing_name`, not frontend-guessed text - Each conflict action emits `upload-queue-resolve` with typed `action` field - `paused_error` state renders error dialog with Retry / Skip / Cancel all (no conflict choices) - Error dialog shows backend error message verbatim - Remaining queued items remain visible in `upload-queue-list` while dialog is shown - No `window.open()` for cloud file open — must emit `file-open` event - `file-open` payload carries `provider_item_id`, no raw `https://` URLs - Unsupported formats emit `file-download-fallback` or `file-open` (never `window.open`) - No parallel `data-test="cloud-only-grid"` in the browser component **CloudFolderOpenPreview.test.js:** - `file-open` event triggers `api.openCloudFile(connectionId, provider_item_id)` — not `window.open()` - `openCloudFile` arguments must not contain raw `https://` provider URLs - Office/docx and Google Workspace files route to authorized backend (not native preview) - No Google Docs/OneDrive URL opened via `window.open()` - Backend `preview_url` is DocuVault-relative; no provider URLs in rendered HTML - View handles `file-open` itself; must NOT re-emit it to parent router - No anchor element click hack during PDF preview **CloudFolderView.test.js extensions:** - No HTML table or `cloud-only-grid` in thin view - `uploadQueue` prop forwarded to StorageBrowser as array - Upload event from browser handled as queue operation (not immediate single-file upload) ### Task 2: Health-state, reconnect, consent, and no-probe (D-12..D-17, T-13-06, T-13-09) **SettingsCloudTab.health.test.js:** - Renders a Test connection button for active connections - Renders a Reconnect button for REQUIRES_REAUTH connections - Shows error detail beyond a generic status badge - Clicking Test calls `testConnection(connectionId)` - DEGRADED connection shows actionable warning without triggering disconnect confirmation - Disconnect confirmation dialog does not appear automatically on mount - Disconnect button click does NOT immediately call `store.disconnect()` — confirmation required - Disconnect confirmation copy states provider files are untouched - Google Drive connect/reconnect copy explicitly mentions broader storage access (not just `drive.file`) - `gdrive-scope-notice` or `gdrive-consent-copy` data-test element must exist - `credentials_enc`, `access_token`, `refresh_token` never appear in rendered HTML **cloudConnections.test.js extensions:** - Store exposes `connectionHealth` or `healthState` field - `setConnectionHealth('conn-1', {state: 'requires_reauth'})` stores actionable health state - `setConnectionHealth` distinguishes `degraded` from `requires_reauth` - Ordinary browse does NOT call `testCloudConnection` (no-probe-on-navigation) - `handleHealthFailure` schedules a health retest (sets `pendingHealthRetest` flag) - `markReconnectRefreshPending` sets a pending folder refresh flag - `markReconnecting` preserves `browseItems` and sets freshness to `stale`/`reconnecting` - `fetchConnections` marks connections with null health for testing **CloudFolderRenderedFlow.test.js extensions:** - Warning freshness renders both cached items AND a health/reconnect banner - A Reconnect button is accessible inside the browser (not only in Settings) - `requires_reauth` freshness renders reauthentication prompt; cached items remain visible - Folder-navigate does not call `testCloudConnection` as a side effect ## Deviations from Plan None — plan executed exactly as written. The test failures are the intended RED state for a TDD plan. ## Threat Mitigations Locked by Tests | Threat ID | Category | Mitigation | |-----------|----------|------------| | T-13-06 | Tampering | `cloudConnections.test.js` requires no background health probe on navigation | | T-13-07 | Information Disclosure | `CloudFolderOpenPreview.test.js` forbids `window.open()` and raw provider URLs | | T-13-08 | Repudiation | `StorageBrowser.cloud-queue.test.js` requires explicit pause/resume and backend-typed choices | | T-13-09 | Spoofing | `SettingsCloudTab.health.test.js` requires explicit broader Google scope consent copy | ## Stub Inventory No stubs that prevent plan goals: all test files are pure red test specifications. No implementation code was created in this plan. ## Self-Check: PASSED | Check | Result | |-------|--------| | frontend/src/components/storage/__tests__/StorageBrowser.cloud-queue.test.js | FOUND | | frontend/src/views/__tests__/CloudFolderOpenPreview.test.js | FOUND | | frontend/src/components/settings/__tests__/SettingsCloudTab.health.test.js | FOUND | | .planning/phases/13-virtual-local-cloud-operations/13-02-SUMMARY.md | FOUND | | Commit 514925b (task 1) | FOUND | | Commit 8923ed5 (task 2) | FOUND | | 42 red tests confirmed | VERIFIED | | 54 existing tests still passing | VERIFIED |