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<script>
12WCT = {waitFor: function (cb) {HTMLImports.whenReady(cb)}}
13</script>
14<script src="./test-flags.js"></script>
15<script src="../node_modules/wct-browser-legacy/browser.js"></script>
16<script src="../node_modules/@webcomponents/webcomponents-platform/webcomponents-platform.js"></script>
17<script src="../node_modules/es6-promise/dist/es6-promise.auto.min.js"></script>
18<script src="../node_modules/@webcomponents/template/template.js"></script>
19<script src="../node_modules/@webcomponents/html-imports/html-imports.min.js"></script>
20<script src="../node_modules/@webcomponents/shadydom/shadydom.min.js"></script>
21<script src="../node_modules/@webcomponents/custom-elements/custom-elements.min.js"></script>
22<script src="../scoping-shim.min.js"></script>
23<script src="module/generated/style-transformer.js"></script>
24<title>Style Transformer</title>
25
26<template id="host">
27  <style>
28  :host {
29    color: blue;
30  }
31  :host([red]) {
32    color: red;
33  }
34  :host > * {
35    color: green;
36  }
37  :host(.bar) :-webkit-any(.foo, .bar) {
38    color: purple;
39  };
40  :-webkit-any([baz], [zot="foo"]) :matches(foo, bar) > :-moz-any(:not(:defined), :unresolved) {
41    color: rgb(123, 123, 123);
42  }
43  :matches(a, b) {
44    color: black;
45  }
46  </style>
47</template>
48
49<template id="slotted">
50  <style>
51  div::slotted(.foo) {
52    color: gray;
53  }
54  ::slotted(.bar) {
55    color: lightgray;
56  }
57  :host > ::slotted(*:nth-of-type(2n - 1)) {
58    color: red;
59  }
60  </style>
61</template>
62
63<template id="dir">
64  <style>
65  div:dir(rtl) {
66    color: blue;
67  }
68  :host(:dir(rtl)) {
69    color: blue;
70  }
71  </style>
72</template>
73
74<template id="custom-style">
75  <style>
76  :root {
77    color: black;
78  }
79  </style>
80</template>
81
82<template id="shared-style">
83  <style>
84    html, :host {
85      color: gray;
86    }
87  </style>
88</template>
89
90<template id="attribute-style">
91  <style>
92    [foo="foo:bar"] {
93      background-color: blue;
94    }
95  </style>
96</template>
97
98<template id="nested-attribute-style">
99  <style>
100    [foo="foo:bar"] [foo="foo:bar"] {
101      background-color: blue;
102    }
103  </style>
104</template>
105
106<template id="prepended-attribute-style">
107  <style>
108    foo[foo="foo:bar"] {
109      background-color: blue;
110    }
111  </style>
112</template>
113
114<script>
115function processTemplate(templateName, elementName) {
116  var template = document.querySelector('template#' + templateName);
117  window.ShadyCSS.prepareTemplate(template, elementName);
118  return template._styleAst;
119}
120suite('Style Transformer', function() {
121  setup(function() {
122    if (window.ShadyCSS.nativeShadow) {
123      this.skip();
124    }
125  })
126  suite(':host transforms', function() {
127    var ast;
128    suiteSetup(function() {
129      ast = processTemplate('host', 'x-foo');
130    });
131
132    test(':host{}', function() {
133      assert.equal(ast.rules[0].selector, 'x-foo');
134    });
135
136    test(':host([red]){}', function() {
137      assert.equal(ast.rules[1].selector, 'x-foo[red]');
138    });
139
140    test(':host > *{}', function() {
141      assert.equal(ast.rules[2].selector, 'x-foo > *.x-foo');
142    });
143
144    test(':host() :-webkit-any()', function() {
145      assert.equal(ast.rules[3].selector, 'x-foo.bar :-webkit-any(.foo, .bar).x-foo');
146    });
147
148    test('lots of :matches()', function() {
149      assert.equal(ast.rules[4].selector, ':-webkit-any([baz], [zot="foo"]).x-foo :matches(foo, bar).x-foo > :-moz-any(:not(:defined), :unresolved).x-foo');
150    });
151
152    test('only match', function() {
153      assert.equal(ast.rules[5].selector, ':matches(a, b).x-foo');
154    });
155  });
156
157  suite('::slotted transforms', function() {
158    var ast;
159    suiteSetup(function() {
160      ast = processTemplate('slotted', 'x-slot');
161    });
162
163    test('div::slotted(.foo)', function() {
164      assert.equal(ast.rules[0].selector, 'div.x-slot > .foo');
165    });
166
167    test('::slotted(.bar)', function() {
168      assert.equal(ast.rules[1].selector, 'x-slot > .bar');
169    });
170
171    test(':host > ::slotted(*:nth-of-type(2n - 1))', function() {
172      assert.equal(ast.rules[2].selector, 'x-slot > *:nth-of-type(2n-1)');
173    });
174  });
175
176  suite('dir transforms', function() {
177    var ast;
178    suiteSetup(function() {
179      ast = processTemplate('dir', 'x-dir');
180    });
181
182    test('div:dir(rtl)', function() {
183      assert.equal(ast.rules[0].selector, '[dir="rtl"] div.x-dir, div.x-dir[dir="rtl"]');
184    });
185
186    test('host(:dir(rtl))', function() {
187      assert.equal(ast.rules[1].selector, '[dir="rtl"] x-dir, x-dir[dir="rtl"]');
188    });
189
190  });
191
192  suite('custom-style transforms', function() {
193    var rule;
194    setup(function() {
195      var template = document.querySelector('template#custom-style');
196      var style = template.content.querySelector('style').cloneNode(true);
197      var ast = window.ShadyCSS.ScopingShim.getStyleAst(style);
198      rule = ast.rules[0];
199    });
200
201    test('native ShadowDOM', function() {
202      window.StyleTransformer.normalizeRootSelector(rule);
203      assert.equal(rule.selector, 'html');
204    });
205
206    test('ShadyDOM', function() {
207      window.StyleTransformer.documentRule(rule);
208      assert.equal(rule.selector, 'html:not(.style-scope)');
209    });
210  });
211
212  suite('shared style (light or shadow dom) transforms', function() {
213    let rule;
214
215    setup(function() {
216      const template = document.querySelector('template#shared-style');
217      const style = template.content.querySelector('style').cloneNode(true);
218      const ast = window.ShadyCSS.ScopingShim.getStyleAst(style);
219      rule = ast.rules[0];
220    });
221
222    test('native ShadowDOM', function() {
223      window.StyleTransformer.normalizeRootSelector(rule);
224      assert.equal(rule.selector, 'html, :host');
225    });
226
227    test('ShadyDOM', function() {
228      window.StyleTransformer.documentRule(rule);
229      assert.equal(rule.selector, 'html:not(.style-scope)');
230    });
231  });
232
233  suite('attribute selectors', function() {
234
235    suite('simple', function() {
236      let rule;
237
238      setup(function() {
239        const template = document.querySelector('template#attribute-style');
240        const style = template.content.querySelector('style').cloneNode(true);
241        const ast = window.ShadyCSS.ScopingShim.getStyleAst(style);
242        rule = ast.rules[0];
243      });
244
245      test('native ShadowDOM', function() {
246        window.StyleTransformer.normalizeRootSelector(rule);
247        assert.equal(rule.selector, '[foo="foo:bar"]');
248      });
249
250      test('ShadyDOM', function() {
251        window.StyleTransformer.documentRule(rule);
252        assert.equal(rule.selector, ':not(.style-scope)[foo="foo:bar"]');
253      });
254    });
255
256    suite('nested', function() {
257      let rule;
258
259      setup(function() {
260        const template = document.querySelector('template#nested-attribute-style');
261        const style = template.content.querySelector('style').cloneNode(true);
262        const ast = window.ShadyCSS.ScopingShim.getStyleAst(style);
263        rule = ast.rules[0];
264      });
265
266      test('native ShadowDOM', function() {
267        window.StyleTransformer.normalizeRootSelector(rule);
268        assert.equal(rule.selector, '[foo="foo:bar"] [foo="foo:bar"]');
269      });
270
271      test('ShadyDOM', function() {
272        window.StyleTransformer.documentRule(rule);
273        assert.equal(rule.selector, ':not(.style-scope)[foo="foo:bar"] :not(.style-scope)[foo="foo:bar"]');
274      });
275    });
276
277    suite('prepended', function() {
278      let rule;
279
280      setup(function() {
281        const template = document.querySelector('template#prepended-attribute-style');
282        const style = template.content.querySelector('style').cloneNode(true);
283        const ast = window.ShadyCSS.ScopingShim.getStyleAst(style);
284        rule = ast.rules[0];
285      });
286
287      test('native ShadowDOM', function() {
288        window.StyleTransformer.normalizeRootSelector(rule);
289        assert.equal(rule.selector, 'foo[foo="foo:bar"]');
290      });
291
292      test('ShadyDOM', function() {
293        window.StyleTransformer.documentRule(rule);
294        assert.equal(rule.selector, 'foo:not(.style-scope)[foo="foo:bar"]');
295      });
296    });
297  });
298});
299</script>
300