b286a1f241
CI / test (push) Has been cancelled
Adds the second panel model alongside V1 (800x480, 7.3"). V2 is 1200x1600 panel-native (tall) — the inverse aspect ratio means its "natural" orientation is portrait, not landscape: - DeviceModel::nativeOrientation() — V1 returns Landscape, V2 returns Portrait. Render rotates the source image 90 CCW only when the user's orientation differs from the panel's native, so the .bin stays panel-native scan order without per-model branches. - DeviceModel::panelId() / fromPanelId() — string mapping for the firmware's X-Panel-Id header (matches -DPANEL_ID build flag). - DeviceImageController: on every poll, if X-Panel-Id maps to a known model and differs from the device's current model, auto-correct. New Devices are created with the V1 default, so a freshly-claimed 13.3" unit needs this correction before the first image render produces a wrong-dimension .bin the firmware would reject. 8 new DeviceModel unit tests, 3 new controller tests cover the header-correction behaviour (different, same, unknown panel-id). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
84 lines
2.9 KiB
PHP
84 lines
2.9 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Tests\Unit\Enum;
|
||
|
||
use App\Enum\DeviceModel;
|
||
use App\Enum\Orientation;
|
||
use PHPUnit\Framework\TestCase;
|
||
|
||
/**
|
||
* width()/height() must follow orientation, but nativeWidth()/nativeHeight()
|
||
* are the EPD's hardware scan dimensions and must NOT depend on orientation
|
||
* (the renderer pre-rotates non-native images and streams raw bytes).
|
||
*
|
||
* V1 panel is wide-native (800×480 landscape); V2 is tall-native (1200×1600
|
||
* portrait). nativeOrientation() decides whether rendering rotates.
|
||
*/
|
||
class DeviceModelTest extends TestCase
|
||
{
|
||
public function test_v1_landscape_dimensions_are_800x480(): void
|
||
{
|
||
$this->assertSame(800, DeviceModel::V1->width(Orientation::Landscape));
|
||
$this->assertSame(480, DeviceModel::V1->height(Orientation::Landscape));
|
||
}
|
||
|
||
public function test_v1_portrait_dimensions_are_swapped(): void
|
||
{
|
||
$this->assertSame(480, DeviceModel::V1->width(Orientation::Portrait));
|
||
$this->assertSame(800, DeviceModel::V1->height(Orientation::Portrait));
|
||
}
|
||
|
||
public function test_v1_native_dimensions_ignore_orientation(): void
|
||
{
|
||
$this->assertSame(800, DeviceModel::V1->nativeWidth());
|
||
$this->assertSame(480, DeviceModel::V1->nativeHeight());
|
||
}
|
||
|
||
public function test_v1_native_orientation_is_landscape(): void
|
||
{
|
||
$this->assertSame(Orientation::Landscape, DeviceModel::V1->nativeOrientation());
|
||
}
|
||
|
||
public function test_v2_portrait_dimensions_are_1200x1600(): void
|
||
{
|
||
$this->assertSame(1200, DeviceModel::V2->width(Orientation::Portrait));
|
||
$this->assertSame(1600, DeviceModel::V2->height(Orientation::Portrait));
|
||
}
|
||
|
||
public function test_v2_landscape_dimensions_are_swapped(): void
|
||
{
|
||
$this->assertSame(1600, DeviceModel::V2->width(Orientation::Landscape));
|
||
$this->assertSame(1200, DeviceModel::V2->height(Orientation::Landscape));
|
||
}
|
||
|
||
public function test_v2_native_dimensions_ignore_orientation(): void
|
||
{
|
||
$this->assertSame(1200, DeviceModel::V2->nativeWidth());
|
||
$this->assertSame(1600, DeviceModel::V2->nativeHeight());
|
||
}
|
||
|
||
public function test_v2_native_orientation_is_portrait(): void
|
||
{
|
||
$this->assertSame(Orientation::Portrait, DeviceModel::V2->nativeOrientation());
|
||
}
|
||
|
||
public function test_panel_id_round_trips(): void
|
||
{
|
||
$this->assertSame(DeviceModel::V1, DeviceModel::fromPanelId(DeviceModel::V1->panelId()));
|
||
$this->assertSame(DeviceModel::V2, DeviceModel::fromPanelId(DeviceModel::V2->panelId()));
|
||
}
|
||
|
||
public function test_panel_ids_are_distinct(): void
|
||
{
|
||
$this->assertNotSame(DeviceModel::V1->panelId(), DeviceModel::V2->panelId());
|
||
}
|
||
|
||
public function test_from_panel_id_returns_null_for_unknown(): void
|
||
{
|
||
$this->assertNull(DeviceModel::fromPanelId('not-a-real-panel'));
|
||
$this->assertNull(DeviceModel::fromPanelId(''));
|
||
}
|
||
}
|