Repository: mui/material-ui (TypeScript)
Date: 2021-02-28 20:11:47+00:00
Task type: Bug Fix

Issue:
[Tooltip] styleOverrides not working
I have tried custum styleOverrides Tooltip in my project without success.

but I see it to work on the sandbox
https://codesandbox.io/s/tootip-material-demo-forked-pv2ut

I tested for other components like Button, Text Field ... seems to work, but Tooltip doesn't

Does the current version v26 on npm match the sandbox?




Issue discussion:
A reproduction of the issue: https://codesandbox.io/s/tootip-material-demo-forked-reoq3. The tooltip has no root element. It's a bug, I would propose this fix:

```diff
diff --git a/packages/material-ui/src/styles/experimentalStyled.js b/packages/material-ui/src/styles/experimentalStyled.js
index aee32cb060..b1b3293e8c 100644
--- a/packages/material-ui/src/styles/experimentalStyled.js
+++ b/packages/material-ui/src/styles/experimentalStyled.js
@@ -73,12 +73,10 @@ const experimentalStyled = (tag, options, muiOptions = {}) => {
   const skipSx = muiOptions.skipSx || false;

   let displayName;
-  let name;
   let className;

   if (componentName) {
     displayName = `${componentName}${componentSlot || ''}`;
-    name = !componentSlot || componentSlot === 'Root' ? `${componentName}` : null;
     className = `${componentName}-${lowercaseFirstLetter(componentSlot || 'Root')}`;
   }

@@ -103,10 +101,13 @@ const experimentalStyled = (tag, options, muiOptions = {}) => {

     let transformedStyleArg = styleArg;

-    if (name && overridesResolver) {
+    // Use overridesResolver to identify the style root.
+    // `overridesResolver` should be present on the element that is closest to the root of the component.
+    // A component might not host a DOM root, e.g. the Tooltip.
+    if (componentName && overridesResolver) {
       expressionsWithDefaultTheme.push((props) => {
         const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
-        const styleOverrides = getStyleOverrides(name, theme);
+        const styleOverrides = getStyleOverrides(componentName, theme);

         if (styleOverrides) {
           return overridesResolver(props, styleOverrides);
@@ -116,10 +117,16 @@ const experimentalStyled = (tag, options, muiOptions = {}) => {
       });
     }

-    if (name && !skipVariantsResolver) {
+    // Use overridesResolver to identify the style root.
+    if (componentName && overridesResolver && !skipVariantsResolver) {
       expressionsWithDefaultTheme.push((props) => {
         const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
-        return variantsResolver(props, getVariantStyles(name, theme), theme, name);
+        return variantsResolver(
+          props,
+          getVariantStyles(componentName, theme),
+          theme,
+          componentName,
+        );
       });
     }

@@ -145,8 +152,8 @@ const experimentalStyled = (tag, options, muiOptions = {}) => {

     const Component = defaultStyledResolver(transformedStyleArg, ...expressionsWithDefaultTheme);

-    if (displayName || name) {
-      Component.displayName = displayName || name;
+    if (displayName) {
+      Component.displayName = displayName;
     }

     return Component;
```

As well as the corresponding test cases.
@oliviertassinari  i am taking this issue

@niting143 Great, mind that it requires 2 test cases.
> @niting143 Great, mind that it requires 2 test cases.

@oliviertassinari  okay

