wrongmove/tests/unit
Viktor Barzin c2e08fe46e wrongmove: add "seen" soft-hide decision with price-aware resurfacing
Opening a listing's detail sheet for >3s now passively marks it `seen`
and snapshots its current `total_price`. Seen listings are hidden from
the main list by default but automatically resurface when the price
changes (any direction). Distinct from `disliked` — explicit
like/dislike always overrides the passive seen state.

New "Hidden (N)" toggle on the FilterBar appears whenever at least one
listing is currently being hidden by the seen filter. Toggling it
reveals those rows in-place (without unmarking them) so the user can
review or explicitly clear via the existing Like/Dislike/Clear flow.

## Backend
- Alembic f7a8b9c0d1e2: `ALTER TABLE listingdecision ADD COLUMN
  price_at_decision FLOAT NULL`.
- `models/decision.py`: ListingDecision gains nullable
  `price_at_decision: float | None`.
- `services/decision_service.py`: adds `seen` to VALID_DECISIONS;
  set_decision accepts an optional `price_at_decision`; it's only
  forwarded to the repo for decision='seen' (other types null-out the
  column to keep semantics clean).
- `repositories/decision_repository.py`: upsert_decision now carries
  price_at_decision through the MySQL + SQLite upsert paths.
- `api/decision_routes.py`: SetDecisionRequest + DecisionResponse
  expose the new field.

## Frontend
- `types/index.ts`: DecisionType = 'liked' | 'disliked' | 'seen';
  ListingDecision gains `price_at_decision?: number | null`.
- `services/decisionService.ts`: setDecision sends the price only for
  decision='seen' (and only when it's a finite number).
- `hooks/useDecisions.ts`: rewritten to store `Map<key, DecisionEntry>`
  (decision + price snapshot). New `markSeen(id, price, type)` short-
  circuits on existing liked/disliked. New `getDecisionEntry`,
  `seenCount`.
- `App.tsx`: 3s `setTimeout` dwell timer fires markSeen when the
  detail sheet stays open. Filter logic in `processedListingData`
  hides `seen` rows whose `total_price === price_at_decision`, with
  `showHidden` bypass. Computes `hiddenCount` to drive the toggle.
- `components/FilterBar.tsx`: new conditional "Hidden (N)" / "Showing
  hidden (N)" toggle button (Eye / EyeOff lucide icons), surfaces only
  when hiddenCount > 0.

## Tests
- pytest: 2 new (test_set_seen_carries_price, test_liked_drops_price_
  even_if_supplied) + 1 updated to assert the new 5-arg repo
  signature. 24 passed.
- vitest: 6 new for useDecisions (markSeen liked/disliked skip, price
  snapshot, re-mark, null price, seenCount) + 5 new for decisionService
  payload shape. 221 total passed, tsc clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 11:07:44 +00:00
..
__init__.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_auth.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_cli.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_debug_cli.py Add debug CLI decisions, POIs, and tasks subcommands 2026-02-22 15:15:30 +00:00
test_decision_filtering.py fix: QA fixes for property decisions feature 2026-02-21 14:04:34 +00:00
test_decision_repository.py feat: add DecisionRepository with unit tests 2026-02-21 13:52:20 +00:00
test_decision_routes.py feat: add decision API routes with tests 2026-02-21 13:54:38 +00:00
test_decision_service.py wrongmove: add "seen" soft-hide decision with price-aware resurfacing 2026-05-16 11:07:44 +00:00
test_district_service.py Add comprehensive test suite: 219 new tests across backend and frontend 2026-02-10 21:59:45 +00:00
test_districts.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_dockerfile_uid.py wrongmove: round-3 fix sweep — scrape pipeline, BUY tab, filter URL state, render hygiene, map polish 2026-05-10 22:27:29 +00:00
test_export_service.py Add comprehensive test suite: 219 new tests across backend and frontend 2026-02-10 21:59:45 +00:00
test_floorplan.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_floorplan_detector.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_frontend_build_config.py fix: skip frontend config tests when frontend/ dir absent (Docker build) 2026-02-21 15:52:43 +00:00
test_image_fetcher.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_listing_cache.py wrongmove: round-3 fix sweep — scrape pipeline, BUY tab, filter URL state, render hygiene, map polish 2026-05-10 22:27:29 +00:00
test_listing_fetcher.py Refactor backend for cleaner error handling, DRY, and type safety 2026-02-10 22:19:24 +00:00
test_listing_processor.py Refactor backend for cleaner error handling, DRY, and type safety 2026-02-10 22:19:24 +00:00
test_listing_service.py Add comprehensive test suite: 219 new tests across backend and frontend 2026-02-10 21:59:45 +00:00
test_listing_tasks.py wrongmove: round-3 fix sweep — scrape pipeline, BUY tab, filter URL state, render hygiene, map polish 2026-05-10 22:27:29 +00:00
test_metrics_guard.py Add API rate limiting, metrics guard, and audit middleware 2026-02-08 00:45:43 +00:00
test_models.py Add security regression tests for all hardening fixes 2026-02-08 19:42:53 +00:00
test_openapi_disabled.py Add API anti-abuse hardening: disable docs in prod, origin validator, exception handler 2026-02-08 20:06:46 +00:00
test_origin_validator.py Add API anti-abuse hardening: disable docs in prod, origin validator, exception handler 2026-02-08 20:06:46 +00:00
test_passkey_error_handling.py Add security regression tests for all hardening fixes 2026-02-08 19:42:53 +00:00
test_poi_validation.py Add security regression tests for all hardening fixes 2026-02-08 19:42:53 +00:00
test_query.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_query_splitter.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_rate_limiter.py Add security regression tests for all hardening fixes 2026-02-08 19:42:53 +00:00
test_redis_lock.py wrongmove: round-3 fix sweep — scrape pipeline, BUY tab, filter URL state, render hygiene, map polish 2026-05-10 22:27:29 +00:00
test_redis_repository.py wrongmove: round-3 fix sweep — scrape pipeline, BUY tab, filter URL state, render hygiene, map polish 2026-05-10 22:27:29 +00:00
test_repository.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_route_calculator.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_route_serializer.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_routing.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_schedule_config.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_security_headers.py Add API anti-abuse hardening: disable docs in prod, origin validator, exception handler 2026-02-08 20:06:46 +00:00
test_task_service.py Add security regression tests for all hardening fixes 2026-02-08 19:42:53 +00:00
test_throttle_detection.py Flatten repo structure: move crawler/ to root, remove vqa/ and immoweb/ 2026-02-07 23:01:20 +00:00
test_unhandled_exception.py Add API anti-abuse hardening: disable docs in prod, origin validator, exception handler 2026-02-08 20:06:46 +00:00