Skip to content

Add route-level test coverage for POST /api/update/sync-fork preflight gates, 409 FORK_DIVERGED translation, and 502 failures #6039

Description

@atomantic

Problem

server/routes/update.js:78-125 implements POST /api/update/sync-fork, which fast-forwards a user's GitHub fork from upstream via updateChecker.syncFork.

The route defines input schema validation (syncForkSchema:24-26) and structured error mapping:

  • 502 GIT_UNAVAILABLE when getRemoteInfo throws.
  • 400 NO_ORIGIN when !info?.hasOrigin.
  • 400 NOT_GITHUB when !info.isGithub.
  • 400 ALREADY_UPSTREAM when info.isUpstream.
  • 400 NOT_A_FORK when !info.isFork.
  • 409 FORK_DIVERGED with recovery guidance when syncFork rejects with a non-fast-forward message.
  • 502 FORK_SYNC_FAILED on general syncFork errors.
  • 200 with { synced: true, ... } on success.

Currently, server/routes/update.test.js has zero tests for POST /api/update/sync-fork. The route is completely unasserted at the HTTP boundary.

Trigger

A user operating PortOS on a GitHub fork visits the Update page or triggers fork synchronization via POST /api/update/sync-fork.

Impact

PortOS's distribution model (AGENTS.md and docs/SELF_UPDATE.md) strictly requires fork safety. If origin validation gates drift or the regex matching diverged commits breaks, fork users could receive unhelpful 500 errors or have sync attempts fail silently. Without HTTP boundary tests, regressions in schema validation (e.g. invalid branch characters), status codes, or error messaging cannot be caught before deployment.

Fix

Add a new describe('POST /api/update/sync-fork') test block in server/routes/update.test.js:

  1. Assert 200 OK with sync result when updateChecker.getRemoteInfo returns a valid fork and updateChecker.syncFork succeeds.
  2. Assert 400 NO_ORIGIN when getRemoteInfo returns { hasOrigin: false }.
  3. Assert 400 NOT_GITHUB when getRemoteInfo returns { hasOrigin: true, isGithub: false }.
  4. Assert 400 ALREADY_UPSTREAM when getRemoteInfo returns { hasOrigin: true, isGithub: true, isUpstream: true }.
  5. Assert 400 NOT_A_FORK when getRemoteInfo returns { hasOrigin: true, isGithub: true, isUpstream: false, isFork: false }.
  6. Assert 502 GIT_UNAVAILABLE when getRemoteInfo rejects.
  7. Assert 409 FORK_DIVERGED when syncFork throws an error containing "not a fast forward" or "diverged", verifying the error message includes guidance.
  8. Assert 502 FORK_SYNC_FAILED when syncFork throws an unexpected error.
  9. Assert 400 validation error when branch contains disallowed characters (e.g. ;, spaces, control characters).

Rejected alternative: Relying only on updateChecker.test.js unit tests for syncFork was rejected because unit tests for the service method do not assert route validation schemas, HTTP status codes, or the route's error handling and regex translation.

Acceptance criteria

  • server/routes/update.test.js contains a describe('POST /api/update/sync-fork') block.
  • Tests verify HTTP 200 response on successful fork sync with default and custom branch.
  • Tests verify HTTP 400 for NO_ORIGIN, NOT_GITHUB, ALREADY_UPSTREAM, and NOT_A_FORK.
  • Tests verify HTTP 409 FORK_DIVERGED when syncFork reports divergent commits.
  • Tests verify HTTP 502 for GIT_UNAVAILABLE and FORK_SYNC_FAILED.
  • Tests verify schema rejection on invalid branch names.
  • All tests in server/routes/update.test.js pass with cd server && npm test routes/update.test.js.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions