diff --git a/src/__testing__/theme.test.ts b/src/__testing__/theme.test.ts index 305fecc00..c3e2ec9b0 100644 --- a/src/__testing__/theme.test.ts +++ b/src/__testing__/theme.test.ts @@ -3,6 +3,7 @@ import { readableTextColor, SistentDefaultPrimitivePaletteLight } from '../theme'; +import { MuiButton } from '../theme/components/button.modifier'; const LIGHT_INK = SistentDefaultPrimitivePaletteLight.primaryInverted; // charcoal[100] ≈ near-white const DARK_INK = SistentDefaultPrimitivePaletteLight.foreground; // charcoal[10] ≈ near-black @@ -28,7 +29,7 @@ describe('readableTextColor', () => { describe('createCustomTheme contrast derivation', () => { it('derives readable body text when a brand omits the contrast tokens', () => { // Only base colors provided; background is dark. The derived foreground - // (text.default) must be light so text stays readable — not the Layer5 + // (text.default) must be light so text stays readable - not the Layer5 // default dark ink. const theme = createCustomTheme('light', { navigationBar: '#101010', @@ -57,7 +58,7 @@ describe('createCustomTheme contrast derivation', () => { it('keeps default contrast tokens for base colors the caller did not customize', () => { // Only `background` is overridden, so its contrast token (foreground) - // re-derives — but `primary` is untouched, so its contrast token must + // re-derives - but `primary` is untouched, so its contrast token must // keep the default ink rather than silently re-deriving from KEPPEL. const theme = createCustomTheme('light', { background: '#000000' }); @@ -81,3 +82,65 @@ describe('createCustomTheme contrast derivation', () => { expect(theme.palette.mode).toBe('light'); }); }); + +describe('MuiButton contained honors the semantic color prop', () => { + // The MuiButton override function computes styles from the active theme. + // Call it directly (MUI would call it as `root({ theme, ownerState })`) so the + // assertions read the resolved backgroundColor per contained variant. + const rootStyles = (mode: 'light' | 'dark') => { + const theme = createCustomTheme(mode); + const root = MuiButton.styleOverrides!.root as (arg: { theme: typeof theme }) => Record< + string, + { color?: string; backgroundColor?: string; ['&:hover']?: { backgroundColor?: string } } + >; + return { theme, styles: root({ theme }) }; + }; + + it('paints color="error" contained buttons with the error background, not the brand (keppel)', () => { + const { theme, styles } = rootStyles('light'); + const contained = styles['&.MuiButton-contained']; + const containedError = styles['&.MuiButton-containedError']; + + expect(containedError).toBeDefined(); + // Uses the semantic error background... + expect(containedError.backgroundColor).toBe(theme.palette.background.error.default); + expect(containedError['&:hover']?.backgroundColor).toBe( + theme.palette.background.error.hover + ); + // ...and is NOT the brand background that `&.MuiButton-contained` sets - the + // regression that made `