libra/tests/Feature/Admin/LegalPagesTest.php

322 lines
9.3 KiB
PHP

<?php
use App\Models\AdminLog;
use App\Models\Page;
use App\Models\User;
use Livewire\Volt\Volt;
beforeEach(function () {
$this->admin = User::factory()->admin()->create();
// Ensure test pages exist
Page::factory()->terms()->create();
Page::factory()->privacy()->create();
});
// ===========================================
// Admin Index Page Tests
// ===========================================
test('admin can view legal pages list', function () {
$this->actingAs($this->admin)
->get(route('admin.pages.index'))
->assertOk()
->assertSee('Terms of Service')
->assertSee('Privacy Policy');
});
test('legal pages list shows both pages', function () {
$this->actingAs($this->admin);
$component = Volt::test('admin.pages.index');
expect($component->viewData('pages')->count())->toBe(2);
});
// ===========================================
// Admin Edit Page Tests
// ===========================================
test('admin can view terms edit page', function () {
$this->actingAs($this->admin)
->get(route('admin.pages.edit', 'terms'))
->assertOk();
});
test('admin can view privacy edit page', function () {
$this->actingAs($this->admin)
->get(route('admin.pages.edit', 'privacy'))
->assertOk();
});
test('admin can edit terms of service in Arabic', function () {
$page = Page::where('slug', 'terms')->first();
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'terms'])
->set('content_ar', '<p>شروط الخدمة الجديدة</p>')
->call('save')
->assertHasNoErrors();
expect($page->fresh()->content_ar)->toContain('شروط الخدمة الجديدة');
});
test('admin can edit terms of service in English', function () {
$page = Page::where('slug', 'terms')->first();
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'terms'])
->set('content_en', '<p>New terms content</p>')
->call('save')
->assertHasNoErrors();
expect($page->fresh()->content_en)->toContain('New terms content');
});
test('admin can edit privacy policy in Arabic', function () {
$page = Page::where('slug', 'privacy')->first();
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'privacy'])
->set('content_ar', '<p>سياسة الخصوصية الجديدة</p>')
->call('save')
->assertHasNoErrors();
expect($page->fresh()->content_ar)->toContain('سياسة الخصوصية الجديدة');
});
test('admin can edit privacy policy in English', function () {
$page = Page::where('slug', 'privacy')->first();
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'privacy'])
->set('content_en', '<p>New privacy policy</p>')
->call('save')
->assertHasNoErrors();
expect($page->fresh()->content_en)->toContain('New privacy policy');
});
test('admin can preview page content', function () {
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'terms'])
->assertSet('showPreview', false)
->call('togglePreview')
->assertSet('showPreview', true);
});
test('preview modal can be closed', function () {
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'terms'])
->call('togglePreview')
->assertSet('showPreview', true)
->call('closePreview')
->assertSet('showPreview', false);
});
test('updated_at timestamp changes on save', function () {
$page = Page::where('slug', 'terms')->first();
$originalTimestamp = $page->updated_at;
$this->travel(1)->minute();
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'terms'])
->set('content_en', '<p>Updated content</p>')
->call('save');
expect($page->fresh()->updated_at)->toBeGreaterThan($originalTimestamp);
});
test('html content is sanitized on save', function () {
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'terms'])
->set('content_en', '<script>alert("xss")</script><p>Safe content</p>')
->call('save');
$page = Page::where('slug', 'terms')->first();
expect($page->content_en)->not->toContain('<script>');
expect($page->content_en)->toContain('Safe content');
});
test('admin log created on page update', function () {
$page = Page::where('slug', 'terms')->first();
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'terms'])
->set('content_en', '<p>Updated content</p>')
->call('save');
expect(AdminLog::where('action', 'update')
->where('target_type', 'page')
->where('target_id', $page->id)
->exists())->toBeTrue();
});
test('language tabs switch correctly', function () {
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'terms'])
->assertSet('activeTab', 'ar')
->call('setTab', 'en')
->assertSet('activeTab', 'en')
->call('setTab', 'ar')
->assertSet('activeTab', 'ar');
});
test('empty content can be saved', function () {
$this->actingAs($this->admin);
Volt::test('admin.pages.edit', ['slug' => 'terms'])
->set('content_ar', '')
->set('content_en', '')
->call('save')
->assertHasNoErrors();
$page = Page::where('slug', 'terms')->first();
expect($page->content_ar)->toBe('');
expect($page->content_en)->toBe('');
});
// ===========================================
// Public Page Tests
// ===========================================
test('public can view terms page', function () {
Page::where('slug', 'terms')->update(['content_en' => '<p>Our terms</p>']);
$this->withSession(['locale' => 'en'])
->get('/page/terms')
->assertOk()
->assertSee('Our terms');
});
test('public can view privacy page', function () {
Page::where('slug', 'privacy')->update(['content_en' => '<p>Our privacy policy</p>']);
$this->withSession(['locale' => 'en'])
->get('/page/privacy')
->assertOk()
->assertSee('Our privacy policy');
});
test('public page shows last updated timestamp', function () {
$page = Page::where('slug', 'terms')->first();
$this->get('/page/terms')
->assertOk()
->assertSee($page->updated_at->format('M d, Y'));
});
test('invalid page slug returns 404', function () {
$this->get('/page/invalid-slug')
->assertNotFound();
});
test('legacy terms route redirects to new route', function () {
$this->get('/terms')
->assertRedirect('/page/terms');
});
test('legacy privacy route redirects to new route', function () {
$this->get('/privacy')
->assertRedirect('/page/privacy');
});
test('public page displays content in correct language based on locale', function () {
Page::where('slug', 'terms')->update([
'content_ar' => '<p>شروط الخدمة</p>',
'content_en' => '<p>Terms of Service</p>',
]);
// Test English
$this->withSession(['locale' => 'en'])
->get('/page/terms')
->assertSee('Terms of Service');
// Test Arabic
$this->withSession(['locale' => 'ar'])
->get('/page/terms')
->assertSee('شروط الخدمة');
});
// ===========================================
// Authorization Tests
// ===========================================
test('guest cannot access admin pages editor', function () {
$this->get(route('admin.pages.index'))
->assertRedirect(route('login'));
});
test('client cannot access admin pages editor', function () {
$client = User::factory()->individual()->create();
$this->actingAs($client)
->get(route('admin.pages.index'))
->assertForbidden();
});
test('guest cannot access admin pages edit', function () {
$this->get(route('admin.pages.edit', 'terms'))
->assertRedirect(route('login'));
});
test('client cannot access admin pages edit', function () {
$client = User::factory()->individual()->create();
$this->actingAs($client)
->get(route('admin.pages.edit', 'terms'))
->assertForbidden();
});
// ===========================================
// Page Model Tests
// ===========================================
test('page has localized title accessor', function () {
$page = Page::where('slug', 'terms')->first();
app()->setLocale('ar');
expect($page->getTitle())->toBe('شروط الخدمة');
app()->setLocale('en');
expect($page->getTitle())->toBe('Terms of Service');
});
test('page has localized content accessor', function () {
Page::where('slug', 'terms')->update([
'content_ar' => 'محتوى عربي',
'content_en' => 'English content',
]);
$page = Page::where('slug', 'terms')->first();
app()->setLocale('ar');
expect($page->getContent())->toBe('محتوى عربي');
app()->setLocale('en');
expect($page->getContent())->toBe('English content');
});
test('page content falls back to arabic when english is empty', function () {
Page::where('slug', 'terms')->update([
'content_ar' => 'محتوى عربي',
'content_en' => null,
]);
$page = Page::where('slug', 'terms')->first();
app()->setLocale('en');
// Falls back to Arabic content when English is null
expect($page->getContent())->toBe('محتوى عربي');
});