322 lines
10 KiB
JavaScript
322 lines
10 KiB
JavaScript
import React from 'react';
|
|
import { spy } from 'sinon';
|
|
import { assert } from 'chai';
|
|
import JssProvider from 'react-jss/lib/JssProvider';
|
|
import { create, SheetsRegistry } from 'jss';
|
|
import consoleErrorMock from 'test/utils/consoleErrorMock';
|
|
import jssPreset from './jssPreset';
|
|
import withStyles from './withStyles';
|
|
import MuiThemeProvider from './MuiThemeProvider';
|
|
import createMuiTheme from './createMuiTheme';
|
|
import createGenerateClassName from './createGenerateClassName';
|
|
import { createShallow, createMount, getClasses } from '../test-utils'; // eslint-disable-next-line react/prefer-stateless-function
|
|
|
|
var _ref = React.createElement("div", null);
|
|
|
|
class Empty extends React.Component {
|
|
render() {
|
|
return _ref;
|
|
}
|
|
|
|
}
|
|
|
|
describe('withStyles', () => {
|
|
let shallow;
|
|
let mount;
|
|
before(() => {
|
|
shallow = createShallow();
|
|
mount = createMount();
|
|
});
|
|
after(() => {
|
|
mount.cleanUp();
|
|
});
|
|
describe('props', () => {
|
|
let StyledComponent1;
|
|
let classes;
|
|
|
|
var _ref2 = React.createElement(StyledComponent1, null);
|
|
|
|
before(() => {
|
|
const styles = {
|
|
root: {
|
|
display: 'flex'
|
|
}
|
|
};
|
|
StyledComponent1 = withStyles(styles, {
|
|
name: 'MuiTextField'
|
|
})(Empty);
|
|
classes = getClasses(_ref2);
|
|
});
|
|
|
|
var _ref3 = React.createElement(StyledComponent1, null);
|
|
|
|
it('should provide a classes property', () => {
|
|
const wrapper = shallow(_ref3);
|
|
assert.deepEqual(wrapper.props().classes, classes, 'Should provide the classes property');
|
|
});
|
|
describe('prop: classes', () => {
|
|
before(() => {
|
|
consoleErrorMock.spy();
|
|
});
|
|
after(() => {
|
|
consoleErrorMock.reset();
|
|
});
|
|
it('should accept a classes property', () => {
|
|
const wrapper = shallow(React.createElement(StyledComponent1, {
|
|
classes: {
|
|
root: 'h1'
|
|
}
|
|
}));
|
|
assert.deepEqual(wrapper.props().classes, {
|
|
root: `${classes.root} h1`
|
|
});
|
|
assert.strictEqual(consoleErrorMock.callCount(), 0);
|
|
});
|
|
it('should ignore undefined property', () => {
|
|
const wrapper = shallow(React.createElement(StyledComponent1, {
|
|
classes: {
|
|
root: undefined
|
|
}
|
|
}));
|
|
assert.deepEqual(wrapper.props().classes, {
|
|
root: classes.root
|
|
});
|
|
assert.strictEqual(consoleErrorMock.callCount(), 0);
|
|
});
|
|
it('should warn if providing a unknown key', () => {
|
|
const wrapper = shallow(React.createElement(StyledComponent1, {
|
|
classes: {
|
|
bar: 'foo'
|
|
}
|
|
}));
|
|
assert.deepEqual(wrapper.props().classes, {
|
|
root: classes.root,
|
|
bar: 'undefined foo'
|
|
});
|
|
assert.strictEqual(consoleErrorMock.callCount(), 1);
|
|
assert.match(consoleErrorMock.args()[0][0], /Material-UI: the key `bar` provided to the classes property is not implemented/);
|
|
});
|
|
it('should warn if providing a non string', () => {
|
|
const wrapper = shallow(React.createElement(StyledComponent1, {
|
|
classes: {
|
|
root: {}
|
|
}
|
|
}));
|
|
assert.deepEqual(wrapper.props().classes, {
|
|
root: `${classes.root} [object Object]`
|
|
});
|
|
assert.strictEqual(consoleErrorMock.callCount(), 2);
|
|
assert.match(consoleErrorMock.args()[1][0], /Material-UI: the key `root` provided to the classes property is not valid/);
|
|
});
|
|
});
|
|
describe('prop: innerRef', () => {
|
|
it('should provide a ref on the inner component', () => {
|
|
const handleRef = spy();
|
|
mount(React.createElement(StyledComponent1, {
|
|
innerRef: handleRef
|
|
}));
|
|
assert.strictEqual(handleRef.callCount, 1);
|
|
});
|
|
});
|
|
|
|
var _ref4 = React.createElement(StyledComponent1, null);
|
|
|
|
describe('cache', () => {
|
|
it('should recycle with no classes property', () => {
|
|
const wrapper = mount(_ref4);
|
|
const classes1 = wrapper.find(Empty).props().classes;
|
|
wrapper.update();
|
|
const classes2 = wrapper.find(Empty).props().classes;
|
|
assert.strictEqual(classes1, classes2);
|
|
});
|
|
it('should recycle even when a classes property is provided', () => {
|
|
const inputClasses = {
|
|
root: 'foo'
|
|
};
|
|
const wrapper = mount(React.createElement(StyledComponent1, {
|
|
classes: inputClasses
|
|
}));
|
|
const classes1 = wrapper.find(Empty).props().classes;
|
|
wrapper.setProps({
|
|
classes: inputClasses
|
|
});
|
|
const classes2 = wrapper.find(Empty).props().classes;
|
|
assert.strictEqual(classes1, classes2);
|
|
});
|
|
it('should invalidate the cache', () => {
|
|
const wrapper = mount(React.createElement(StyledComponent1, {
|
|
classes: {
|
|
root: 'foo'
|
|
}
|
|
}));
|
|
const classes1 = wrapper.find(Empty).props().classes;
|
|
assert.deepEqual(classes1, {
|
|
root: `${classes.root} foo`
|
|
});
|
|
wrapper.setProps({
|
|
classes: {
|
|
root: 'bar'
|
|
}
|
|
});
|
|
const classes2 = wrapper.find(Empty).props().classes;
|
|
assert.notStrictEqual(classes1, classes2);
|
|
assert.deepEqual(classes2, {
|
|
root: `${classes.root} bar`
|
|
});
|
|
});
|
|
});
|
|
});
|
|
describe('mount', () => {
|
|
let sheetsRegistry;
|
|
let jss;
|
|
let generateClassName;
|
|
beforeEach(() => {
|
|
jss = create(jssPreset());
|
|
generateClassName = createGenerateClassName();
|
|
sheetsRegistry = new SheetsRegistry();
|
|
});
|
|
it('should run lifecycles with no theme', () => {
|
|
const styles = {
|
|
root: {
|
|
display: 'flex'
|
|
}
|
|
};
|
|
const StyledComponent = withStyles(styles)(Empty);
|
|
const wrapper = mount(React.createElement(MuiThemeProvider, {
|
|
theme: createMuiTheme()
|
|
}, React.createElement(JssProvider, {
|
|
registry: sheetsRegistry,
|
|
jss: jss,
|
|
generateClassName: generateClassName
|
|
}, React.createElement(StyledComponent, null))));
|
|
assert.strictEqual(sheetsRegistry.registry.length, 1);
|
|
assert.deepEqual(sheetsRegistry.registry[0].classes, {
|
|
root: 'Empty-root-1'
|
|
});
|
|
wrapper.update();
|
|
assert.strictEqual(sheetsRegistry.registry.length, 1, 'should only attach once');
|
|
assert.deepEqual(sheetsRegistry.registry[0].classes, {
|
|
root: 'Empty-root-1'
|
|
});
|
|
wrapper.setProps({
|
|
theme: createMuiTheme()
|
|
});
|
|
assert.strictEqual(sheetsRegistry.registry.length, 1, 'should only attach once');
|
|
assert.deepEqual(sheetsRegistry.registry[0].classes, {
|
|
root: 'Empty-root-1'
|
|
});
|
|
wrapper.unmount();
|
|
assert.strictEqual(sheetsRegistry.registry.length, 0);
|
|
});
|
|
it('should work when depending on a theme', () => {
|
|
const styles = theme => ({
|
|
root: {
|
|
padding: theme.spacing.unit
|
|
}
|
|
});
|
|
|
|
const StyledComponent = withStyles(styles, {
|
|
name: 'MuiTextField'
|
|
})(Empty);
|
|
const wrapper = mount(React.createElement(MuiThemeProvider, {
|
|
theme: createMuiTheme()
|
|
}, React.createElement(JssProvider, {
|
|
registry: sheetsRegistry,
|
|
jss: jss,
|
|
generateClassName: generateClassName
|
|
}, React.createElement(StyledComponent, null))));
|
|
assert.strictEqual(sheetsRegistry.registry.length, 1, 'should only attach once');
|
|
assert.deepEqual(sheetsRegistry.registry[0].classes, {
|
|
root: 'MuiTextField-root-1'
|
|
});
|
|
wrapper.setProps({
|
|
theme: createMuiTheme()
|
|
});
|
|
assert.strictEqual(sheetsRegistry.registry.length, 1, 'should only attach once');
|
|
assert.deepEqual(sheetsRegistry.registry[0].classes, {
|
|
root: 'MuiTextField-root-2'
|
|
});
|
|
});
|
|
it('should support the overrides key', () => {
|
|
const styles = {
|
|
root: {
|
|
padding: 8
|
|
}
|
|
};
|
|
const StyledComponent = withStyles(styles, {
|
|
name: 'MuiTextField'
|
|
})(Empty);
|
|
mount(React.createElement(MuiThemeProvider, {
|
|
theme: createMuiTheme({
|
|
overrides: {
|
|
MuiTextField: {
|
|
root: {
|
|
padding: 9
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}, React.createElement(JssProvider, {
|
|
registry: sheetsRegistry,
|
|
jss: jss,
|
|
generateClassName: generateClassName
|
|
}, React.createElement(StyledComponent, null))));
|
|
assert.strictEqual(sheetsRegistry.registry.length, 1, 'should only attach once');
|
|
assert.deepEqual(sheetsRegistry.registry[0].rules.raw, {
|
|
root: {
|
|
padding: 9
|
|
}
|
|
});
|
|
});
|
|
describe('options: disableStylesGeneration', () => {
|
|
it('should not generate the styles', () => {
|
|
const styles = {
|
|
root: {
|
|
display: 'flex'
|
|
}
|
|
};
|
|
const StyledComponent = withStyles(styles)(Empty);
|
|
const wrapper = mount(React.createElement(MuiThemeProvider, {
|
|
theme: createMuiTheme(),
|
|
disableStylesGeneration: true
|
|
}, React.createElement(JssProvider, {
|
|
registry: sheetsRegistry,
|
|
jss: jss,
|
|
generateClassName: generateClassName
|
|
}, React.createElement(StyledComponent, null))));
|
|
assert.strictEqual(sheetsRegistry.registry.length, 0);
|
|
assert.deepEqual(wrapper.find(Empty).props().classes, {});
|
|
wrapper.unmount();
|
|
assert.strictEqual(sheetsRegistry.registry.length, 0);
|
|
});
|
|
});
|
|
});
|
|
describe('HMR with same state', () => {
|
|
it('should take the new stylesCreator into account', () => {
|
|
const styles1 = {
|
|
root: {
|
|
padding: 1
|
|
}
|
|
};
|
|
const StyledComponent1 = withStyles(styles1, {
|
|
name: 'MuiTextField'
|
|
})(Empty);
|
|
const wrapper = mount(React.createElement(StyledComponent1, null));
|
|
const styles2 = {
|
|
root: {
|
|
padding: 2
|
|
}
|
|
};
|
|
const StyledComponent2 = withStyles(styles2, {
|
|
name: 'MuiTextField'
|
|
})(Empty); // Simulate react-hot-loader behavior
|
|
|
|
wrapper.instance().componentDidUpdate = StyledComponent2.prototype.componentDidUpdate;
|
|
const classes1 = wrapper.childAt(0).props().classes.root;
|
|
wrapper.setProps({});
|
|
wrapper.update();
|
|
const classes2 = wrapper.childAt(0).props().classes.root;
|
|
assert.notStrictEqual(classes1, classes2, 'should generate new classes');
|
|
});
|
|
});
|
|
}); |