Index: frog/tests/css/src/SelectorLiteralTest.dart |
diff --git a/frog/tests/css/src/SelectorLiteralTest.dart b/frog/tests/css/src/SelectorLiteralTest.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..94164c5a5ca0729fb8f502d263f44ea96e2a4a7a |
--- /dev/null |
+++ b/frog/tests/css/src/SelectorLiteralTest.dart |
@@ -0,0 +1,238 @@ |
+// Copyright (c) 2011, 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("../../../css/css.dart"); |
+ |
+class SelectorLiteralTest { |
+ static final String ERROR = 'CssParserException: <buffer>:'; |
+ |
+ static testMain() { |
+ testSimpleClassSelectorSuccesses(); |
+ testSimpleClassSelectorFailures(); |
+ testPrivateNameFailures(); |
+ } |
+ |
+ static void testSimpleClassSelectorSuccesses() { |
+ List<String> knownClasses = ['foobar', 'xyzzy', 'a-story', 'b-story']; |
+ List<String> knownIds = ['id1', 'id2', 'id-number-3']; |
+ |
+ CssWorld cssWorld = new CssWorld(knownClasses, knownIds); |
+ |
+ try { |
+ // Valid selectors for class names. |
+ CssTemplate.xlate('@{.foobar}', cssWorld); |
+ CssTemplate.xlate('@{.foobar .xyzzy}', cssWorld); |
+ CssTemplate.xlate('@{.foobar .a-story .xyzzy}', cssWorld); |
+ CssTemplate.xlate('@{.foobar .xyzzy .a-story .b-story}', cssWorld); |
+ |
+ // Valid selectors for element IDs. |
+ CssTemplate.xlate('@{#id1}', cssWorld); |
+ CssTemplate.xlate('@{#id-number-3}', cssWorld); |
+ CssTemplate.xlate('@{#_privateId}', cssWorld); |
+ |
+ // Valid selectors for private class names (leading underscore). |
+ CssTemplate.xlate('@{.foobar ._privateClass}', cssWorld); |
+ CssTemplate.xlate('@{.foobar ._privateClass .xyzzy}', cssWorld); |
+ CssTemplate.xlate('@{.foobar ._private1 .xyzzy ._private2}', cssWorld); |
+ |
+ // Valid selectors for private element IDs (leading underscore). |
+ CssTemplate.xlate('@{._privateClass}', cssWorld); |
+ } catch (var e) { |
+ // CSS Expressions failed |
+ Expect.fail(e.toString()); |
+ } |
+ } |
+ |
+ static void testSimpleClassSelectorFailures() { |
+ List<String> knownClasses = ['foobar', 'xyzzy', 'a-story', 'b-story']; |
+ List<String> knownIds = ['id1', 'id2', 'id-number-3']; |
+ |
+ CssWorld cssWorld = new CssWorld(knownClasses, knownIds); |
+ |
+ // Invalid class name. |
+ String css = '@{.-foobar}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("${ERROR}1:4: expected identifier\n${css}\n ^", |
+ e.toString()); |
+ } |
+ |
+ // Error this class name is not known. |
+ css = '@{.foobar1}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Unknown selector name .foobar1", |
+ e.toString()); |
+ } |
+ |
+ // Error if any class name is not known. |
+ css = '@{.foobar .xyzzy1}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Unknown selector name .xyzzy1", |
+ e.toString()); |
+ } |
+ |
+ // Test for invalid class name (can't start with number). |
+ css = '@{.foobar .1a-story .xyzzy}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("${ERROR}1:12: expected identifier\n${css}\n ^^", |
+ e.toString()); |
+ } |
+ |
+ // element id must be single selector. |
+ css = '@{#id1 #id2}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Use of Id selector must be " + |
+ "singleton starting at #id2", e.toString()); |
+ } |
+ |
+ // element id must be single selector. |
+ css = '@{#id-number-3 .foobar}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("@{#id-number-3 .foobar} should not succeed."); |
+ } catch (var e) { |
+ // CSS Expressions failed |
+ Expect.equals("CssSelectorException: Can not mix Id selector with "+ |
+ "class selector(s). Id selector must be singleton too many " + |
+ "starting at .foobar", e.toString(), ''); |
+ } |
+ |
+ // element id must be alone and only one element id. |
+ css = '@{.foobar #id-number-3 #id1}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ // CSS Expressions failed |
+ Expect.equals("CssSelectorException: Use of Id selector must be " + |
+ "singleton starting at #id-number-3", e.toString()); |
+ } |
+ |
+ // Namespace selector not valid in @{css_expression} |
+ css = '@{foo|div}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Invalid selector foo|div", |
+ e.toString()); |
+ } |
+ |
+ // class and element id not allowed together. |
+ css = '@{.foobar foo|div}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("$css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Invalid selector foo|div", |
+ e.toString()); |
+ } |
+ |
+ // Element id and namespace not allowed together. |
+ css = '@{#id1 foo|div}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Invalid selector foo|div", |
+ e.toString()); |
+ } |
+ |
+ // namespace and element id not allowed together. |
+ css = '@{foo|div #id1}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Invalid selector foo|div", |
+ e.toString()); |
+ } |
+ |
+ // namespace / element not allowed. |
+ css = '@{foo|div .foobar}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Invalid selector foo|div", |
+ e.toString()); |
+ } |
+ |
+ // Combinators not allowed. |
+ css = '@{.foobar > .xyzzy}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Selectors can not have combinators (>, +, or ~) before .xyzzy", |
+ e.toString()); |
+ } |
+ } |
+ |
+ static void testPrivateNameFailures() { |
+ List<String> knownClasses = ['foobar', 'xyzzy', 'a-story', 'b-story']; |
+ List<String> knownIds = ['id1', 'id2', 'id-number-3']; |
+ |
+ CssWorld cssWorld = new CssWorld(knownClasses, knownIds); |
+ |
+ // Too many. |
+ String css = '@{._private #id2}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Use of Id selector must be " + |
+ "singleton starting at #id2", e.toString()); |
+ } |
+ |
+ // Unknown class foobar2. |
+ css = '@{._private .foobar2}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Unknown selector name .foobar2", |
+ e.toString()); |
+ } |
+ |
+ // Too many element IDs. |
+ css = '@{#_privateId #id2}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Use of Id selector must be " + |
+ "singleton starting at #id2", e.toString()); |
+ } |
+ |
+ // Too many element IDs. |
+ css = '@{#_privateId1 #_privateId2}'; |
+ try { |
+ CssTemplate.xlate('${css}', cssWorld); |
+ Expect.fail("${css} should not succeed."); |
+ } catch (var e) { |
+ Expect.equals("CssSelectorException: Use of Id selector must be " + |
+ "singleton starting at #_privateId2", e.toString()); |
+ } |
+ } |
+ |
+} |
+ |
+main() { |
+ SelectorLiteralTest.testMain(); |
+} |