alloy-js-test-san 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/README.rdoc +83 -0
  2. data/Rakefile +27 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/jstest +10 -0
  5. data/lib/js_test_san/runner.rb +70 -0
  6. data/lib/js_test_san/test.rb +17 -0
  7. data/lib/js_test_san/test_case.rb +103 -0
  8. data/lib/js_test_san.rb +2 -0
  9. data/test/fixtures/a_unit_test.html +27 -0
  10. data/test/fixtures/a_unit_test.js +22 -0
  11. data/test/regression/prototype/unit/ajax_test.html +29 -0
  12. data/test/regression/prototype/unit/array_test.html +28 -0
  13. data/test/regression/prototype/unit/assets/prototype.js +4900 -0
  14. data/test/regression/prototype/unit/assets/unittest.css +50 -0
  15. data/test/regression/prototype/unit/assets/unittest.js +615 -0
  16. data/test/regression/prototype/unit/assets/unittest_transport.js +1 -0
  17. data/test/regression/prototype/unit/base_test.html +27 -0
  18. data/test/regression/prototype/unit/class_test.html +27 -0
  19. data/test/regression/prototype/unit/date_test.html +27 -0
  20. data/test/regression/prototype/unit/dom_test.html +304 -0
  21. data/test/regression/prototype/unit/element_mixins_test.html +30 -0
  22. data/test/regression/prototype/unit/enumerable_test.html +35 -0
  23. data/test/regression/prototype/unit/event_test.html +31 -0
  24. data/test/regression/prototype/unit/fixtures/ajax.html +2 -0
  25. data/test/regression/prototype/unit/fixtures/ajax.js +42 -0
  26. data/test/regression/prototype/unit/fixtures/array.html +1 -0
  27. data/test/regression/prototype/unit/fixtures/class.js +83 -0
  28. data/test/regression/prototype/unit/fixtures/content.html +1 -0
  29. data/test/regression/prototype/unit/fixtures/data.json +1 -0
  30. data/test/regression/prototype/unit/fixtures/dom.css +84 -0
  31. data/test/regression/prototype/unit/fixtures/dom.html +278 -0
  32. data/test/regression/prototype/unit/fixtures/dom.js +17 -0
  33. data/test/regression/prototype/unit/fixtures/element_mixins.html +4 -0
  34. data/test/regression/prototype/unit/fixtures/element_mixins.js +2 -0
  35. data/test/regression/prototype/unit/fixtures/empty.html +0 -0
  36. data/test/regression/prototype/unit/fixtures/empty.js +1 -0
  37. data/test/regression/prototype/unit/fixtures/enumerable.html +8 -0
  38. data/test/regression/prototype/unit/fixtures/enumerable.js +23 -0
  39. data/test/regression/prototype/unit/fixtures/event.html +4 -0
  40. data/test/regression/prototype/unit/fixtures/form.html +108 -0
  41. data/test/regression/prototype/unit/fixtures/function.js +13 -0
  42. data/test/regression/prototype/unit/fixtures/hash.js +25 -0
  43. data/test/regression/prototype/unit/fixtures/hello.js +1 -0
  44. data/test/regression/prototype/unit/fixtures/logo.gif +0 -0
  45. data/test/regression/prototype/unit/fixtures/object.html +6 -0
  46. data/test/regression/prototype/unit/fixtures/object.js +7 -0
  47. data/test/regression/prototype/unit/fixtures/position.html +9 -0
  48. data/test/regression/prototype/unit/fixtures/selector.html +71 -0
  49. data/test/regression/prototype/unit/fixtures/string.js +8 -0
  50. data/test/regression/prototype/unit/fixtures/unittest.html +18 -0
  51. data/test/regression/prototype/unit/form_test.html +135 -0
  52. data/test/regression/prototype/unit/function_test.html +27 -0
  53. data/test/regression/prototype/unit/hash_test.html +27 -0
  54. data/test/regression/prototype/unit/number_test.html +27 -0
  55. data/test/regression/prototype/unit/object_test.html +32 -0
  56. data/test/regression/prototype/unit/periodical_executer_test.html +27 -0
  57. data/test/regression/prototype/unit/position_test.html +36 -0
  58. data/test/regression/prototype/unit/prototype_test.html +27 -0
  59. data/test/regression/prototype/unit/range_test.html +27 -0
  60. data/test/regression/prototype/unit/regexp_test.html +27 -0
  61. data/test/regression/prototype/unit/selector_test.html +98 -0
  62. data/test/regression/prototype/unit/string_test.html +27 -0
  63. data/test/regression/prototype/unit/tests/ajax_test.js +379 -0
  64. data/test/regression/prototype/unit/tests/array_test.js +186 -0
  65. data/test/regression/prototype/unit/tests/base_test.js +43 -0
  66. data/test/regression/prototype/unit/tests/class_test.js +136 -0
  67. data/test/regression/prototype/unit/tests/date_test.js +5 -0
  68. data/test/regression/prototype/unit/tests/dom_test.js +1493 -0
  69. data/test/regression/prototype/unit/tests/element_mixins_test.js +32 -0
  70. data/test/regression/prototype/unit/tests/enumerable_test.js +271 -0
  71. data/test/regression/prototype/unit/tests/event_test.js +235 -0
  72. data/test/regression/prototype/unit/tests/form_test.js +382 -0
  73. data/test/regression/prototype/unit/tests/function_test.js +133 -0
  74. data/test/regression/prototype/unit/tests/hash_test.js +178 -0
  75. data/test/regression/prototype/unit/tests/number_test.js +44 -0
  76. data/test/regression/prototype/unit/tests/object_test.js +180 -0
  77. data/test/regression/prototype/unit/tests/periodical_executer_test.js +15 -0
  78. data/test/regression/prototype/unit/tests/position_test.js +44 -0
  79. data/test/regression/prototype/unit/tests/prototype_test.js +43 -0
  80. data/test/regression/prototype/unit/tests/range_test.js +58 -0
  81. data/test/regression/prototype/unit/tests/regexp_test.js +42 -0
  82. data/test/regression/prototype/unit/tests/selector_test.js +408 -0
  83. data/test/regression/prototype/unit/tests/string_test.js +548 -0
  84. data/test/regression/prototype/unit/tests/unittest_test.js +148 -0
  85. data/test/regression/prototype/unit/unittest_test.html +45 -0
  86. data/test/regression/prototype/upstream +1 -0
  87. data/test/test_helper.rb +20 -0
  88. data/test/unit/runner_test.rb +165 -0
  89. data/test/unit/test_case_test.rb +167 -0
  90. data/test/unit/test_test.rb +24 -0
  91. metadata +145 -0