Solution patch:
diff --git a/packages/material-ui/src/styles/experimentalStyled.js b/packages/material-ui/src/styles/experimentalStyled.js
--- a/packages/material-ui/src/styles/experimentalStyled.js
+++ b/packages/material-ui/src/styles/experimentalStyled.js
@@ -73,12 +73,10 @@ const experimentalStyled = (tag, options, muiOptions = {}) => {
   const skipSx = muiOptions.skipSx || false;
 
   let displayName;
-  let name;
   let className;
 
   if (componentName) {
     displayName = `${componentName}${componentSlot || ''}`;
-    name = !componentSlot || componentSlot === 'Root' ? `${componentName}` : null;
     className = `${componentName}-${lowercaseFirstLetter(componentSlot || 'Root')}`;
   }
 
@@ -103,10 +101,10 @@ const experimentalStyled = (tag, options, muiOptions = {}) => {
 
     let transformedStyleArg = styleArg;
 
-    if (name && overridesResolver) {
+    if (componentName && overridesResolver) {
       expressionsWithDefaultTheme.push((props) => {
         const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
-        const styleOverrides = getStyleOverrides(name, theme);
+        const styleOverrides = getStyleOverrides(componentName, theme);
 
         if (styleOverrides) {
           return overridesResolver(props, styleOverrides);
@@ -116,10 +114,15 @@ const experimentalStyled = (tag, options, muiOptions = {}) => {
       });
     }
 
-    if (name && !skipVariantsResolver) {
+    if (componentName && overridesResolver && !skipVariantsResolver) {
       expressionsWithDefaultTheme.push((props) => {
         const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
-        return variantsResolver(props, getVariantStyles(name, theme), theme, name);
+        return variantsResolver(
+          props,
+          getVariantStyles(componentName, theme),
+          theme,
+          componentName,
+        );
       });
     }
 
@@ -145,8 +148,8 @@ const experimentalStyled = (tag, options, muiOptions = {}) => {
 
     const Component = defaultStyledResolver(transformedStyleArg, ...expressionsWithDefaultTheme);
 
-    if (displayName || name) {
-      Component.displayName = displayName || name;
+    if (displayName) {
+      Component.displayName = displayName;
     }
 
     return Component;


Test patch:
diff --git a/packages/material-ui/src/Tooltip/Tooltip.test.js b/packages/material-ui/src/Tooltip/Tooltip.test.js
--- a/packages/material-ui/src/Tooltip/Tooltip.test.js
+++ b/packages/material-ui/src/Tooltip/Tooltip.test.js
@@ -49,7 +49,7 @@ describe('<Tooltip />', () => {
   const render = createClientRender();
 
   describeConformanceV5(
-    <Tooltip title="Hello World">
+    <Tooltip title="Hello World" open>
       <button type="submit">Hello World</button>
     </Tooltip>,
     () => ({
@@ -59,13 +59,11 @@ describe('<Tooltip />', () => {
       mount,
       muiName: 'MuiTooltip',
       refInstanceof: window.HTMLButtonElement,
-      testVariantProps: { arrow: true },
+      testRootOverrides: { slotName: 'popper', slotClassName: classes.popper },
       testDeepOverrides: { slotName: 'tooltip', slotClassName: classes.tooltip },
       skip: [
         'componentProp',
         'componentsProp',
-        // There are no root
-        'themeStyleOverrides',
         'themeVariants',
         // react-transition-group issue
         'reactTestRenderer',
diff --git a/packages/material-ui/src/styles/experimentalStyled.test.js b/packages/material-ui/src/styles/experimentalStyled.test.js
--- a/packages/material-ui/src/styles/experimentalStyled.test.js
+++ b/packages/material-ui/src/styles/experimentalStyled.test.js
@@ -192,6 +192,28 @@ describe('experimentalStyled', () => {
       });
     });
 
+    it('should support override as long as a resolver is provided', () => {
+      const CustomTest = styled(
+        'div',
+        {},
+        { name: 'MuiTest', slot: 'Rect', overridesResolver: (props, styles) => styles.rect },
+      )({
+        width: '200px',
+        height: '300px',
+      });
+
+      const { container } = render(
+        <ThemeProvider theme={theme}>
+          <CustomTest>Test</CustomTest>
+        </ThemeProvider>,
+      );
+
+      expect(container.firstChild).toHaveComputedStyle({
+        width: '200px',
+        height: '250px',
+      });
+    });
+
     it('should work with specified muiOptions', () => {
       const { container } = render(<Test>Test</Test>);
 
diff --git a/test/utils/describeConformanceV5.js b/test/utils/describeConformanceV5.js
--- a/test/utils/describeConformanceV5.js
+++ b/test/utils/describeConformanceV5.js
@@ -106,27 +106,32 @@ function testThemeStyleOverrides(element, getOptions) {
         this.skip();
       }
 
-      const { muiName, testDeepOverrides, render } = getOptions();
+      const {
+        muiName,
+        testDeepOverrides,
+        testRootOverrides = { slotName: 'root' },
+        render,
+      } = getOptions();
 
       const testStyle = {
-        marginTop: '13px',
+        mixBlendMode: 'darken',
       };
 
       const theme = createMuiTheme({
         components: {
           [muiName]: {
             styleOverrides: {
-              root: {
+              [testRootOverrides.slotName]: {
                 ...testStyle,
                 ...(testDeepOverrides && {
                   [`& .${testDeepOverrides.slotClassName}`]: {
-                    marginBottom: '10px',
+                    fontVariantCaps: 'all-petite-caps',
                   },
                 }),
               },
               ...(testDeepOverrides && {
                 [testDeepOverrides.slotName]: {
-                  marginTop: '10px',
+                  mixBlendMode: 'darken',
                 },
               }),
             },
@@ -134,45 +139,42 @@ function testThemeStyleOverrides(element, getOptions) {
         },
       });
 
-      const { container } = render(<ThemeProvider theme={theme}>{element}</ThemeProvider>);
+      const { container, setProps } = render(
+        <ThemeProvider theme={theme}>{element}</ThemeProvider>,
+      );
 
-      expect(container.firstChild).to.toHaveComputedStyle(testStyle);
+      if (testRootOverrides.slotClassName) {
+        expect(
+          document.querySelector(`.${testRootOverrides.slotClassName}`),
+        ).to.toHaveComputedStyle(testStyle);
+      } else {
+        expect(container.firstChild).to.toHaveComputedStyle(testStyle);
+      }
 
       if (testDeepOverrides) {
         expect(
-          container.firstChild.getElementsByClassName(testDeepOverrides.slotClassName)[0],
+          document.querySelector(`.${testDeepOverrides.slotClassName}`),
         ).to.toHaveComputedStyle({
-          marginBottom: '10px',
-          marginTop: '10px',
+          fontVariantCaps: 'all-petite-caps',
+          mixBlendMode: 'darken',
         });
-      }
 
-      const themeWithoutRootOverrides = createMuiTheme({
-        components: {
-          [muiName]: {
-            styleOverrides: {
-              ...(testDeepOverrides && {
-                [testDeepOverrides.slotName]: {
-                  marginTop: '10px',
-                },
-              }),
+        const themeWithoutRootOverrides = createMuiTheme({
+          components: {
+            [muiName]: {
+              styleOverrides: {
+                ...(testDeepOverrides && {
+                  [testDeepOverrides.slotName]: testStyle,
+                }),
+              },
             },
           },
-        },
-      });
-
-      const { container: containerWithoutRootOverrides } = render(
-        <ThemeProvider theme={themeWithoutRootOverrides}>{element}</ThemeProvider>,
-      );
+        });
 
-      if (testDeepOverrides) {
+        setProps({ theme: themeWithoutRootOverrides });
         expect(
-          containerWithoutRootOverrides.firstChild.getElementsByClassName(
-            testDeepOverrides.slotClassName,
-          )[0],
-        ).to.toHaveComputedStyle({
-          marginTop: '10px',
-        });
+          document.querySelector(`.${testDeepOverrides.slotClassName}`),
+        ).to.toHaveComputedStyle(testStyle);
       }
     });
   });