• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!doctype html>
2<!--
3@license
4Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
5This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
6The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
7The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
8Code distributed by Google as part of the polymer project is also
9subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
10-->
11<html>
12<head>
13
14  <meta charset="utf-8">
15  <script>
16  WCT = {waitFor: function (cb) {HTMLImports.whenReady(cb)}}
17  </script>
18  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>
19  <script src="../../node_modules/@webcomponents/webcomponents-platform/webcomponents-platform.js"></script>
20  <script src="../../node_modules/es6-promise/dist/es6-promise.auto.min.js"></script>
21  <script src="../../node_modules/@webcomponents/template/template.js"></script>
22  <script src="../../node_modules/@webcomponents/html-imports/html-imports.min.js"></script>
23  <script src="../../node_modules/@webcomponents/shadydom/shadydom.min.js"></script>
24  <script src="../../node_modules/@webcomponents/custom-elements/custom-elements.min.js"></script>
25  <script src="../../apply-shim.min.js"></script>
26  <script src="../../custom-style-interface.min.js"></script>
27  <script src="../module/generated/make-element.js"></script>
28  <script src="../module/generated/custom-style-element.js"></script>
29  <script src="../module/generated/style-util.js"></script>
30  <title>Apply Shim</title>
31
32</head>
33<body>
34  <template id="basic">
35    <style>
36    :host {
37      --mixin: {
38        border: 2px solid black;
39      };
40    }
41    div {
42      @apply --mixin;
43    }
44    </style>
45  </template>
46
47  <template id="defaults">
48    <style>
49    :host {
50      --mixin: {
51        border: 2px solid black;
52      }
53    }
54    div {
55      border: 1px dotted orange;
56      @apply --mixin;
57    }
58    span {
59      border: inherit;
60      @apply --mixin;
61    }
62    span {
63      border: initial;
64      @apply --mixin;
65    }
66    </style>
67  </template>
68
69  <template id="override">
70    <style>
71    :host {
72      --override: {
73        padding: 2px;
74      };
75    }
76    :host([override]) {
77      --override: {
78        border: 2px solid black;
79      };
80    }
81    div {
82      @apply --override;
83    }
84    </style>
85  </template>
86
87  <template id="override-with-property">
88    <style>
89    :root {
90      --prop-mixin: {
91        border: 2px solid black;
92      };
93    }
94    x-foo {
95      --prop-mixin: blue;
96      color: var(--prop-mixin);
97    }
98    div {
99      @apply --prop-mixin;
100    }
101    </style>
102  </template>
103
104  <template id="define-with-var">
105    <style>
106    :root {
107      --mixin-var: {
108        border: 2px solid black;
109      };
110    }
111    div {
112      --mixin-var2: var(--mixin-var);
113    }
114    span {
115      --mixin-var: 20px;
116      --variable: var(--mixin-var);
117    }
118    </style>
119  </template>
120
121  <template id="x-element">
122    <style>
123    :host {
124      @apply --my-mixin;
125    }
126    </style>
127  </template>
128
129  <template id="x-element2">
130    <custom-style>
131    <style>
132    html {
133      --my-mixin: {
134        border: 2px solid black;
135      };
136    }
137    </style>
138    </custom-style>
139  </template>
140
141  <template id="css-build" css-build="shadow">
142    <style>:host{@apply --fake;}</style>
143  </template>
144
145  <template id="css-build-comment"><!--css-build:shadow-->
146    <style>:host{@apply --fake;}</style>
147  </template>
148
149  <script>
150  suite('Apply Shim', function() {
151    function copy(name) {
152      var template = document.querySelector('template#' + name);
153      return template.content.cloneNode(true);
154    }
155
156    function prep(templateName, elementName) {
157      var style = copy(templateName).querySelector('style');
158      var ast = window.ShadyCSS.ApplyShim.transformStyle(style, elementName);
159      return {style: style, ast: ast};
160    }
161
162    suite('Basic', function() {
163      var style, ast;
164      suiteSetup(function() {
165        var info = prep('basic');
166        style = info.style;
167        ast = info.ast;
168        style.textContent = window.StyleUtil.toCssText(ast);
169      });
170
171      test('style is transformed', function() {
172        var orig = copy('basic').querySelector('style');
173        assert.notEqual(style.textContent, orig.textContent);
174      });
175
176      test('mixin became custom properties', function() {
177        var definition = ast.rules[0];
178        var application = ast.rules[1];
179        assert.match(definition.cssText, /--mixin_-_border:\s*2px solid black/);
180        assert.match(application.cssText, /border:\s*var\(--mixin_-_border\)/);
181      });
182    });
183    suite('Defaults', function() {
184      var style, ast; // eslint-disable-line no-unused-vars
185      suiteSetup(function() {
186        var info = prep('defaults');
187        style = info.style;
188        ast = info.ast;
189      });
190
191      test('properties defined before mixin are used as defaults', function() {
192        var application = ast.rules[1];
193        assert.match(application.cssText, /border:\s*var\(--mixin_-_border,\s*1px dotted orange\)/);
194      });
195
196      test('inherit and initial default values are preserved', function () {
197        var application = ast.rules[2];
198        assert.match(application.cssText, /border:\s*var\(--mixin_-_border,\s*inherit\)/);
199        application = ast.rules[3];
200        assert.match(application.cssText, /border:\s*var\(--mixin_-_border,\s*initial\)/);
201      });
202    });
203
204    suite('override', function() {
205      var style, ast; // eslint-disable-line no-unused-vars
206      suiteSetup(function() {
207        var info = prep('override');
208        style = info.style;
209        ast = info.ast;
210      });
211
212      test('mixin redefinition sets unused properties to initial', function() {
213        var def1 = ast.rules[0];
214        assert.match(def1.cssText, /--override_-_padding:\s*2px/);
215        var def2 = ast.rules[1];
216        assert.match(def2.cssText, /--override_-_padding:\s*initial/);
217        assert.match(def2.cssText, /--override_-_border:\s*2px solid black/);
218      });
219
220      test('mixin application includes all values', function() {
221        var application = ast.rules[2];
222        assert.match(application.cssText, /padding:\s*var\(--override_-_padding\)/);
223        assert.match(application.cssText, /border:\s*var\(--override_-_border\)/);
224      });
225    });
226
227    suite('override with property', function() {
228      var style, ast; // eslint-disable-line no-unused-vars
229      suiteSetup(function() {
230        var info = prep('override-with-property');
231        style = info.style;
232        ast = info.ast;
233      });
234
235      test('mixin definition defers to property definition', function() {
236        var def = ast.rules[1];
237        assert.notMatch(def.cssText, /border:\s*var\(--prop-mixin_-_border\)/);
238      });
239
240      test('mixin can still be used by other parts of the page', function() {
241        var def = ast.rules[2];
242        assert.match(def.cssText, /border:\s*var\(--prop-mixin_-_border\)/);
243      });
244    });
245
246    suite('define with var()', function() {
247      var style, ast; // eslint-disable-line no-unused-vars
248      suiteSetup(function() {
249        var info = prep('define-with-var');
250        style = info.style;
251        ast = info.ast;
252      });
253
254      test('mixin-var2 is defined with mixin-var\'s values', function() {
255        var def = ast.rules[1];
256        assert.match(def.cssText, /--mixin-var2_-_border:\s*var\(--mixin-var_-_border\)/);
257      });
258
259      test('var usage of mixin is not removed, preserving override functionality', function() {
260        var def = ast.rules[2];
261        assert.match(def.cssText, /--variable:\s*var\(--mixin-var\)/);
262      });
263    });
264
265    suite('invalidation on new definitions', function() {
266      var style, ast, element;
267      suiteSetup(function() {
268        makeElement('x-element');
269        element = document.createElement('x-element');
270        document.body.appendChild(element);
271        style = element.shadowRoot ? element.shadowRoot.querySelector('style') : document.head.querySelector('style[scope=x-element]');
272      });
273
274      test('element initially has no definition', function() {
275        var ast = window.StyleUtil.rulesForStyle(style);
276        assert.equal(ast.rules[0].cssText, ';');
277      });
278
279      test('Revalidating Apply Shim on element template fills in properties', function() {
280        var nodes = copy('x-element2');
281        document.body.appendChild(nodes);
282        window.ShadyCSS.styleDocument();
283        var ast = window.StyleUtil.rulesForStyle(style);
284        assert.match(ast.rules[0].cssText, /border:\s*var\(--my-mixin_-_border\)/);
285      });
286    });
287
288    test('templates with "css-build" will not be processed by ApplyShim', function() {
289      makeElement('css-build');
290      const template = document.querySelector('template#css-build');
291      assert.equal(template._styleAst, undefined);
292      const style = template.content.querySelector('style');
293      assert.match(style.textContent.trim(), /:host\s*{\s*@apply --fake;\s*}/);
294    });
295
296    test('templates with "css-build" comment will not be processed by ApplyShim', function () {
297      const template = document.querySelector('template#css-build-comment');
298      const buildComment = template.content.firstChild;
299      assert.instanceOf(buildComment, Comment, 'first node in template content should be a Comment');
300      makeElement('css-build-comment');
301      assert.equal(template._styleAst, undefined);
302      const style = template.content.querySelector('style');
303      assert.match(style.textContent.trim(), /:host\s*{\s*@apply --fake;\s*}/);
304      assert.equal(buildComment.parentNode, null, 'build comment should be removed');
305    });
306  });
307  </script>
308</body>
309</html>
310