Skip to content

test(e2e): add comprehensive E2E test coverage for Labels, Links, and Navigation#33

Merged
patchmemory merged 22 commits intomainfrom
pr/e2e-test-coverage
Feb 4, 2026
Merged

test(e2e): add comprehensive E2E test coverage for Labels, Links, and Navigation#33
patchmemory merged 22 commits intomainfrom
pr/e2e-test-coverage

Conversation

@patchmemory
Copy link
Owner

Summary

Completes task:test/mvp/e2e-label-link-coverage by adding comprehensive E2E test coverage for Label and Link pages, plus a navigation test covering all 7 pages.

Changes

1. Navigation Test (e2e/core-flows.spec.ts)

  • ✅ Added test covering all 7 pages: Home, Files, Maps, Chats, Labels, Links, Settings
  • ✅ Verifies navigation links are visible
  • ✅ Verifies page loads correctly with proper URLs and titles
  • ✅ Tests home navigation via logo click

2. Neo4j Conditional Tests (e2e/labels.spec.ts)

  • ✅ Added "push label to neo4j" test with conditional skip when NEO4J_URI not set
  • ✅ Added "pull labels from neo4j" test with conditional skip when NEO4J_URI not set
  • ✅ Tests gracefully skip in environments without Neo4j configured

3. Existing Coverage Verified

  • ✅ Label page: 9 tests covering create, edit, delete, properties, relationships, validation
  • ✅ Link page: 15 tests covering CSV/Graph workflows, wizard navigation, templates, validation
  • ✅ All tests use stable selectors (data-testid attributes and ID selectors)

Test Results

All 33 E2E tests pass:

33 passed (24.5s)

Unit/Integration tests:

177 passed, 4 skipped

Acceptance Criteria Met

  • ✅ E2E test for Label page covers full workflow
  • ✅ E2E test for Link page covers CSV import workflow
  • ✅ Navigation test covers all 7 pages
  • ✅ Tests use stable selectors (data-testid)
  • ✅ Tests pass in CI environment
  • ✅ Tests work with/without Neo4j configured (conditional logic)

Related

  • Task: task:test/mvp/e2e-label-link-coverage
  • Story: story:refactor-and-extend
  • Phase: phase:refactor-and-extend/06-e2e-tests

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

patchmemory and others added 22 commits February 3, 2026 23:35
Add complete Label page functionality with:
- Label definitions CRUD (create, read, update, delete)
- Property management (name, type, required flag)
- Relationship definitions (type, target label)
- Neo4j push/pull synchronization
- Two-panel UI (list + editor)
- Full test coverage (unit + E2E)

