Files
ghassanandClaude Opus 4.7 5aef41201a test(admin): pagination controls, HTML strip, Ready label
Four tests covering the admin polish follow-ups to Phase 7:
- Pagination partial renders both First and Last anchors with the
  correct aria-labels and page URLs on a middle-page view.
- Pagination partial degrades to a disabled First span on page 1 so
  the admin can't click into an invalid negative page.
- Admin video list strips HTML tags from the description preview
  (no "<p>Hello" leaking into the row) and carries the full
  title in a title="" tooltip on the ellipsized columns.
- Dashboard stat card now shows "Ready" instead of the misleading
  "Live Videos" label the Phase 7 commit renamed.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-10-21 12:03:22 +03:00

140 lines
5.0 KiB
PHP

<?php
namespace Tests\Feature;
use App\Http\Middleware\VerifyCsrfToken;
use App\Models\User;
use App\Models\Video;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Pagination\LengthAwarePaginator;
use Tests\TestCase;
/**
* Admin polish follow-ups to Phase 7 — storage math, pagination controls,
* HTML-stripped descriptions and the grouped error log viewer.
*/
class AdminPolishTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
putenv('DB_CONNECTION=sqlite');
putenv('DB_DATABASE=:memory:');
$_ENV['DB_CONNECTION'] = 'sqlite';
$_ENV['DB_DATABASE'] = ':memory:';
parent::setUp();
$this->withoutMiddleware([
VerifyCsrfToken::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
]);
}
// ─── Pagination partial: First + Last buttons ─────
public function test_pagination_partial_renders_first_and_last_controls(): void
{
$paginator = new LengthAwarePaginator(
items: ['a', 'b', 'c'],
total: 100,
perPage: 10,
currentPage: 5,
options: ['path' => '/videos']
);
$html = view('partials.pagination', [
'paginator' => $paginator,
'elements' => $paginator->linkCollection()->toArray(),
])->render();
$this->assertStringContainsString('aria-label="First page"', $html);
$this->assertStringContainsString('aria-label="Last page"', $html);
$this->assertStringContainsString('aria-label="Previous page"', $html);
$this->assertStringContainsString('aria-label="Next page"', $html);
// The anchors should link to page 1 and page 10 respectively.
$this->assertStringContainsString('href="/videos?page=1"', $html);
$this->assertStringContainsString('href="/videos?page=10"', $html);
}
public function test_pagination_disables_first_on_page_one(): void
{
// Two-page paginator — if there's only one page the partial
// short-circuits via @if($paginator->hasPages()) and renders
// nothing, which isn't what we're testing.
$paginator = new LengthAwarePaginator(
items: ['a'],
total: 20,
perPage: 10,
currentPage: 1,
options: ['path' => '/videos']
);
$html = view('partials.pagination', [
'paginator' => $paginator,
'elements' => $paginator->linkCollection()->toArray(),
])->render();
// On page 1 the First button is a disabled span, not an anchor.
$this->assertMatchesRegularExpression(
'/<span[^>]+class="pag-item disabled"[^>]+title="First page"/',
$html
);
}
// ─── Admin videos list: HTML-stripped description ─
public function test_admin_video_description_renders_without_html_tags(): void
{
$owner = User::factory()->create([
'username' => 'u'.substr(bin2hex(random_bytes(4)), 0, 8),
'role' => 'super_admin',
]);
$video = Video::create([
'user_id' => $owner->id,
'title' => 'The Full Video Title That Will Be Ellipsized',
'description' => '<p>Hello <strong>world</strong> <a href="#">link</a></p>',
'filename' => 'users/x/videos/y/video.mp4',
'path' => 'users/x/videos/y/video.mp4',
'type' => 'generic',
'visibility' => 'public',
'status' => 'ready',
'share_token' => bin2hex(random_bytes(8)),
]);
$this->actingAs($owner);
$html = $this->get('/admin/videos')->getContent();
// Admin list must render plain text, not literal <p> / <strong>.
$this->assertStringNotContainsString('&lt;p&gt;Hello', $html,
'Description must be stripped of HTML tags before display.');
$this->assertStringContainsString('Hello world link', $html,
'Stripped text should still be visible.');
// Title tooltip in both the title column and description preview.
$this->assertStringContainsString(
'title="The Full Video Title That Will Be Ellipsized"',
$html,
'Admin title column must carry a title="" attribute for the full name.'
);
}
// ─── Dashboard: Ready label ──────────────────────
public function test_dashboard_ready_stat_card_uses_the_new_label(): void
{
$owner = User::factory()->create([
'username' => 'ad'.substr(bin2hex(random_bytes(4)), 0, 6),
'role' => 'super_admin',
]);
$this->actingAs($owner);
$html = $this->get('/admin/dashboard')->getContent();
$this->assertStringContainsString('>Ready<', $html);
$this->assertStringNotContainsString('>Live Videos<', $html,
'The old "Live Videos" stat-card label should be gone.');
}
}