jbarnette-johnson 1.0.0.200806240111

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. data/CHANGELOG +5 -0
  2. data/MANIFEST +385 -0
  3. data/MINGW32.mk +124 -0
  4. data/README.rdoc +51 -0
  5. data/Rakefile +166 -0
  6. data/bin/johnson +107 -0
  7. data/cross-compile.txt +38 -0
  8. data/ext/spidermonkey/context.c +122 -0
  9. data/ext/spidermonkey/context.h +19 -0
  10. data/ext/spidermonkey/conversions.c +286 -0
  11. data/ext/spidermonkey/conversions.h +18 -0
  12. data/ext/spidermonkey/debugger.c +208 -0
  13. data/ext/spidermonkey/debugger.h +9 -0
  14. data/ext/spidermonkey/extconf.rb +25 -0
  15. data/ext/spidermonkey/extensions.c +37 -0
  16. data/ext/spidermonkey/extensions.h +12 -0
  17. data/ext/spidermonkey/global.c +40 -0
  18. data/ext/spidermonkey/global.h +11 -0
  19. data/ext/spidermonkey/idhash.c +16 -0
  20. data/ext/spidermonkey/idhash.h +8 -0
  21. data/ext/spidermonkey/immutable_node.c.erb +522 -0
  22. data/ext/spidermonkey/immutable_node.h +22 -0
  23. data/ext/spidermonkey/jroot.h +187 -0
  24. data/ext/spidermonkey/js_land_proxy.c +609 -0
  25. data/ext/spidermonkey/js_land_proxy.h +20 -0
  26. data/ext/spidermonkey/ruby_land_proxy.c +537 -0
  27. data/ext/spidermonkey/ruby_land_proxy.h +17 -0
  28. data/ext/spidermonkey/runtime.c +304 -0
  29. data/ext/spidermonkey/runtime.h +25 -0
  30. data/ext/spidermonkey/spidermonkey.c +20 -0
  31. data/ext/spidermonkey/spidermonkey.h +29 -0
  32. data/js/johnson/browser.js +9 -0
  33. data/js/johnson/browser/env.js +687 -0
  34. data/js/johnson/browser/jquery.js +3444 -0
  35. data/js/johnson/browser/xmlsax.js +1564 -0
  36. data/js/johnson/browser/xmlw3cdom.js +4189 -0
  37. data/js/johnson/cli.js +30 -0
  38. data/js/johnson/prelude.js +80 -0
  39. data/js/johnson/template.js +29 -0
  40. data/lib/hoe.rb +748 -0
  41. data/lib/johnson.rb +46 -0
  42. data/lib/johnson/cli.rb +7 -0
  43. data/lib/johnson/cli/options.rb +56 -0
  44. data/lib/johnson/error.rb +4 -0
  45. data/lib/johnson/nodes.rb +7 -0
  46. data/lib/johnson/nodes/binary_node.rb +64 -0
  47. data/lib/johnson/nodes/for.rb +14 -0
  48. data/lib/johnson/nodes/for_in.rb +12 -0
  49. data/lib/johnson/nodes/function.rb +13 -0
  50. data/lib/johnson/nodes/list.rb +27 -0
  51. data/lib/johnson/nodes/node.rb +68 -0
  52. data/lib/johnson/nodes/ternary_node.rb +20 -0
  53. data/lib/johnson/parser.rb +21 -0
  54. data/lib/johnson/parser/syntax_error.rb +13 -0
  55. data/lib/johnson/runtime.rb +55 -0
  56. data/lib/johnson/spidermonkey/context.rb +10 -0
  57. data/lib/johnson/spidermonkey/debugger.rb +67 -0
  58. data/lib/johnson/spidermonkey/immutable_node.rb +280 -0
  59. data/lib/johnson/spidermonkey/js_land_proxy.rb +62 -0
  60. data/lib/johnson/spidermonkey/mutable_tree_visitor.rb +233 -0
  61. data/lib/johnson/spidermonkey/ruby_land_proxy.rb +52 -0
  62. data/lib/johnson/spidermonkey/runtime.rb +94 -0
  63. data/lib/johnson/version.rb +4 -0
  64. data/lib/johnson/visitable.rb +16 -0
  65. data/lib/johnson/visitors.rb +4 -0
  66. data/lib/johnson/visitors/dot_visitor.rb +167 -0
  67. data/lib/johnson/visitors/ecma_visitor.rb +315 -0
  68. data/lib/johnson/visitors/enumerating_visitor.rb +115 -0
  69. data/lib/johnson/visitors/sexp_visitor.rb +172 -0
  70. data/lib/rails/init.rb +37 -0
  71. data/test/assets/index.html +38 -0
  72. data/test/assets/jquery_test.html +186 -0
  73. data/test/helper.rb +58 -0
  74. data/test/johnson/browser_test.rb +38 -0
  75. data/test/johnson/conversions/array_test.rb +32 -0
  76. data/test/johnson/conversions/boolean_test.rb +17 -0
  77. data/test/johnson/conversions/callable_test.rb +34 -0
  78. data/test/johnson/conversions/file_test.rb +15 -0
  79. data/test/johnson/conversions/nil_test.rb +20 -0
  80. data/test/johnson/conversions/number_test.rb +34 -0
  81. data/test/johnson/conversions/regexp_test.rb +24 -0
  82. data/test/johnson/conversions/string_test.rb +26 -0
  83. data/test/johnson/conversions/struct_test.rb +15 -0
  84. data/test/johnson/conversions/symbol_test.rb +19 -0
  85. data/test/johnson/conversions/thread_test.rb +24 -0
  86. data/test/johnson/error_test.rb +9 -0
  87. data/test/johnson/extensions_test.rb +56 -0
  88. data/test/johnson/nodes/array_literal_test.rb +57 -0
  89. data/test/johnson/nodes/array_node_test.rb +26 -0
  90. data/test/johnson/nodes/binary_node_test.rb +61 -0
  91. data/test/johnson/nodes/bracket_access_test.rb +16 -0
  92. data/test/johnson/nodes/delete_test.rb +11 -0
  93. data/test/johnson/nodes/do_while_test.rb +12 -0
  94. data/test/johnson/nodes/dot_accessor_test.rb +15 -0
  95. data/test/johnson/nodes/export_test.rb +9 -0
  96. data/test/johnson/nodes/for_test.rb +54 -0
  97. data/test/johnson/nodes/function_test.rb +71 -0
  98. data/test/johnson/nodes/if_test.rb +41 -0
  99. data/test/johnson/nodes/import_test.rb +13 -0
  100. data/test/johnson/nodes/label_test.rb +19 -0
  101. data/test/johnson/nodes/object_literal_test.rb +110 -0
  102. data/test/johnson/nodes/return_test.rb +16 -0
  103. data/test/johnson/nodes/semi_test.rb +8 -0
  104. data/test/johnson/nodes/switch_test.rb +55 -0
  105. data/test/johnson/nodes/ternary_test.rb +25 -0
  106. data/test/johnson/nodes/throw_test.rb +9 -0
  107. data/test/johnson/nodes/try_node_test.rb +59 -0
  108. data/test/johnson/nodes/typeof_test.rb +11 -0
  109. data/test/johnson/nodes/unary_node_test.rb +23 -0
  110. data/test/johnson/nodes/void_test.rb +11 -0
  111. data/test/johnson/nodes/while_test.rb +26 -0
  112. data/test/johnson/nodes/with_test.rb +10 -0
  113. data/test/johnson/prelude_test.rb +56 -0
  114. data/test/johnson/runtime_test.rb +46 -0
  115. data/test/johnson/spidermonkey/context_test.rb +21 -0
  116. data/test/johnson/spidermonkey/immutable_node_test.rb +34 -0
  117. data/test/johnson/spidermonkey/js_land_proxy_test.rb +236 -0
  118. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +225 -0
  119. data/test/johnson/spidermonkey/runtime_test.rb +17 -0
  120. data/test/johnson/version_test.rb +13 -0
  121. data/test/johnson/visitors/dot_visitor_test.rb +39 -0
  122. data/test/johnson/visitors/enumerating_visitor_test.rb +12 -0
  123. data/test/johnson_test.rb +16 -0
  124. data/test/jquery_units/test.js +27 -0
  125. data/test/jquery_units/test_helper.js +197 -0
  126. data/test/jquery_units/units/ajax.js +795 -0
  127. data/test/jquery_units/units/core.js +1563 -0
  128. data/test/jquery_units/units/event.js +299 -0
  129. data/test/jquery_units/units/fx.js +427 -0
  130. data/test/jquery_units/units/offset.js +112 -0
  131. data/test/jquery_units/units/selector.js +224 -0
  132. data/test/jspec/helper.js +7 -0
  133. data/test/jspec/jspec.js +192 -0
  134. data/test/jspec/simple_spec.js +68 -0
  135. data/test/parser_test.rb +276 -0
  136. data/todo/.keep +0 -0
  137. metadata +501 -0
