Merge pull request 'fix(e2e): restore the frontend build by typing the responses findOrFail searches (#254)' (#255) from fix/254-frontend-build-break into main
Reviewed-on: #255
This commit was merged in pull request #255.
This commit is contained in:
@@ -33,10 +33,12 @@ test.describe('Disabling a customer account', () => {
|
||||
await accountModal.open();
|
||||
await expect(accountModal.emailText(customer.email)).toBeVisible();
|
||||
|
||||
const customers = await (await request.get('/api/admin/customers')).json();
|
||||
const customers: { id: number; email: string }[] = await (
|
||||
await request.get('/api/admin/customers')
|
||||
).json();
|
||||
const id = findOrFail(
|
||||
customers,
|
||||
(c: { email: string }) => c.email === customer.email,
|
||||
(c) => c.email === customer.email,
|
||||
`the customer ${customer.email}`
|
||||
).id;
|
||||
await request.post(`/api/admin/customers/${id}/disable`);
|
||||
@@ -56,10 +58,12 @@ test.describe('Disabling a customer account', () => {
|
||||
authModal,
|
||||
header
|
||||
}) => {
|
||||
const customers = await (await request.get('/api/admin/customers')).json();
|
||||
const customers: { id: number; email: string }[] = await (
|
||||
await request.get('/api/admin/customers')
|
||||
).json();
|
||||
const id = findOrFail(
|
||||
customers,
|
||||
(c: { email: string }) => c.email === customer.email,
|
||||
(c) => c.email === customer.email,
|
||||
`the customer ${customer.email}`
|
||||
).id;
|
||||
await request.post(`/api/admin/customers/${id}/disable`);
|
||||
|
||||
@@ -31,12 +31,14 @@ test.describe('Inline category creation from the item form', () => {
|
||||
await adminInventory.confirmButton.click();
|
||||
await expect(page.getByText('Item added')).toBeVisible();
|
||||
|
||||
const items = await (await page.request.get('/api/admin/items')).json();
|
||||
const items: { name: string; category_name: string | null }[] = await (
|
||||
await page.request.get('/api/admin/items')
|
||||
).json();
|
||||
// findOrFail already fails with the row count when the item is missing,
|
||||
// which the toBeTruthy assertion this replaces could not report.
|
||||
const saved = findOrFail(
|
||||
items,
|
||||
(item: { name: string }) => item.name === itemName,
|
||||
(item) => item.name === itemName,
|
||||
`the item named ${itemName}`
|
||||
);
|
||||
expect(saved.category_name).toBe(categoryName);
|
||||
|
||||
@@ -40,10 +40,12 @@ test.describe('Admin taxonomy', () => {
|
||||
|
||||
// The table paginates and the shared database holds many tags, so the new
|
||||
// row is confirmed through the API rather than hunted for across pages.
|
||||
const tags = await (await page.request.get('/api/admin/tags')).json();
|
||||
const tags: { name: string; color: string | null }[] = await (
|
||||
await page.request.get('/api/admin/tags')
|
||||
).json();
|
||||
const created = findOrFail(
|
||||
tags,
|
||||
(tag: { name: string }) => tag.name === `vintage-${RUN}`,
|
||||
(tag) => tag.name === `vintage-${RUN}`,
|
||||
`the tag vintage-${RUN}`
|
||||
);
|
||||
expect(created.color).toBeTruthy();
|
||||
|
||||
@@ -50,10 +50,12 @@ test.describe('Editing the customer emails', () => {
|
||||
await expect(page.getByText('Password reset saved')).toBeVisible();
|
||||
|
||||
// Persisted, not merely accepted by the form.
|
||||
const stored = await (await page.request.get('/api/admin/email-templates')).json();
|
||||
const stored: { key: string; subject: string | null; body: string | null }[] = await (
|
||||
await page.request.get('/api/admin/email-templates')
|
||||
).json();
|
||||
const reset = findOrFail(
|
||||
stored,
|
||||
(t: { key: string }) => t.key === 'passwordReset',
|
||||
(t) => t.key === 'passwordReset',
|
||||
'the passwordReset template'
|
||||
);
|
||||
expect(reset.subject).toBe(subject);
|
||||
@@ -72,10 +74,12 @@ test.describe('Editing the customer emails', () => {
|
||||
await expect(page.getByText('the body must keep {{resetUrl}}')).toBeVisible();
|
||||
|
||||
// And nothing was stored.
|
||||
const stored = await (await page.request.get('/api/admin/email-templates')).json();
|
||||
const stored: { key: string; subject: string | null; body: string | null }[] = await (
|
||||
await page.request.get('/api/admin/email-templates')
|
||||
).json();
|
||||
const reset = findOrFail(
|
||||
stored,
|
||||
(t: { key: string }) => t.key === 'passwordReset',
|
||||
(t) => t.key === 'passwordReset',
|
||||
'the passwordReset template'
|
||||
);
|
||||
expect(reset.body).toBeNull();
|
||||
@@ -95,10 +99,12 @@ test.describe('Editing the customer emails', () => {
|
||||
|
||||
await expect(page.getByText('Password reset restored to the default')).toBeVisible();
|
||||
|
||||
const stored = await (await page.request.get('/api/admin/email-templates')).json();
|
||||
const stored: { key: string; subject: string | null; body: string | null }[] = await (
|
||||
await page.request.get('/api/admin/email-templates')
|
||||
).json();
|
||||
const reset = findOrFail(
|
||||
stored,
|
||||
(t: { key: string }) => t.key === 'passwordReset',
|
||||
(t) => t.key === 'passwordReset',
|
||||
'the passwordReset template'
|
||||
);
|
||||
expect(reset.subject).toBeNull();
|
||||
@@ -124,10 +130,12 @@ test.describe('Previewing the customer emails', () => {
|
||||
// point: an admin sees the effect before committing to it.
|
||||
await expect(adminEmails.preview('Password reset').getByText(wording)).toBeVisible();
|
||||
|
||||
const stored = await (await page.request.get('/api/admin/email-templates')).json();
|
||||
const stored: { key: string; subject: string | null; body: string | null }[] = await (
|
||||
await page.request.get('/api/admin/email-templates')
|
||||
).json();
|
||||
expect(findOrFail(
|
||||
stored,
|
||||
(t: { key: string }) => t.key === 'passwordReset',
|
||||
(t) => t.key === 'passwordReset',
|
||||
'the passwordReset template'
|
||||
).body).toBeNull();
|
||||
});
|
||||
|
||||
@@ -178,10 +178,10 @@ test.describe('Filtering the storefront by favorites', () => {
|
||||
await favorite(storefront, favoritePrompt, SELLS);
|
||||
|
||||
const api = await createAdminContext(playwright);
|
||||
const items = await (await api.get('/api/items')).json();
|
||||
const items: { id: number; name: string }[] = await (await api.get('/api/items')).json();
|
||||
const sells = findOrFail(
|
||||
items,
|
||||
(item: { name: string }) => item.name === SELLS,
|
||||
(item) => item.name === SELLS,
|
||||
`the item named ${SELLS}`
|
||||
);
|
||||
await sellItem(api, sells.id);
|
||||
|
||||
@@ -19,7 +19,14 @@
|
||||
*/
|
||||
export function findOrFail<T>(
|
||||
items: T[],
|
||||
predicate: (item: T) => boolean,
|
||||
// NoInfer so the element type comes from `items` alone. Callers annotate the
|
||||
// predicate parameter as documentation — `(c: { email: string }) => ...` — and
|
||||
// without this the compiler would infer T from that annotation instead, so
|
||||
// findOrFail would return the one-field shape written in the lambda rather
|
||||
// than the row. Every caller then failed on the field it actually wanted:
|
||||
// `.id does not exist on type { email: string }`. Array.prototype.find has no
|
||||
// such problem, which is why the code this replaced type-checked.
|
||||
predicate: (item: NoInfer<T>) => boolean,
|
||||
description: string
|
||||
): T {
|
||||
const found = items.find(predicate);
|
||||
|
||||
Reference in New Issue
Block a user