| // 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'; |
| |
| 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); |
| } |