@@ -0,0 +1,112 @@
1
+ module("offset");
2
+
3
+ // opens a new window to run the tests against
4
+ var testwin = function(name, fn) {
5
+ testwin[name] = load_offset_fixture(name);
6
+ var interval = setInterval(function() {
7
+ if (testwin[name] && testwin[name].$ && testwin[name].$.isReady) {
8
+ clearInterval(interval);
9
+ test(name, fn);
10
+ }
11
+ }, 0);
12
+
13
+ function load_offset_fixture(name) {
14
+ var win = window.open( "./data/offset/" + name + ".html?num"+parseInt(Math.random()*1000), name, 'left=0,top=0,width=500,height=500,toolbar=1,resizable=0' );
15
+ if ( !win ) {
16
+ alert("Please disable your popup blocker for the offset test suite");
17
+ throw "Please disable your popup blocker for the offset test suite";
18
+ }
19
+ return win;
20
+ }
21
+ };
22
+
23
+ testwin("absolute", function() {
24
+ var $w = testwin["absolute"].$;
25
+
26
+ equals( $w('#absolute-1').offset().top, 1, "$('#absolute-1').offset().top" );
27
+ equals( $w('#absolute-1').offset().left, 1, "$('#absolute-1').offset().left" );
28
+
29
+ equals( $w('#absolute-1-1').offset().top, 5, "$('#absolute-1-1').offset().top" );
30
+ equals( $w('#absolute-1-1').offset().left, 5, "$('#absolute-1-1').offset().left" );
31
+
32
+ equals( $w('#absolute-1-1-1').offset().top, 9, "$('#absolute-1-1-1').offset().top" );
33
+ equals( $w('#absolute-1-1-1').offset().left, 9, "$('#absolute-1-1-1').offset().left" );
34
+
35
+ equals( $w('#absolute-2').offset().top, 20, "$('#absolute-2').offset().top" );
36
+ equals( $w('#absolute-2').offset().left, 20, "$('#absolute-2').offset().left" );
37
+
38
+ testwin["absolute"].close();
39
+ });
40
+
41
+ testwin("relative", function() {
42
+ var $w = testwin["relative"].$;
43
+
44
+ equals( $w('#relative-1').offset().top, $.browser.msie ? 6 : 7, "$('#relative-1').offset().top" );
45
+ equals( $w('#relative-1').offset().left, 7, "$('#relative-1').offset().left" );
46
+
47
+ equals( $w('#relative-1-1').offset().top, $.browser.msie ? 13 : 15, "$('#relative-1-1').offset().top" );
48
+ equals( $w('#relative-1-1').offset().left, 15, "$('#relative-1-1').offset().left" );
49
+
50
+ equals( $w('#relative-2').offset().top, $.browser.msie ? 141 : 142, "$('#relative-2').offset().top" );
51
+ equals( $w('#relative-2').offset().left, 27, "$('#relative-2').offset().left" );
52
+
53
+ testwin["relative"].close();
54
+ });
55
+
56
+ testwin("static", function() {
57
+ var $w = testwin["static"].$;
58
+
59
+ equals( $w('#static-1').offset().top, $.browser.msie ? 6 : 7, "$('#static-1').offset().top" );
60
+ equals( $w('#static-1').offset().left, 7, "$('#static-1').offset().left" );
61
+
62
+ equals( $w('#static-1-1').offset().top, $.browser.msie ? 13 : 15, "$('#static-1-1').offset().top" );
63
+ equals( $w('#static-1-1').offset().left, 15, "$('#static-1-1').offset().left" );
64
+
65
+ equals( $w('#static-1-1-1').offset().top, $.browser.msie ? 20 : 23, "$('#static-1-1-1').offset().top" );
66
+ equals( $w('#static-1-1-1').offset().left, 23, "$('#static-1-1-1').offset().left" );
67
+
68
+ equals( $w('#static-2').offset().top, $.browser.msie ? 121 : 122, "$('#static-2').offset().top" );
69
+ equals( $w('#static-2').offset().left, 7, "$('#static-2').offset().left" );
70
+
71
+ testwin["static"].close();
72
+ });
73
+
74
+ if ( !$.browser.msie || ($.browser.msie && parseInt($.browser.version) > 6) )
75
+ testwin("fixed", function() {
76
+ var $w = testwin["fixed"].$;
77
+
78
+ equals( $w('#fixed-1').offset().top, 1001, "$('#fixed-1').offset().top" );
79
+ equals( $w('#fixed-1').offset().left, $.browser.msie ? 994 : 1001, "$('#fixed-1').offset().left" );
80
+
81
+ equals( $w('#fixed-2').offset().top, 1021, "$('#fixed-2').offset().top" );
82
+ equals( $w('#fixed-2').offset().left, $.browser.msie ? 1014 : 1021, "$('#fixed-2').offset().left" );
83
+
84
+ testwin["fixed"].close();
85
+ });
86
+
87
+ testwin("table", function() {
88
+ var $w = testwin["table"].$;
89
+
90
+ equals( $w('#table-1').offset().top, 6, "$('#table-1').offset().top" );
91
+ equals( $w('#table-1').offset().left, 6, "$('#table-1').offset().left" );
92
+
93
+ equals( $w('#th-1').offset().top, 10, "$('#table-1').offset().top" );
94
+ equals( $w('#th-1').offset().left, 10, "$('#table-1').offset().left" );
95
+
96
+ equals( $w('#th-2').offset().top, 10, "$('#table-1').offset().top" );
97
+ equals( $w('#th-2').offset().left, 116, "$('#table-1').offset().left" );
98
+
99
+ testwin["table"].close();
100
+ });
101
+
102
+ testwin("scroll", function() {
103
+ var $w = testwin["scroll"].$;
104
+
105
+ equals( $w('#scroll-1').offset().top, $.browser.msie ? 6 : 7, "$('#scroll-1').offset().top" );
106
+ equals( $w('#scroll-1').offset().left, 7, "$('#scroll-1').offset().left" );
107
+
108
+ equals( $w('#scroll-1-1').offset().top, $.browser.msie ? 9 : 11, "$('#scroll-1-1').offset().top" );
109
+ equals( $w('#scroll-1-1').offset().left, 11, "$('#scroll-1-1').offset().left" );
110
+
111
+ testwin["scroll"].close();
112
+ });
@@ -0,0 +1,224 @@
1
+ module("selector");
2
+
3
+ test("element", function() {
4
+ expect(9);
5
+ ok( $("*").size() >= 30, "Select all" );
6
+ var all = $("*"), good = true;
7
+ for ( var i = 0; i < all.length; i++ )
8
+ if ( all[i].nodeType == 8 )
9
+ good = false;
10
+ ok( good, "Select all elements, no comment nodes" );
11
+ t( "Element Selector", "p", ["firstp","ap","sndp","en","sap","first"] );
12
+ t( "Element Selector", "body", ["body"] );
13
+ t( "Element Selector", "html", ["html"] );
14
+ t( "Parent Element", "div p", ["firstp","ap","sndp","en","sap","first"] );
15
+ ok( $("param", "#object1").length == 2, "Object/param as context" );
16
+
17
+ ok( $("#length").length, '&lt;input name="length"&gt; cannot be found under IE, see #945' );
18
+ ok( $("#lengthtest input").length, '&lt;input name="length"&gt; cannot be found under IE, see #945' );
19
+ });
20
+
21
+ if ( location.protocol != "file:" ) {
22
+ test("Element Selector with underscore", function() {
23
+ expect(1);
24
+ stop();
25
+ $.get("data/with_fries.xml", function(xml) {
26
+ ok( $("foo_bar", xml).length == 1, "Element Selector with underscore" );
27
+ start();
28
+ });
29
+ });
30
+ }
31
+
32
+ test("broken", function() {
33
+ expect(7);
34
+ t( "Broken Selector", "[", [] );
35
+ t( "Broken Selector", "(", [] );
36
+ t( "Broken Selector", "{", [] );
37
+ t( "Broken Selector", "<", [] );
38
+ t( "Broken Selector", "()", [] );
39
+ t( "Broken Selector", "<>", [] );
40
+ t( "Broken Selector", "{}", [] );
41
+ });
42
+
43
+ test("id", function() {
44
+ expect(25);
45
+ t( "ID Selector", "#body", ["body"] );
46
+ t( "ID Selector w/ Element", "body#body", ["body"] );
47
+ t( "ID Selector w/ Element", "ul#first", [] );
48
+ t( "ID selector with existing ID descendant", "#firstp #simon1", ["simon1"] );
49
+ t( "ID selector with non-existant descendant", "#firstp #foobar", [] );
50
+ t( "ID selector using UTF8", "#台北Táiběi", ["台北Táiběi"] );
51
+ t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", ["台北Táiběi","台北"] );
52
+ t( "Descendant ID selector using UTF8", "div #台北", ["台北"] );
53
+ t( "Child ID selector using UTF8", "form > #台北", ["台北"] );
54
+
55
+ t( "Escaped ID", "#foo\\:bar", ["foo:bar"] );
56
+ t( "Escaped ID", "#test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
57
+ t( "Descendant escaped ID", "div #foo\\:bar", ["foo:bar"] );
58
+ t( "Descendant escaped ID", "div #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
59
+ t( "Child escaped ID", "form > #foo\\:bar", ["foo:bar"] );
60
+ t( "Child escaped ID", "form > #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
61
+
62
+ t( "ID Selector, child ID present", "#form > #radio1", ["radio1"] ); // bug #267
63
+ t( "ID Selector, not an ancestor ID", "#form #first", [] );
64
+ t( "ID Selector, not a child ID", "#form > #option1a", [] );
65
+
66
+ t( "All Children of ID", "#foo > *", ["sndp", "en", "sap"] );
67
+ t( "All Children of ID with no children", "#firstUL/*", [] );
68
+
69
+ $('<a name="tName1">tName1 A</a><a name="tName2">tName2 A</a><div id="tName1">tName1 Div</div>').appendTo('#main');
70
+ ok( $("#tName1")[0].id == 'tName1', "ID selector with same value for a name attribute" );
71
+ ok( $("#tName2").length == 0, "ID selector non-existing but name attribute on an A tag" );
72
+ t( "ID Selector on Form with an input that has a name of 'id'", "#lengthtest", ["lengthtest"] );
73
+
74
+ t( "ID selector with non-existant ancestor", "#asdfasdf #foobar", [] ); // bug #986
75
+
76
+ isSet( $("body").find("div#form"), [], "ID selector within the context of another element" );
77
+ });
78
+
79
+ test("class", function() {
80
+ expect(16);
81
+ t( "Class Selector", ".blog", ["mark","simon"] );
82
+ t( "Class Selector", ".blog.link", ["simon"] );
83
+ t( "Class Selector w/ Element", "a.blog", ["mark","simon"] );
84
+ t( "Parent Class Selector", "p .blog", ["mark","simon"] );
85
+
86
+ t( "Class selector using UTF8", ".台北Táiběi", ["utf8class1"] );
87
+ t( "Class selector using UTF8", ".台北", ["utf8class1","utf8class2"] );
88
+ t( "Class selector using UTF8", ".台北Táiběi.台北", ["utf8class1"] );
89
+ t( "Class selector using UTF8", ".台北Táiběi, .台北", ["utf8class1","utf8class2"] );
90
+ t( "Descendant class selector using UTF8", "div .台北Táiběi", ["utf8class1"] );
91
+ t( "Child class selector using UTF8", "form > .台北Táiběi", ["utf8class1"] );
92
+
93
+ t( "Escaped Class", ".foo\\:bar", ["foo:bar"] );
94
+ t( "Escaped Class", ".test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
95
+ t( "Descendant scaped Class", "div .foo\\:bar", ["foo:bar"] );
96
+ t( "Descendant scaped Class", "div .test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
97
+ t( "Child escaped Class", "form > .foo\\:bar", ["foo:bar"] );
98
+ t( "Child escaped Class", "form > .test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
99
+ });
100
+
101
+ test("multiple", function() {
102
+ expect(4);
103
+ t( "Comma Support", "a.blog, p", ["mark","simon","firstp","ap","sndp","en","sap","first"] );
104
+ t( "Comma Support", "a.blog , p", ["mark","simon","firstp","ap","sndp","en","sap","first"] );
105
+ t( "Comma Support", "a.blog ,p", ["mark","simon","firstp","ap","sndp","en","sap","first"] );
106
+ t( "Comma Support", "a.blog,p", ["mark","simon","firstp","ap","sndp","en","sap","first"] );
107
+ });
108
+
109
+ test("child and adjacent", function() {
110
+ expect(37);
111
+ t( "Child", "p > a", ["simon1","google","groups","mark","yahoo","simon"] );
112
+ t( "Child", "p> a", ["simon1","google","groups","mark","yahoo","simon"] );
113
+ t( "Child", "p >a", ["simon1","google","groups","mark","yahoo","simon"] );
114
+ t( "Child", "p>a", ["simon1","google","groups","mark","yahoo","simon"] );
115
+ t( "Child w/ Class", "p > a.blog", ["mark","simon"] );
116
+ t( "All Children", "code > *", ["anchor1","anchor2"] );
117
+ t( "All Grandchildren", "p > * > *", ["anchor1","anchor2"] );
118
+ t( "Adjacent", "a + a", ["groups"] );
119
+ t( "Adjacent", "a +a", ["groups"] );
120
+ t( "Adjacent", "a+ a", ["groups"] );
121
+ t( "Adjacent", "a+a", ["groups"] );
122
+ t( "Adjacent", "p + p", ["ap","en","sap"] );
123
+ t( "Comma, Child, and Adjacent", "a + a, code > a", ["groups","anchor1","anchor2"] );
124
+
125
+ t( "First Child", "p:first-child", ["firstp","sndp"] );
126
+ t( "Nth Child", "p:nth-child(1)", ["firstp","sndp"] );
127
+
128
+ t( "Last Child", "p:last-child", ["sap"] );
129
+ t( "Last Child", "a:last-child", ["simon1","anchor1","mark","yahoo","anchor2","simon"] );
130
+
131
+ t( "Nth-child", "#main form#form > *:nth-child(2)", ["text2"] );
132
+ t( "Nth-child", "#main form#form > :nth-child(2)", ["text2"] );
133
+
134
+ t( "Nth-child", "#form select:first option:nth-child(3)", ["option1c"] );
135
+ t( "Nth-child", "#form select:first option:nth-child(0n+3)", ["option1c"] );
136
+ t( "Nth-child", "#form select:first option:nth-child(1n+0)", ["option1a", "option1b", "option1c", "option1d"] );
137
+ t( "Nth-child", "#form select:first option:nth-child(1n)", ["option1a", "option1b", "option1c", "option1d"] );
138
+ t( "Nth-child", "#form select:first option:nth-child(n)", ["option1a", "option1b", "option1c", "option1d"] );
139
+ t( "Nth-child", "#form select:first option:nth-child(even)", ["option1b", "option1d"] );
140
+ t( "Nth-child", "#form select:first option:nth-child(odd)", ["option1a", "option1c"] );
141
+ t( "Nth-child", "#form select:first option:nth-child(2n)", ["option1b", "option1d"] );
142
+ t( "Nth-child", "#form select:first option:nth-child(2n+1)", ["option1a", "option1c"] );
143
+ t( "Nth-child", "#form select:first option:nth-child(3n)", ["option1c"] );
144
+ t( "Nth-child", "#form select:first option:nth-child(3n+1)", ["option1a", "option1d"] );
145
+ t( "Nth-child", "#form select:first option:nth-child(3n+2)", ["option1b"] );
146
+ t( "Nth-child", "#form select:first option:nth-child(3n+3)", ["option1c"] );
147
+ t( "Nth-child", "#form select:first option:nth-child(3n-1)", ["option1b"] );
148
+ t( "Nth-child", "#form select:first option:nth-child(3n-2)", ["option1a", "option1d"] );
149
+ t( "Nth-child", "#form select:first option:nth-child(3n-3)", ["option1c"] );
150
+ t( "Nth-child", "#form select:first option:nth-child(3n+0)", ["option1c"] );
151
+ t( "Nth-child", "#form select:first option:nth-child(-n+3)", ["option1a", "option1b", "option1c"] );
152
+ });
153
+
154
+ test("attributes", function() {
155
+ expect(20);
156
+ t( "Attribute Exists", "a[title]", ["google"] );
157
+ t( "Attribute Exists", "*[title]", ["google"] );
158
+ t( "Attribute Exists", "[title]", ["google"] );
159
+
160
+ t( "Attribute Equals", "a[rel='bookmark']", ["simon1"] );
161
+ t( "Attribute Equals", 'a[rel="bookmark"]', ["simon1"] );
162
+ t( "Attribute Equals", "a[rel=bookmark]", ["simon1"] );
163
+ t( "Multiple Attribute Equals", "#form input[type='hidden'],#form input[type='radio']", ["hidden1","radio1","radio2"] );
164
+ t( "Multiple Attribute Equals", "#form input[type=\"hidden\"],#form input[type='radio']", ["hidden1","radio1","radio2"] );
165
+ t( "Multiple Attribute Equals", "#form input[type=hidden],#form input[type=radio]", ["hidden1","radio1","radio2"] );
166
+
167
+ t( "Attribute selector using UTF8", "span[lang=中文]", ["台北"] );
168
+
169
+ t( "Attribute Begins With", "a[href ^= 'http://www']", ["google","yahoo"] );
170
+ t( "Attribute Ends With", "a[href $= 'org/']", ["mark"] );
171
+ t( "Attribute Contains", "a[href *= 'google']", ["google","groups"] );
172
+
173
+ t("Select options via [selected]", "#select1 option[selected]", ["option1a"] );
174
+ t("Select options via [selected]", "#select2 option[selected]", ["option2d"] );
175
+ t("Select options via [selected]", "#select3 option[selected]", ["option3b", "option3c"] );
176
+
177
+ t( "Grouped Form Elements", "input[name='foo[bar]']", ["hidden2"] );
178
+
179
+ t( ":not() Existing attribute", "#form select:not([multiple])", ["select1", "select2"]);
180
+ t( ":not() Equals attribute", "#form select:not([name=select1])", ["select2", "select3"]);
181
+ t( ":not() Equals quoted attribute", "#form select:not([name='select1'])", ["select2", "select3"]);
182
+ });
183
+
184
+ test("pseudo (:) selectors", function() {
185
+ expect(35);
186
+ t( "First Child", "p:first-child", ["firstp","sndp"] );
187
+ t( "Last Child", "p:last-child", ["sap"] );
188
+ t( "Only Child", "a:only-child", ["simon1","anchor1","yahoo","anchor2"] );
189
+ t( "Empty", "ul:empty", ["firstUL"] );
190
+ t( "Enabled UI Element", "#form input:enabled", ["text1","radio1","radio2","check1","check2","hidden1","hidden2","name"] );
191
+ t( "Disabled UI Element", "#form input:disabled", ["text2"] );
192
+ t( "Checked UI Element", "#form input:checked", ["radio2","check1"] );
193
+ t( "Selected Option Element", "#form option:selected", ["option1a","option2d","option3b","option3c"] );
194
+ t( "Text Contains", "a:contains('Google')", ["google","groups"] );
195
+ t( "Text Contains", "a:contains('Google Groups')", ["groups"] );
196
+ t( "Element Preceded By", "p ~ div", ["foo","fx-queue","fx-tests", "moretests"] );
197
+ t( "Not", "a.blog:not(.link)", ["mark"] );
198
+ t( "Not - multiple", "#form option:not(:contains('Nothing'),#option1b,:selected)", ["option1c", "option1d", "option2b", "option2c", "option3d"] );
199
+ t( "Not - complex", "#form option:not([id^='opt']:gt(0):nth-child(-n+3))", [ "option1a", "option1d", "option2d", "option3d"] );
200
+ t( "Not - recursive", "#form option:not(:not(:selected))[id^='option3']", [ "option3b", "option3c"] );
201
+
202
+ t( "nth Element", "p:nth(1)", ["ap"] );
203
+ t( "First Element", "p:first", ["firstp"] );
204
+ t( "Last Element", "p:last", ["first"] );
205
+ t( "Even Elements", "p:even", ["firstp","sndp","sap"] );
206
+ t( "Odd Elements", "p:odd", ["ap","en","first"] );
207
+ t( "Position Equals", "p:eq(1)", ["ap"] );
208
+ t( "Position Greater Than", "p:gt(0)", ["ap","sndp","en","sap","first"] );
209
+ t( "Position Less Than", "p:lt(3)", ["firstp","ap","sndp"] );
210
+ t( "Is A Parent", "p:parent", ["firstp","ap","sndp","en","sap","first"] );
211
+ t( "Is Visible", "#form input:visible", ["text1","text2","radio1","radio2","check1","check2","name"] );
212
+ t( "Is Hidden", "#form input:hidden", ["hidden1","hidden2"] );
213
+
214
+ t( "Form element :input", "#form :input", ["text1", "text2", "radio1", "radio2", "check1", "check2", "hidden1", "hidden2", "name", "button", "area1", "select1", "select2", "select3"] );
215
+ t( "Form element :radio", "#form :radio", ["radio1", "radio2"] );
216
+ t( "Form element :checkbox", "#form :checkbox", ["check1", "check2"] );
217
+ t( "Form element :text", "#form :text", ["text1", "text2", "hidden2", "name"] );
218
+ t( "Form element :radio:checked", "#form :radio:checked", ["radio2"] );
219
+ t( "Form element :checkbox:checked", "#form :checkbox:checked", ["check1"] );
220
+ t( "Form element :checkbox:checked, :radio:checked", "#form :checkbox:checked, #form :radio:checked", ["check1", "radio2"] );
221
+
222
+ t( "Headers", ":header", ["header", "banner", "userAgent"] );
223
+ t( "Has Children - :has()", "p:has(a)", ["firstp","ap","en","sap"] );
224
+ });
@@ -0,0 +1,7 @@
1
+ Johnson.require("test/jspec/jspec");
2
+ Johnson.require("johnson/browser");
3
+
4
+ Johnson.waitForThreads = function() {
5
+ // FIXME: This sucks ass
6
+ Ruby.eval("(Thread.list - [Thread.main]).each {|t| t.join}");
7
+ };
@@ -0,0 +1,192 @@
1
+ console = {
2
+ indentation: 0,
3
+ indent: function() {
4
+ for(i=0;i<this.indentation - 1;i++) Ruby.print(" ");
5
+ if(this.indentation > 0) Ruby.print("- ");
6
+ },
7
+ group: function(msg) {
8
+ this.info(msg);
9
+ this.indentation += 1;
10
+ },
11
+ info: function(msg) {
12
+ this.indent();
13
+ Ruby.puts(msg);
14
+ },
15
+ error: function(msg) {
16
+ this.info("F " + msg);
17
+ },
18
+ warn: function(msg) {
19
+ this.info("W " + msg);
20
+ },
21
+ groupEnd: function() {
22
+ this.indentation -= 1;
23
+ }
24
+ };
25
+
26
+ jspec = {
27
+ fn_contents: function(fn) {
28
+ return fn.toString().match(/^[^\{]*{((.*\n*)*)}/m)[1];
29
+ },
30
+ TOP_LEVEL: 0, DESCRIBE: 1, IT_SHOULD_PASS: 2, IT_SHOULD_FAIL: 3,
31
+ FAILURE: 4, DONE_EXAMPLE: 5, DONE_GROUP: 6, PENDING: 7,
32
+ logger: function(state, message) {
33
+ switch(state) {
34
+ case jspec.TOP_LEVEL:
35
+ console.group(message);
36
+ break;
37
+ case jspec.DESCRIBE:
38
+ console.group(message);
39
+ break;
40
+ case jspec.IT_SHOULD_PASS:
41
+ console.info(message);
42
+ break;
43
+ case jspec.IT_SHOULD_FAIL:
44
+ console.group(message);
45
+ break;
46
+ case jspec.FAILURE:
47
+ console.error(message);
48
+ console.groupEnd();
49
+ break;
50
+ case jspec.DONE_EXAMPLE:
51
+ console.groupEnd();
52
+ break;
53
+ case jspec.DONE_GROUP:
54
+ console.groupEnd();
55
+ break;
56
+ case jspec.PENDING:
57
+ console.warn("Pending: " + message);
58
+ break;
59
+ }
60
+
61
+ },
62
+ describe: function(str, desc) {
63
+ jspec.logger(jspec.TOP_LEVEL, str);
64
+ var it = function(str, fn) {
65
+ if(fn) {
66
+ jspec.logger(jspec.DESCRIBE, str);
67
+ fn();
68
+ jspec.logger(jspec.DONE_EXAMPLE);
69
+ } else {
70
+ jspec.logger(jspec.PENDING, str);
71
+ };
72
+ };
73
+ var Expectation = function(p) { this.expectation = p; };
74
+ Expectation.prototype.to = function(fn_str, to_compare, not) {
75
+ try {
76
+ var pass = jspec.matchers[fn_str].matches(this.expectation, to_compare);
77
+ if(not) var pass = !pass;
78
+ } catch(e) {
79
+ var pass = null;
80
+ }
81
+ var should_string = (jspec.matchers[fn_str].describe &&
82
+ jspec.matchers[fn_str].describe(this.expectation, to_compare, not)) ||
83
+ this.toString() + " should " + (not ? "not " : "") + fn_str + " " + to_compare;
84
+ if(pass) {
85
+ jspec.logger(jspec.IT_SHOULD_PASS, should_string + " (PASS)");
86
+ } else {
87
+ jspec.logger(jspec.IT_SHOULD_FAIL, should_string + (pass == false ? " (FAIL)" : " (ERROR)"));
88
+ jspec.logger(jspec.FAILURE, jspec.matchers[fn_str].failure_message(this.expectation, to_compare, not))
89
+ }
90
+ }
91
+ Expectation.prototype.not_to = function(fn_str, to_compare) { this.to(fn_str, to_compare, true) }
92
+ var expect = function(p) { return new Expectation(p) };
93
+ x = desc.toString()
94
+ var fn_body = this.fn_contents(desc);
95
+ var fn = new Function("it", "expect", fn_body);
96
+ fn.call(this, it, expect);
97
+ jspec.logger(jspec.DONE_GROUP);
98
+ }
99
+ }
100
+
101
+ // Helper for
102
+
103
+ jspec.print_object = function(obj) {
104
+ if(obj instanceof Function) {
105
+ return obj.toString().match(/^([^\{]*) {/)[1];
106
+ } else if(obj instanceof Array) {
107
+ return "[" + obj.toString() + "]";
108
+ } else if(typeof HTMLElement != "undefined" && obj instanceof HTMLElement) {
109
+ return "<" + obj.tagName + (obj.className != "" ? " class='" + obj.className + "'" : "") +
110
+ (obj.id != "" ? " id='" + obj.id + "'" : "") + ">";
111
+ } else if(typeof DOMDocument != "undefined" && obj instanceof DOMDocument) {
112
+ return "The document element";
113
+ } else {
114
+ return obj.toString().replace(/\n\s*/g, "");
115
+ }
116
+ }
117
+
118
+ // Matchers begin here
119
+
120
+ jspec.matchers = {};
121
+
122
+ jspec.matchers["=="] = {
123
+ describe: function(self, target, not) {
124
+ return jspec.print_object(self) + " should " + (not ? "not " : "") + "equal " + jspec.print_object(target)
125
+ },
126
+ matches: function(self, target) {
127
+ return self == target;
128
+ },
129
+ failure_message: function(self, target, not) {
130
+ if (not)
131
+ return "Expected " + jspec.print_object(self) + " not to equal " + jspec.print_object(target);
132
+ else
133
+ return "Expected " + jspec.print_object(self) + ". Got " + jspec.print_object(target);
134
+ }
135
+ }
136
+
137
+ jspec.matchers["include"] = {
138
+ matches: function(self, target) {
139
+ if(Array.prototype.indexOf) return Array.prototype.indexOf.call(self, target) != -1;
140
+ else {
141
+ for(i=0,j=self.length;i<j;i++) {
142
+ if(target == self[i]) return true;
143
+ }
144
+ return false;
145
+ }
146
+ },
147
+ failure_message: function(self, target, not) {
148
+ return "Expected [" + jspec.print_object(self) + "] " + (not ? "not " : "") + "to include " + target;
149
+ }
150
+ }
151
+
152
+ jspec.matchers["exist"] = {
153
+ describe: function(self, target, not) {
154
+ return jspec.print_object(self) + " should " + (not ? "not " : "") + "exist."
155
+ },
156
+ matches: function(self, target) {
157
+ return !!this;
158
+ },
159
+ failure_message: function(self, target, not) {
160
+ return "Expected " + (not ? "not " : "") + "to exist, but was " + jspec.print_object(self);
161
+ }
162
+ }
163
+
164
+ jspec.matchers["be_instanceof"] = {
165
+ describe: function(self, target, not) {
166
+ return jspec.print_object(self) + " should " + (not ? "not " : "") +
167
+ "be an instance of " + jspec.print_object(target);
168
+ },
169
+ matches: function(self, target) {
170
+ return self instanceof target;
171
+ },
172
+ failure_message: function(self, target, not) {
173
+ return "Expected " + jspec.print_object(self) + (not ? "not " : "") +
174
+ "to be an instance of " + jspec.print_object(target) + ", but was " +
175
+ jspec.print_object(target.constructor);
176
+ }
177
+ }
178
+
179
+ jspec.matchers["have_constructor"] = {
180
+ describe: function(self, target, not) {
181
+ return jspec.print_object(self) + " should " + (not ? "not " : "") +
182
+ "have " + jspec.print_object(target) + " as its constructor";
183
+ },
184
+ matches: function(self, target) {
185
+ return self instanceof target;
186
+ },
187
+ failure_message: function(self, target, not) {
188
+ return "Expected " + jspec.print_object(self) + (not ? "not " : "") +
189
+ "to have " + jspec.print_object(target) + ", as its constructor but was " +
190
+ jspec.print_object(target.constructor);
191
+ }
192
+ }