Backend:
- SQLite migration v5: label_definitions table
- LabelService in scidk/services/label_service.py
- API blueprint: /api/labels/* endpoints
- Neo4j integration: push/pull schema

Frontend:
- Labels page at /labels route
- Navigation link in header
- Interactive two-panel layout
- Form validation and error handling
- Toast notifications

Tests:
- 14 unit tests in tests/test_labels_api.py (all passing)
- 6 E2E tests in e2e/labels.spec.ts (all passing)
- Full workflow coverage: create → edit → delete

Implements task:ui/mvp/label-page-impl
Related to story:refactor-and-extend, phase 03-label-page

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Implements task:ui/mvp/link-page-impl with comprehensive functionality for creating
relationships between data instances using various sources (Graph, CSV, API).

**Backend Components:**
- Add SQLite migrations (v6) for link_definitions and link_jobs tables
- Create LinkService class with CRUD operations and execution logic
- Implement source adapters (GraphSource, CSVSource, APISource)
- Implement target adapters (GraphTarget, LabelTarget)
- Implement matching strategies (PropertyMatch, IDMatch, CustomCypher)
- Add batch relationship creation in Neo4j (1000 per transaction)
- Create API blueprint with endpoints:
  - GET/POST /api/links - CRUD for link definitions
  - POST /api/links/<id>/preview - Dry-run preview
  - POST /api/links/<id>/execute - Execute link job
  - GET /api/links/jobs/<job_id> - Job status tracking

**Frontend Components:**
- Create 4-step wizard interface:
  1. Configure Source (Graph/CSV/API)
  2. Configure Target (Label/Graph Query) with Match Strategy
  3. Define Relationship Type and Properties
  4. Preview & Execute
- Add wizard state management with navigation
- Add dynamic form rendering based on source/target type
- Add preview functionality with sample matches display
- Add job execution with polling for status
- Add save/load/delete link definitions
- Add Links navigation item in header

**Testing:**
- Add 17 unit tests for API endpoints (100% pass)
- Add 15 E2E tests for wizard workflows (Playwright TypeScript)

All acceptance criteria met:
✓ User can configure source (Graph/CSV/API)
✓ User can configure target (Graph/Label)
✓ User can define matching strategy (property/ID/Cypher)
✓ User can define relationship type and properties
✓ User can preview sample matches before executing
✓ User can execute workflow to create relationships
✓ User can save/load link definitions
✓ Background job tracks execution progress
✓ Clear error messages for validation failures
✓ Navigation shows "Link" link in header
✓ Page accessible at /links route

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The scidk/web/__init__.py create_app function was not calling register_blueprints,
causing all blueprint routes (including /api/links) to return 404 errors.

This fix adds the call to register_blueprints after attempting legacy route
registration, ensuring all blueprints are properly registered.

Fixes E2E test failures where /api/links returned 500/404 errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add validation to check if saveResult.link.id exists before trying to use it.
This prevents calling /api/links/null when the save operation fails or returns
an unexpected response structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
SQLite connections are not thread-safe. The previous implementation stored
a single connection in __init__ which was reused across all requests,
causing 500 errors in concurrent scenarios (E2E tests).

**Changes:**
- Replace  with  method that returns fresh connections
- Wrap all database operations in try/finally blocks to ensure connections are closed
- Fixed methods: list_labels, get_label, save_label, delete_label

Also adds error handling in links.html to prevent calling /api/links/null
when link save fails.

This fixes the intermittent 500 errors seen in E2E tests for /api/labels.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Replaced self.conn with conn references in LinkService to prepare for
per-request connection management like LabelService.

**Status:**
- ✓ Replaced all self.conn.cursor() with conn.cursor()
- ✓ Replaced all self.conn.commit() with conn.commit()
- ✓ Added _get_conn() method
- ✓ Wrapped list_link_definitions() with try/finally
- ⚠️ Other methods still need conn = self._get_conn() + try/finally wrapping

This partial fix prevents the shared connection issue. Full refactor needed
in follow-up to add proper connection lifecycle management to all methods.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed indentation and connection management in all LinkService methods:
- save_link_definition: Wrapped in try/finally with conn.close()
- execute_link_job: Proper indentation for nested try/except
- get_job_status: Aligned cursor.execute properly
- list_jobs: Fixed return statement indentation
- _execute_job_impl: Already had correct structure

All methods now use per-request connections via _get_conn() to avoid
SQLite thread-safety issues in Flask concurrent request scenarios.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed test flakiness caused by multiple test runs leaving stale data:
- Use Date.now() timestamps in test link names for uniqueness
- Filter link items by name instead of assuming .first()
- Add cleanup in save/load test to delete created link
- Update delete test to verify unique name removal

This ensures tests are isolated and don't interfere with each other.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Replaced fixed timeouts with proper wait conditions:
- Wait for DELETE API response before checking list
- Wait for GET /api/links response after delete to ensure list reloaded
- This ensures assertions run after async operations complete

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Root cause: definition.get('id') was returning empty string instead of None,
causing links to be saved with empty IDs. This broke loading and deleting.

Fixes:
- Check for falsy/empty string IDs and generate UUID
- Filter out invalid links from UI list rendering
- Add console logging to E2E tests for debugging

Also cleaned up 55 invalid link records from database.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Problem: Test scans from E2E runs were accumulating in the database,
showing up in demos and UI.

Solution:
- Created global-teardown.ts that calls /api/admin/cleanup-test-scans
- Configured playwright to run teardown after all tests complete
- Cleanup removes scans with /tmp/, nonexistent, or scidk-e2e paths
- Manually cleaned 85 test scans from database (87 -> 2)

The cleanup endpoint was already implemented but wasn't being called.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive quickstart documentation and demo script for
task:ops/mvp/docs-quickstart.

Changes:
- QUICKSTART.md: Fresh install to first RO-Crate in < 30 minutes
- scripts/demo_rocrate_export.sh: End-to-end demo script covering
  scan → browse → select → create RO-Crate → zip export
- Fix syntax error in scidk/app.py (except Except → except Exception:)

DoD met:
- [x] docs: QUICKSTART.md with step-by-step guide
- [x] demo_steps: Executable demo script with verification

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Updated dev submodule to point to commit marking task:ops/mvp/docs-quickstart
as Done.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add comprehensive 7-page navigation test to core-flows.spec.ts
- Add Neo4j conditional tests for push/pull operations in labels.spec.ts
- Tests skip Neo4j features when NEO4J_URI is not configured
- All 33 E2E tests pass successfully

Closes task:test/mvp/e2e-label-link-coverage
@patchmemory patchmemory merged commit ed62c90 into main Feb 4, 2026
2 checks passed
@patchmemory patchmemory deleted the pr/e2e-test-coverage branch February 4, 2026 22:10
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.

1 participant