admin = User::factory()->admin()->create(); $this->client = User::factory()->individual()->create(); }); describe('Responsive Utility Classes', function () { test('app.css contains responsive design system section', function () { $cssPath = resource_path('css/app.css'); $cssContent = file_get_contents($cssPath); expect($cssContent)->toContain('Responsive Design System (Story 9.9)') ->and($cssContent)->toContain('.dashboard-grid') ->and($cssContent)->toContain('.stats-grid') ->and($cssContent)->toContain('.table-responsive') ->and($cssContent)->toContain('.touch-target') ->and($cssContent)->toContain('.page-header') ->and($cssContent)->toContain('.empty-state'); }); test('app.css contains breakpoint utilities per PRD 7.4', function () { $cssPath = resource_path('css/app.css'); $cssContent = file_get_contents($cssPath); // Check for mobile-first responsive breakpoints expect($cssContent)->toContain('sm:grid-cols-2') ->and($cssContent)->toContain('lg:grid-cols-3') ->and($cssContent)->toContain('xl:grid-cols-4'); }); test('app.css contains touch-friendly minimum size', function () { $cssPath = resource_path('css/app.css'); $cssContent = file_get_contents($cssPath); // Check for 44px minimum touch target (Apple HIG recommendation) expect($cssContent)->toContain('min-h-[44px]') ->and($cssContent)->toContain('min-w-[44px]'); }); test('app.css prevents horizontal page scroll', function () { $cssPath = resource_path('css/app.css'); $cssContent = file_get_contents($cssPath); expect($cssContent)->toContain('overflow-x-hidden'); }); test('app.css contains RTL-aware sidebar responsive styles', function () { $cssPath = resource_path('css/app.css'); $cssContent = file_get_contents($cssPath); expect($cssContent)->toContain('.sidebar-responsive') ->and($cssContent)->toContain('[dir="rtl"] .sidebar-responsive'); }); }); describe('Admin Dashboard Responsive', function () { test('admin dashboard uses stats-grid class', function () { $viewPath = resource_path('views/livewire/admin/dashboard.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('stats-grid'); }); test('admin dashboard uses page-header class', function () { $viewPath = resource_path('views/livewire/admin/dashboard.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('page-header'); }); test('admin dashboard uses widget-grid class', function () { $viewPath = resource_path('views/livewire/admin/dashboard.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('widget-grid'); }); }); describe('Client Dashboard Responsive', function () { test('client dashboard has responsive padding', function () { $viewPath = resource_path('views/livewire/client/dashboard.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('p-4 sm:p-6'); }); test('client dashboard has responsive grid', function () { $viewPath = resource_path('views/livewire/client/dashboard.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('grid-cols-1 sm:grid-cols-2'); }); test('client dashboard has responsive text sizing', function () { $viewPath = resource_path('views/livewire/client/dashboard.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('text-lg sm:text-xl lg:text-2xl'); }); }); describe('Table Responsive', function () { test('individual clients table uses table-scroll-wrapper', function () { $viewPath = resource_path('views/livewire/admin/clients/individual/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('table-scroll-wrapper'); }); test('company clients table uses table-scroll-wrapper', function () { $viewPath = resource_path('views/livewire/admin/clients/company/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('table-scroll-wrapper'); }); test('individual clients uses header-actions class', function () { $viewPath = resource_path('views/livewire/admin/clients/individual/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('header-actions'); }); }); describe('Calendar Responsive', function () { test('availability calendar uses calendar-grid class', function () { $viewPath = resource_path('views/livewire/availability-calendar.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('calendar-grid'); }); test('availability calendar uses calendar-cell class', function () { $viewPath = resource_path('views/livewire/availability-calendar.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('calendar-cell'); }); test('availability calendar uses time-slots-grid class', function () { $viewPath = resource_path('views/livewire/availability-calendar.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('time-slots-grid'); }); test('availability calendar time slots are touch-friendly', function () { $viewPath = resource_path('views/livewire/availability-calendar.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('time-slot-btn'); }); }); describe('Forms Responsive', function () { test('booking form buttons have touch-friendly sizing', function () { $viewPath = resource_path('views/livewire/client/consultations/book.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('min-h-[44px]'); }); test('booking form buttons are full-width on mobile', function () { $viewPath = resource_path('views/livewire/client/consultations/book.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('w-full sm:w-auto'); }); }); describe('Footer Responsive', function () { test('footer has responsive grid', function () { $viewPath = resource_path('views/components/footer.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('grid-cols-1 sm:grid-cols-2 lg:grid-cols-3'); }); test('footer has responsive padding', function () { $viewPath = resource_path('views/components/footer.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('px-4 sm:px-6 lg:px-8'); }); test('footer links are touch-friendly', function () { $viewPath = resource_path('views/components/footer.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('min-h-[44px]'); }); }); describe('Public Pages Responsive', function () { test('home page has responsive grid', function () { $viewPath = resource_path('views/pages/home.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('grid-cols-1 sm:grid-cols-2 lg:grid-cols-3'); }); test('home page has responsive text sizing', function () { $viewPath = resource_path('views/pages/home.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('text-2xl sm:text-3xl lg:text-4xl'); }); test('public layout has responsive padding', function () { $viewPath = resource_path('views/components/layouts/public.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('px-4 sm:px-6 lg:px-8'); }); }); describe('Posts Responsive', function () { test('posts list has responsive styling', function () { $viewPath = resource_path('views/livewire/pages/posts/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('p-4 sm:p-6'); }); test('posts list uses empty-state class', function () { $viewPath = resource_path('views/livewire/pages/posts/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('empty-state'); }); test('posts read more link is touch-friendly', function () { $viewPath = resource_path('views/livewire/pages/posts/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('min-h-[44px]'); }); }); describe('Consultations Page Responsive', function () { test('consultations index uses page-header class', function () { $viewPath = resource_path('views/livewire/client/consultations/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('page-header'); }); test('consultations index uses empty-state class', function () { $viewPath = resource_path('views/livewire/client/consultations/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('empty-state'); }); test('consultations index has responsive card padding', function () { $viewPath = resource_path('views/livewire/client/consultations/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('p-3 sm:p-4'); }); }); describe('Timelines Responsive', function () { test('timelines index has responsive layout', function () { $viewPath = resource_path('views/livewire/client/timelines/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('flex-col sm:flex-row'); }); test('timelines index uses empty-state class', function () { $viewPath = resource_path('views/livewire/client/timelines/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('empty-state'); }); test('timelines view button is touch-friendly', function () { $viewPath = resource_path('views/livewire/client/timelines/index.blade.php'); $viewContent = file_get_contents($viewPath); expect($viewContent)->toContain('min-h-[44px]'); }); });