// 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 extend_test; import 'package:unittest/unittest.dart'; import 'testing.dart'; var options = ['--warnings_as_errors', '--no-colors', 'memory']; compileAndValidate(String input, String generated) { var errors = []; var stylesheet = compileCss(input, errors: errors, opts: options); expect(stylesheet != null, true); expect(errors.isEmpty, true, reason: errors.toString()); expect(prettyPrint(stylesheet), generated); } void simpleExtend() { compileAndValidate(r''' .error { border: 1px red; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; } ''', r'''.error, .seriousError { border: 1px #f00; background-color: #fdd; } .seriousError { border-width: 3px; }'''); } void complexSelectors() { compileAndValidate(r''' .error { border: 1px #f00; background-color: #fdd; } .error.intrusion { background-image: url("/image/hacked.png"); } .seriousError { @extend .error; border-width: 3px; } ''', r'''.error, .seriousError { border: 1px #f00; background-color: #fdd; } .error.intrusion, .seriousError.intrusion { background-image: url("/image/hacked.png"); } .seriousError { border-width: 3px; }'''); compileAndValidate(r''' a:hover { text-decoration: underline; } .hoverlink { @extend a:hover; } ''', r'''a:hover, .hoverlink { text-decoration: underline; } .hoverlink { }'''); } void multipleExtends() { compileAndValidate(r''' .error { border: 1px #f00; background-color: #fdd; } .attention { font-size: 3em; background-color: #ff0; } .seriousError { @extend .error; @extend .attention; border-width: 3px; } ''', r'''.error, .seriousError { border: 1px #f00; background-color: #fdd; } .attention, .seriousError { font-size: 3em; background-color: #ff0; } .seriousError { border-width: 3px; }'''); } void chaining() { compileAndValidate(r''' .error { border: 1px #f00; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; } .criticalError { @extend .seriousError; position: fixed; top: 10%; bottom: 10%; left: 10%; right: 10%; } ''', r'''.error, .seriousError, .criticalError { border: 1px #f00; background-color: #fdd; } .seriousError, .criticalError { border-width: 3px; } .criticalError { position: fixed; top: 10%; bottom: 10%; left: 10%; right: 10%; }'''); } void nestedSelectors() { compileAndValidate(r''' a { color: blue; &:hover { text-decoration: underline; } } #fake-links .link { @extend a; } ''', r'''a, #fake-links .link { color: #00f; } a:hover, #fake-links .link:hover { text-decoration: underline; } #fake-links .link { }'''); } void nestedMulty() { compileAndValidate(r''' .btn { display: inline-block; } input[type="checkbox"].toggle-button { color: red; + label { @extend .btn; } } ''', r'''.btn, input[type="checkbox"].toggle-button label { display: inline-block; } input[type="checkbox"].toggle-button { color: #f00; } input[type="checkbox"].toggle-button label { }'''); } void nWayExtends() { compileAndValidate(r''' .btn > .btn { margin-left: 5px; } input.second + label { @extend .btn; } ''', '.btn > .btn, ' 'input.second + label > .btn, ' '.btn > input.second + label, ' 'input.second + label > input.second + label, ' 'input.second + label > input.second + label {\n' ' margin-left: 5px;\n}\n' 'input.second + label {\n' '}'); // TODO(terry): Optimize merge selectors would be: // // .btn + .btn, input.second + label + .btn, input.second.btn + label { // margin-left: 5px; // } // input.second + label { // color: blue; // } compileAndValidate(r''' .btn + .btn { margin-left: 5px; } input.second + label { @extend .btn; color: blue; } ''', '.btn + .btn, ' 'input.second + label + .btn, ' '.btn + input.second + label, ' 'input.second + label + input.second + label, ' 'input.second + label + input.second + label {\n' ' margin-left: 5px;\n}\n' 'input.second + label {\n' ' color: #00f;\n}'); } main() { test("Simple Extend", simpleExtend); test("complex", complexSelectors); test("multiple", multipleExtends); test("chaining", chaining); test("nested selectors", nestedSelectors); test("nested many selector sequences", nestedMulty); test("N-way extends", nWayExtends); }