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,225 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module SpiderMonkey
5
+ class RubyLandProxyTest < Johnson::TestCase
6
+ def setup
7
+ @runtime = Johnson::Runtime.new(Johnson::SpiderMonkey::Runtime)
8
+ end
9
+
10
+ def test_constructing_a_proxy_directly_asplodes
11
+ assert_raise(Johnson::Error) { Johnson::SpiderMonkey::RubyLandProxy.new }
12
+ end
13
+
14
+ def test_objects_get_wrapped_as_proxies
15
+ assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, @runtime.evaluate("x = {}"))
16
+ assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, @runtime.evaluate("new Object()"))
17
+ end
18
+
19
+ def test_proxies_get_unwrapped_when_roundtripping
20
+ proxy = @runtime.evaluate("x = {}")
21
+ @runtime["y"] = proxy
22
+ assert(@runtime.evaluate("x === y"))
23
+ end
24
+
25
+ def test_array_indexable
26
+ proxy = @runtime.evaluate("var x = [1,2,3]; x")
27
+ assert_equal(1, proxy[0])
28
+ assert_equal(1, proxy['0'])
29
+
30
+ proxy[0] = 10
31
+ assert_js_equal(10, 'x[0]')
32
+ end
33
+
34
+ def test_hash_indexable
35
+ proxy = @runtime.evaluate("var x = { 0: 1, 1: 2, 2: 3 }; x")
36
+ assert_equal(1, proxy[0])
37
+ assert_equal(1, proxy['0'])
38
+
39
+ proxy[0] = 10
40
+ assert_js_equal(10, 'x[0]')
41
+ end
42
+
43
+ def test_functions_get_wrapped_as_proxies
44
+ f = @runtime.evaluate("function() {}")
45
+ assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, f)
46
+ assert(f.function?)
47
+ end
48
+
49
+ def test_function?
50
+ f = @runtime.evaluate("function() {}")
51
+ assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, f)
52
+ assert(f.function?)
53
+
54
+ f = @runtime.evaluate("new Object()")
55
+ assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, f)
56
+ assert(!f.function?)
57
+ end
58
+
59
+ def test_calling_non_functions_complains
60
+ assert_raise(RuntimeError) { @runtime.evaluate("new Object()").call }
61
+ end
62
+
63
+ def test_functions_can_be_called
64
+ f = @runtime.evaluate("function() { return 42; }")
65
+ assert_equal(42, f.call)
66
+ end
67
+
68
+ def test_functions_can_be_called_with_args
69
+ f = @runtime.evaluate("function(x) { return x * 2; }")
70
+ assert_equal(84, f.call(42))
71
+ end
72
+
73
+ def test_functions_can_be_used_as_procs
74
+ f = @runtime.evaluate("function(x) { return x * 2; }")
75
+ a = [1, 2, 3]
76
+
77
+ assert_equal([2, 4, 6], a.collect(&f))
78
+ end
79
+
80
+ def test_function_proxies_are_called_with_a_global_this
81
+ f = @runtime.evaluate("x = 42; function() { return this.x; }")
82
+ assert_equal(42, f.call)
83
+ end
84
+
85
+ def test_can_be_indexed_by_string
86
+ proxy = @runtime.evaluate("x = { foo: 42 }")
87
+ assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, proxy)
88
+
89
+ assert_equal(42, proxy["foo"])
90
+
91
+ proxy["foo"] = 99
92
+ proxy["bar"] = 42
93
+
94
+ assert_js_equal(99, "x.foo")
95
+ assert_equal(99, proxy["foo"])
96
+ assert_equal(42, proxy["bar"])
97
+ end
98
+
99
+ def test_multilevel_indexing_works
100
+ proxy = @runtime.evaluate("x = { foo: { bar: 42 , baz: function() { return 42 } } }")
101
+ assert_equal(42, proxy["foo"]["bar"])
102
+ assert_equal(42, proxy["foo"]["baz"].call)
103
+ end
104
+
105
+ def test_respond_to_works
106
+ proxy = @runtime.evaluate("x = { foo: 42 }")
107
+ assert(!proxy.respond_to?(:bar))
108
+ assert(proxy.respond_to?(:foo))
109
+ end
110
+
111
+ def test_respond_to_always_returns_true_for_assignment
112
+ proxy = @runtime.evaluate("x = {}")
113
+ assert(proxy.respond_to?(:bar=))
114
+ end
115
+
116
+ def test_accessor
117
+ proxy = @runtime.evaluate("x = { foo: 42 }")
118
+ assert_equal(42, proxy.foo)
119
+ end
120
+
121
+ def test_mutator
122
+ proxy = @runtime.evaluate("x = {}")
123
+ proxy.foo = 42
124
+
125
+ assert_js_equal(42, "x.foo")
126
+ assert_equal(42, proxy.foo)
127
+ end
128
+
129
+ def test_method_with_no_arguments
130
+ proxy = @runtime.evaluate("x = { foo: function() { return 42 } }")
131
+ assert_equal(42, proxy.foo)
132
+ end
133
+
134
+ def test_method_with_one_argument
135
+ proxy = @runtime.evaluate("f = { f: function(x) { return x * 2 } }")
136
+ assert_equal(84, proxy.f(42))
137
+ end
138
+
139
+ def test_method_with_multiple_arguments
140
+ proxy = @runtime.evaluate("x = { add: function(x, y) { return x + y } }")
141
+ assert_equal(42, proxy.add(40, 2))
142
+ end
143
+
144
+ def test_supports_each_on_arrays
145
+ proxy = @runtime.evaluate("[1, 2, 3]")
146
+ values = []
147
+
148
+ proxy.each { |n| values << n }
149
+ assert_equal([1, 2, 3], values)
150
+ end
151
+
152
+ def test_supports_each_on_things_that_arent_arrays
153
+ proxy = @runtime.evaluate("x = { foo: 'fooval', bar: 'barval' }; x[0] = 42; x")
154
+ values = {}
155
+
156
+ proxy.each { |k, v| values[k] = v }
157
+ assert_equal({ 'foo' => 'fooval', 'bar' => 'barval', 0 => 42 }, values)
158
+ end
159
+
160
+ def test_each_passes_an_exception
161
+ proxy = @runtime.evaluate("x = { foo: 'fooval', bar: 'barval' }; x[0] = 42; x")
162
+ values = {}
163
+
164
+ assert_raise(RuntimeError) do
165
+ proxy.each do |k, v|
166
+ values[k] = v
167
+ raise "splat" if values.keys.size == 2
168
+ end
169
+ end
170
+ assert_equal({ 'foo' => 'fooval', 'bar' => 'barval' }, values)
171
+ end
172
+
173
+ def test_is_enumerable
174
+ proxy = @runtime.evaluate("[1, 2, 3]")
175
+ assert_kind_of(Enumerable, proxy)
176
+
177
+ assert_equal([2, 4, 6], proxy.collect { |n| n * 2 })
178
+ end
179
+
180
+ def test_has_a_length
181
+ proxy = @runtime.evaluate("[1, 2, 3]")
182
+ assert_equal(3, proxy.length)
183
+ end
184
+
185
+ def test_length_is_aliased_as_size
186
+ proxy = @runtime.evaluate("[1, 2, 3]")
187
+ assert_equal(3, proxy.size)
188
+ end
189
+
190
+ def test_length_for_arrays_ignores_non_numeric_properties
191
+ proxy = @runtime.evaluate("x = [1, 2, 3]; x['foo'] = 'bar'; x")
192
+ assert_equal(3, proxy.length)
193
+ end
194
+
195
+ def test_length_for_objects_includes_all_properties
196
+ proxy = @runtime.evaluate("x = { foo: 'foo', bar: 'bar', 0: 42 }")
197
+ assert_equal(3, proxy.length)
198
+ end
199
+
200
+ def test_raises_in_js
201
+ err = RuntimeError.new("an exception")
202
+ asplode = lambda { raise err }
203
+ assert_js_equal(err, "x = null; try { foo(); } catch(ex) { x = ex; }; x", :foo => asplode)
204
+ end
205
+
206
+ # FIXME: If you uncomment this test, we get this error:
207
+ #
208
+ # JS API usage error: the address passed to JS_AddNamedRoot currently holds an
209
+ # invalid jsval. This is usually caused by a missing call to JS_RemoveRoot.
210
+ # The root's name is "ruby_land_proxy.c[210]:native_call: proxy_value".
211
+ # Assertion failure: root_points_to_gcArenaList, at jsgc.c:2618
212
+ #
213
+ # WTF?
214
+ #
215
+ # -Aaron
216
+ #
217
+ #def test_throwing_in_js_goes_to_ruby
218
+ # func = @runtime.evaluate('function () { throw "foo"; }')
219
+ # assert_raise(Johnson::Error) {
220
+ # func.call
221
+ # }
222
+ #end
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module SpiderMonkey
5
+ class RuntimeTest < Johnson::TestCase
6
+ def setup
7
+ @runtime = Johnson::SpiderMonkey::Runtime.new
8
+ end
9
+
10
+ def test_can_create_more_than_one_without_barfing
11
+ assert_nothing_raised {
12
+ Johnson::SpiderMonkey::Runtime.new
13
+ }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../helper"))
2
+
3
+ module Johnson
4
+ class VersionTest < Johnson::TestCase
5
+ def test_has_a_version
6
+ assert_not_nil(Johnson::VERSION)
7
+ end
8
+
9
+ def test_has_a_spidermonkey_version
10
+ assert_not_nil(Johnson::SpiderMonkey::VERSION)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class DotVisitorTest < Test::Unit::TestCase
4
+ def test_var_foo
5
+ dot = Johnson.parse('var foo;').to_dot
6
+ assert_equal(3, dot.nodes.length)
7
+ assert_equal(2, dot.links.length)
8
+ end
9
+
10
+ def test_for
11
+ dot = Johnson.parse('for(var x = 0; x < 10; x++) { }').to_dot
12
+ assert_equal(12, dot.nodes.length)
13
+ assert_equal(11, dot.links.length)
14
+ end
15
+
16
+ def test_for_in
17
+ dot = Johnson.parse('for(var x in johnson(1,2,"asdf")) { }').to_dot
18
+ assert_equal(11, dot.nodes.length)
19
+ assert_equal(10, dot.links.length)
20
+ end
21
+
22
+ def test_try
23
+ dot = Johnson.parse('try { var x = 10; } finally { var x = 20; }').to_dot
24
+ assert_equal(12, dot.nodes.length)
25
+ assert_equal(11, dot.links.length)
26
+ end
27
+
28
+ def test_try_catch
29
+ dot = Johnson.parse('try { var x = 10; } catch(a) { var x = 20; x++; }').to_dot
30
+ assert_equal(16, dot.nodes.length)
31
+ assert_equal(15, dot.links.length)
32
+ end
33
+
34
+ def test_function
35
+ dot = Johnson.parse("var foo = function(a,b) { }").to_dot
36
+ assert_equal(6, dot.nodes.length)
37
+ assert_equal(5, dot.links.length)
38
+ end
39
+ end
@@ -0,0 +1,12 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class EnumeratingVisitorTest < Test::Unit::TestCase
4
+ def test_for
5
+ ast = Johnson.parse('for(var x = 0; x < 10; x++) { }')
6
+ counter = 0
7
+ ast.each do |node|
8
+ counter += 1
9
+ end
10
+ assert_equal(12, counter)
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "helper"))
2
+
3
+ class JohnsonTest < Test::Unit::TestCase
4
+ def test_shortcut_evaluate
5
+ assert_equal(4, Johnson.evaluate("2 + 2"))
6
+ end
7
+
8
+ def test_can_provide_context_vars_to_evaluate
9
+ assert_equal(4, Johnson.evaluate("2 + foo", :foo => 2))
10
+ end
11
+
12
+ def test_evaluate_uses_a_new_runtime_each_time
13
+ assert_equal(4, Johnson.evaluate("foo", :foo => 4))
14
+ assert_raise(Johnson::Error) { Johnson.evaluate("foo") }
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ // Init
2
+ Johnson.require("johnson/browser");
3
+ Johnson.require("johnson/browser/jquery");
4
+
5
+ Johnson.waitForThreads = function() {
6
+ // FIXME: This sucks ass
7
+ Ruby.eval("(Thread.list - [Thread.main]).each {|t| t.join}");
8
+ };
9
+
10
+ window.location = "file://" + Ruby.File.expand_path(Ruby.Dir.pwd()) + "/test/assets/jquery_test.html";
11
+ Ruby.eval("(Thread.list - [Thread.main]).each {|t| t.join}");
12
+
13
+ // Load the test runner
14
+ Johnson.require("test/jquery_units/test_helper.js");
15
+
16
+ Johnson.require("test/jquery_units/units/core.js");
17
+ // // Load the tests
18
+ // load(
19
+ // "test/unit/core.js",
20
+ // "test/unit/selector.js",
21
+ // "test/unit/event.js"
22
+ // //"test/unit/fx.js",
23
+ // //"test/unit/ajax.js"
24
+ // );
25
+
26
+ // Display the results
27
+ results();
@@ -0,0 +1,197 @@
1
+ function test(name, fn){
2
+ expected = -1;
3
+ numTests = 0;
4
+ reset();
5
+
6
+ fn();
7
+
8
+ if ( expected != -1 && expected != numTests )
9
+ log( false, "Wrong number of tests run. " + numTests + " ran, expected " + expected );
10
+ }
11
+
12
+ var orig = document.getElementById('main').innerHTML;
13
+
14
+ /**
15
+ * Resets the test setup. Useful for tests that modify the DOM.
16
+ */
17
+ function reset() {
18
+ document.getElementById('main').innerHTML = orig;
19
+ }
20
+
21
+ var currentModule = "";
22
+
23
+ // call on start of module test to prepend name to all tests
24
+ function module(moduleName) {
25
+ currentModule = moduleName;
26
+ }
27
+
28
+ var expected = -1;
29
+
30
+ /**
31
+ * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
32
+ */
33
+ function expect(asserts) {
34
+ expected = asserts;
35
+ }
36
+
37
+ /**
38
+ * Asserts true.
39
+ * @example ok( $("a").size() > 5, "There must be at least 5 anchors" );
40
+ */
41
+ function ok(a, msg) {
42
+ log( !!a, msg );
43
+ }
44
+
45
+ /**
46
+ * Asserts that two arrays are the same
47
+ */
48
+ function isSet(a, b, msg) {
49
+ var ret = true;
50
+ if ( a && b && a.length != undefined && a.length == b.length ) {
51
+ for ( var i = 0; i < a.length; i++ ) {
52
+ if ( a[i] != b[i] )
53
+ ret = false;
54
+ }
55
+ } else
56
+ ret = false;
57
+ if ( !ret )
58
+ log( ret, msg + " expected: " + serialArray(b) + " result: " + serialArray(a) );
59
+ else
60
+ log( ret, msg );
61
+ }
62
+
63
+ /**
64
+ * Asserts that two objects are equivalent
65
+ */
66
+ function isObj(a, b, msg) {
67
+ var ret = true;
68
+
69
+ if ( a && b ) {
70
+ for ( var i in a )
71
+ if ( a[i] != b[i] )
72
+ ret = false;
73
+
74
+ for ( i in b )
75
+ if ( a[i] != b[i] )
76
+ ret = false;
77
+ } else
78
+ ret = false;
79
+
80
+ log( ret, msg );
81
+ }
82
+
83
+ function serialArray( a ) {
84
+ var r = [];
85
+
86
+ if ( a && a.length )
87
+ for ( var i = 0; i < a.length; i++ ) {
88
+ var str = a[i] ? a[i].nodeName : "";
89
+ if ( str ) {
90
+ str = str.toLowerCase();
91
+ if ( a[i].id )
92
+ str += "#" + a[i].id;
93
+ } else
94
+ str = a[i];
95
+ r.push( str );
96
+ }
97
+
98
+ return "[ " + r.join(", ") + " ]"
99
+ }
100
+
101
+ /**
102
+ * Returns an array of elements with the given IDs, eg.
103
+ * @example q("main", "foo", "bar")
104
+ * @result [<div id="main">, <span id="foo">, <input id="bar">]
105
+ */
106
+ function q() {
107
+ var r = [];
108
+ for ( var i = 0; i < arguments.length; i++ )
109
+ r.push( document.getElementById( arguments[i] ) );
110
+ return r;
111
+ }
112
+
113
+ /**
114
+ * Asserts that a select matches the given IDs
115
+ * @example t("Check for something", "//[a]", ["foo", "baar"]);
116
+ * @result returns true if "//[a]" return two elements with the IDs 'foo' and 'baar'
117
+ */
118
+ function t(a,b,c) {
119
+ var f = jQuery(b);
120
+ var s = "";
121
+ for ( var i = 0; i < f.length; i++ )
122
+ s += (s && ",") + '"' + f[i].id + '"';
123
+ isSet(f, q.apply(q,c), a + " (" + b + ")");
124
+ }
125
+
126
+ /**
127
+ * Checks that the first two arguments are equal, with an optional message.
128
+ * Prints out both expected and actual values on failure.
129
+ *
130
+ * Prefered to ok( expected == actual, message )
131
+ *
132
+ * @example equals( "Expected 2 characters.", v.formatMessage("Expected {0} characters.", 2) );
133
+ *
134
+ * @param Object expected
135
+ * @param Object actual
136
+ * @param String message (optional)
137
+ */
138
+ function equals(expected, actual, message) {
139
+ var result = expected == actual;
140
+ message = message || (result ? "okay" : "failed");
141
+ log( result, result ? message + ": " + expected : message + " expected: " + expected + " actual: " + actual );
142
+ }
143
+
144
+ var numTests = 0, total = 0, pass = 0, fail = 0;
145
+
146
+ function log(state, msg){
147
+ print( (state ? "PASS" : "FAIL") + " (" + (++total) + ") " +
148
+ (currentModule ? "[" + currentModule + "] " : "") + msg );
149
+
150
+ numTests++;
151
+
152
+ if ( state )
153
+ pass++;
154
+ else
155
+ fail++;
156
+ }
157
+
158
+ function results(){
159
+ print( pass + " Passed, " + fail + " Failed" );
160
+ }
161
+
162
+ function start(){}
163
+ function stop(){}
164
+
165
+ /**
166
+ * Trigger an event on an element.
167
+ *
168
+ * @example triggerEvent( document.body, "click" );
169
+ *
170
+ * @param DOMElement elem
171
+ * @param String type
172
+ */
173
+ function triggerEvent( elem, type, event ) {
174
+ /*
175
+ if ( jQuery.browser.mozilla || jQuery.browser.opera ) {
176
+ event = document.createEvent("MouseEvents");
177
+ event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
178
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
179
+ elem.dispatchEvent( event );
180
+ } else if ( jQuery.browser.msie ) {
181
+ elem.fireEvent("on"+type);
182
+ }
183
+ */
184
+ }
185
+
186
+ /**
187
+ * Add random number to url to stop IE from caching
188
+ *
189
+ * @example url("data/test.html")
190
+ * @result "data/test.html?10538358428943"
191
+ *
192
+ * @example url("data/test.php?foo=bar")
193
+ * @result "data/test.php?foo=bar&10538358345554"
194
+ */
195
+ function url(value) {
196
+ return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000);
197
+ }