Files
LivingDexTracker/tests/bdd/steps/sharing.steps.ts
T
2026-09-14 14:25:22 +01:00

66 lines
3.0 KiB
TypeScript

import { createBdd } from 'playwright-bdd';
import { test, expect } from '../fixtures';
const { When, Then } = createBdd(test);
When('I open the Pokédex share dialog', async ({ page, state }) => {
const detailsDialog = page.getByRole('dialog').filter({ hasText: 'Notes:' });
if (await detailsDialog.count()) {
await detailsDialog.getByRole('button', { name: 'Close', exact: true }).click();
}
await page.getByRole('button', { name: 'Share', exact: true }).click();
const dialog = page.getByRole('dialog', { name: /Share Public Journey/ });
await expect(dialog).toBeVisible();
state.shareUrl = await dialog.getByLabel('Read-only link').inputValue();
});
Then('I receive an unguessable read-only link', async ({ state }) => {
expect(state.shareUrl).toMatch(
/^https?:\/\/[^/]+\/shared\/[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
);
});
When('I visit the shared link while signed out', async ({ page, context, state }) => {
if (!state.shareUrl) throw new Error('A share URL is required');
await context.clearCookies();
await page.goto(state.shareUrl);
});
Then('I can browse the shared Pokédex without editing it', async ({ page }) => {
await expect(page.getByRole('heading', { name: 'Public Journey' })).toBeVisible();
await expect(page.getByText('Read-only shared Pokédex')).toBeVisible();
await expect(page.getByLabel('Choose box view layout density')).toBeVisible();
await expect(page.getByText('Filters:', { exact: true })).toBeVisible();
await expect(page.getByRole('button', { name: 'Open bulk actions menu' })).toHaveCount(0);
await expect(page.getByRole('button', { name: /Create Pokédex data/ })).toHaveCount(0);
await expect(page.getByText('Personal notes')).toHaveCount(0);
});
Then('the shared page does not expose the private note', async ({ page }) => {
await expect(page.getByText('share-secret-note')).toHaveCount(0);
});
Then('the shared page advertises a social progress image', async ({ page }) => {
const canonical = await page.locator('link[rel="canonical"]').getAttribute('href');
const image = await page.locator('meta[property="og:image"]').getAttribute('content');
expect(canonical).toBe(page.url());
expect(image).toBe(`${page.url()}/preview.png`);
await expect(page.locator('meta[name="twitter:card"]')).toHaveAttribute(
'content',
'summary_large_image'
);
await expect(page.locator('meta[name="robots"]')).toHaveAttribute('content', 'noindex, nofollow');
await expect(page.locator('meta[name="referrer"]')).toHaveAttribute('content', 'no-referrer');
});
Then('the social progress image is a PNG', async ({ page }) => {
const image = await page.locator('meta[property="og:image"]').getAttribute('content');
if (!image) throw new Error('Open Graph image URL is required');
const response = await page.request.get(image);
expect(response.status()).toBe(200);
expect(response.headers()['content-type']).toBe('image/png');
expect(response.headers()['cache-control']).toContain('max-age=300');
const body = await response.body();
expect([...body.subarray(0, 8)]).toEqual([137, 80, 78, 71, 13, 10, 26, 10]);
});