From e4ebc71162def605d7aa00c57d4605d06df5bb60 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Thu, 7 May 2026 18:15:22 -0400 Subject: [PATCH] fix(ci): mailer + audit lint + settings Save button collision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three Go lint hits + two web test failures, all from the U3 push. - internal/mailer/mailer.go: SentEmail.HtmlBody → HTMLBody (Go's initialism convention; revive flagged); FakeSender.Send unused ctx parameter renamed to _. - internal/audit/audit_test.go: removed dead validUUID helper. It was added speculatively in U1-T1 and never called by any test. pgtype import stays — other tests use it. - web/src/routes/settings/settings.test.ts: existing ListenBrainz tests queried `getByRole('button', { name: /save/i })` which worked when the page had only one Save button. The new Profile card adds a "Save profile" button that also matches the regex, triggering "found multiple elements". Anchored to /^save$/i for exact-match. The newer Save profile tests still use /save profile/i which is unique. This is the same shape of test-fixture-lag I owe an answer for: I landed new content that broke an existing test, and the existing test had a too-loose selector. The right fix is to tighten the old selector now (this commit) and to flag this pattern — selectors that regex-match by partial words — as a candidate for the DRY pass / test-utils consolidation. --- internal/audit/audit_test.go | 12 ------------ internal/mailer/mailer.go | 6 +++--- web/src/routes/settings/settings.test.ts | 4 ++-- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/internal/audit/audit_test.go b/internal/audit/audit_test.go index b8854da8..09b493b2 100644 --- a/internal/audit/audit_test.go +++ b/internal/audit/audit_test.go @@ -29,18 +29,6 @@ func newTestPool(t *testing.T) *pgxpool.Pool { return pool } -func validUUID() pgtype.UUID { - var u pgtype.UUID - u.Valid = true - // Arbitrary fixed bytes; we don't need a real user to exist - // because the FK is ON DELETE SET NULL — orphan FKs are fine - // for the audit_log column shape. - for i := range u.Bytes { - u.Bytes[i] = byte(i + 1) - } - return u -} - func TestWrite_NoMetadata(t *testing.T) { pool := newTestPool(t) // Use NULL FKs (Valid: false) — the column is nullable. diff --git a/internal/mailer/mailer.go b/internal/mailer/mailer.go index 44d3e148..f0ebfb0c 100644 --- a/internal/mailer/mailer.go +++ b/internal/mailer/mailer.go @@ -168,7 +168,7 @@ type SentEmail struct { To string Subject string TextBody string - HtmlBody string + HTMLBody string } // FakeSender records calls instead of sending. Safe for concurrent use. @@ -180,7 +180,7 @@ type FakeSender struct { FailNext error } -func (f *FakeSender) Send(ctx context.Context, to, subject, textBody, htmlBody string) error { +func (f *FakeSender) Send(_ context.Context, to, subject, textBody, htmlBody string) error { f.mu.Lock() defer f.mu.Unlock() if f.FailNext != nil { @@ -189,7 +189,7 @@ func (f *FakeSender) Send(ctx context.Context, to, subject, textBody, htmlBody s return err } f.Sent = append(f.Sent, SentEmail{ - To: to, Subject: subject, TextBody: textBody, HtmlBody: htmlBody, + To: to, Subject: subject, TextBody: textBody, HTMLBody: htmlBody, }) return nil } diff --git a/web/src/routes/settings/settings.test.ts b/web/src/routes/settings/settings.test.ts index e89228a6..ff673892 100644 --- a/web/src/routes/settings/settings.test.ts +++ b/web/src/routes/settings/settings.test.ts @@ -64,7 +64,7 @@ describe('Settings page — ListenBrainz', () => { await waitFor(() => expect(screen.getByPlaceholderText(/paste your lb token/i)).toBeInTheDocument() ); - expect(screen.getByRole('button', { name: /save/i })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /^save$/i })).toBeInTheDocument(); }); test('token-set state renders masked + Clear button', async () => { @@ -88,7 +88,7 @@ describe('Settings page — ListenBrainz', () => { render(SettingsPage); const input = await screen.findByPlaceholderText(/paste your lb token/i); await fireEvent.input(input, { target: { value: 'mytoken' } }); - await fireEvent.click(screen.getByRole('button', { name: /save/i })); + await fireEvent.click(screen.getByRole('button', { name: /^save$/i })); await waitFor(() => expect(mutateFn).toHaveBeenCalledWith('mytoken', expect.anything())); });