library angular2.test.compiler.shadow_css_spec;
import "package:angular2/testing_internal.dart"
show
describe,
beforeEach,
it,
expect,
ddescribe,
iit,
SpyObject,
el,
normalizeCSS;
import "package:angular2/src/compiler/shadow_css.dart"
show ShadowCss, processRules, CssRule;
import "package:angular2/src/facade/lang.dart"
show RegExpWrapper, StringWrapper, isPresent;
main() {
describe("ShadowCss", () {
s(String css, String contentAttr, [String hostAttr = ""]) {
var shadowCss = new ShadowCss();
var shim = shadowCss.shimCssText(css, contentAttr, hostAttr);
var nlRegexp = new RegExp(r'\n');
return normalizeCSS(StringWrapper.replaceAll(shim, nlRegexp, ""));
}
it("should handle empty string", () {
expect(s("", "a")).toEqual("");
});
it("should add an attribute to every rule", () {
var css = "one {color: red;}two {color: red;}";
var expected = "one[a] {color:red;}two[a] {color:red;}";
expect(s(css, "a")).toEqual(expected);
});
it("should handle invalid css", () {
var css = "one {color: red;}garbage";
var expected = "one[a] {color:red;}garbage";
expect(s(css, "a")).toEqual(expected);
});
it("should add an attribute to every selector", () {
var css = "one, two {color: red;}";
var expected = "one[a], two[a] {color:red;}";
expect(s(css, "a")).toEqual(expected);
});
it("should support newlines in the selector and content ", () {
var css = "one, \ntwo {\ncolor: red;}";
var expected = "one[a], two[a] {color:red;}";
expect(s(css, "a")).toEqual(expected);
});
it("should handle media rules", () {
var css =
"@media screen and (max-width:800px, max-height:100%) {div {font-size:50px;}}";
var expected =
"@media screen and (max-width:800px, max-height:100%) {div[a] {font-size:50px;}}";
expect(s(css, "a")).toEqual(expected);
});
it("should handle media rules with simple rules", () {
var css =
"@media screen and (max-width: 800px) {div {font-size: 50px;}} div {}";
var expected =
"@media screen and (max-width:800px) {div[a] {font-size:50px;}} div[a] {}";
expect(s(css, "a")).toEqual(expected);
});
// Check that the browser supports unprefixed CSS animation
it("should handle keyframes rules", () {
var css = "@keyframes foo {0% {transform:translate(-50%) scaleX(0);}}";
expect(s(css, "a")).toEqual(css);
});
it("should handle -webkit-keyframes rules", () {
var css =
"@-webkit-keyframes foo {0% {-webkit-transform:translate(-50%) scaleX(0);}}";
expect(s(css, "a")).toEqual(css);
});
it("should handle complicated selectors", () {
expect(s("one::before {}", "a")).toEqual("one[a]::before {}");
expect(s("one two {}", "a")).toEqual("one[a] two[a] {}");
expect(s("one > two {}", "a")).toEqual("one[a] > two[a] {}");
expect(s("one + two {}", "a")).toEqual("one[a] + two[a] {}");
expect(s("one ~ two {}", "a")).toEqual("one[a] ~ two[a] {}");
var res = s(".one.two > three {}", "a");
expect(res == ".one.two[a] > three[a] {}" ||
res == ".two.one[a] > three[a] {}").toEqual(true);
expect(s("one[attr=\"value\"] {}", "a"))
.toEqual("one[attr=\"value\"][a] {}");
expect(s("one[attr=value] {}", "a")).toEqual("one[attr=\"value\"][a] {}");
expect(s("one[attr^=\"value\"] {}", "a"))
.toEqual("one[attr^=\"value\"][a] {}");
expect(s("one[attr\$=\"value\"] {}", "a"))
.toEqual("one[attr\$=\"value\"][a] {}");
expect(s("one[attr*=\"value\"] {}", "a"))
.toEqual("one[attr*=\"value\"][a] {}");
expect(s("one[attr|=\"value\"] {}", "a"))
.toEqual("one[attr|=\"value\"][a] {}");
expect(s("one[attr] {}", "a")).toEqual("one[attr][a] {}");
expect(s("[is=\"one\"] {}", "a")).toEqual("[is=\"one\"][a] {}");
});
it("should handle :host", () {
expect(s(":host {}", "a", "a-host")).toEqual("[a-host] {}");
expect(s(":host(.x,.y) {}", "a", "a-host"))
.toEqual("[a-host].x, [a-host].y {}");
expect(s(":host(.x,.y) > .z {}", "a", "a-host"))
.toEqual("[a-host].x > .z, [a-host].y > .z {}");
});
it("should handle :host-context", () {
expect(s(":host-context(.x) {}", "a", "a-host"))
.toEqual("[a-host].x, .x [a-host] {}");
expect(s(":host-context(.x) > .y {}", "a", "a-host"))
.toEqual("[a-host].x > .y, .x [a-host] > .y {}");
});
it("should support polyfill-next-selector", () {
var css = s("polyfill-next-selector {content: 'x > y'} z {}", "a");
expect(css).toEqual("x[a] > y[a]{}");
css = s("polyfill-next-selector {content: \"x > y\"} z {}", "a");
expect(css).toEqual("x[a] > y[a]{}");
});
it("should support polyfill-unscoped-rule", () {
var css = s(
"polyfill-unscoped-rule {content: '#menu > .bar';color: blue;}", "a");
expect(StringWrapper.contains(css, "#menu > .bar {;color:blue;}"))
.toBeTruthy();
css = s("polyfill-unscoped-rule {content: \"#menu > .bar\";color: blue;}",
"a");
expect(StringWrapper.contains(css, "#menu > .bar {;color:blue;}"))
.toBeTruthy();
});
it("should support multiple instances polyfill-unscoped-rule", () {
var css = s(
"polyfill-unscoped-rule {content: 'foo';color: blue;}" +
"polyfill-unscoped-rule {content: 'bar';color: blue;}",
"a");
expect(StringWrapper.contains(css, "foo {;color:blue;}")).toBeTruthy();
expect(StringWrapper.contains(css, "bar {;color:blue;}")).toBeTruthy();
});
it("should support polyfill-rule", () {
var css = s("polyfill-rule {content: ':host.foo .bar';color: blue;}", "a",
"a-host");
expect(css).toEqual("[a-host].foo .bar {;color:blue;}");
css = s("polyfill-rule {content: \":host.foo .bar\";color:blue;}", "a",
"a-host");
expect(css).toEqual("[a-host].foo .bar {;color:blue;}");
});
it("should handle ::shadow", () {
var css = s("x::shadow > y {}", "a");
expect(css).toEqual("x[a] > y[a] {}");
});
it("should handle /deep/", () {
var css = s("x /deep/ y {}", "a");
expect(css).toEqual("x[a] y[a] {}");
});
it("should handle >>>", () {
var css = s("x >>> y {}", "a");
expect(css).toEqual("x[a] y[a] {}");
});
it("should pass through @import directives", () {
var styleStr =
"@import url(\"https://fonts.googleapis.com/css?family=Roboto\");";
var css = s(styleStr, "a");
expect(css).toEqual(styleStr);
});
it("should shim rules after @import", () {
var styleStr = "@import url(\"a\"); div {}";
var css = s(styleStr, "a");
expect(css).toEqual("@import url(\"a\"); div[a] {}");
});
it("should leave calc() unchanged", () {
var styleStr = "div {height:calc(100% - 55px);}";
var css = s(styleStr, "a");
expect(css).toEqual("div[a] {height:calc(100% - 55px);}");
});
it("should strip comments", () {
expect(s("/* x */b {c}", "a")).toEqual("b[a] {c}");
});
it("should ignore special characters in comments", () {
expect(s("/* {;, */b {c}", "a")).toEqual("b[a] {c}");
});
it("should support multiline comments", () {
expect(s("/* \n */b {c}", "a")).toEqual("b[a] {c}");
});
});
describe("processRules", () {
describe("parse rules", () {
List<CssRule> captureRules(String input) {
var result = [];
processRules(input, (cssRule) {
result.add(cssRule);
return cssRule;
});
return result;
}
it("should work with empty css", () {
expect(captureRules("")).toEqual([]);
});
it("should capture a rule without body", () {
expect(captureRules("a;")).toEqual([new CssRule("a", "")]);
});
it("should capture css rules with body", () {
expect(captureRules("a {b}")).toEqual([new CssRule("a", "b")]);
});
it("should capture css rules with nested rules", () {
expect(captureRules("a {b {c}} d {e}"))
.toEqual([new CssRule("a", "b {c}"), new CssRule("d", "e")]);
});
it("should capture mutiple rules where some have no body", () {
expect(captureRules("@import a ; b {c}"))
.toEqual([new CssRule("@import a", ""), new CssRule("b", "c")]);
});
});
describe("modify rules", () {
it("should allow to change the selector while preserving whitespaces",
() {
expect(processRules(
"@import a; b {c {d}} e {f}",
(cssRule) =>
new CssRule(cssRule.selector + "2", cssRule.content)))
.toEqual("@import a2; b2 {c {d}} e2 {f}");
});
it("should allow to change the content", () {
expect(processRules(
"a {b}",
(cssRule) =>
new CssRule(cssRule.selector, cssRule.content + "2")))
.toEqual("a {b2}");
});
});
});
}