test: tighten coverage to 99.69% backend / 98.62% frontend
CI / test (push) Has been cancelled

Started: 89.08% backend / 97.01% frontend lines.
Landed: 99.69% backend / 98.62% frontend.

Closed gaps targeted at logic gates, branches, and assumption boundaries
that real users hit. Each test exercises a use case the production code
actually serves; nothing here is line-padding.

Backend additions:
  - DeviceModelTest: pin landscape vs portrait dimension swap, plus the
    nativeWidth/Height "ignore orientation" contract the firmware relies on.
  - DeviceApiControllerTest: validation branches the PWA forms can't
    even produce (raw API misuse) — non-array wakeTimes, non-int entries,
    invalid rotation mode, invalid timezone, empty name, invalid orientation,
    other-user PATCH returns 404. Plus full /preview coverage: 404 for
    other-user / no-current / no-asset / missing-file / soft-deleted, and
    happy paths for landscape AND portrait (the rotateImage(90) branch).
  - ImageApiControllerTest: cropOrientation now exercised on both upload
    and reprocess paths.
  - TokenActionControllerTest: TK-01c covers the bad-device-id "continue"
    branch in submit.
  - RenderImageMessageHandlerTest: explicit portrait test pins the
    rotateImage(-90) branch and the 192,000-byte EPD-native bin shape.
  - SeedFakeDevicesCommandTest: 4 cases covering missing-user, fresh
    create, idempotent re-run, and --remove path. The dev seed command
    is load-bearing for the multi-frame UI; a silent break would surface
    a week later.
  - RerenderAssetsCommandTest: reset + dispatch path, no-assets path.

Frontend additions:
  - FrameCardTest: lastSync-only and nextSync-only rendering branches.
  - HomeView.test:
    * + Add time fallback path when all 9 default candidates are taken.
    * Multi-day "in Nd" nextSync formatting (offline / huge-interval case).
    * Medium-horizon (5h) nextSync formats as clock-time + day label.
    * visibilitychange triggers a silent re-fetch.
    * add-photo handler creates input + navigates to /upload after pick.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-08 14:22:46 -04:00
parent 2a8bf3895f
commit a9ad014bd1
9 changed files with 712 additions and 0 deletions
@@ -91,6 +91,44 @@ class TokenActionControllerTest extends AppWebTestCase
$this->assertSame($recipient->getId(), $sharedReloaded->getRecipientUser()->getId());
}
/**
* TK-01c: A device_ids list containing an unknown / not-recipient-owned id
* MUST be silently skipped (not 500). Locks the "continue on bad id"
* branch in TokenActionController::submit.
*/
public function test_approve_submit_skips_unknown_device_ids(): void
{
$sender = $this->createUser('tk01c_sender@example.com');
$recipient = $this->createUser('tk01c_recip@example.com');
$image = $this->makeImage($sender);
$token = $this->issueToken($image, TokenType::ShareApprove);
$shared = new SharedImage($image, $recipient, $sender);
$this->em()->persist($shared);
// Recipient owns one device; the form will submit a real id and a bogus one.
$real = new \App\Entity\Device();
$real->setMac('AA:BB:CC:DD:EE:F1');
$real->setName('Recip Frame');
$real->setUser($recipient);
$this->em()->persist($real);
$this->em()->flush();
$client = $this->loginAs($recipient);
$client->request('POST', '/token/' . $token->getUuid() . '/approve', [
'device_ids' => [(string) $real->getId(), '999999'],
]);
$this->assertResponseIsSuccessful();
// The real device should now have the image approved; the bogus id is a no-op.
$this->em()->clear();
$reloadedImage = $this->em()->find(\App\Entity\Image::class, $image->getId());
$approvedIds = array_map(
fn(\App\Entity\Device $d) => $d->getId(),
$reloadedImage->getApprovedDevices()->toArray(),
);
$this->assertContains($real->getId(), $approvedIds);
}
/**
* TK-02: GET /token/{uuid}/approve with a missing UUID renders the invalid page.
*/