fix: show short, accurate placeholders with a tooltip on the admin branding fields of a domain

This commit is contained in:
Linus Rath
2026-10-28 10:26:32 +01:00
parent e3fd576543
commit 1934584eb6
2 changed files with 42 additions and 1 deletions
@@ -0,0 +1,37 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { useAdminUnsavedStore } from '@/stores/admin-unsaved-store';
// Branding per domain: the image fields said "Enter URL (uploads only for
// default scope)", cut off in the field and wrong for a single domain, which
// can upload. Only a wildcard domain takes a URL alone.
vi.mock('@/lib/browser-navigation', () => ({
apiFetch: vi.fn(async () => new Response(JSON.stringify({
domainBranding: { source: 'admin', value: [{ host: 'mail.example.com' }, { host: '*.example.com' }] },
}), { status: 200, headers: { 'content-type': 'application/json' } })),
withBasePath: (p: string) => p,
}));
vi.mock('next/link', () => ({ default: ({ children }: { children: React.ReactNode }) => children }));
import { BrandingPage } from '../_pages/branding';
afterEach(() => {
useAdminUnsavedStore.setState({ dirty: {}, pendingLeave: null, pendingScope: null });
});
describe('admin branding image fields', () => {
it('offers upload for a single domain and a URL only for a wildcard, with the full hint as a title', async () => {
render(<BrandingPage />);
fireEvent.click(await screen.findByRole('button', { name: 'mail.example.com' }));
const favicon = screen.getByRole('textbox', { name: 'Favicon' });
expect(favicon.getAttribute('placeholder')).toBe('Enter URL or upload a file');
expect(favicon.getAttribute('title')).toBe('Enter URL or upload a file');
fireEvent.click(screen.getByRole('button', { name: '*.example.com' }));
const wildcardFavicon = screen.getByRole('textbox', { name: 'Favicon' });
expect(wildcardFavicon.getAttribute('placeholder')).toBe('Enter URL');
expect(wildcardFavicon.getAttribute('title')).toBe('Enter URL');
});
});
+5 -1
View File
@@ -396,7 +396,9 @@ export function BrandingPage() {
accept={field.accept}
value={currentValue(field.key)}
badge={overrideBadge(field.key)}
placeholder={selectedHost ? 'Enter URL (uploads only for default scope)' : 'Enter URL or upload a file'}
// Files upload to the default scope and to exact hosts; a wildcard has
// no single host to serve them from (the scope line says so).
placeholder={wildcardScope ? 'Enter URL' : 'Enter URL or upload a file'}
uploading={uploading === field.key}
uploadDisabled={wildcardScope}
uploaded={isUploadedFile(field.key)}
@@ -417,6 +419,7 @@ export function BrandingPage() {
value={currentValue(field.key)}
onChange={(e) => handleChange(field.key, e.target.value)}
placeholder={placeholder}
title={placeholder}
aria-label={field.label}
autoComplete="off"
spellCheck={false}
@@ -592,6 +595,7 @@ function ImageItem({ label, accept, value, badge, placeholder, uploading, upload
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
title={placeholder}
aria-label={label}
autoComplete="off"
spellCheck={false}