headless-squirrel 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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