container = new AppContainer(); $this->pushAppContainer($this->container); } protected function tearDown(): void { $this->restoreAppContainer(); $_SESSION = []; } public function testFallsBackToAppLogoWithoutTenantContext(): void { $this->mockLogoService(false, false); $this->mockBrandingLogo(false); $url = appTenantLogoUrl(128, 'light'); $this->assertStringContainsString('brand/logo.svg', $url); } public function testUsesRequestedThemeWhenAvailable(): void { $_SESSION['current_tenant'] = ['uuid' => $this->tenantUuid]; $this->mockLogoService(true, true); $url = appTenantLogoUrl(256, 'dark'); $this->assertStringContainsString('auth/tenant-logo-file', $url); $this->assertStringContainsString('theme=dark', $url); } public function testFallsBackToOtherThemeWhenRequestedMissing(): void { $_SESSION['current_tenant'] = ['uuid' => $this->tenantUuid]; $this->mockLogoService(true, false); $url = appTenantLogoUrl(256, 'dark'); $this->assertStringContainsString('auth/tenant-logo-file', $url); $this->assertStringContainsString('theme=light', $url); } public function testFallsBackToAppLogoWhenTenantHasNoLogos(): void { $_SESSION['current_tenant'] = ['uuid' => $this->tenantUuid]; $this->mockLogoService(false, false); $this->mockBrandingLogo(true); $url = appTenantLogoUrl(128, 'light'); $this->assertStringContainsString('branding/logo', $url); } private function mockLogoService(bool $hasLight, bool $hasDark): void { $mock = $this->createMock(TenantLogoService::class); $mock->method('hasLogo')->willReturnCallback(function (string $uuid, string $theme) use ($hasLight, $hasDark): bool { return $theme === 'light' ? $hasLight : $hasDark; }); $this->container->set(TenantLogoService::class, fn () => $mock); } private function mockBrandingLogo(bool $hasLogo): void { $mock = $this->createMock(BrandingLogoService::class); $mock->method('hasLogo')->willReturn($hasLogo); $this->container->set(BrandingLogoService::class, fn () => $mock); } }