diff --git a/packages/material-ui/src/Hidden/HiddenCss.js b/packages/material-ui/src/Hidden/HiddenCss.js index ca5ab322938ca6..289464b68fd539 100644 --- a/packages/material-ui/src/Hidden/HiddenCss.js +++ b/packages/material-ui/src/Hidden/HiddenCss.js @@ -28,34 +28,22 @@ const styles = theme => { * @ignore - internal component. */ function HiddenCss(props) { - const { - children, - classes, - className, - lgDown, - lgUp, - mdDown, - mdUp, - only, - smDown, - smUp, - xlDown, - xlUp, - xsDown, - xsUp, - ...other - } = props; + const { children, classes, className, only, ...other } = props; const theme = useTheme(); if (process.env.NODE_ENV !== 'production') { - if ( - Object.keys(other).length !== 0 && - !(Object.keys(other).length === 1 && other.hasOwnProperty('ref')) - ) { + const unknownProps = Object.keys(other).filter(propName => { + const isUndeclaredBreakpoint = !theme.breakpoints.keys.some(breakpoint => { + return `${breakpoint}Up` === propName || `${breakpoint}Down` === propName; + }); + return isUndeclaredBreakpoint; + }); + + if (unknownProps.length > 0) { console.error( - `Material-UI: unsupported props received ${Object.keys(other).join( + `Material-UI: unsupported props received by \`\`: ${unknownProps.join( ', ', - )} by \`\`.`, + )}. Did you forget to wrap this component in a ThemeProvider declaring these breakpoints?`, ); } } diff --git a/packages/material-ui/src/Hidden/HiddenCss.test.js b/packages/material-ui/src/Hidden/HiddenCss.test.js index 7336ba72e493a3..e9f7f9ae717d7a 100644 --- a/packages/material-ui/src/Hidden/HiddenCss.test.js +++ b/packages/material-ui/src/Hidden/HiddenCss.test.js @@ -1,15 +1,22 @@ import React from 'react'; import { assert } from 'chai'; -import { createShallow, getClasses } from '@material-ui/core/test-utils'; +import { createShallow, createMount, getClasses } from '@material-ui/core/test-utils'; import HiddenCss from './HiddenCss'; +import { createMuiTheme, MuiThemeProvider } from '../styles'; +import consoleErrorMock from 'test/utils/consoleErrorMock'; const Foo = () =>
bar
; describe('', () => { + /** + * @type {ReturnType} + */ + let mount; let shallow; let classes; before(() => { + mount = createMount({ strict: true }); shallow = createShallow({ untilSelector: 'div' }); classes = getClasses( @@ -18,6 +25,10 @@ describe('', () => { ); }); + after(() => { + mount.cleanUp(); + }); + describe('the generated class names', () => { it('should be ok with only', () => { const wrapper = shallow( @@ -82,6 +93,19 @@ describe('', () => { ); assert.strictEqual(wrapper.hasClass('custom'), true); }); + + it('allows custom breakpoints', () => { + const theme = createMuiTheme({ breakpoints: { keys: ['xxl'] } }); + const wrapper = mount( + + +
+ + , + ); + + assert.strictEqual(wrapper.find('div.testid').hasClass('xxlUp'), true); + }); }); describe('prop: children', () => { @@ -119,4 +143,28 @@ describe('', () => { assert.strictEqual(wrapper.childAt(2).text(), 'foo'); }); }); + + describe('warnings', () => { + beforeEach(() => { + consoleErrorMock.spy(); + }); + + afterEach(() => { + consoleErrorMock.reset(); + }); + + it('warns about excess props (potentially undeclared breakpoints)', () => { + mount( + +
+ , + ); + + assert.strictEqual(consoleErrorMock.callCount(), 1); + assert.include( + consoleErrorMock.args()[0][0], + 'Material-UI: unsupported props received by ``: xxlUp.', + ); + }); + }); });