MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-41

1.3.5 Vitest: project CRUD + identifier uniqueness + gap-free key counter + active-project

Done
Description

Estimate: 14m · Depends on: 1.3.1

Service-layer integration tests against a real Postgres (no DB mocks, per CLAUDE.md), mirroring tests/workspaces-service.test.ts. Can run as soon as 1.3.1 lands — does not wait on the UI (1.3.4).

Coverage: createProject happy path (identifier derived + workspace-unique); identifier collision → numeric-suffix retry; slug + identifier uniqueness within a workspace (same identifier allowed in a DIFFERENT workspace); allocateWorkItemNumber is gap-free and monotonic per project AND independent across projects (PROD counter and ACME counter don't interfere); concurrent allocations don't double-issue a number (sequential calls in the same transaction return 1,2,3…); setActiveProject persists and is per-member; archiveProject sets archivedAt and the project drops out of the active list; cascade — deleting the workspace removes its projects; SetNull — archiving/deleting a project clears members' activeProjectId.

Acceptance criteria

  • tests/projects-service.test.ts covers all cases above; passes against the real dev Postgres.
  • The gap-free-counter test proves per-project independence and monotonicity explicitly.
  • All quality gates green; total Vitest count grows accordingly; prior suite stays green.

Context refs

  • tests/workspaces-service.test.ts — the exact service-test pattern (truncate beforeEach, real DB, typed-error assertions)
  • lib/services/projectsService.ts + lib/repositories/projectRepository.ts from 1.3.1
Status
Done
Type
Sub-task