UNPKG

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
'use strict'; 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, ' ')); }); }); });