data/README.rdoc ADDED
@@ -0,0 +1,83 @@
1
+ = JSTestSan
2
+
3
+ A JavaScript test runner to run JavaScript tests from the comfort of your
4
+ terminal.
5
+
6
+ == Why?
7
+
8
+ Because we want to run tests in a real browser environment, in our case WebKit,
9
+ but in the same fashion we run out other (Rails) unit tests.
10
+
11
+ And we want to write the tests in a way that we can easily run them on other
12
+ browsers as well, you know, html and js… This way we can run the tests from the
13
+ terminal during regular development but still test on other browsers by loading
14
+ the html/js files manually.
15
+
16
+ == Install & Usage
17
+
18
+ $ sudo gem install alloy-js-test-san -s http://gems.github.com
19
+ $ jstest path/to/a/unit_test.html
20
+
21
+ To automatically run your test see http://github.com/alloy/kicker/tree/master.
22
+
23
+ == Problems?
24
+
25
+ You betcha! (See the example.)
26
+
27
+ But these shouldn't likely be a typical use case outside of testing the
28
+ Prototype implementation, I hope. So it actually works quite well seeing how
29
+ many tests pass ;)
30
+
31
+ == Example:
32
+
33
+ This is the output of the regression tests which are the Prototype unit tests:
34
+
35
+ $ ./bin/jstest test/regression/prototype/unit/*_test.html
36
+ EEFF.......F..............................................................................................................................F
37
+ ..............................................................F............................................................................
38
+ ..............................................................................
39
+
40
+ 1) Error:
41
+ testSynchronousRequest (Unit test file | Ajax | default template | 2009-04-11 15:28) [test/regression/prototype/unit/ajax_test.html]:
42
+ TypeError: Null value, error=(TypeError: Null value)
43
+
44
+ 2) Error:
45
+ testAsynchronousRequest (Unit test file | Ajax | default template | 2009-04-11 15:28) [test/regression/prototype/unit/ajax_test.html]:
46
+ TypeError: Null value, error=(TypeError: Null value)
47
+
48
+ 3) Failed:
49
+ testUpdater (Unit test file | Ajax | default template | 2009-04-11 15:28) [test/regression/prototype/unit/ajax_test.html]:
50
+ Failure: assertEqual
51
+ expected: <'pack my box with <em>five dozen</em> liquor jugs! oh, how <strong>quickly</strong> daft jumping zebras vex...'>, actual: <''>
52
+ Failure: assertEqual
53
+ expected: <'pack my box with <em>five dozen</em> liquor jugs! oh, how <strong>quickly</strong> daft jumping zebras vex...'>, actual: <''>
54
+
55
+ 4) Failed:
56
+ testUpdaterWithInsertion (Unit test file | Ajax | default template | 2009-04-11 15:28) [test/regression/prototype/unit/ajax_test.html]:
57
+ Failure: assertEqual
58
+ expected: <'pack my box with <em>five dozen</em> liquor jugs! oh, how <strong>quickly</strong> daft jumping zebras vex...'>, actual: <''>
59
+ Failure: assertEqual
60
+ expected: <'pack my box with <em>five dozen</em> liquor jugs! oh, how <strong>quickly</strong> daft jumping zebras vex...'>, actual: <''>
61
+ Failure: assertEqual
62
+ expected: <'five dozen'>, actual: <''>
63
+
64
+ 5) Failed:
65
+ testResponseText (Unit test file | Ajax | default template | 2009-04-11 15:28) [test/regression/prototype/unit/ajax_test.html]:
66
+ Failure: assertEqual
67
+ expected: <'pack my box with <em>five dozen</em> liquor jugs! oh, how <strong>quickly</strong> daft jumping zebras vex...'>, actual: <''>
68
+
69
+ 6) Failed:
70
+ testViewportDimensions (Unit test file | Dom | default template | 2009-04-11 15:28) [test/regression/prototype/unit/dom_test.html]:
71
+ Failure: NOTE: YOU MUST ALLOW JAVASCRIPT TO RESIZE YOUR WINDOW FOR THIS TEST TO PASS
72
+ expected: <50>, actual: <0>
73
+ Failure: NOTE: YOU MUST ALLOW JAVASCRIPT TO RESIZE YOUR WINDOW FOR THIS TEST TO PASS
74
+ expected: <50>, actual: <0>
75
+
76
+ 7) Failed:
77
+ testFormRequest (Unit test file | Form | default template | 2009-04-11 15:28) [test/regression/prototype/unit/form_test.html]:
78
+ Failure: wrong default action for form element with empty action attribute
79
+ got <false>
80
+
81
+ Finished in 17.729032 seconds.
82
+
83
+ 356 tests, 2237 assertions, 9 failures, 2 errors
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ task :default => :test
2
+
3
+ desc "Run the tests"
4
+ task :test do
5
+ sh "specrb -s #{Dir['test/unit/*_test.rb'].join(' ')}"
6
+ end
7
+
8
+ # JSTestSan::Rake::Runner.new :regression do |t|
9
+ # t.files = Dir['test/regression/prototype/unit/*.html']
10
+ # end
11
+
12
+ desc "Run the regression tests"
13
+ task :ci do
14
+ sh "./bin/jstest #{Dir['test/regression/prototype/unit/*.html'].join(' ')}"
15
+ end
16
+
17
+ begin
18
+ require 'jeweler'
19
+ Jeweler::Tasks.new do |gemspec|
20
+ gemspec.name = "js-test-san"
21
+ gemspec.summary = gemspec.description = "A JavaScript test runner which runs from the comfort of the terminal. OS X only."
22
+ gemspec.email = "eloy.de.enige@gmail.com"
23
+ gemspec.homepage = "http://github.com/alloy/js-test-san/tree/master"
24
+ gemspec.authors = ["Eloy Duran"]
25
+ end
26
+ rescue LoadError
27
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 0
4
+ :minor: 1
data/bin/jstest ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path('../../lib', __FILE__)
4
+ require 'js_test_san'
5
+
6
+ if ARGV.empty?
7
+ puts "Usage: #{$0} [html files]"
8
+ else
9
+ JSTestSan::Runner.alloc.initWithHTMLFiles(ARGV).run
10
+ end
@@ -0,0 +1,70 @@
1
+ require 'osx/cocoa'
2
+
3
+ module JSTestSan
4
+ class Runner < OSX::NSObject
5
+ attr_reader :test_cases, :queued, :did_not_pass
6
+
7
+ def initWithHTMLFiles(html_files)
8
+ if init
9
+ @test_cases = []
10
+ @test_cases = html_files.map { |file| TestCase.alloc.initWithHTMLFile_delegate(file, self) }
11
+ @queued = @test_cases.dup
12
+ @did_not_pass = []
13
+
14
+ $stdout.sync = true
15
+
16
+ self
17
+ end
18
+ end
19
+
20
+ def run
21
+ @start_time = Time.now
22
+ @queued.first.run
23
+ OSX::NSApplication.sharedApplication.run
24
+ end
25
+
26
+ def tests; sum :tests end
27
+ def assertions; sum :assertions end
28
+ def failures; sum :failures end
29
+ def errors; sum :errors end
30
+
31
+ def test_ran(test)
32
+ @did_not_pass << test unless test.state == :passed
33
+
34
+ print case test.state
35
+ when :passed
36
+ '.'
37
+ when :failed
38
+ 'F'
39
+ when :error
40
+ 'E'
41
+ end
42
+ end
43
+
44
+ def test_case_finished(test_case)
45
+ @queued.delete(test_case)
46
+ @queued.empty? ? finalize : @queued.first.run
47
+ end
48
+
49
+ def finished?
50
+ @finished
51
+ end
52
+
53
+ private
54
+
55
+ def sum(attr)
56
+ @test_cases.inject(0) { |sum, tc| sum += tc.send(attr) }
57
+ end
58
+
59
+ def finalize
60
+ @finished = true
61
+
62
+ puts
63
+ @did_not_pass.each_with_index { |test, index| puts "\n #{index+1}) #{test}" }
64
+ puts "\nFinished in #{Time.now - @start_time} seconds."
65
+ puts "\n#{tests} tests, #{assertions} assertions, #{failures} failures, #{errors} errors"
66
+
67
+ OSX::NSApplication.sharedApplication.terminate(self)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,17 @@
1
+ module JSTestSan
2
+ class TestCase < OSX::NSObject
3
+ class Test
4
+ attr_reader :test_case, :name, :state, :output
5
+
6
+ def initialize(test_case, name, state, output)
7
+ @test_case, @name, @state, @output = test_case, name, state, output
8
+ end
9
+
10
+ def to_s
11
+ %{#{@state.to_s.capitalize}:
12
+ #{@name} (#{@test_case.title}) [#{@test_case.html_file}]:
13
+ #{@output}}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,103 @@
1
+ require "osx/cocoa"
2
+ OSX.require_framework 'WebKit'
3
+
4
+ require 'js_test_san/test'
5
+
6
+ module JSTestSan
7
+ class TestCase < OSX::NSObject
8
+ class FileDoesNotExistError < StandardError; end
9
+
10
+ def self.sharedWebView
11
+ @sharedWebView ||= OSX::WebView.alloc.init
12
+ end
13
+
14
+ RESULTS_REGEXP = /^((\d+) tests, )?(\d+) assertions, (\d+) failures, (\d+) errors\n?/
15
+
16
+ STATES = %w{ passed failed error }
17
+
18
+ attr_reader :html_file, :delegate, :title
19
+ attr_reader :tests, :assertions, :failures, :errors
20
+
21
+ def initWithHTMLFile_delegate(html_file, delegate)
22
+ if init
23
+ raise FileDoesNotExistError, "The file `#{html_file}' does not exist." unless File.exist?(html_file)
24
+ @html_file, @delegate = html_file, delegate
25
+ @tests = @assertions = @failures = @errors = 0
26
+ @title = ''
27
+ self
28
+ end
29
+ end
30
+
31
+ def run
32
+ webView
33
+ end
34
+
35
+ def finished?
36
+ @finished
37
+ end
38
+
39
+ def webView
40
+ @webView ||= load_webView
41
+ end
42
+
43
+ def document
44
+ webView.mainFrame.DOMDocument
45
+ end
46
+
47
+ def log
48
+ document.getElementsByClassName('logsummary').item(0)
49
+ end
50
+
51
+ def loglines
52
+ document.getElementsByClassName('loglines').item(0)
53
+ end
54
+
55
+ # Not yet sure why the extra check for log not being nil is necessary.
56
+ # Might be a test only thing.
57
+ def webView_didFinishLoadForFrame(_, __)
58
+ @title = webView.mainFrameTitle.to_s
59
+ [log, loglines].each do |element|
60
+ element.addEventListener___('DOMSubtreeModified', self, true) if element
61
+ end
62
+ end
63
+
64
+ def handleEvent(event)
65
+ element = event.target
66
+ case element
67
+ when OSX::DOMText
68
+ finalize unless log.innerText == 'running...'
69
+ else
70
+ parent = element.parentNode
71
+ state = parent.className
72
+
73
+ if element == parent.lastChild && STATES.include?(state)
74
+ output = parent.children.item(2).innerText.to_s
75
+ return if output.empty?
76
+
77
+ output.sub!(RESULTS_REGEXP, '')
78
+ name = parent.children.item(0).innerText
79
+
80
+ @delegate.test_ran(Test.new(self, name, state.to_sym, output))
81
+ end
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def load_webView
88
+ url = OSX::NSURL.fileURLWithPath(@html_file)
89
+ req = OSX::NSURLRequest.requestWithURL(url)
90
+ webView = self.class.sharedWebView
91
+ webView.mainFrame.loadRequest(req)
92
+ webView.frameLoadDelegate = self
93
+ webView
94
+ end
95
+
96
+ def finalize
97
+ @finished = true
98
+ results = log.innerText.to_s.scan(RESULTS_REGEXP).first[1..-1]
99
+ @tests, @assertions, @failures, @errors = results.map { |x| x.to_i }
100
+ @delegate.test_case_finished(self)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,2 @@
1
+ require 'js_test_san/test_case'
2
+ require 'js_test_san/runner'
@@ -0,0 +1,27 @@
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>A JSTestSan Unit Test HTML File</title>
6
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7
+
8
+ <script type="text/javascript" charset="utf-8">
9
+ var eventResults = {};
10
+ var originalElement = window.Element;
11
+ </script>
12
+
13
+ <script src="../regression/prototype/unit/assets/prototype.js" type="text/javascript" charset="utf-8"></script>
14
+ <script src="../regression/prototype/unit/assets/unittest.js" type="text/javascript" charset="utf-8"></script>
15
+ <script src="a_unit_test.js" type="text/javascript" charset="utf-8"></script>
16
+ </head>
17
+ <body>
18
+
19
+ <div id="testlog"></div>
20
+
21
+ <div id="content"></div>
22
+
23
+ </body>
24
+ </html>
25
+ <script type="text/javascript" charset="utf-8">
26
+ eventResults.endOfDocument = true;
27
+ </script>
@@ -0,0 +1,22 @@
1
+ // 3 tests, 2 assertions, 1 failures, 1 errors
2
+
3
+ new Test.Unit.Runner({
4
+ setup: function() {
5
+ this.content = $('content');
6
+ this.content.update('');
7
+ },
8
+
9
+ testHelloWorldSuccess: function() {
10
+ this.assertEqual("", this.content.innerHTML);
11
+ this.content.update('Hello world!');
12
+ this.assertEqual("Hello world!", this.content.innerHTML);
13
+ },
14
+
15
+ testHelloWorldFailure: function() {
16
+ this.assertEqual("Hello world!", this.content.innerHTML);
17
+ },
18
+
19
+ testHelloWorldError: function() {
20
+ this.content.foo();
21
+ },
22
+ });
@@ -0,0 +1,29 @@
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>Unit test file | Ajax | default template | 2009-04-11 15:28</title>
6
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7
+ <script type="text/javascript" charset="utf-8">
8
+ var eventResults = {};
9
+ var originalElement = window.Element;
10
+ </script>
11
+ <script src="assets/prototype.js" type="text/javascript" charset="utf-8"></script>
12
+ <script src="assets/unittest.js" type="text/javascript" charset="utf-8"></script>
13
+ <link rel="stylesheet" href="assets/unittest.css" type="text/css" />
14
+
15
+ <script src="fixtures/ajax.js" type="text/javascript" charset="utf-8"></script>
16
+ <script src="tests/ajax_test.js" type="text/javascript" charset="utf-8"></script>
17
+ </head>
18
+ <body>
19
+
20
+ <div id="testlog"></div>
21
+
22
+ <div id="content"></div>
23
+ <div id="content2" style="color:red"></div>
24
+
25
+ </body>
26
+ </html>
27
+ <script type="text/javascript" charset="utf-8">
28
+ eventResults.endOfDocument = true;
29
+ </script>
@@ -0,0 +1,28 @@
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>Unit test file | Array | default template | 2009-04-11 15:28</title>
6
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
7
+ <script type="text/javascript" charset="utf-8">
8
+ var eventResults = {};
9
+ var originalElement = window.Element;
10
+ </script>
11
+ <script src="assets/prototype.js" type="text/javascript" charset="utf-8"></script>
12
+ <script src="assets/unittest.js" type="text/javascript" charset="utf-8"></script>
13
+ <link rel="stylesheet" href="assets/unittest.css" type="text/css" />
14
+
15
+
16
+ <script src="tests/array_test.js" type="text/javascript" charset="utf-8"></script>
17
+ </head>
18
+ <body>
19
+
20
+ <div id="testlog"></div>
21
+
22
+ <div id="test_node">22<span id="span_1"></span><span id="span_2"></span></div>
23
+
24
+ </body>
25
+ </html>
26
+ <script type="text/javascript" charset="utf-8">
27
+ eventResults.endOfDocument = true;
28
+ </script>