Files
redefined-designs/frontend/tests/e2e/intake-submit.spec.ts
T
bermudalambandClaude Opus 5 9c5935e8e0 feat(admin): ask for the contributor's address when creating a link (#260)
The address is now a required field beside the label, the links table shows where each link was sent, and the admin is told plainly when the mail did not go — with the link still on screen to copy, which is the case that matters in QA and in local development where there is no mail at all.

Two specs in unrelated features created links with only a label and the route now refuses that, so they are updated here rather than left to go red on somebody else's branch. That is the cost of making the address required, and it is a small one: the compiler and the suite find every call site.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 18:07:37 -05:00

105 lines
4.0 KiB
TypeScript

import { test, expect, createAdminContext, uniqueSuffix } from './fixtures';
/**
* The public submission page (#222).
*
* Every fixture here carries a run id and every assertion names only what this
* run created. The suite is fullyParallel against one shared database, so a
* spec that asserts on anything catalogue-wide is asserting on other specs too
* (#241).
*/
const RUN = `i${uniqueSuffix()}`;
let token = '';
test.beforeAll(async ({ playwright }) => {
const api = await createAdminContext(playwright);
const res = await api.post('/api/admin/upload-links', {
data: { label: `Intake spec ${RUN}`, email: `intake-${RUN}@example.com` }
});
expect(res.status(), 'creating the upload link').toBe(201);
token = (await res.json()).token;
await api.dispose();
});
test.describe('Sending in an item through a link', () => {
test('shows the form for a link that works', async ({ page }) => {
await page.goto(`/submit/${token}`);
await expect(page.getByRole('heading', { name: 'Send in an item' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Choose photos' })).toBeVisible();
});
// Nothing to send is not a submission, and the server would refuse it — but
// the sender should not have to find that out by pressing the button.
test('will not send until a photo is chosen', async ({ page }) => {
await page.goto(`/submit/${token}`);
await expect(page.getByRole('button', { name: 'Send' })).toBeDisabled();
});
// One state for every refusal, matching the server's single 404. Saying which
// kind of dead a link is would tell a stranger whether one they guessed at
// exists.
test('explains an unusable link without saying which kind', async ({ page }) => {
await page.goto('/submit/not-a-real-token');
await expect(page.getByRole('heading', { name: 'This link is not active' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Choose photos' })).toHaveCount(0);
});
test('accepts a photo and says it arrived', async ({ page }) => {
await page.goto(`/submit/${token}`);
// A real 1x1 PNG, so the server's magic-byte check sees what it expects
// rather than a buffer that merely starts correctly.
const png = Buffer.from(
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==',
'base64'
);
await page.setInputFiles('input[type="file"]', {
name: `${RUN}.png`,
mimeType: 'image/png',
buffer: png
});
await page.getByLabel('Anything you know about this item').fill(`Stoneware ${RUN}`);
await page.getByRole('button', { name: 'Send' }).click();
await expect(page.getByRole('heading', { name: 'Thank you — it arrived' })).toBeVisible();
// The wording matters: it is what stops a sender wondering why their item
// is not on the site.
await expect(page.getByText(/Nothing is listed for sale until/)).toBeVisible();
});
// Ticked by default, because that is the decision: most items look better
// cut out, and the reverse default would mean almost nobody got it.
test('offers to remove the background, already ticked', async ({ page }) => {
await page.goto(`/submit/${token}`);
const control = page.getByRole('checkbox', { name: /remove the background/i });
await expect(control).toBeVisible();
await expect(control).toBeChecked();
});
test('lets a sender turn it off and still send', async ({ page }) => {
await page.goto(`/submit/${token}`);
const png = Buffer.from(
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==',
'base64'
);
await page.setInputFiles('input[type="file"]', {
name: `${RUN}-nobg.png`,
mimeType: 'image/png',
buffer: png
});
await page.getByRole('checkbox', { name: /remove the background/i }).uncheck();
await page.getByRole('button', { name: 'Send' }).click();
await expect(page.getByRole('heading', { name: 'Thank you — it arrived' })).toBeVisible();
});
});