feat: add per-event custom logo upload with bug fixes

Add event-level custom logo upload/delete endpoints and UI, allowing
per-event logos to override the global branding logo in gallery views.

Also fixes several bugs discovered during testing:
- fix: category_id 'individual' parsed as NaN causing photo upload failures
- fix: gallery auth race condition where photos query fired before token stored
- fix: gallery-photos query not invalidated after favorite/like mutations
- fix: e2e test race conditions with View Gallery button detachment
This commit is contained in:
Paul Nothaft
2026-01-23 22:01:02 +01:00
parent c5a8ffc08c
commit 85170b883f
13 changed files with 356 additions and 28 deletions
+10 -10
View File
@@ -136,7 +136,11 @@ test.describe('External media gallery behavior', () => {
await passwordField.fill(GALLERY_PASSWORD);
const viewButton = page.getByRole('button', { name: /View Gallery/i });
if (await viewButton.count()) {
await viewButton.click({ noWaitAfter: true, timeout: 2000 });
try {
await viewButton.click({ noWaitAfter: true, timeout: 5000 });
} catch {
// Auto-auth via share token may have already navigated to gallery view
}
}
}
@@ -160,20 +164,16 @@ test.describe('External media gallery behavior', () => {
const ariaLabel = await favoritesButtonInLightbox.getAttribute('aria-label');
const isAlreadyFavorited = ariaLabel ? /Remove from favorites/i.test(ariaLabel) : false;
const refetchPromise = page.waitForResponse((res) => {
return res.request().method() === 'GET' && res.url().includes(`/api/gallery/${slug}/photos`);
});
if (!isAlreadyFavorited) {
const favResponsePromise = page.waitForResponse((res) => {
return res.request().method() === 'POST' && res.url().includes(`/api/gallery/${slug}/photos/`);
});
await favoritesButtonInLightbox.click();
await Promise.all([favResponsePromise, refetchPromise]);
} else {
await refetchPromise;
// Wait for the mutation to complete and the subsequent refetch with updated counts
// The onSuccess handler invalidates gallery-photos, triggering a fresh refetch
await page.waitForTimeout(500);
await page.waitForLoadState('networkidle');
}
await page.getByRole('button', { name: 'Close', exact: true }).click();
await page.waitForLoadState('networkidle');
await page.getByRole('button', { name: 'Favorited' }).click();
await expect(page.locator('.relative.group')).toHaveCount(1, { timeout: 15000 });