blob: dd2213679062ac8ad24166ef37a263ae6544048d [file] [log] [blame]
<!doctype html>
<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<meta charset="utf-8">
<script>
WCT = {waitFor: function (cb) {HTMLImports.whenReady(cb)}}
</script>
<script src="./test-flags.js"></script>
<script src="../node_modules/wct-browser-legacy/browser.js"></script>
<script src="../node_modules/@webcomponents/webcomponents-platform/webcomponents-platform.js"></script>
<script src="../node_modules/es6-promise/dist/es6-promise.auto.min.js"></script>
<script src="../node_modules/@webcomponents/template/template.js"></script>
<script src="../node_modules/@webcomponents/html-imports/html-imports.min.js"></script>
<script src="../node_modules/@webcomponents/shadydom/shadydom.min.js"></script>
<script src="../node_modules/@webcomponents/custom-elements/custom-elements.min.js"></script>
<script src="../scoping-shim.min.js"></script>
<script src="../apply-shim.min.js"></script>
<script>
if (customElements.polyfillWrapFlushCallback) {
// delay definition of custom-style until after template polyfill loads
customElements.polyfillWrapFlushCallback(function(cb) {
HTMLImports.whenReady(cb);
});
}
</script>
<script src="../custom-style-interface.min.js"></script>
<script src="module/generated/custom-style-element.js"></script>
<script src="module/generated/make-element.js"></script>
<title>Apply Shim</title>
</head>
<body>
<template id="basic">
<style>
:host {
--mixin: {
border: 2px solid black;
};
}
div {
@apply --mixin;
}
</style>
</template>
<template id="defaults">
<style>
:host {
--mixin: {
border: 2px solid black;
}
}
div {
border: 1px dotted orange;
@apply --mixin;
}
span {
border: inherit;
@apply --mixin;
}
span {
border: initial;
@apply --mixin;
}
</style>
</template>
<template id="override">
<style>
:host {
--override: {
padding: 2px;
};
}
:host([override]) {
--override: {
border: 2px solid black;
};
}
div {
@apply --override;
}
</style>
</template>
<template id="override-with-property">
<style>
:root {
--prop-mixin: {
border: 2px solid black;
};
}
x-foo {
--prop-mixin: blue;
color: var(--prop-mixin);
}
div {
@apply --prop-mixin;
}
</style>
</template>
<template id="define-with-var">
<style>
:root {
--mixin-var: {
border: 2px solid black;
};
}
div {
--mixin-var2: var(--mixin-var);
}
span {
--mixin-var: 20px;
--variable: var(--mixin-var);
}
</style>
</template>
<template id="x-element">
<style>
:host {
@apply --my-mixin;
}
</style>
</template>
<template id="x-element2">
<custom-style>
<style>
html {
--my-mixin: {
border: 2px solid black;
};
}
</style>
</custom-style>
</template>
<template id="important">
<style>
:host {
--mixin-important: {
background-color: white;
border: 2px solid black !important;
color: white !important;
};
--mixin: {
background-color: red;
border: 1px dotted orange;
color: black !important;
};
}
div {
@apply --mixin-important;
@apply --mixin;
}
</style>
</template>
<script>
suite('Apply Shim', function() {
function copy(name) {
var template = document.querySelector('template#' + name);
return template.content.cloneNode(true);
}
function prep(templateName, elementName) {
var style = copy(templateName).querySelector('style');
var ast = window.ShadyCSS.ApplyShim.transformStyle(style, elementName);
return {style: style, ast: ast};
}
suite('Basic', function() {
var style, ast;
suiteSetup(function() {
var info = prep('basic');
style = info.style;
ast = info.ast;
style.textContent = window.ShadyCSS.ScopingShim.styleAstToString(ast);
});
test('style is transformed', function() {
var orig = copy('basic').querySelector('style');
assert.notEqual(style.textContent, orig.textContent);
});
test('mixin became custom properties', function() {
var definition = ast.rules[0];
var application = ast.rules[1];
assert.match(definition.cssText, /--mixin_-_border:\s*2px solid black/);
assert.match(application.cssText, /border:\s*var\(--mixin_-_border\)/);
});
});
suite('Defaults', function() {
var style, ast; // eslint-disable-line no-unused-vars
suiteSetup(function() {
var info = prep('defaults');
style = info.style;
ast = info.ast;
});
test('properties defined before mixin are used as defaults', function() {
var application = ast.rules[1];
assert.match(application.cssText, /border:\s*var\(--mixin_-_border,\s*1px dotted orange\)/);
});
test('inherit and initial default values are preserved', function() {
var application = ast.rules[2];
assert.match(application.cssText, /border:\s*var\(--mixin_-_border,\s*inherit\)/);
application = ast.rules[3];
assert.match(application.cssText, /border:\s*var\(--mixin_-_border,\s*initial\)/);
});
});
suite('override', function() {
var style, ast; // eslint-disable-line no-unused-vars
suiteSetup(function() {
var info = prep('override');
style = info.style;
ast = info.ast;
});
test('mixin redefinition sets unused properties to initial', function() {
var def1 = ast.rules[0];
assert.match(def1.cssText, /--override_-_padding:\s*2px/);
var def2 = ast.rules[1];
assert.match(def2.cssText, /--override_-_padding:\s*initial/);
assert.match(def2.cssText, /--override_-_border:\s*2px solid black/);
});
test('mixin application includes all values', function() {
var application = ast.rules[2];
assert.match(application.cssText, /padding:\s*var\(--override_-_padding\)/);
assert.match(application.cssText, /border:\s*var\(--override_-_border\)/);
});
});
suite('override with property', function() {
var style, ast; // eslint-disable-line no-unused-vars
suiteSetup(function() {
var info = prep('override-with-property');
style = info.style;
ast = info.ast;
});
test('mixin definition defers to property definition', function() {
var def = ast.rules[1];
assert.notMatch(def.cssText, /border:\s*var\(--prop-mixin_-_border\)/);
});
test('mixin can still be used by other parts of the page', function() {
var def = ast.rules[2];
assert.match(def.cssText, /border:\s*var\(--prop-mixin_-_border\)/);
});
});
suite('define with var()', function() {
var style, ast; // eslint-disable-line no-unused-vars
suiteSetup(function() {
var info = prep('define-with-var');
style = info.style;
ast = info.ast;
});
test('mixin-var2 is defined with mixin-var\'s values', function() {
var def = ast.rules[1];
assert.match(def.cssText, /--mixin-var2_-_border:\s*var\(--mixin-var_-_border\)/);
});
test('var usage of mixin is not removed, preserving override functionality', function() {
var def = ast.rules[2];
assert.match(def.cssText, /--variable:\s*var\(--mixin-var\)/);
});
});
suite('invalidation on new definitions', function() {
var style, ast, element;
suiteSetup(function() {
makeElement('x-element');
element = document.createElement('x-element');
document.body.appendChild(element);
style = element.shadowRoot ? element.shadowRoot.querySelector('style') : document.head.querySelector('style[scope=x-element]');
});
test('element initially has no definition', function() {
var ast = window.ShadyCSS.ScopingShim._styleInfoForNode(element)._getStyleRules();
assert.equal(ast.rules[0].cssText, ';');
});
test('Revalidating Apply Shim on element template fills in properties', function() {
var nodes = copy('x-element2');
document.body.appendChild(nodes);
window.ShadyCSS.styleDocument();
var ast = window.ShadyCSS.ScopingShim._styleInfoForNode(element)._getStyleRules();
if (window.ShadyCSS.nativeCss) {
assert.match(ast.rules[0].cssText, /border:\s*var\(--my-mixin_-_border\)/);
} else {
assert.match(ast.rules[0].cssText, /border:\s*2px solid black/);
}
});
});
suite('!important', function() {
var ast;
suiteSetup(function() {
var info = prep('important');
ast = info.ast;
});
test('!important in mixin correctly translates to !important in resulting custom property', function() {
var application = ast.rules[1];
assert.match(application.cssText, /border:\s*var\(--mixin-important_-_border\)\s*!important/);
});
test("Fallback of related property without !important is kept without !important in resulting custom property", function() {
var application = ast.rules[1];
assert.match(application.cssText, /border:\s*var\(--mixin_-_border,\s*var\(--mixin-important_-_border\)\)/);
});
test('Two mixins with both !important are treated in correct order while also preserving !important in resulting custom property', function () {
var application = ast.rules[1];
assert.match(application.cssText, /color:\s*var\(--mixin-important_-_color\)\s*!important/);
assert.match(application.cssText, /color:\s*var\(--mixin_-_color,\s*var\(--mixin-important_-_color\)\)\s*!important/);
})
test('Properties without !important in a mixin with !important are treated independently', function() {
var application = ast.rules[1];
assert.match(application.cssText, /background-color:\s*var\(--mixin_-_background-color,\s*var\(--mixin-important_-_background-color\)\)/);
assert.notMatch(application.cssText, /background-color:\s*var\(--mixin_-_background-color,\s*var\(--mixin-important_-_background-color\)\)\s*!important/);
assert.match(application.cssText, /background-color:\s*var\(--mixin-important_-_background-color\)/);
assert.notMatch(application.cssText, /background-color:\s*var\(--mixin-important_-_background-color\)\s*!important/);
});
});
});
</script>
</body>
</html>