Skip to content

Accounts — tests

Responsibilities

The accounts test suite verifies that the app behaves correctly at the model, service, serializer, and API levels.

It is responsible for testing:

  • authentication and password flows
  • device and session lifecycle behavior
  • invite lifecycle behavior
  • user profile, settings, and work schedule behavior
  • skill directory and user-skill assignment flows
  • signal-driven creation of related user records

The test suite is also responsible for protecting the refactored architecture:

  • views stay thin
  • services own business logic
  • serializers enforce input validation
  • models preserve derived behavior and constraints

Test structure

The current test strategy is intentionally split by layer.

API tests

These verify:

  • route wiring
  • permissions and authentication requirements
  • request/response shape
  • integration between views, serializers, and services

Examples: - test_auth.py - test_invites.py - test_profile_api.py - skill API tests

Service tests

These verify:

  • business rules
  • multi-step workflows
  • state transitions
  • side effects such as membership creation or email task dispatch

Examples: - test_auth_services.py - test_invite_services.py

Model tests

These verify:

  • defaults
  • derived properties
  • string representations
  • calculations such as effective weekly hours

Examples: - test_user_signals.py - profile/work schedule model tests


Main test groups

Authentication API tests

These tests verify the public auth endpoints.

Typical coverage: - login with username - login with email identifier - invalid credentials rejected - logout succeeds - logout-all endpoint responds correctly - users can view their devices - users cannot revoke sessions they do not own - password change endpoint works - forgot/reset password endpoints behave correctly

The API auth tests focus on endpoint behavior rather than duplicating all service-level business logic.


Authentication service tests

These tests verify the auth business workflows directly.

Typical coverage: - identifier resolution - login creates or updates device and creates session - invalid credentials raise service exceptions - logout revokes the correct session - logout-all revokes all active sessions - session revocation only works for owned sessions - password change updates stored password - password reset issuance queues the reset email task - password reset updates the password

These tests are the main protection for the auth service layer.


Invite API tests

These tests verify the invite endpoints and permission boundaries.

Typical coverage: - invite creation requires authentication - only allowed org roles can create invites - org-scoped invite listing works - cross-org invite access is forbidden - preview endpoint returns public-safe invite data - resend endpoint wiring works - cancel endpoint wiring works - accept endpoint works for matching authenticated user - accept endpoint works for anonymous invitee account creation - invalid token returns 404

These tests intentionally avoid re-checking every invite business branch already covered by service tests.


Invite service tests

These tests verify the full invite lifecycle logic.

Typical coverage: - role-based permission to invite into org - duplicate active invite detection - invite creation - invite listing and status filtering - resend behavior - cancel behavior - accept behavior for: - existing authenticated user - existing user by email - new user creation - internal membership creation - customer membership creation - invalid state rejection: - expired - cancelled - accepted

These tests are the primary protection for invite business rules.


Profile API tests

These tests verify workforce profile read/write behavior.

Typical coverage: - current profile payload includes expanded workforce fields - profile patch updates new workforce fields - manager helper fields are returned - negative travel radius is rejected - self-manager assignment is rejected - manager can be cleared - effective minimum weekly hours is returned correctly - anonymous access is rejected

These tests protect the operational workforce profile contract used by the frontend.


Profile and schedule model tests

These tests verify model defaults and derived calculations.

Typical coverage: - default values for new workforce profile fields - __str__ methods - effective_minimum_weekly_hours - derived_weekly_hours - default break logic - per-day break override logic - no-negative-hour behavior - schedule day string representation - manager can be assigned and cleared

These tests protect derived behavior that would be easy to regress during refactoring.


Skills API tests

These tests verify the skill directory and user-skill assignment endpoints.

Typical coverage: - skill list requires auth and org context - inactive skills are hidden by default - admins can create skills - non-admins cannot create/update/delete skills - users can replace their own skills - managers can edit same-org users - cross-org access is forbidden - unknown skill ids are rejected - replace semantics remove omitted skills - single UserSkill rows can be patched and deleted

These tests protect both permission boundaries and skill assignment workflows.


Signal tests

These tests verify that user creation consistently prepares related records.

Typical coverage: - creating a user creates: - UserProfile - UserSettings - UserWorkSchedule - 7 UserWorkDay rows - re-saving the user does not duplicate related rows

These tests are important because multiple parts of the API assume those related objects always exist.


Layered testing strategy

The accounts app uses a layered testing strategy to avoid unnecessary duplication.

API layer tests focus on

  • endpoint routing
  • permissions
  • serializer validation integration
  • response format
  • one representative happy path per endpoint

Service layer tests focus on

  • state mutation
  • domain branching
  • multi-step workflows
  • exception behavior
  • task dispatch side effects

Model layer tests focus on

  • defaults
  • properties
  • calculations
  • constraints and representations

This keeps the suite both broad and maintainable.


Fixture usage

The test suite reuses shared project fixtures from conftest.py.

Common fixtures include: - engineer_user - manager_user - other_user - api_client - manager_api_client - other_api_client - anon_api_client - org - org_other

These fixtures provide: - authenticated clients - organization scoping headers - realistic org membership setup - stable reusable setup across apps

This is especially important because many accounts endpoints depend on organization context and authenticated user type.


Relationship overview

flowchart TD
    Tests["Accounts tests"]

    APITests["API tests"]
    ServiceTests["Service tests"]
    ModelTests["Model tests"]
    SignalTests["Signal tests"]

    AuthAPI["Auth API"]
    InviteAPI["Invite API"]
    ProfileAPI["Profile API"]
    SkillsAPI["Skills API"]

    AuthSvc["Auth services"]
    InviteSvc["Invite services"]

    ProfileModel["Profile/Schedule models"]
    UserSignal["User signal behavior"]

    Tests --> APITests
    Tests --> ServiceTests
    Tests --> ModelTests
    Tests --> SignalTests

    APITests --> AuthAPI
    APITests --> InviteAPI
    APITests --> ProfileAPI
    APITests --> SkillsAPI

    ServiceTests --> AuthSvc
    ServiceTests --> InviteSvc

    ModelTests --> ProfileModel
    SignalTests --> UserSignal

Test flow philosophy

sequenceDiagram
    participant API as API tests
    participant View as Views
    participant Serializer as Serializers
    participant Service as Services
    participant Model as Models

    API->>View: exercise endpoint
    View->>Serializer: validate input
    View->>Service: run workflow
    Service->>Model: mutate/query state
    Model-->>Service: result
    Service-->>View: domain result
    View-->>API: response assertions
sequenceDiagram
    participant SvcTest as Service tests
    participant Service as Services
    participant Model as Models
    participant Task as Async tasks

    SvcTest->>Service: call function directly
    Service->>Model: mutate/query state
    Service->>Task: dispatch async job when needed
    Model-->>Service: state result
    Service-->>SvcTest: result / exception


What is intentionally not over-tested

The suite avoids excessive duplication where one layer already protects the behavior well.

Examples: • deep business branching is primarily tested in service tests • API tests do not repeat every service branch • serializer-only tests are added only when validation is non-trivial • admin configuration is not heavily tested unless it becomes complex

This keeps the suite fast and focused.


Regression risks this suite protects against

The current tests are especially valuable for preventing regressions in: • login behavior after auth refactors • session revocation correctness • password reset flow integrity • invite lifecycle state transitions • org-scoped permission boundaries • profile field expansion and validation • work schedule hour calculations • signal-created related models • user-skill replacement semantics

These are the parts of the app most likely to break during continued expansion.