fixed mobile

This commit is contained in:
Mark Gregory
2026-06-11 12:29:18 +01:00
parent 29004e46c2
commit b993881d52
14 changed files with 1388 additions and 8 deletions
@@ -0,0 +1,101 @@
<?php
namespace Tests\Unit\Architecture;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use SplFileInfo;
use PHPUnit\Framework\TestCase;
class ProjectCoverageStructureTest extends TestCase
{
/**
* Ensure every controller has at least one matching feature test area.
*/
public function test_controllers_are_accounted_for_by_feature_tests(): void
{
$controllers = $this->filesMatching(['/../../../app', '/../../../Modules'], '/Controller\.php$/');
$this->assertNotEmpty($controllers);
$testCorpus = '';
foreach ($this->filesMatching(['/../../Feature', '/../../../Modules'], '/Test\.php$/') as $testFile) {
$testCorpus .= file_get_contents($testFile) ?: '';
}
foreach ($controllers as $controller) {
$controllerName = pathinfo($controller, PATHINFO_FILENAME);
$resourceName = str_replace(['Controller', 'Dashboard'], '', $controllerName);
$this->assertTrue(
str_contains($testCorpus, $controllerName) || str_contains($testCorpus, $resourceName) || $controllerName === 'Controller',
"Controller [{$controllerName}] does not appear to be covered by the feature test corpus.",
);
}
}
/**
* Ensure the WMS baseline component is used without duplicate headers across module views.
*/
public function test_module_views_do_not_contain_duplicate_wms_page_hero_components(): void
{
$views = $this->filesMatching(['/../../../Modules'], '/\.blade\.php$/');
$this->assertNotEmpty($views);
foreach ($views as $view) {
if (str_ends_with($view, 'partials.blade.php') || str_ends_with($view, '_form.blade.php')) {
continue;
}
$contents = file_get_contents($view) ?: '';
$this->assertLessThanOrEqual(
1,
substr_count($contents, '<x-wms.page-hero'),
"View [{$view}] should not contain duplicate page headers.",
);
}
}
/**
* Ensure browser tests exist for desktop and mobile navigation flows.
*/
public function test_browser_navigation_tests_exist_for_mobile_and_desktop(): void
{
$browserTests = $this->filesMatching(['/../../Browser'], '/Test\.php$/');
$contents = implode("\n", array_map(static fn (string $file): string => file_get_contents($file) ?: '', $browserTests));
$this->assertStringContainsString('desktop sidebar', strtolower($contents));
$this->assertStringContainsString('mobile menu', strtolower($contents));
}
/**
* @param array<int, string> $relativeDirectories
* @return array<int, string>
*/
private function filesMatching(array $relativeDirectories, string $pattern): array
{
$files = [];
foreach ($relativeDirectories as $relativeDirectory) {
$directory = realpath(__DIR__ . $relativeDirectory);
if (! is_string($directory) || ! is_dir($directory)) {
continue;
}
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
foreach ($iterator as $file) {
if (! $file instanceof SplFileInfo || ! $file->isFile()) {
continue;
}
if (preg_match($pattern, $file->getFilename()) === 1) {
$files[] = $file->getPathname();
}
}
}
return array_values(array_unique($files));
}
}
+5 -5
View File
@@ -2,15 +2,15 @@
namespace Tests\Unit;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
public function test_that_true_is_true(): void
/**
* Keep the base PHPUnit harness covered with a real assertion.
*/
public function test_phpunit_harness_is_available(): void
{
$this->assertTrue(true);
$this->assertTrue(class_exists(TestCase::class));
}
}
@@ -0,0 +1,127 @@
<?php
namespace Tests\Unit\Models;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Modules\Platform\app\Models\Company;
use Modules\Platform\app\Models\LicenseKey;
use Modules\Platform\app\Models\Payment;
use Modules\Platform\app\Models\PlatformPrice;
use Modules\Warehouse\app\Models\Warehouse;
use Modules\Warehouse\app\Models\WarehouseValidationRule;
use Tests\TestCase;
class PlatformAndWarehouseModelsTest extends TestCase
{
use RefreshDatabase;
/**
* Ensure company defaults are generated and relationships are wired.
*/
public function test_company_defaults_relationships_and_active_license_logic(): void
{
$company = Company::create(['name' => 'Model Tenant']);
$user = User::factory()->create(['company_id' => $company->id]);
$warehouse = Warehouse::create(['company_id' => $company->id, 'code' => 'M1', 'name' => 'Model Warehouse']);
$payment = Payment::create(['company_id' => $company->id, 'amount' => 1000, 'currency' => 'gbp', 'status' => 'paid']);
$this->assertNotNull($company->uuid);
$this->assertSame('model-tenant', $company->slug);
$this->assertSame('active', $company->status);
$this->assertSame('Europe/London', $company->timezone);
$this->assertFalse($company->hasActiveLicense());
LicenseKey::issueFor($company, 'Model licence');
$this->assertTrue($company->fresh()->hasActiveLicense());
$this->assertTrue($company->users->contains($user));
$this->assertTrue($company->warehouses->contains($warehouse));
$this->assertTrue($company->payments->contains($payment));
$this->assertCount(1, $company->licenseKeys);
}
/**
* Ensure system companies bypass licence checks.
*/
public function test_system_company_is_always_licensed(): void
{
$company = Company::create(['name' => 'MPBA Limited', 'slug' => 'mpba-limited', 'is_system_company' => true]);
$this->assertTrue($company->hasActiveLicense());
}
/**
* Ensure revoked or expired licences do not count as active.
*/
public function test_inactive_expired_or_revoked_licenses_are_not_active(): void
{
$company = Company::create(['name' => 'Expired Tenant', 'slug' => 'expired-tenant']);
LicenseKey::create([
'company_id' => $company->id,
'key_hash' => hash('sha256', 'expired'),
'key_prefix' => 'expired',
'label' => 'Expired',
'plan' => 'standard',
'max_users' => 10,
'is_active' => true,
'starts_at' => now()->subYears(2),
'expires_at' => now()->subDay(),
]);
$this->assertFalse($company->hasActiveLicense());
}
/**
* Ensure user helper methods work for names and platform admins.
*/
public function test_user_initials_and_platform_admin_detection(): void
{
$admin = User::factory()->mpbaPlatformAdmin()->create(['name' => 'Mark Gregory']);
$ordinary = User::factory()->create(['name' => 'Warehouse Operator']);
$this->assertSame('MG', $admin->initials());
$this->assertTrue($admin->isMpbaPlatformAdmin());
$this->assertSame('WO', $ordinary->initials());
$this->assertFalse($ordinary->isMpbaPlatformAdmin());
}
/**
* Ensure warehouse defaults and validation rule relationships work.
*/
public function test_warehouse_defaults_and_validation_rule_relationships(): void
{
$company = Company::create(['name' => 'Warehouse Model', 'slug' => 'warehouse-model']);
$warehouse = Warehouse::create(['company_id' => $company->id, 'code' => 'WM', 'name' => 'Warehouse Model']);
$rule = WarehouseValidationRule::create([
'warehouse_id' => $warehouse->id,
'name' => 'Check quantity',
'rule_key' => 'quantity-check',
'severity' => 'warning',
'configuration' => ['minimum' => 1],
]);
$this->assertNotNull($warehouse->uuid);
$this->assertSame('active', $warehouse->status);
$this->assertSame('Europe/London', $warehouse->timezone);
$this->assertTrue($warehouse->company->is($company));
$this->assertTrue($warehouse->validationRules->contains($rule));
$this->assertTrue($rule->warehouse->is($warehouse));
$this->assertSame(['minimum' => 1], $rule->configuration);
}
/**
* Ensure price helpers filter blank and non-string feature rows.
*/
public function test_platform_price_feature_rows_are_normalised(): void
{
$price = new PlatformPrice([
'currency' => 'gbp',
'features' => [' Two warehouses ', '', null, 'Ten users'],
]);
$this->assertSame(['Two warehouses', 'Ten users'], $price->featureRows());
$this->assertSame('£49.00', $price->formatAmount(4900));
}
}