headless-squirrel 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. data/README.rdoc +55 -0
  2. data/Rakefile +27 -0
  3. data/bin/jstest +10 -0
  4. data/lib/headless_squirrel.rb +2 -0
  5. data/lib/headless_squirrel/console.rb +24 -0
  6. data/lib/headless_squirrel/runner.rb +70 -0
  7. data/lib/headless_squirrel/test.rb +17 -0
  8. data/lib/headless_squirrel/test_case.rb +158 -0
  9. data/test/fixtures/a_unit_test.html +27 -0
  10. data/test/fixtures/a_unit_test.js +22 -0
  11. data/test/fixtures/syntax_error.html +27 -0
  12. data/test/fixtures/syntax_error.js +5 -0
  13. data/test/fixtures/type_error.html +27 -0
  14. data/test/fixtures/type_error.js +1 -0
  15. data/test/regression/prototype/unit/ajax_test.html +29 -0
  16. data/test/regression/prototype/unit/array_test.html +28 -0
  17. data/test/regression/prototype/unit/assets/prototype.js +4900 -0
  18. data/test/regression/prototype/unit/assets/unittest.css +50 -0
  19. data/test/regression/prototype/unit/assets/unittest.js +615 -0
  20. data/test/regression/prototype/unit/assets/unittest_transport.js +1 -0
  21. data/test/regression/prototype/unit/base_test.html +27 -0
  22. data/test/regression/prototype/unit/class_test.html +27 -0
  23. data/test/regression/prototype/unit/date_test.html +27 -0
  24. data/test/regression/prototype/unit/dom_test.html +304 -0
  25. data/test/regression/prototype/unit/element_mixins_test.html +30 -0
  26. data/test/regression/prototype/unit/enumerable_test.html +35 -0
  27. data/test/regression/prototype/unit/event_test.html +31 -0
  28. data/test/regression/prototype/unit/fixtures/ajax.html +2 -0
  29. data/test/regression/prototype/unit/fixtures/ajax.js +42 -0
  30. data/test/regression/prototype/unit/fixtures/array.html +1 -0
  31. data/test/regression/prototype/unit/fixtures/class.js +83 -0
  32. data/test/regression/prototype/unit/fixtures/content.html +1 -0
  33. data/test/regression/prototype/unit/fixtures/data.json +1 -0
  34. data/test/regression/prototype/unit/fixtures/dom.css +84 -0
  35. data/test/regression/prototype/unit/fixtures/dom.html +278 -0
  36. data/test/regression/prototype/unit/fixtures/dom.js +17 -0
  37. data/test/regression/prototype/unit/fixtures/element_mixins.html +4 -0
  38. data/test/regression/prototype/unit/fixtures/element_mixins.js +2 -0
  39. data/test/regression/prototype/unit/fixtures/empty.html +0 -0
  40. data/test/regression/prototype/unit/fixtures/empty.js +1 -0
  41. data/test/regression/prototype/unit/fixtures/enumerable.html +8 -0
  42. data/test/regression/prototype/unit/fixtures/enumerable.js +23 -0
  43. data/test/regression/prototype/unit/fixtures/event.html +4 -0
  44. data/test/regression/prototype/unit/fixtures/form.html +108 -0
  45. data/test/regression/prototype/unit/fixtures/function.js +13 -0
  46. data/test/regression/prototype/unit/fixtures/hash.js +25 -0
  47. data/test/regression/prototype/unit/fixtures/hello.js +1 -0
  48. data/test/regression/prototype/unit/fixtures/logo.gif +0 -0
  49. data/test/regression/prototype/unit/fixtures/object.html +6 -0
  50. data/test/regression/prototype/unit/fixtures/object.js +7 -0
  51. data/test/regression/prototype/unit/fixtures/position.html +9 -0
  52. data/test/regression/prototype/unit/fixtures/selector.html +71 -0
  53. data/test/regression/prototype/unit/fixtures/string.js +8 -0
  54. data/test/regression/prototype/unit/fixtures/unittest.html +18 -0
  55. data/test/regression/prototype/unit/form_test.html +135 -0
  56. data/test/regression/prototype/unit/function_test.html +27 -0
  57. data/test/regression/prototype/unit/hash_test.html +27 -0
  58. data/test/regression/prototype/unit/number_test.html +27 -0
  59. data/test/regression/prototype/unit/object_test.html +32 -0
  60. data/test/regression/prototype/unit/periodical_executer_test.html +27 -0
  61. data/test/regression/prototype/unit/position_test.html +36 -0
  62. data/test/regression/prototype/unit/prototype_test.html +27 -0
  63. data/test/regression/prototype/unit/range_test.html +27 -0
  64. data/test/regression/prototype/unit/regexp_test.html +27 -0
  65. data/test/regression/prototype/unit/selector_test.html +98 -0
  66. data/test/regression/prototype/unit/string_test.html +27 -0
  67. data/test/regression/prototype/unit/tests/ajax_test.js +379 -0
  68. data/test/regression/prototype/unit/tests/array_test.js +186 -0
  69. data/test/regression/prototype/unit/tests/base_test.js +43 -0
  70. data/test/regression/prototype/unit/tests/class_test.js +136 -0
  71. data/test/regression/prototype/unit/tests/date_test.js +5 -0
  72. data/test/regression/prototype/unit/tests/dom_test.js +1493 -0
  73. data/test/regression/prototype/unit/tests/element_mixins_test.js +32 -0
  74. data/test/regression/prototype/unit/tests/enumerable_test.js +271 -0
  75. data/test/regression/prototype/unit/tests/event_test.js +235 -0
  76. data/test/regression/prototype/unit/tests/form_test.js +382 -0
  77. data/test/regression/prototype/unit/tests/function_test.js +133 -0
  78. data/test/regression/prototype/unit/tests/hash_test.js +178 -0
  79. data/test/regression/prototype/unit/tests/number_test.js +44 -0
  80. data/test/regression/prototype/unit/tests/object_test.js +180 -0
  81. data/test/regression/prototype/unit/tests/periodical_executer_test.js +15 -0
  82. data/test/regression/prototype/unit/tests/position_test.js +44 -0
  83. data/test/regression/prototype/unit/tests/prototype_test.js +43 -0
  84. data/test/regression/prototype/unit/tests/range_test.js +58 -0
  85. data/test/regression/prototype/unit/tests/regexp_test.js +42 -0
  86. data/test/regression/prototype/unit/tests/selector_test.js +408 -0
  87. data/test/regression/prototype/unit/tests/string_test.js +548 -0
  88. data/test/regression/prototype/unit/tests/unittest_test.js +148 -0
  89. data/test/regression/prototype/unit/unittest_test.html +45 -0
  90. data/test/regression/prototype/upstream +1 -0
  91. data/test/regression/scriptaculous/unit/_ajax_inplaceeditor_ipce_alt_text.html +1 -0
  92. data/test/regression/scriptaculous/unit/_ajax_inplaceeditor_ipce_collection.js +1 -0
  93. data/test/regression/scriptaculous/unit/_ajax_inplaceeditor_result.html +1 -0
  94. data/test/regression/scriptaculous/unit/_ajax_inplaceeditor_result2.html +1 -0
  95. data/test/regression/scriptaculous/unit/_ajax_inplaceeditor_tagged.html +1 -0
  96. data/test/regression/scriptaculous/unit/_ajax_inplaceeditor_text.html +1 -0
  97. data/test/regression/scriptaculous/unit/_ajax_updater_result.html +20 -0
  98. data/test/regression/scriptaculous/unit/_autocomplete_result.html +11 -0
  99. data/test/regression/scriptaculous/unit/_autocomplete_result_nobr.html +1 -0
  100. data/test/regression/scriptaculous/unit/ajax_autocompleter_test.html +243 -0
  101. data/test/regression/scriptaculous/unit/ajax_inplaceeditor_test.html +895 -0
  102. data/test/regression/scriptaculous/unit/assets/builder.js +134 -0
  103. data/test/regression/scriptaculous/unit/assets/controls.js +963 -0
  104. data/test/regression/scriptaculous/unit/assets/dragdrop.js +973 -0
  105. data/test/regression/scriptaculous/unit/assets/effects.js +1122 -0
  106. data/test/regression/scriptaculous/unit/assets/javascripttest.rb +203 -0
  107. data/test/regression/scriptaculous/unit/assets/prototype.js +4320 -0
  108. data/test/regression/scriptaculous/unit/assets/scriptaculous.js +66 -0
  109. data/test/regression/scriptaculous/unit/assets/slider.js +273 -0
  110. data/test/regression/scriptaculous/unit/assets/sound.js +57 -0
  111. data/test/regression/scriptaculous/unit/assets/unittest.js +566 -0
  112. data/test/regression/scriptaculous/unit/bdd_test.html +150 -0
  113. data/test/regression/scriptaculous/unit/builder_test.html +262 -0
  114. data/test/regression/scriptaculous/unit/dragdrop_test.html +131 -0
  115. data/test/regression/scriptaculous/unit/effects_test.html +547 -0
  116. data/test/regression/scriptaculous/unit/element_test.html +116 -0
  117. data/test/regression/scriptaculous/unit/icon.png +0 -0
  118. data/test/regression/scriptaculous/unit/index.html +70 -0
  119. data/test/regression/scriptaculous/unit/loading_test.html +41 -0
  120. data/test/regression/scriptaculous/unit/position_clone_test.html +312 -0
  121. data/test/regression/scriptaculous/unit/slider_test.html +437 -0
  122. data/test/regression/scriptaculous/unit/sortable_test.html +205 -0
  123. data/test/regression/scriptaculous/unit/string_test.html +71 -0
  124. data/test/regression/scriptaculous/unit/unittest_test.html +154 -0
  125. data/test/regression/scriptaculous/upstream +1 -0
  126. data/test/test_helper.rb +20 -0
  127. data/test/unit/runner_test.rb +165 -0
  128. data/test/unit/test_case_test.rb +207 -0
  129. data/test/unit/test_test.rb +24 -0
  130. metadata +209 -0
