@@ -1510,6 +1510,99 @@ describe("SettingsPage", () => {
15101510 expect ( document . getElementById ( "appearance-mobile-surface-opacity" ) ) . toBeInTheDocument ( ) ;
15111511 } ) ;
15121512
1513+ it ( "groups background material controls into asset and material surfaces" , async ( ) => {
1514+ const sendCommand = vi . fn ( ) . mockImplementation ( async ( op : string ) => {
1515+ if ( op === "settings.get" ) {
1516+ return {
1517+ "appearance.personalization.common.backgroundMode" : "image" ,
1518+ "appearance.personalization.common.backgroundAssetId" : "asset-common" ,
1519+ "appearance.personalization.common.backgroundFit" : "contain" ,
1520+ "appearance.personalization.common.backgroundDimness" : 33 ,
1521+ "appearance.personalization.common.backgroundBlur" : 8 ,
1522+ "appearance.personalization.common.glassEnabled" : true ,
1523+ "appearance.personalization.common.glassIntensity" : 44 ,
1524+ "appearance.personalization.common.surfaceOpacity" : 91 ,
1525+ } ;
1526+ }
1527+ return { } ;
1528+ } ) ;
1529+ const store = createConnectedStore ( sendCommand ) ;
1530+
1531+ renderSettingsPage ( store ) ;
1532+ fireEvent . click ( screen . getByRole ( "button" , { name : "外观" } ) ) ;
1533+
1534+ const backgroundMaterialGroup = (
1535+ await screen . findByRole ( "heading" , { name : "背景与材质" } )
1536+ ) . closest ( ".settings-group" ) ;
1537+
1538+ expect ( backgroundMaterialGroup ) . not . toBeNull ( ) ;
1539+
1540+ const assetPanel = backgroundMaterialGroup ?. querySelector ( ".settings-appearance-panel--asset" ) ;
1541+ const materialPanel = backgroundMaterialGroup ?. querySelector (
1542+ ".settings-appearance-panel--material"
1543+ ) ;
1544+
1545+ expect ( assetPanel ) . not . toBeNull ( ) ;
1546+ expect ( materialPanel ) . not . toBeNull ( ) ;
1547+ expect (
1548+ document
1549+ . getElementById ( "appearance-background-mode" )
1550+ ?. closest ( ".settings-appearance-panel--asset" )
1551+ ) . toBe ( assetPanel ) ;
1552+ expect (
1553+ document
1554+ . getElementById ( "appearance-background-fit" )
1555+ ?. closest ( ".settings-appearance-panel--asset" )
1556+ ) . toBe ( assetPanel ) ;
1557+ expect ( screen . getByText ( "asset-common" ) ) . toHaveClass ( "settings-appearance-asset-id" ) ;
1558+ expect ( assetPanel ?. querySelector ( ".settings-appearance-actions" ) ) . not . toBeNull ( ) ;
1559+ expect (
1560+ screen
1561+ . getByRole ( "spinbutton" , { name : "背景压暗" } )
1562+ . closest ( ".settings-appearance-material-grid" )
1563+ ) . toBeTruthy ( ) ;
1564+ expect (
1565+ screen
1566+ . getByRole ( "spinbutton" , { name : "面板不透明度" } )
1567+ . closest ( ".settings-appearance-material-grid" )
1568+ ) . toBeTruthy ( ) ;
1569+ } ) ;
1570+
1571+ it ( "renders desktop and mobile override controls inside nested appearance panels" , async ( ) => {
1572+ const sendCommand = vi . fn ( ) . mockImplementation ( async ( op : string ) => {
1573+ if ( op === "settings.get" ) {
1574+ return {
1575+ "appearance.personalization.common.backgroundMode" : "image" ,
1576+ "appearance.personalization.common.backgroundAssetId" : "asset-common" ,
1577+ } ;
1578+ }
1579+ return { } ;
1580+ } ) ;
1581+ const store = createConnectedStore ( sendCommand ) ;
1582+
1583+ renderSettingsPage ( store ) ;
1584+ fireEvent . click ( screen . getByRole ( "button" , { name : "外观" } ) ) ;
1585+
1586+ fireEvent . click ( await screen . findByRole ( "switch" , { name : "桌面端覆盖" } ) ) ;
1587+
1588+ const desktopSurfaceOpacity = document . getElementById ( "appearance-desktop-surface-opacity" ) ;
1589+
1590+ expect ( desktopSurfaceOpacity ) . not . toBeNull ( ) ;
1591+ expect ( desktopSurfaceOpacity ?. closest ( ".settings-appearance-override-panel" ) ) . toBeTruthy ( ) ;
1592+ expect (
1593+ desktopSurfaceOpacity
1594+ ?. closest ( ".settings-appearance-override-panel" )
1595+ ?. querySelector ( ".settings-appearance-actions" )
1596+ ) . toBeTruthy ( ) ;
1597+
1598+ fireEvent . click ( screen . getByRole ( "switch" , { name : "移动端覆盖" } ) ) ;
1599+
1600+ const mobileSurfaceOpacity = document . getElementById ( "appearance-mobile-surface-opacity" ) ;
1601+
1602+ expect ( mobileSurfaceOpacity ) . not . toBeNull ( ) ;
1603+ expect ( mobileSurfaceOpacity ?. closest ( ".settings-appearance-override-panel" ) ) . toBeTruthy ( ) ;
1604+ } ) ;
1605+
15131606 it ( "deletes the shared appearance background asset and persists a null background asset id" , async ( ) => {
15141607 appearanceMocks . deleteAppearanceAsset . mockResolvedValue ( undefined ) ;
15151608 const sendCommand = vi . fn ( ) . mockImplementation ( async ( op : string ) => {
0 commit comments