diff --git a/tests/Screenshots/DemoData.php b/tests/Screenshots/DemoData.php index a457fbb..9fead43 100644 --- a/tests/Screenshots/DemoData.php +++ b/tests/Screenshots/DemoData.php @@ -24,6 +24,9 @@ final class DemoData public const PROTECTED_PASSWORD = 'autumn-harbour-42'; + /** The share the desktop upload creates, so its link and QR code read the same on every run. */ + public const CREATED_TOKEN = 'Tf8gH2jK4mN6pQ3r'; + public static function admin(): User { return User::factory()->admin()->create([ diff --git a/tests/Screenshots/ScreenshotsTest.php b/tests/Screenshots/ScreenshotsTest.php index 0793c5e..b6d0d68 100644 --- a/tests/Screenshots/ScreenshotsTest.php +++ b/tests/Screenshots/ScreenshotsTest.php @@ -5,6 +5,7 @@ use App\Services\QrCodeService; use App\Services\ShareService; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Str; use Tests\Screenshots\DemoData; use Tests\Screenshots\Publisher; @@ -24,6 +25,10 @@ beforeEach(function () { DemoData::shares(); }); +afterEach(function () { + Str::createRandomStringsNormally(); +}); + /** * A visited page on a device in a theme, once it can be used. Tests call `visit()` themselves, on a * line of its own: Pest starts its browser only for tests under tests/Browser or whose body calls @@ -45,10 +50,10 @@ function shotPage(mixed $visit, string $device, string $theme): mixed * every run: the page is shown as it reads on an installation at https://files.example.com, the * server's origin replaced in text and fields, and the QR code drawn for that address. */ -function shoot(mixed $page, string $device, string $theme, string $name): void +function shoot(mixed $page, string $device, string $theme, string $name, string $token = DemoData::DELIVERY_TOKEN): void { $origin = 'https://files.example.com'; - $qrCode = app(QrCodeService::class)->svg($origin.'/s/'.DemoData::DELIVERY_TOKEN); + $qrCode = app(QrCodeService::class)->svg($origin.'/s/'.$token); $page->script("document.head.insertAdjacentHTML('beforeend', '')"); $page->script('(() => { const from = location.origin, to = '.json_encode($origin).'; document.querySelectorAll("input").forEach((input) => { input.value = input.value.replaceAll(from, to) }); const text = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); while (text.nextNode()) { text.currentNode.nodeValue = text.currentNode.nodeValue.replaceAll(from, to) } document.querySelectorAll("[data-qr-code]").forEach((panel) => { panel.innerHTML = '.json_encode($qrCode).' }) })()'); @@ -101,23 +106,37 @@ function selectFiles(mixed $page, array $files): void $files = ['Q3 Report.pdf' => 2400, 'Contract 2026.pdf' => 380, 'Product photos/hero-shot.jpg' => 4800, 'Product photos/detail.jpg' => 3900]; test('desktop', function (string $theme) use ($files) { + // The share this upload creates takes a fixed token (share tokens are the only 16-character random + // strings); sessions and everything else stay random. + Str::createRandomStringsUsing(fn (int $length): string => $length === 16 + ? DemoData::CREATED_TOKEN + : substr(bin2hex(random_bytes($length)), 0, $length)); + $upload = visit('/upload'); $page = shotPage($upload, 'desktop', $theme); selectFiles($page, $files); $page->click('label:has-text("Password protect")') - ->type('input[wire\:model="password"]', DemoData::PROTECTED_PASSWORD) - ->type('input[wire\:model="maxDownloads"]', '5'); + ->click('[data-test="generate-password"]') + ->wait(1) + ->assertScript("document.querySelector('input[autocomplete=\"new-password\"]').value.length > 0"); + $page->type('input[wire\:model="maxDownloads"]', '5'); // The drop zone, the files and the options fill the window; typing left the page wherever it scrolled. $page->script("document.activeElement?.blur(); window.scrollTo(0, document.querySelector('[data-test=drop-zone]').getBoundingClientRect().top + window.scrollY - 24)"); shoot($page, 'desktop', $theme, '01-upload'); - $created = visit(route('share.created', DemoData::DELIVERY_TOKEN, false)); - $page = shotPage($created, 'desktop', $theme); - shoot($page, 'desktop', $theme, '02-share-created'); + // Creating the share is what offers the password once more beside the link. + $page->click('[data-test="create-share"]') + ->waitForText('Share Created!'); + $page->waitForEvent('networkidle') + ->assertScript("document.querySelector('[data-test=\"share-password\"]') !== null"); + shoot($page, 'desktop', $theme, '02-share-created', DemoData::CREATED_TOKEN); $page->click('[data-test="show-qr-code"]') ->assertScript("document.querySelector('[data-test=\"qr-code-dialog\"]').open"); - shoot($page, 'desktop', $theme, '03-qr-code'); + shoot($page, 'desktop', $theme, '03-qr-code', DemoData::CREATED_TOKEN); + + // The dashboard shows the eight demo shares, as before. + app(ShareService::class)->deleteShare(Share::query()->where('token', DemoData::CREATED_TOKEN)->firstOrFail()); $download = visit(route('share.download', DemoData::DELIVERY_TOKEN, false)); shoot(shotPage($download, 'desktop', $theme), 'desktop', $theme, '04-download'); diff --git a/website/img/screenshots/desktop/dark/01-upload-1600.webp b/website/img/screenshots/desktop/dark/01-upload-1600.webp index 95a9e2d..6bcf065 100644 Binary files a/website/img/screenshots/desktop/dark/01-upload-1600.webp and b/website/img/screenshots/desktop/dark/01-upload-1600.webp differ diff --git a/website/img/screenshots/desktop/dark/01-upload-800.webp b/website/img/screenshots/desktop/dark/01-upload-800.webp index 68fbcdc..b3f03de 100644 Binary files a/website/img/screenshots/desktop/dark/01-upload-800.webp and b/website/img/screenshots/desktop/dark/01-upload-800.webp differ diff --git a/website/img/screenshots/desktop/dark/02-share-created-1600.webp b/website/img/screenshots/desktop/dark/02-share-created-1600.webp index 85b2b76..2ff80b9 100644 Binary files a/website/img/screenshots/desktop/dark/02-share-created-1600.webp and b/website/img/screenshots/desktop/dark/02-share-created-1600.webp differ diff --git a/website/img/screenshots/desktop/dark/02-share-created-800.webp b/website/img/screenshots/desktop/dark/02-share-created-800.webp index a1b0227..e0d734e 100644 Binary files a/website/img/screenshots/desktop/dark/02-share-created-800.webp and b/website/img/screenshots/desktop/dark/02-share-created-800.webp differ diff --git a/website/img/screenshots/desktop/dark/03-qr-code-1600.webp b/website/img/screenshots/desktop/dark/03-qr-code-1600.webp index a0b51f6..f0a71f6 100644 Binary files a/website/img/screenshots/desktop/dark/03-qr-code-1600.webp and b/website/img/screenshots/desktop/dark/03-qr-code-1600.webp differ diff --git a/website/img/screenshots/desktop/dark/03-qr-code-800.webp b/website/img/screenshots/desktop/dark/03-qr-code-800.webp index 466588f..864fd1f 100644 Binary files a/website/img/screenshots/desktop/dark/03-qr-code-800.webp and b/website/img/screenshots/desktop/dark/03-qr-code-800.webp differ diff --git a/website/img/screenshots/desktop/dark/05-admin-dashboard-1600.webp b/website/img/screenshots/desktop/dark/05-admin-dashboard-1600.webp index f97e66a..ddd6472 100644 Binary files a/website/img/screenshots/desktop/dark/05-admin-dashboard-1600.webp and b/website/img/screenshots/desktop/dark/05-admin-dashboard-1600.webp differ diff --git a/website/img/screenshots/desktop/dark/05-admin-dashboard-800.webp b/website/img/screenshots/desktop/dark/05-admin-dashboard-800.webp index 5aaf08c..a640fc5 100644 Binary files a/website/img/screenshots/desktop/dark/05-admin-dashboard-800.webp and b/website/img/screenshots/desktop/dark/05-admin-dashboard-800.webp differ diff --git a/website/img/screenshots/desktop/light/01-upload-1600.webp b/website/img/screenshots/desktop/light/01-upload-1600.webp index 55490c6..53e0c3d 100644 Binary files a/website/img/screenshots/desktop/light/01-upload-1600.webp and b/website/img/screenshots/desktop/light/01-upload-1600.webp differ diff --git a/website/img/screenshots/desktop/light/01-upload-800.webp b/website/img/screenshots/desktop/light/01-upload-800.webp index 5c96ebb..b2ad069 100644 Binary files a/website/img/screenshots/desktop/light/01-upload-800.webp and b/website/img/screenshots/desktop/light/01-upload-800.webp differ diff --git a/website/img/screenshots/desktop/light/02-share-created-1600.webp b/website/img/screenshots/desktop/light/02-share-created-1600.webp index e8893f8..1030874 100644 Binary files a/website/img/screenshots/desktop/light/02-share-created-1600.webp and b/website/img/screenshots/desktop/light/02-share-created-1600.webp differ diff --git a/website/img/screenshots/desktop/light/02-share-created-800.webp b/website/img/screenshots/desktop/light/02-share-created-800.webp index 8c10007..51edf75 100644 Binary files a/website/img/screenshots/desktop/light/02-share-created-800.webp and b/website/img/screenshots/desktop/light/02-share-created-800.webp differ diff --git a/website/img/screenshots/desktop/light/03-qr-code-1600.webp b/website/img/screenshots/desktop/light/03-qr-code-1600.webp index 368c92c..d8ea0e1 100644 Binary files a/website/img/screenshots/desktop/light/03-qr-code-1600.webp and b/website/img/screenshots/desktop/light/03-qr-code-1600.webp differ diff --git a/website/img/screenshots/desktop/light/03-qr-code-800.webp b/website/img/screenshots/desktop/light/03-qr-code-800.webp index 3bff3ce..3675948 100644 Binary files a/website/img/screenshots/desktop/light/03-qr-code-800.webp and b/website/img/screenshots/desktop/light/03-qr-code-800.webp differ diff --git a/website/img/screenshots/desktop/light/05-admin-dashboard-1600.webp b/website/img/screenshots/desktop/light/05-admin-dashboard-1600.webp index 699ccff..ec79b56 100644 Binary files a/website/img/screenshots/desktop/light/05-admin-dashboard-1600.webp and b/website/img/screenshots/desktop/light/05-admin-dashboard-1600.webp differ diff --git a/website/img/screenshots/desktop/light/05-admin-dashboard-800.webp b/website/img/screenshots/desktop/light/05-admin-dashboard-800.webp index f5b34bd..7752660 100644 Binary files a/website/img/screenshots/desktop/light/05-admin-dashboard-800.webp and b/website/img/screenshots/desktop/light/05-admin-dashboard-800.webp differ