Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Unified Diff: pkg/csslib/test/mixin_test.dart

Issue 23819036: Support for @mixin, @include and @extend (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: mixin w/o parameters Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/csslib/test/mixin_test.dart
diff --git a/pkg/csslib/test/mixin_test.dart b/pkg/csslib/test/mixin_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d1de2e33aa4006964e85c50c83ff3ec23aadaec9
--- /dev/null
+++ b/pkg/csslib/test/mixin_test.dart
@@ -0,0 +1,685 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library mixin_test;
+
+import 'package:unittest/unittest.dart';
+import 'testing.dart';
+
+var options = ['--warnings_as_errors', '--no-colors', 'memory'];
Jennifer Messerly 2013/09/18 06:44:15 extra space here?
nweiz 2013/09/18 22:40:54 "final", not "var".
terry 2013/10/09 03:40:33 Done.
+
+void topLevelMixin() {
nweiz 2013/09/18 22:40:54 Why are you defining a separate function for each
+ var errors = [];
+ final input1 = r'''
nweiz 2013/09/18 22:40:54 Why is this [input1]? There's no other [input] var
terry 2013/10/09 03:40:33 Probably other test at one point. 1 is gone. On 20
+@mixin silly-links {
+ a {
+ color: blue;
+ background-color: red;
+ }
+}
+
+@include silly-links;
+''';
nweiz 2013/09/18 22:40:54 These no-indentation strings are difficult to read
terry 2013/10/09 03:40:33 I'll consider it but I fine pre-processing to be a
+
+ final generated1 = r'''a {
+ color: #00f;
+ background-color: #f00;
+}''';
+
+ final stylesheet1 = compileCss(input1, errors: errors, opts: options);
nweiz 2013/09/18 22:40:54 Using an out parameter like [errors] here is a cod
terry 2013/10/09 03:40:33 It's something we've liked so far for tooling. On
+
+ expect(stylesheet1 != null, true);
nweiz 2013/09/18 22:40:54 This could be written as "expect(stylesheet, isNot
+ expect(errors.isEmpty, true, reason: errors.toString());
nweiz 2013/09/18 22:40:54 expect(errors, isEmpty, ...)
+ expect(prettyPrint(stylesheet1), generated1);
+
+ // TODO(terry): Test using a declaration @mixin as a top-level @include.
nweiz 2013/09/18 22:40:54 Why is this a TODO and not an actual test?
terry 2013/10/09 03:40:33 comment old. On 2013/09/18 22:40:54, nweiz wrote:
+}
+
+void topLevelMixin2Includes() {
+ final errors = [];
+ final input = r'''
+@mixin a {
+ a {
+ color: blue;
+ background-color: red;
+ }
+}
+@mixin b {
+ span {
+ color: black;
+ background-color: orange;
+ }
+}
+@include a;
+@include b;
+''';
+
+ final generated = r'''a {
+ color: #00f;
+ background-color: #f00;
+}
+span {
+ color: #000;
+ background-color: #ffa500;
+}''';
+
+ final stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void topLevelMixinMultiRulesets() {
nweiz 2013/09/18 22:40:54 What do multiple rulesets have to do with this tes
terry 2013/10/09 03:40:33 Tests top-level mixins that includes another mixin
+ final errors = [];
+ final input = r'''
+@mixin a {
+ a {
+ color: blue;
+ background-color: red;
+ }
+}
+@mixin b {
+ span {
+ color: black;
+ background-color: orange;
+ }
+ @include c;
+}
+@mixin c {
+ #foo-id {
+ border-top: 1px solid red;
+ border-bottom: 2px solid green;
+ }
+}
+@include a;
+@include b;
+''';
+
+ final generated = r'''a {
+ color: #00f;
+ background-color: #f00;
+}
+span {
+ color: #000;
+ background-color: #ffa500;
+}
+#foo-id {
+ border-top: 1px solid #f00;
+ border-bottom: 2px solid #008000;
+}''';
+
+ final stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void topLevelMixinMultiRulesets2() {
nweiz 2013/09/18 22:40:54 I have no idea what this test is testing. Is it ju
terry 2013/10/09 03:40:33 1, 2 and 3 nesting levels of includes. On 2013/09/
+ final errors = [];
+ final input = r'''
+@mixin a {
+ a {
+ color: blue;
+ background-color: red;
+ }
+}
+@mixin b {
+ @include a;
+ span {
+ color: black;
+ background-color: orange;
+ }
+ @include c;
+ @include d;
+}
+@mixin c {
+ #foo-id {
+ border-top: 1px solid red;
+ border-bottom: 2px solid green;
+ }
+}
+@mixin d {
+ a:hover {
+ cursor: arrow;
+ }
+ @include e
+}
+@mixin e {
+ #split-bar:visited {
+ color: gray;
+ }
+ @include f;
+}
+@mixin f {
+ #split-bar div {
+ border: 1px solid lightgray;
+ }
+}
+@include b;
+''';
+
+ final generated = r'''a {
+ color: #00f;
+ background-color: #f00;
+}
+span {
+ color: #000;
+ background-color: #ffa500;
+}
+#foo-id {
+ border-top: 1px solid #f00;
+ border-bottom: 2px solid #008000;
+}
+a:hover {
+ cursor: arrow;
+}
+#split-bar:visited {
+ color: #808080;
+}
+#split-bar div {
+ border: 1px solid #d3d3d3;
+}''';
+
+ final stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void topLevelMixinSelectors() {
nweiz 2013/09/18 22:40:54 All the previous tests had selectors. Saying that
terry 2013/10/09 03:40:33 testing with combinators and selector groups. On 2
+ final errors = [];
+ final input = r'''
+@mixin a {
+ a, b {
+ color: blue;
+ background-color: red;
+ }
+ div > span {
+ color: black;
+ background-color: orange;
+ }
+}
+
+@include a;
+''';
+
+ final generated = r'''a, b {
+ color: #00f;
+ background-color: #f00;
+}
+div > span {
+ color: #000;
+ background-color: #ffa500;
+}''';
+
+ final stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void declSimpleMixin() {
+ final errors = [];
+ final input = r'''
+@mixin div-border {
+ border: 2px dashed red;
+}
+div {
+ @include div-border;
+}
+''';
+
+ final generated = r'''div {
+ border: 2px dashed #f00;
+}''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void declMixin2Includes() {
+ final errors = [];
+ final input = r'''
+@mixin div-border {
+ border: 2px dashed red;
+}
+@mixin div-color {
+ color: blue;
+}
+div {
+ @include div-border;
+ @include div-color;
+}
+''';
+
+ final generated = r'''div {
+ border: 2px dashed #f00;
+ color: #00f;
+}''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void declMixinNestedIncludes() {
nweiz 2013/09/18 22:40:54 As above, "div-border" is unrelated to what this t
terry 2013/10/09 03:40:33 As test implies for than one level of testing. On
+ final errors = [];
+ final input = r'''
+@mixin div-border {
+ border: 2px dashed red;
+}
+@mixin div-color {
+ @include div-padding;
+ color: blue;
+ @include div-margin;
+}
+@mixin div-padding {
+ padding: .5em;
+}
+@mixin div-margin {
+ margin: 5px;
+}
+div {
+ @include div-border;
+ @include div-color;
+}
+''';
+
+ final generated = r'''div {
+ border: 2px dashed #f00;
+ padding: .5em;
+ color: #00f;
+ margin: 5px;
+}''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void declMixinNestedIncludes2() {
nweiz 2013/09/18 22:40:54 I can't understand what this test tests that the p
terry 2013/10/09 03:40:33 nesting with other selectors pseudo. On 2013/09/18
+ final errors = [];
+ final input = r'''
+@mixin div-border {
+ border: 2px dashed red;
+}
+@mixin div-color {
+ @include div-padding;
+ @include div-margin;
+}
+@mixin div-padding {
+ padding: .5em;
+}
+@mixin div-margin {
+ margin: 5px;
+}
+div {
+ @include div-border;
+ @include div-color;
+}
+''';
+
+ final generated = r'''div {
+ border: 2px dashed #f00;
+ padding: .5em;
+ margin: 5px;
+}''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void mixinArg() {
+ final errors = [];
+ final input = r'''
+@mixin div-border {
+ border: 2px dashed red;
+}
+
+@mixin div-inside(@dist) {
nweiz 2013/09/18 22:40:54 If your arguments are going to use this syntax, yo
terry 2013/10/09 03:40:33 Vars are now different in CSS (var-) but we're sup
+ margin-left: var(dist);
+
+}
+
+div {
+ @include left(10px);
+ @include div-border;
+}
+''';
+
+ final generated = r''' ''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+
+ // TODO(terry): Test using a top-level @mixin as a declaration @include.
+}
+
+void mixinArgs() {
+ final errors = [];
+ var input = r'''
+@mixin box-shadow(@shadows...) {
+ -moz-box-shadow: var(shadows);
+ -webkit-box-shadow: var(shadows;
+ box-shadow: var(shadows);
+}
+
+.shadows {
+ @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
+}''';
+
+ var generated = r'''
+.shadowed {
+ -moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
+ -webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
+ box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
+}
+''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void mixinArgs_2() {
+ final errors = [];
+ var input = r'''
+@mixin colors(@text, @background, @border) {
+ color: var(text);
+ background-color: var(background);
+ border-color: var(border);
+}
+
+@values: #ff0000, #00ff00, #0000ff;
+.primary {
+ @include colors(var(values));
+}
+''';
+
+ var generated = r'''
+.primary {
+ color: #ff0000;
+ background-color: #00ff00;
+ border-color: #0000ff;
+}
+''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void mixinArgs_var() {
+ final errors = [];
+ var input = r'''
+@mixin wrapped-stylish-mixin(@args...) {
+ font-weight: bold;
+ @include stylish-mixin(var(args));
+}
+
+.stylish {
+ // The @width argument will get passed on to "stylish-mixin" as a keyword
+ @include wrapped-stylish-mixin(#00ff00, @width: 100px);
+}
+''';
+
+ var generated = r'''
+''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void mixin_content_toplevel() {
+ void mixinArgs_var() {
+ final errors = [];
+ var input = r'''
+@mixin apply-to-ie6-only {
+ * html {
+ @content;
+ }
+}
+@include apply-to-ie6-only {
+ #logo {
+ background-image: url(/logo.gif);
+ }
+}
+''';
+
+ var generated = r'''* html #logo {
+ background-image: url(/logo.gif);
+}''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+ }
+}
+
+void mixin_content() {
+ void mixinArgs_var() {
+ final errors = [];
+ var input = r'''
+@mixin keyframes {
+ @-moz-keyframes { @content; }
+ @-webkit-keyframes { @content; }
+}
+
+@include keyframes {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+}
+''';
+
+ var generated = r'''@-moz-keyframes {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+}
+
+@-webkit-keyframes {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+}''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+ }
+}
+
+void mixin_content_var() {
+ void mixinArgs_var() {
+ final errors = [];
+ var input = r'''
+@color: white;
+@mixin colors(@color: blue) {
+ background-color: var(color);
+ @content;
+ border-color: var(color);
+}
+.colors {
+ @include colors { color: var(color); }
+}
+''';
+
+ var generated = r'''.colors {
+ background-color: blue;
+ color: white;
+ border-color: blue;
+}
+''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+ }
+}
+
+void badDeclarationInclude() {
nweiz 2013/09/18 22:40:54 This shouldn't cause an error.
terry 2013/10/09 03:40:33 Seems weird that top-level will close a declaratio
+ final errors = [];
+ final input = r'''
+@mixin a {
+ span {
+ border: 2px dashed red;
+ @include b;
+ }
+}
+
+@mixin b {
+ #foo-id {
+ color: red;
+ }
+}
+ ''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isNotEmpty, true, reason: errors.toString());
+ expect(errors.length, 1, reason: errors.toString());
+ var error = errors[0];
+ expect(error.message,
+ 'Trying to use top-level ruleset in a declaration - @include b');
+ expect(error.span.end.offset, 60);
+}
+
+void badTopInclude() {
nweiz 2013/09/18 22:40:54 This *should* cause an error.
terry 2013/10/09 03:40:33 Currently, we really report everything as a warnin
+ final errors = [];
+ final input = r'''
+@mixin a {
+ span {
+ border: 2px dashed red;
+ }
+ @include b;
+}
+
+@mixin b {
+ color: red;
+}
+
+@include a;
+ ''';
+
+ var generated = r'''span {
+ border: 2px dashed #f00;
+}''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+ expect(stylesheet != null, true);
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(prettyPrint(stylesheet), generated);
+}
+
+void cycleDetect() {
+ final errors = [];
+ final input = r'''
+@mixin a {
+ @include b;
+}
+@mixin b {
+ span {
+ border: 2px dashed red;
+ }
+ @include a;
+}
+@include b;
+ ''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isNotEmpty, true, reason: errors.toString());
nweiz 2013/09/18 22:40:54 expect(errors, isNotEmpty) [reason] here doesn't
terry 2013/10/09 03:40:33 test is gone. On 2013/09/18 22:40:54, nweiz wrote:
+ expect(errors.length, 2, reason: errors.toString());
+ var error = errors[0];
+ expect(error.message, 'mixin cycle detected @mixin a');
nweiz 2013/09/18 22:40:54 Test the type of the error, not the message. Testi
+ expect(error.span.end.offset, 24);
+ error = errors[1];
+ expect(error.message, 'mixin cycle detected @mixin b');
+ expect(error.span.end.offset, 92);
+}
+
+void cycleNesting() {
+ final errors = [];
+ final input = r'''
+@mixin a {
+ @include b;
+}
+@mixin b {
+ border: 2px dashed red;
+ @include a;
+}
+div {
+ @include b;
+}
+ ''';
+
+ var stylesheet = compileCss(input, errors: errors, opts: options);
+
+ expect(stylesheet != null, true);
+ expect(errors.isNotEmpty, true, reason: errors.toString());
+ expect(errors.length, 2, reason: errors.toString());
+ var error = errors[0];
+ expect(error.message, 'mixin cycle detected @mixin a');
+ expect(error.span.end.offset, 24);
+ error = errors[1];
+ expect(error.message, 'mixin cycle detected @mixin b');
+ expect(error.span.end.offset, 77);
+}
+
+main() {
+ test('top-level mixin', topLevelMixin);
+ test('top-level mixin 2 @includes', topLevelMixin2Includes);
nweiz 2013/09/18 22:40:54 "2" -> "two", here and elsewhere. Also, at least u
terry 2013/10/09 03:40:33 Done.
+ test('top-level multi rulesets', topLevelMixinMultiRulesets);
+ test('top-level multi rulesets and nesting', topLevelMixinMultiRulesets2);
+ test('top-level selector groups', topLevelMixinSelectors);
+
+ test('declaration mixin', declSimpleMixin);
+ test('declaration mixin 2 @includes', declMixin2Includes);
+ test('declaration mixin includes', declMixinNestedIncludes);
+ test('declaration mixin includes #2', declMixinNestedIncludes2);
nweiz 2013/09/18 22:40:54 Adding "#2" here doesn't tell me anything about th
terry 2013/10/09 03:40:33 Done.
+
+ test('detect cycle', cycleDetect);
+ test('detect cycle nesting', cycleNesting);
+ test('detect bad top-level as declaration', badDeclarationInclude);
+ test('detect bad declaration as top-level', badTopInclude);
+
+ // TODO(Terry): More tests to enable.
nweiz 2013/09/18 22:40:54 Don't include tests that don't work. You can add t
terry 2013/10/09 03:40:33 Done.
+ // test('mixin arg', mixinArg);
+ // test('mixin args', mixinArgs);
+ // test('mixin args fanout', mixinArgs_2);
+ // test('mixin args with variables', mixinArgs_var);
+ // test('mixin content top-level', mixin_content_toplevel);
+ // test('mixin content', mixin_content);
+ // test('mixin content with variables', mixin_content_var);
+}

Powered by Google App Engine
This is Rietveld 408576698