styled-components
Version:
**This is a work in progress** based off of [this demo](https://github.com/geelen/css-components-demo).
262 lines (208 loc) • 11.1 kB
JavaScript
;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* eslint-disable no-unused-expressions */
/**
* This is our end-to-end test suite, which essentially makes sure our public API works the way we
* promise/want
*/
var _templateObject = _taggedTemplateLiteral([''], ['']),
_templateObject2 = _taggedTemplateLiteral([' \n '], [' \\n ']),
_templateObject3 = _taggedTemplateLiteral(['\n ', '\n '], ['\n ', '\n ']),
_templateObject4 = _taggedTemplateLiteral(['\n ', '\n ', '\n '], ['\n ', '\n ', '\n ']),
_templateObject5 = _taggedTemplateLiteral(['color: blue;'], ['color: blue;']),
_templateObject6 = _taggedTemplateLiteral(['color: red;'], ['color: red;']),
_templateObject7 = _taggedTemplateLiteral(['\n color: blue;\n > h1 { font-size: 4rem; }\n '], ['\n color: blue;\n > h1 { font-size: 4rem; }\n ']);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _expect = require('expect');
var _expect2 = _interopRequireDefault(_expect);
var _proxyquire = require('proxyquire');
var _proxyquire2 = _interopRequireDefault(_proxyquire);
var _enzyme = require('enzyme');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Setup
*/
var styleSheet = void 0;
var styled = void 0;
var StubStylesheet = function () {
function StubStylesheet() {
_classCallCheck(this, StubStylesheet);
// TODO: there must be a better way to get a handle on the instance each time
// For the tests so far, the first stylesheet to be created is the good one
// TODO: fix GlobalStyle.js
if (!styleSheet) styleSheet = this;
this.injected = false;
this.rules = [];
}
_createClass(StubStylesheet, [{
key: 'inject',
value: function inject() {
this.injected = true;
}
}, {
key: 'insert',
value: function insert(string) {
var rule = string ? [string] : [];
this.rules.push(rule);
return { appendRule: function appendRule(css) {
return rule.push(css);
} };
}
}, {
key: 'toCSS',
value: function toCSS() {
return this.rules.map(function (r) {
return r.join('\n');
}).join('\n');
}
}]);
return StubStylesheet;
}();
var stubbedSheet = {
StyleSheet: StubStylesheet,
'@global': true
};
/* Ignore hashing, just return class names sequentially as .a .b .c etc */
var index = 0;
var classNames = function classNames(code) {
var lastLetter = String.fromCodePoint(97 + code);
return code > 26 ? '' + classNames(Math.floor(code / 26)) + lastLetter : lastLetter;
};
var stubbedEmoji = function stubbedEmoji() {
return classNames(index++);
}; // eslint-disable-line no-plusplus
stubbedEmoji['@global'] = true;
describe('e2e', function () {
/**
* Make sure the setup is the same for every test
*/
beforeEach(function () {
styleSheet = null;
index = 0;
styled = (0, _proxyquire2.default)('../index', {
'../vendor/glamor/sheet': stubbedSheet,
'../utils/toEmoji': stubbedEmoji
}).default;
});
/**
* Tests
*/
describe('basic', function () {
it('should not throw an error when called', function () {
styled.div(_templateObject);
});
it('should inject a stylesheet when a component is created', function () {
var Comp = styled.div(_templateObject);
(0, _enzyme.shallow)(_react2.default.createElement(Comp, null));
(0, _expect2.default)(styleSheet.injected).toBe(true);
});
it('should not generate any styles by default', function () {
styled.div(_templateObject);
(0, _expect2.default)(styleSheet.toCSS()).toEqual('');
});
it('should generate an empty tag once rendered', function () {
var Comp = styled.div(_templateObject);
(0, _enzyme.shallow)(_react2.default.createElement(Comp, null));
(0, _expect2.default)(styleSheet.toCSS()).toEqual('.a { }');
});
/* TODO: we should probably pretty-format the output so this test might have to change */
it('should pass through all whitespace', function () {
var Comp = styled.div(_templateObject2);
(0, _enzyme.shallow)(_react2.default.createElement(Comp, null));
(0, _expect2.default)(styleSheet.toCSS()).toEqual('.a { \n }');
});
it('should inject only once for a styled component, no matter how often it\'s mounted', function () {
var Comp = styled.div(_templateObject);
(0, _enzyme.shallow)(_react2.default.createElement(Comp, null));
(0, _enzyme.shallow)(_react2.default.createElement(Comp, null));
(0, _expect2.default)(styleSheet.toCSS()).toEqual('.a { }');
});
});
describe('with styles', function () {
it('should append a style', function () {
var rule = 'color: blue;';
var Comp = styled.div(_templateObject3, rule);
(0, _enzyme.shallow)(_react2.default.createElement(Comp, null));
(0, _expect2.default)(styleSheet.toCSS().replace(/\s+/g, ' ')).toEqual('.a { color: blue; }');
});
it('should append multiple styles', function () {
var rule1 = 'color: blue;';
var rule2 = 'background: red;';
var Comp = styled.div(_templateObject4, rule1, rule2);
(0, _enzyme.shallow)(_react2.default.createElement(Comp, null));
(0, _expect2.default)(styleSheet.toCSS().replace(/\s+/g, ' ')).toEqual('.a { color: blue; background: red; }');
});
it('should inject styles of multiple components', function () {
var firstRule = 'background: blue;';
var secondRule = 'background: red;';
var FirstComp = styled.div(_templateObject3, firstRule);
var SecondComp = styled.div(_templateObject3, secondRule);
(0, _enzyme.shallow)(_react2.default.createElement(FirstComp, null));
(0, _enzyme.shallow)(_react2.default.createElement(SecondComp, null));
(0, _expect2.default)(styleSheet.toCSS().replace(/\s+/g, ' ')).toEqual('.a { background: blue; } .b { background: red; }');
});
it('should inject styles of multiple components based on creation, not rendering order', function () {
var firstRule = 'content: "first rule";';
var secondRule = 'content: "second rule";';
var FirstComp = styled.div(_templateObject3, firstRule);
var SecondComp = styled.div(_templateObject3, secondRule);
// Switch rendering order, shouldn't change injection order
(0, _enzyme.shallow)(_react2.default.createElement(SecondComp, null));
(0, _enzyme.shallow)(_react2.default.createElement(FirstComp, null));
// Classes _do_ get generated in the order of rendering but that's ok
(0, _expect2.default)(styleSheet.toCSS().replace(/\s+/g, ' ')).toEqual('\n .b { content: "first rule"; }\n .a { content: "second rule"; }\n '.trim().replace(/\s+/g, ' '));
});
it('should ignore a JS-style (invalid) comment in the styles', function () {
var comment = '// This is an invalid comment';
var rule = 'color: blue;';
var Comp = styled.div(_templateObject4, comment, rule);
(0, _enzyme.shallow)(_react2.default.createElement(Comp, null));
(0, _expect2.default)(styleSheet.toCSS().replace(/\s+/g, ' ')).toEqual(('\n .a {\n // This is an invalid comment ' + '\n color: blue;\n }\n ').trim().replace(/\s+/g, ' '));
});
});
describe('extending', function () {
it('should generate a single class with no styles', function () {
var Parent = styled.div(_templateObject);
var Child = styled(Parent)(_templateObject);
(0, _enzyme.shallow)(_react2.default.createElement(Parent, null));
(0, _enzyme.shallow)(_react2.default.createElement(Child, null));
(0, _expect2.default)(styleSheet.toCSS().trim().replace(/\s+/g, ' ')).toEqual('.a { }');
});
it('should generate a single class if only parent has styles', function () {
var Parent = styled.div(_templateObject5);
var Child = styled(Parent)(_templateObject);
(0, _enzyme.shallow)(_react2.default.createElement(Parent, null));
(0, _enzyme.shallow)(_react2.default.createElement(Child, null));
(0, _expect2.default)(styleSheet.toCSS().trim().replace(/\s+/g, ' ')).toEqual('.a { color: blue; }');
});
it('should generate a single class if only child has styles', function () {
var Parent = styled.div(_templateObject5);
var Child = styled(Parent)(_templateObject);
(0, _enzyme.shallow)(_react2.default.createElement(Parent, null));
(0, _enzyme.shallow)(_react2.default.createElement(Child, null));
(0, _expect2.default)(styleSheet.toCSS().trim().replace(/\s+/g, ' ')).toEqual('.a { color: blue; }');
});
it('should generate a class for the child with the rules of the parent', function () {
var Parent = styled.div(_templateObject5);
var Child = styled(Parent)(_templateObject6);
(0, _enzyme.shallow)(_react2.default.createElement(Child, null));
(0, _expect2.default)(styleSheet.toCSS().trim().replace(/\s+/g, ' ')).toEqual('.a { color: blue;color: red; }');
});
it('should generate different classes for both parent and child', function () {
var Parent = styled.div(_templateObject5);
var Child = styled(Parent)(_templateObject6);
(0, _enzyme.shallow)(_react2.default.createElement(Parent, null));
(0, _enzyme.shallow)(_react2.default.createElement(Child, null));
(0, _expect2.default)(styleSheet.toCSS().trim().replace(/\s+/g, ' ')).toEqual('.a { color: blue; } .b { color: blue;color: red; }');
});
it('should copy nested rules to the child', function () {
var Parent = styled.div(_templateObject7);
var Child = styled(Parent)(_templateObject6);
(0, _enzyme.shallow)(_react2.default.createElement(Parent, null));
(0, _enzyme.shallow)(_react2.default.createElement(Child, null));
(0, _expect2.default)(styleSheet.toCSS().trim().replace(/\s+/g, ' ')).toEqual('\n .a { color: blue; }\n .a > h1 { font-size: 4rem; }\n .b { color: blue; color: red; }\n .b > h1 { font-size: 4rem; }\n '.trim().replace(/\s+/g, ' '));
});
});
});