@@ -0,0 +1,71 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <title>script.aculo.us Unit test file</title>
6
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7
+ <script src="assets/prototype.js" type="text/javascript"></script>
8
+ <script src="assets/scriptaculous.js" type="text/javascript"></script>
9
+ <script src="assets/unittest.js" type="text/javascript"></script>
10
+ <link rel="stylesheet" href="../test.css" type="text/css" />
11
+ </head>
12
+ <body>
13
+ <h1>script.aculo.us Unit test file</h1>
14
+ <p>
15
+ Tests for String.prototype extensions in effects.js
16
+ </p>
17
+
18
+ <!-- Log output -->
19
+ <div id="testlog"> </div>
20
+
21
+ <!-- Tests follow -->
22
+ <script type="text/javascript" language="javascript" charset="utf-8">
23
+ // <![CDATA[
24
+
25
+ new Test.Unit.Runner({
26
+
27
+ testStringParseColor: function() { with(this) {
28
+ assertEqual('#000000', "#000000".parseColor());
29
+ assertEqual('#000000', "rgb(0,0,0)".parseColor());
30
+ assertEqual('#000000', "rgb(0, 0, 0)".parseColor());
31
+ assertEqual('#000000', "#000".parseColor());
32
+
33
+ assertEqual('#1', "#1".parseColor());
34
+ assertEqual('#12', "#12".parseColor());
35
+ assertEqual('#112233', "#123".parseColor());
36
+ assertEqual('#1234', "#1234".parseColor());
37
+ assertEqual('#12345', "#12345".parseColor());
38
+ assertEqual('#123456', "#123456".parseColor());
39
+
40
+ assertEqual('#abcdef', "#aBcDeF".parseColor());
41
+ assertEqual('#aabbcc', "#aBc".parseColor());
42
+
43
+ assertEqual('white', "white".parseColor());
44
+ assertEqual('#123456', "#123456".parseColor('#000000')); // default to #000000 if not parseable
45
+ assertEqual('#000000', "white".parseColor('#000000')); // default to #000000 if not parseable
46
+
47
+ assertEqual('#ffffff', "rgb(255,255,255)".parseColor());
48
+ assertEqual('#ff0000', "rgb(255,0,0)".parseColor());
49
+ assertEqual('#00ff00', "rgb(0,255,0)".parseColor());
50
+ assertEqual('#0000ff', "rgb(0,0,255)".parseColor());
51
+ }},
52
+
53
+ testStringParseStyle: function() { with(this) {
54
+ var expected = "#<Hash:{'fontSize': '11px'}>";
55
+ var expectedMultiple = "#<Hash:{'fontSize': '11px', 'width': '780px'}>";
56
+
57
+ assertInspect(expected, "font-size:11px".parseStyle());
58
+ assertInspect(expected, "font-SIZE: 11px".parseStyle());
59
+ assertInspect(expected, "font-size:11px ".parseStyle());
60
+ assertInspect(expected, " Font-size: 11px ".parseStyle());
61
+
62
+ assertInspect(expectedMultiple, " font-size: 11px;width:780px".parseStyle());
63
+
64
+ }}
65
+
66
+ });
67
+
68
+ // ]]>
69
+ </script>
70
+ </body>
71
+ </html>
@@ -0,0 +1,154 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <title>script.aculo.us Unit test file</title>
6
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7
+ <script src="assets/prototype.js" type="text/javascript"></script>
8
+ <script src="assets/scriptaculous.js" type="text/javascript"></script>
9
+ <script src="assets/unittest.js" type="text/javascript"></script>
10
+ <link rel="stylesheet" href="../test.css" type="text/css" />
11
+ <style type="text/css" media="screen">
12
+ /* <![CDATA[ */
13
+ #testcss1 { font-size:11px; color: #f00; }
14
+ #testcss2 { font-size:12px; color: #0f0; display: none; }
15
+ /* ]]> */
16
+ </style>
17
+ </head>
18
+ <body>
19
+ <h1>script.aculo.us Unit test file</h1>
20
+ <p>
21
+ This is a preliminary version mostly for testing the unittest library.
22
+ </p>
23
+
24
+ <!-- Log output -->
25
+ <div id="testlog"> </div>
26
+
27
+ <!-- Test elements follow -->
28
+ <div id="test_1" class="a bbbbbbbbbbbb cccccccccc dddd"> </div>
29
+
30
+ <div id="test_2"> <span> </span>
31
+
32
+
33
+
34
+ <div><div></div> </div><span> </span>
35
+ </div>
36
+
37
+ <ul id="tlist"><li id="tlist_1">x1</li><li id="tlist_2">x2</li></ul>
38
+ <ul id="tlist2"><li class="a" id="tlist2_1">x1</li><li id="tlist2_2">x2</li></ul>
39
+
40
+ <div id="testmoveby" style="background-color:#333;width:100px;">XXXX</div>
41
+
42
+ <div id="testcss1">testcss1<span id="testcss1_span" style="display:none;">blah</span></div><div id="testcss2">testcss1</div>
43
+
44
+ <!-- Tests follow -->
45
+ <script type="text/javascript" language="javascript" charset="utf-8">
46
+ // <![CDATA[
47
+
48
+ var testObj = {
49
+ isNice: function(){
50
+ return true;
51
+ },
52
+ isBroken: function(){
53
+ return false;
54
+ }
55
+ }
56
+
57
+ new Test.Unit.Runner({
58
+
59
+ testAssertEqual: function() { with(this) {
60
+ assertEqual(0, 0);
61
+ assertEqual(0, 0, "test");
62
+
63
+ assertEqual(0,'0');
64
+ assertEqual(65.0, 65);
65
+
66
+ assertEqual("a", "a");
67
+ assertEqual("a", "a", "test");
68
+
69
+ assertNotEqual(0, 1);
70
+ assertNotEqual("a","b");
71
+ assertNotEqual({},{});
72
+ assertNotEqual([],[]);
73
+ assertNotEqual([],{});
74
+ }},
75
+
76
+ testAssertRespondsTo: function() { with(this) {
77
+ assertRespondsTo('isNice', testObj);
78
+ assertRespondsTo('isBroken', testObj);
79
+ }},
80
+
81
+ testAssertIndentical: function() { with(this) {
82
+ assertIdentical(0, 0);
83
+ assertIdentical(0, 0, "test");
84
+ assertIdentical(1, 1);
85
+ assertIdentical('a', 'a');
86
+ assertIdentical('a', 'a', "test");
87
+ assertIdentical('', '');
88
+ assertIdentical(undefined, undefined);
89
+ assertIdentical(null, null);
90
+ assertIdentical(true, true);
91
+ assertIdentical(false, false);
92
+
93
+ var obj = {a:'b'};
94
+ assertIdentical(obj, obj);
95
+
96
+ assertNotIdentical({1:2,3:4},{1:2,3:4});
97
+
98
+ assertIdentical(1, 1.0); // both are typeof == 'number'
99
+
100
+ assertNotIdentical(1, '1');
101
+ assertNotIdentical(1, '1.0');
102
+ }},
103
+
104
+ testAssertMatch: function() { with(this) {
105
+ assertMatch(/knowmad.jpg$/, 'http://script.aculo.us/images/knowmad.jpg');
106
+ assertMatch(/Fuc/, 'Thomas Fuchs');
107
+ assertMatch(/^\$(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/, '$19.95');
108
+ assertMatch(/(\d{3}\) ?)|(\d{3}[- \.])?\d{3}[- \.]\d{4}(\s(x\d+)?){0,1}$/, '704-343-9330');
109
+ assertMatch(/^(?:(?:(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\/|-|\.)(?:0?2\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\d)?\d{2})(\/|-|\.)(?:(?:(?:0?[13578]|1[02])\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\2(?:0?[1-9]|1\d|2[0-8]))))$/, '2001-06-16');
110
+ assertMatch(/^((0?[123456789])|(1[012]))\s*:\s*([012345]\d)(\s*:\s*([012345]\d))?\s*[ap]m\s*-\s*((0?[123456789])|(1[012]))\s*:\s*([012345]\d)(\s*:\s*([012345]\d))?\s*[ap]m$/i, '2:00PM-2:15PM');
111
+
112
+ }},
113
+
114
+ testAssertInstanceOf: function() { with(this) {
115
+ assertInstanceOf(Effect.Opacity, new Effect.Opacity('testcss1',{sync:true}));
116
+ assertNotInstanceOf(String, new Effect.Opacity('testcss1',{sync:true}));
117
+
118
+ // note: fails with firefox 1.0.X (bug, fixed in Deer Park)
119
+ assertNotInstanceOf(Effect.Parallel, new Effect.Opacity('testcss1',{sync:true}), "(note: fails with firefox 1.0.X, fixed in Deer Park)");
120
+ }},
121
+
122
+ testAssertReturns: function() { with(this) {
123
+
124
+ assertReturnsTrue('isNice',testObj);
125
+ assertReturnsFalse('isBroken',testObj);
126
+
127
+ assertReturnsTrue('nice',testObj);
128
+ assertReturnsFalse('broken',testObj);
129
+
130
+ }},
131
+
132
+ testAssertVisible: function() { with(this) {
133
+ assertVisible('testcss1');
134
+ assertNotVisible('testcss1_span');
135
+ assertNotVisible('testcss2', "Due to a Safari bug, this test fails in Safari.");
136
+
137
+ Element.hide('testcss1');
138
+ assertNotVisible('testcss1');
139
+ assertNotVisible('testcss1_span');
140
+ Element.show('testcss1');
141
+ assertVisible('testcss1');
142
+ assertNotVisible('testcss1_span');
143
+
144
+ Element.show('testcss1_span');
145
+ assertVisible('testcss1_span');
146
+ Element.hide('testcss1');
147
+ assertNotVisible('testcss1_span'); // hidden by parent
148
+ }}
149
+
150
+ }, "testlog");
151
+ // ]]>
152
+ </script>
153
+ </body>
154
+ </html>
@@ -0,0 +1 @@
1
+ 4b49fd8884920d4ee760b0194431f4f433f878df
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'test/spec'
3
+ require 'mocha'
4
+
5
+ $:.unshift File.expand_path('../../lib', __FILE__)
6
+ require 'headless_squirrel'
7
+
8
+ FIXTURES = File.expand_path('../fixtures', __FILE__)
9
+
10
+ module TestHelper
11
+ def fixture(name)
12
+ File.join(FIXTURES, name)
13
+ end
14
+ end
15
+
16
+ Test::Unit::TestCase.send(:include, TestHelper)
17
+
18
+ Thread.new do
19
+ OSX::NSApplication.sharedApplication.run
20
+ end
@@ -0,0 +1,165 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module RunnerTestHelper
4
+ def setup
5
+ files = [fixture('a_unit_test.html'), fixture('a_unit_test.html')]
6
+ @runner = HeadlessSquirrel::Runner.alloc.initWithHTMLFiles(files)
7
+
8
+ @runner.stubs(:puts)
9
+ @runner.stubs(:print)
10
+ @runner.test_cases.first.stubs(:run)
11
+ @runner.test_cases.last.stubs(:run)
12
+
13
+ OSX::NSApplication.sharedApplication.stubs(:run)
14
+ OSX::NSApplication.sharedApplication.stubs(:terminate)
15
+ end
16
+
17
+ private
18
+
19
+ def test_stub(name)
20
+ test_case = HeadlessSquirrel::TestCase.alloc.initWithHTMLFile_delegate(fixture('a_unit_test.html'), stub_everything)
21
+ test_case.stubs(:title).returns("A test case with #{name}")
22
+ HeadlessSquirrel::TestCase::Test.new(test_case, name.to_s, name.to_sym, name.to_s)
23
+ end
24
+ end
25
+
26
+ describe "HeadlessSquirrel::Runner" do
27
+ include RunnerTestHelper
28
+
29
+ it "should have instantiated a HeadlessSquirrel::TestCase for each html file" do
30
+ @runner.test_cases.length.should == 2
31
+ @runner.test_cases.each do |test_case|
32
+ test_case.html_file.should == fixture('a_unit_test.html')
33
+ test_case.delegate.should == @runner
34
+ end
35
+ end
36
+
37
+ it "should not have finished yet" do
38
+ @runner.should.not.be.finished
39
+ end
40
+
41
+ it "should return the total amount of tests" do
42
+ @runner.test_cases.each { |tc| tc.stubs(:tests).returns(3) }
43
+ @runner.tests.should == 6
44
+ end
45
+
46
+ it "should return the total amount of assertions" do
47
+ @runner.test_cases.each { |tc| tc.stubs(:assertions).returns(2) }
48
+ @runner.assertions.should == 4
49
+ end
50
+
51
+ it "should return the total amount of failures" do
52
+ @runner.test_cases.each { |tc| tc.stubs(:failures).returns(1) }
53
+ @runner.failures.should == 2
54
+ end
55
+
56
+ it "should return the total amount of errors" do
57
+ @runner.test_cases.each { |tc| tc.stubs(:errors).returns(1) }
58
+ @runner.errors.should == 2
59
+ end
60
+
61
+ it "should run the tests cases and start a runloop" do
62
+ @runner.test_cases.first.expects(:run)
63
+ @runner.run
64
+ end
65
+
66
+ it "should start a runloop when running the tests" do
67
+ OSX::NSApplication.sharedApplication.expects(:run)
68
+ @runner.run
69
+ end
70
+
71
+ it "should store the start time" do
72
+ time = Time.now
73
+ Time.stubs(:now).returns(time)
74
+
75
+ @runner.run
76
+ @runner.instance_variable_get(:@start_time).should == time
77
+ end
78
+
79
+ it "should keep a `queued' stack which contains all test cases that are running" do
80
+ @runner.run
81
+ @runner.queued.should == @runner.test_cases
82
+ end
83
+
84
+ it "should remove a finished test case from the `queued' stack" do
85
+ @runner.run
86
+ @runner.test_case_finished(@runner.test_cases.first)
87
+ @runner.queued.should == [@runner.test_cases.last]
88
+ end
89
+
90
+ it "should have finished once the `queued' stack is empty" do
91
+ @runner.run
92
+ @runner.test_case_finished(@runner.test_cases.first)
93
+ @runner.test_case_finished(@runner.test_cases.last)
94
+ @runner.should.be.finished
95
+ end
96
+
97
+ it "should return tests that have ran but didn't pass" do
98
+ test_case = stub(:title => 'A test case')
99
+
100
+ @runner.test_ran(test_stub(:passed))
101
+ @runner.test_ran(test_stub(:failed))
102
+ @runner.test_ran(test_stub(:error))
103
+
104
+ @runner.did_not_pass.first.name.should == 'failed'
105
+ @runner.did_not_pass.last.name.should == 'error'
106
+ end
107
+
108
+ it "should print a dot when a test ran and passed" do
109
+ @runner.expects(:print).with('.')
110
+ @runner.test_ran(test_stub(:passed))
111
+ end
112
+
113
+ it "should print a F when a test ran and failed" do
114
+ @runner.expects(:print).with('F')
115
+ @runner.test_ran(test_stub(:failed))
116
+ end
117
+
118
+ it "should print an E when a test ran and an error occured" do
119
+ @runner.expects(:print).with('E')
120
+ @runner.test_ran(test_stub(:error))
121
+ end
122
+ end
123
+
124
+ describe "HeadlessSquirrel::Runner, when finalizing" do
125
+ include RunnerTestHelper
126
+
127
+ def setup
128
+ super
129
+ time = Time.now
130
+ @runner.instance_variable_set(:@start_time, time)
131
+ Time.stubs(:now).returns(time + 2.3)
132
+ end
133
+
134
+ it "should print the tests that did not pass" do
135
+ test1, test2 = test_stub(:failed), test_stub(:error)
136
+ @runner.test_ran(test1)
137
+ @runner.test_ran(test2)
138
+
139
+ @runner.expects(:puts).with("\n 1) #{test1}")
140
+ @runner.expects(:puts).with("\n 2) #{test2}")
141
+ @runner.send(:finalize)
142
+ end
143
+
144
+ it "should print the time it took to run the tests" do
145
+ @runner.expects(:puts).with("Finished in 2.3 seconds.")
146
+ @runner.send(:finalize)
147
+ end
148
+
149
+ it "should print the total amount of tests, assertions, failures, and errors that have been ran" do
150
+ @runner.test_cases.each do |tc|
151
+ tc.stubs(:tests).returns(3)
152
+ tc.stubs(:assertions).returns(2)
153
+ tc.stubs(:failures).returns(1)
154
+ tc.stubs(:errors).returns(1)
155
+ end
156
+
157
+ @runner.expects(:puts).with("\n6 tests, 4 assertions, 2 failures, 2 errors")
158
+ @runner.send(:finalize)
159
+ end
160
+
161
+ it "should terminate the application" do
162
+ OSX::NSApplication.sharedApplication.expects(:terminate).with(@runner)
163
+ @runner.send(:finalize)
164
+ end
165
+ end
@@ -0,0 +1,207 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module TestCaseHelper
4
+ def run_test_case!
5
+ @test_case.run
6
+ sleep 0.25 while not @test_case.finished?
7
+ end
8
+ end
9
+
10
+ describe "HeadlessSquirrel::TestCase, class methods" do
11
+ it "should return a shared WebView instance" do
12
+ HeadlessSquirrel::TestCase.sharedWebView.should.be.instance_of OSX::WebView
13
+ end
14
+ end
15
+
16
+ describe "HeadlessSquirrel::TestCase" do
17
+ before do
18
+ @delegate = stub_everything('delegate')
19
+ @test_case = HeadlessSquirrel::TestCase.alloc.initWithHTMLFile_delegate(fixture('a_unit_test.html'), @delegate)
20
+ end
21
+
22
+ it "should initialize with a html file and delegate" do
23
+ @test_case.html_file.should == fixture('a_unit_test.html')
24
+ @test_case.delegate.should == @delegate
25
+ end
26
+
27
+ it "should raise a FileDoesNotExistError if the given html file does not exist" do
28
+ lambda {
29
+ HeadlessSquirrel::TestCase.alloc.initWithHTMLFile_delegate('/does/not/exist/test.html', @delegate)
30
+ }.should.raise HeadlessSquirrel::TestCase::FileDoesNotExistError
31
+ end
32
+
33
+ it "should instantiate a WebView with the html file and set itself as the frameLoadDelegate" do
34
+ @test_case.webView.should == HeadlessSquirrel::TestCase.sharedWebView
35
+ @test_case.webView.mainFrameURL.should == "file://#{fixture('a_unit_test.html')}"
36
+ @test_case.webView.frameLoadDelegate.should == @test_case
37
+ end
38
+
39
+ it "should not have finished yet" do
40
+ @test_case.should.not.be.finished
41
+ end
42
+
43
+ it "should have set tests, assertions, failures, and errors to zero" do
44
+ @test_case.tests.should == 0
45
+ @test_case.assertions.should == 0
46
+ @test_case.failures.should == 0
47
+ @test_case.errors.should == 0
48
+ end
49
+
50
+ it "should run the tests" do
51
+ @test_case.expects(:webView)
52
+ @test_case.run
53
+ end
54
+ end
55
+
56
+ describe "HeadlessSquirrel::TestCase, when running" do
57
+ include TestCaseHelper
58
+
59
+ before do
60
+ @delegate = stub_everything('delegate')
61
+ @test_case = HeadlessSquirrel::TestCase.alloc.initWithHTMLFile_delegate(fixture('a_unit_test.html'), @delegate)
62
+ run_test_case!
63
+ end
64
+
65
+ it "should return the DOM document" do
66
+ @test_case.document.should.be.instance_of OSX::DOMHTMLDocument
67
+ end
68
+
69
+ it "should have stored the document title" do
70
+ @test_case.title.should == 'A HeadlessSquirrel Unit Test HTML File'
71
+ @test_case.instance_variable_get(:@title).should == 'A HeadlessSquirrel Unit Test HTML File'
72
+ end
73
+
74
+ it "should return the `log' element" do
75
+ @test_case.log.should.be.instance_of OSX::DOMHTMLDivElement
76
+ @test_case.log.className.should == 'logsummary'
77
+ end
78
+
79
+ it "should return the `loglines' element" do
80
+ @test_case.loglines.should.be.instance_of OSX::DOMHTMLTableSectionElement
81
+ @test_case.loglines.className.should == 'loglines'
82
+ end
83
+
84
+ it "should register itself as an event handler for DOMSubtreeModified events on the `log' and `loglines' element" do
85
+ @test_case.log.expects(:addEventListener___).with('DOMSubtreeModified', @test_case, true)
86
+ @test_case.loglines.expects(:addEventListener___).with('DOMSubtreeModified', @test_case, true)
87
+ @test_case.webView_didFinishLoadForFrame(nil, nil)
88
+ end
89
+
90
+ it "should have finished once the inner html of the `log' element is not longer `running...'" do
91
+ @test_case.instance_variable_set(:@finished, nil)
92
+ @test_case.handleEvent(stubbed_log_event)
93
+ @test_case.should.be.finished
94
+ end
95
+
96
+ it "should return the number of tests, assertions, failures, and errors" do
97
+ @test_case.tests.should == 3
98
+ @test_case.assertions.should == 2
99
+ @test_case.failures.should == 1
100
+ @test_case.errors.should == 1
101
+ end
102
+
103
+ it "should let its delegate know its finished running" do
104
+ @delegate.expects(:test_case_finished).with(@test_case)
105
+ @test_case.handleEvent(stubbed_log_event)
106
+ end
107
+
108
+ it "should not let its delegate know a test ran if the targets class is not one of passed, failed, or error" do
109
+ @delegate.expects(:test_ran).never
110
+ event = stubbed_loglines_event('passed')
111
+
112
+ event.target.parentNode.stubs(:className).returns('')
113
+ @test_case.handleEvent(event)
114
+
115
+ event.target.parentNode.stubs(:className).returns('foo')
116
+ @test_case.handleEvent(event)
117
+ end
118
+
119
+ it "should not let its delegate know a test ran if the output is still empty" do
120
+ @delegate.expects(:test_ran).never
121
+ String.any_instance.stubs(:sub).returns('')
122
+ @test_case.handleEvent(stubbed_loglines_event('failed'))
123
+ end
124
+
125
+ xit "should let its delegate know a test ran if the targets class is one of passed, failed, or error" do
126
+ @test_case = HeadlessSquirrel::TestCase.alloc.initWithHTMLFile_delegate(fixture('a_unit_test.html'), @delegate)
127
+
128
+ @delegate.expects(:test_ran).times(3).with do |test|
129
+ test.name.should == case test.state
130
+ when :passed
131
+ 'testHelloWorldSuccess'
132
+ when :failed
133
+ 'testHelloWorldFailure'
134
+ when :error
135
+ 'testHelloWorldError'
136
+ end
137
+
138
+ test.output.should == case test.state
139
+ when :passed
140
+ ""
141
+ when :failed
142
+ "Failure: assertEqual\nexpected: <'Hello world!'>, actual: <''>"
143
+ when :error
144
+ "TypeError: Value undefined (result of expression this.content.foo) is not object., error=(TypeError: Value undefined (result of expression this.content.foo) is not object.)"
145
+ end
146
+
147
+ true # for mocha
148
+ end
149
+
150
+ run_test_case!
151
+ end
152
+
153
+ private
154
+
155
+ def stubbed_log_event
156
+ stub('Event', :target => @test_case.log.firstChild)
157
+ end
158
+
159
+ def stubbed_loglines_event(klass)
160
+ element = @test_case.loglines.getElementsByClassName(klass).item(0).children.item(3)
161
+ element.stubs(:parentNode).returns(@test_case.loglines.getElementsByClassName(klass).item(0))
162
+ stub('Event', :target => element)
163
+ end
164
+ end
165
+
166
+ describe "HeadlessSquirrel::TestCase, when running a file with problems" do
167
+ include TestCaseHelper
168
+
169
+ before do
170
+ @delegate = stub_everything('delegate')
171
+ end
172
+
173
+ it "should warn and terminate if a syntax error was encountered in the JavaScript" do
174
+ OSX::NSApplication.sharedApplication.expects(:terminate)
175
+ message = message_printed_while_running('syntax_error.html')
176
+ message.should == "#{fixture('syntax_error.js')}:4: SyntaxError: Parse error"
177
+ end
178
+
179
+ it "should warn and terminate if a type error was raised from the JavaScript runtime" do
180
+ OSX::NSApplication.sharedApplication.expects(:terminate)
181
+ message = message_printed_while_running('type_error.html')
182
+ message.should == "#{fixture('type_error.js')}:1: TypeError: Result of expression 'this.doesNotExist' [undefined] is not a function."
183
+ end
184
+
185
+ it "should only warn if a message was logged which does not match the error regexp" do
186
+ @test_case = HeadlessSquirrel::TestCase.alloc.initWithHTMLFile_delegate(fixture('a_unit_test.html'), @delegate)
187
+ info = { 'message' => 'some other message', 'sourceURL' => 'file:///some/file.js', 'lineNumber' => '1' }
188
+
189
+ OSX::NSApplication.sharedApplication.expects(:terminate).never
190
+ @test_case.expects(:puts).with("/some/file.js:1: some other message")
191
+ @test_case.webView_addMessageToConsole(@test_case.webView, info)
192
+ end
193
+
194
+ private
195
+
196
+ def message_printed_while_running(fixture)
197
+ @test_case = HeadlessSquirrel::TestCase.alloc.initWithHTMLFile_delegate(fixture(fixture), @delegate)
198
+
199
+ def @test_case.puts(message)
200
+ @printed_message = message
201
+ @finished = true
202
+ end
203
+
204
+ run_test_case!
205
+ @test_case.instance_variable_get(:@printed_message)
206
+ end
207
+ end