| // 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. | |
| import 'package:csslib/src/messages.dart'; | |
| import 'package:test/test.dart'; | |
| import 'testing.dart'; | |
| void compileAndValidate(String input, String generated) { | |
| var errors = <Message>[]; | |
| var stylesheet = compileCss(input, errors: errors, opts: simpleOptions); | |
| expect(errors.isEmpty, true, reason: errors.toString()); | |
| expect(prettyPrint(stylesheet), generated); | |
| } | |
| void selectorVariations() { | |
| final input1 = r'''html { color: red; }'''; | |
| final generated1 = r'''html { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input1, generated1); | |
| final input2 = r'''button { span { height: 200 } }'''; | |
| final generated2 = r'''button { | |
| } | |
| button span { | |
| height: 200; | |
| }'''; | |
| compileAndValidate(input2, generated2); | |
| final input3 = r'''div { color: red; } button { span { height: 200 } }'''; | |
| final generated3 = r'''div { | |
| color: #f00; | |
| } | |
| button { | |
| } | |
| button span { | |
| height: 200; | |
| }'''; | |
| compileAndValidate(input3, generated3); | |
| final input4 = r'''#header { color: red; h1 { font-size: 26px; } }'''; | |
| final generated4 = r'''#header { | |
| color: #f00; | |
| } | |
| #header h1 { | |
| font-size: 26px; | |
| }'''; | |
| compileAndValidate(input4, generated4); | |
| final input5 = r''' | |
| #header { | |
| color: red; | |
| h1 { font-size: 26px; } | |
| background-color: blue; | |
| }'''; | |
| final generated5 = r'''#header { | |
| color: #f00; | |
| background-color: #00f; | |
| } | |
| #header h1 { | |
| font-size: 26px; | |
| }'''; | |
| compileAndValidate(input5, generated5); | |
| final input6 = r'''html { body {color: red; }}'''; | |
| final generated6 = r'''html { | |
| } | |
| html body { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input6, generated6); | |
| final input7 = r'''html body {color: red; }'''; | |
| final generated7 = r'''html body { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input7, generated7); | |
| final input8 = r''' | |
| html, body { color: red; } | |
| button { height: 200 } | |
| body { width: 300px; }'''; | |
| final generated8 = r'''html, body { | |
| color: #f00; | |
| } | |
| button { | |
| height: 200; | |
| } | |
| body { | |
| width: 300px; | |
| }'''; | |
| compileAndValidate(input8, generated8); | |
| final input9 = ''' | |
| html, body { | |
| color: red; | |
| button { height: 200 } | |
| div { width: 300px; } | |
| }'''; | |
| final generated9 = r'''html, body { | |
| color: #f00; | |
| } | |
| html button, body button { | |
| height: 200; | |
| } | |
| html div, body div { | |
| width: 300px; | |
| }'''; | |
| compileAndValidate(input9, generated9); | |
| final input10 = ''' | |
| html { | |
| color: red; | |
| button, div { height: 200 } | |
| body { width: 300px; } | |
| }'''; | |
| final generated10 = r'''html { | |
| color: #f00; | |
| } | |
| html button, html div { | |
| height: 200; | |
| } | |
| html body { | |
| width: 300px; | |
| }'''; | |
| compileAndValidate(input10, generated10); | |
| final input11 = ''' | |
| html, body { | |
| color: red; | |
| button, div { height: 200 } | |
| table { width: 300px; } | |
| }'''; | |
| final generated11 = r'''html, body { | |
| color: #f00; | |
| } | |
| html button, body button, html div, body div { | |
| height: 200; | |
| } | |
| html table, body table { | |
| width: 300px; | |
| }'''; | |
| compileAndValidate(input11, generated11); | |
| final input12 = ''' | |
| html, body { | |
| color: red; | |
| button, div { | |
| span, a, ul { height: 200 } | |
| } | |
| table { width: 300px; } | |
| }'''; | |
| final generated12 = r'''html, body { | |
| color: #f00; | |
| } | |
| ''' | |
| 'html button span, body button span, html div span, body div span, ' | |
| 'html button a, body button a, html div a, body div a, html button ul, ' | |
| r'''body button ul, html div ul, body div ul { | |
| height: 200; | |
| } | |
| html table, body table { | |
| width: 300px; | |
| }'''; | |
| compileAndValidate(input12, generated12); | |
| final input13 = r''' | |
| #header { | |
| div { | |
| width: 100px; | |
| a { height: 200px; } | |
| } | |
| color: blue; | |
| } | |
| span { color: #1f1f1f; } | |
| '''; | |
| final generated13 = r'''#header { | |
| color: #00f; | |
| } | |
| #header div { | |
| width: 100px; | |
| } | |
| #header div a { | |
| height: 200px; | |
| } | |
| span { | |
| color: #1f1f1f; | |
| }'''; | |
| compileAndValidate(input13, generated13); | |
| } | |
| void simpleNest() { | |
| final input = ''' | |
| div span { color: green; } | |
| #header { | |
| color: red; | |
| h1 { | |
| font-size: 26px; | |
| font-weight: bold; | |
| } | |
| p { | |
| font-size: 12px; | |
| a { | |
| text-decoration: none; | |
| } | |
| } | |
| background-color: blue; | |
| } | |
| div > span[attr="foo"] { color: yellow; } | |
| '''; | |
| final generated = r'''div span { | |
| color: #008000; | |
| } | |
| #header { | |
| color: #f00; | |
| background-color: #00f; | |
| } | |
| #header h1 { | |
| font-size: 26px; | |
| font-weight: bold; | |
| } | |
| #header p { | |
| font-size: 12px; | |
| } | |
| #header p a { | |
| text-decoration: none; | |
| } | |
| div > span[attr="foo"] { | |
| color: #ff0; | |
| }'''; | |
| compileAndValidate(input, generated); | |
| } | |
| void complexNest() { | |
| final input = ''' | |
| @font-face { font-family: arial; } | |
| div { color: #f0f0f0; } | |
| #header + div { | |
| color: url(abc.png); | |
| *[attr="bar"] { | |
| font-size: 26px; | |
| font-weight: bold; | |
| } | |
| p~ul { | |
| font-size: 12px; | |
| :not(p) { | |
| text-decoration: none; | |
| div > span[attr="foo"] { color: yellow; } | |
| } | |
| } | |
| background-color: blue; | |
| span { | |
| color: red; | |
| .one { color: blue; } | |
| .two { color: green; } | |
| .three { color: yellow; } | |
| .four { | |
| .four-1 { background-color: #00000f; } | |
| .four-2 { background-color: #0000ff; } | |
| .four-3 { background-color: #000fff; } | |
| .four-4 { | |
| height: 44px; | |
| .four-4-1 { height: 10px; } | |
| .four-4-2 { height: 20px; } | |
| .four-4-3 { height: 30px; } | |
| width: 44px; | |
| } | |
| } | |
| } | |
| } | |
| span { color: #1f1f2f; } | |
| '''; | |
| final generated = r'''@font-face { | |
| font-family: arial; | |
| } | |
| div { | |
| color: #f0f0f0; | |
| } | |
| #header + div { | |
| color: url("abc.png"); | |
| background-color: #00f; | |
| } | |
| #header + div *[attr="bar"] { | |
| font-size: 26px; | |
| font-weight: bold; | |
| } | |
| #header + div p ~ ul { | |
| font-size: 12px; | |
| } | |
| #header + div p ~ ul :not(p) { | |
| text-decoration: none; | |
| } | |
| #header + div p ~ ul :not(p) div > span[attr="foo"] { | |
| color: #ff0; | |
| } | |
| #header + div span { | |
| color: #f00; | |
| } | |
| #header + div span .one { | |
| color: #00f; | |
| } | |
| #header + div span .two { | |
| color: #008000; | |
| } | |
| #header + div span .three { | |
| color: #ff0; | |
| } | |
| #header + div span .four .four-1 { | |
| background-color: #00000f; | |
| } | |
| #header + div span .four .four-2 { | |
| background-color: #00f; | |
| } | |
| #header + div span .four .four-3 { | |
| background-color: #000fff; | |
| } | |
| #header + div span .four .four-4 { | |
| height: 44px; | |
| width: 44px; | |
| } | |
| #header + div span .four .four-4 .four-4-1 { | |
| height: 10px; | |
| } | |
| #header + div span .four .four-4 .four-4-2 { | |
| height: 20px; | |
| } | |
| #header + div span .four .four-4 .four-4-3 { | |
| height: 30px; | |
| } | |
| span { | |
| color: #1f1f2f; | |
| }'''; | |
| compileAndValidate(input, generated); | |
| } | |
| void mediaNesting() { | |
| final input = r''' | |
| @media screen and (-webkit-min-device-pixel-ratio:0) { | |
| #toggle-all { | |
| image: url(test.jpb); | |
| div, table { | |
| background: none; | |
| a { width: 100px; } | |
| } | |
| color: red; | |
| } | |
| } | |
| '''; | |
| final generated = r''' | |
| @media screen AND (-webkit-min-device-pixel-ratio:0) { | |
| #toggle-all { | |
| image: url("test.jpb"); | |
| color: #f00; | |
| } | |
| #toggle-all div, #toggle-all table { | |
| background: none; | |
| } | |
| #toggle-all div a, #toggle-all table a { | |
| width: 100px; | |
| } | |
| }'''; | |
| compileAndValidate(input, generated); | |
| } | |
| void simpleThis() { | |
| final input = '''#header { | |
| h1 { | |
| font-size: 26px; | |
| font-weight: bold; | |
| } | |
| p { font-size: 12px; | |
| a { text-decoration: none; | |
| &:hover { border-width: 1px } | |
| } | |
| } | |
| } | |
| '''; | |
| final generated = r'''#header { | |
| } | |
| #header h1 { | |
| font-size: 26px; | |
| font-weight: bold; | |
| } | |
| #header p { | |
| font-size: 12px; | |
| } | |
| #header p a { | |
| text-decoration: none; | |
| } | |
| #header p a:hover { | |
| border-width: 1px; | |
| }'''; | |
| compileAndValidate(input, generated); | |
| } | |
| void complexThis() { | |
| final input1 = r''' | |
| .light { | |
| .leftCol { | |
| .textLink { | |
| color: fooL1; | |
| &:hover { color: barL1;} | |
| } | |
| .picLink { | |
| background-image: url(/fooL1.jpg); | |
| &:hover { background-image: url(/barL1.jpg);} | |
| } | |
| .textWithIconLink { | |
| color: fooL2; | |
| background-image: url(/fooL2.jpg); | |
| &:hover { color: barL2; background-image: url(/barL2.jpg);} | |
| } | |
| } | |
| }'''; | |
| final generated1 = r'''.light { | |
| } | |
| .light .leftCol .textLink { | |
| color: fooL1; | |
| } | |
| .light .leftCol .textLink:hover { | |
| color: barL1; | |
| } | |
| .light .leftCol .picLink { | |
| background-image: url("/fooL1.jpg"); | |
| } | |
| .light .leftCol .picLink:hover { | |
| background-image: url("/barL1.jpg"); | |
| } | |
| .light .leftCol .textWithIconLink { | |
| color: fooL2; | |
| background-image: url("/fooL2.jpg"); | |
| } | |
| .light .leftCol .textWithIconLink:hover { | |
| color: barL2; | |
| background-image: url("/barL2.jpg"); | |
| }'''; | |
| compileAndValidate(input1, generated1); | |
| final input2 = r''' | |
| .textLink { | |
| .light .leftCol & { | |
| color: fooL1; | |
| &:hover { color: barL1; } | |
| } | |
| .light .rightCol & { | |
| color: fooL3; | |
| &:hover { color: barL3; } | |
| } | |
| }'''; | |
| final generated2 = r''' | |
| .textLink { | |
| } | |
| .light .leftCol .textLink { | |
| color: fooL1; | |
| } | |
| .light .leftCol .textLink:hover { | |
| color: barL1; | |
| } | |
| .light .rightCol .textLink { | |
| color: fooL3; | |
| } | |
| .light .rightCol .textLink:hover { | |
| color: barL3; | |
| }'''; | |
| compileAndValidate(input2, generated2); | |
| } | |
| void variationsThis() { | |
| final input1 = r''' | |
| .textLink { | |
| a { | |
| light .leftCol & { | |
| color: red; | |
| } | |
| } | |
| }'''; | |
| final generated1 = r'''.textLink { | |
| } | |
| light .leftCol .textLink a { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input1, generated1); | |
| final input2 = r'''.textLink { | |
| a { | |
| & light .leftCol & { | |
| color: red; | |
| } | |
| } | |
| }'''; | |
| final generated2 = r'''.textLink { | |
| } | |
| .textLink a light .leftCol .textLink a { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input2, generated2); | |
| final input3 = r''' | |
| .textLink { | |
| a { | |
| & light .leftCol { color: red; } | |
| } | |
| }'''; | |
| final generated3 = r'''.textLink { | |
| } | |
| .textLink a light .leftCol { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input3, generated3); | |
| final input4 = r''' | |
| .textLink { | |
| a { | |
| & light .leftCol { color: red; } | |
| &:hover { width: 100px; } | |
| } | |
| }'''; | |
| final generated4 = r'''.textLink { | |
| } | |
| .textLink a light .leftCol { | |
| color: #f00; | |
| } | |
| .textLink a:hover { | |
| width: 100px; | |
| }'''; | |
| compileAndValidate(input4, generated4); | |
| final input5 = r'''.textLink { a { &:hover { color: red; } } }'''; | |
| final generated5 = r'''.textLink { | |
| } | |
| .textLink a:hover { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input5, generated5); | |
| final input6 = r'''.textLink { &:hover { color: red; } }'''; | |
| final generated6 = r'''.textLink { | |
| } | |
| .textLink:hover { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input6, generated6); | |
| final input7 = r'''.textLink { a { & + & { color: red; } } }'''; | |
| final generated7 = r'''.textLink { | |
| } | |
| .textLink a + .textLink a { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input7, generated7); | |
| final input8 = r'''.textLink { a { & { color: red; } } }'''; | |
| final generated8 = r'''.textLink { | |
| } | |
| .textLink a { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input8, generated8); | |
| final input9 = r'''.textLink { a { & ~ & { color: red; } } }'''; | |
| final generated9 = r'''.textLink { | |
| } | |
| .textLink a ~ .textLink a { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input9, generated9); | |
| final input10 = r'''.textLink { a { & & { color: red; } } }'''; | |
| final generated10 = r'''.textLink { | |
| } | |
| .textLink a .textLink a { | |
| color: #f00; | |
| }'''; | |
| compileAndValidate(input10, generated10); | |
| } | |
| void thisCombinator() { | |
| var input = r''' | |
| .btn { | |
| color: red; | |
| } | |
| .btn + .btn { | |
| margin-left: 5px; | |
| } | |
| input.second { | |
| & + label { | |
| color: blue; | |
| } | |
| } | |
| '''; | |
| var generated = r'''.btn { | |
| color: #f00; | |
| } | |
| .btn + .btn { | |
| margin-left: 5px; | |
| } | |
| input.second { | |
| } | |
| input.second + label { | |
| color: #00f; | |
| }'''; | |
| compileAndValidate(input, generated); | |
| } | |
| void main() { | |
| test('Selector and Nested Variations', selectorVariations); | |
| test('Simple nesting', simpleNest); | |
| test('Complex nesting', complexNest); | |
| test('@media nesting', mediaNesting); | |
| test('Simple &', simpleThis); | |
| test('Variations &', variationsThis); | |
| test('Complex &', complexThis); | |
| test('& with + selector', thisCombinator); | |
| } |