screw-unit-server 0.3.0

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 (96) hide show
  1. data/CHANGES +5 -0
  2. data/README.markdown +347 -0
  3. data/Rakefile +70 -0
  4. data/bin/screw_unit +6 -0
  5. data/bin/screw_unit_server +10 -0
  6. data/core/EXAMPLE.html +68 -0
  7. data/core/LICENSE +22 -0
  8. data/core/README.markdown +307 -0
  9. data/core/TODO +2 -0
  10. data/core/example/models/cat.js +5 -0
  11. data/core/example/models/man.js +17 -0
  12. data/core/example/spec/matchers/have.js +8 -0
  13. data/core/example/spec/models/cat_spec.js +31 -0
  14. data/core/example/spec/models/man_spec.js +34 -0
  15. data/core/example/spec/spec_helper.js +5 -0
  16. data/core/example/spec/suite.html +25 -0
  17. data/core/lib/jquery-1.2.3.js +3408 -0
  18. data/core/lib/jquery.fn.js +29 -0
  19. data/core/lib/jquery.print.js +108 -0
  20. data/core/lib/screw.assets.js +36 -0
  21. data/core/lib/screw.behaviors.js +91 -0
  22. data/core/lib/screw.builder.js +80 -0
  23. data/core/lib/screw.css +90 -0
  24. data/core/lib/screw.events.js +38 -0
  25. data/core/lib/screw.matchers.js +65 -0
  26. data/core/lib/screw.server.js +21 -0
  27. data/core/spec/behaviors_spec.js +178 -0
  28. data/core/spec/matchers_spec.js +93 -0
  29. data/core/spec/print_spec.js +119 -0
  30. data/core/spec/spec_helper.js +0 -0
  31. data/core/spec/suite.html +18 -0
  32. data/init.rb +0 -0
  33. data/lib/screw_unit.rb +26 -0
  34. data/lib/screw_unit/resources.rb +2 -0
  35. data/lib/screw_unit/resources/spec.rb +37 -0
  36. data/spec/functional/functional_spec.rb +14 -0
  37. data/spec/functional/functional_spec_helper.rb +55 -0
  38. data/spec/functional_suite.rb +10 -0
  39. data/spec/spec_suite.rb +3 -0
  40. data/spec/unit/js_test_core/specs/spec_dir_spec.rb +43 -0
  41. data/spec/unit/js_test_core/specs/spec_file_spec.rb +43 -0
  42. data/spec/unit/unit_spec_helper.rb +120 -0
  43. data/spec/unit_suite.rb +10 -0
  44. data/vendor/js-test-core/CHANGES +9 -0
  45. data/vendor/js-test-core/README +12 -0
  46. data/vendor/js-test-core/Rakefile +72 -0
  47. data/vendor/js-test-core/lib/js_test_core.rb +30 -0
  48. data/vendor/js-test-core/lib/js_test_core/client.rb +50 -0
  49. data/vendor/js-test-core/lib/js_test_core/rack.rb +2 -0
  50. data/vendor/js-test-core/lib/js_test_core/rack/commonlogger.rb +5 -0
  51. data/vendor/js-test-core/lib/js_test_core/rails_server.rb +22 -0
  52. data/vendor/js-test-core/lib/js_test_core/resources.rb +11 -0
  53. data/vendor/js-test-core/lib/js_test_core/resources/dir.rb +52 -0
  54. data/vendor/js-test-core/lib/js_test_core/resources/file.rb +32 -0
  55. data/vendor/js-test-core/lib/js_test_core/resources/file_not_found.rb +15 -0
  56. data/vendor/js-test-core/lib/js_test_core/resources/runners.rb +15 -0
  57. data/vendor/js-test-core/lib/js_test_core/resources/runners/firefox_runner.rb +75 -0
  58. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_dir.rb +50 -0
  59. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_file.rb +17 -0
  60. data/vendor/js-test-core/lib/js_test_core/resources/suite.rb +24 -0
  61. data/vendor/js-test-core/lib/js_test_core/resources/suite_finish.rb +19 -0
  62. data/vendor/js-test-core/lib/js_test_core/resources/web_root.rb +62 -0
  63. data/vendor/js-test-core/lib/js_test_core/selenium.rb +2 -0
  64. data/vendor/js-test-core/lib/js_test_core/selenium/selenium_driver.rb +5 -0
  65. data/vendor/js-test-core/lib/js_test_core/server.rb +111 -0
  66. data/vendor/js-test-core/lib/js_test_core/thin.rb +3 -0
  67. data/vendor/js-test-core/lib/js_test_core/thin/backends/js_test_core_server.rb +9 -0
  68. data/vendor/js-test-core/lib/js_test_core/thin/js_test_core_connection.rb +42 -0
  69. data/vendor/js-test-core/spec/example_core/JsTestCore.css +0 -0
  70. data/vendor/js-test-core/spec/example_core/JsTestCore.js +0 -0
  71. data/vendor/js-test-core/spec/example_public/favicon.ico +0 -0
  72. data/vendor/js-test-core/spec/example_public/javascripts/foo.js +3 -0
  73. data/vendor/js-test-core/spec/example_public/robots.txt +0 -0
  74. data/vendor/js-test-core/spec/example_public/stylesheets/example.css +3 -0
  75. data/vendor/js-test-core/spec/example_specs/failing_spec.js +5 -0
  76. data/vendor/js-test-core/spec/example_specs/foo/failing_spec.js +6 -0
  77. data/vendor/js-test-core/spec/example_specs/foo/passing_spec.js +6 -0
  78. data/vendor/js-test-core/spec/spec_suite.rb +2 -0
  79. data/vendor/js-test-core/spec/specs/failing_spec.js +0 -0
  80. data/vendor/js-test-core/spec/unit/js_test_core/client_spec.rb +137 -0
  81. data/vendor/js-test-core/spec/unit/js_test_core/rails_server_spec.rb +45 -0
  82. data/vendor/js-test-core/spec/unit/js_test_core/resources/dir_spec.rb +42 -0
  83. data/vendor/js-test-core/spec/unit/js_test_core/resources/file_not_found_spec.rb +26 -0
  84. data/vendor/js-test-core/spec/unit/js_test_core/resources/file_spec.rb +88 -0
  85. data/vendor/js-test-core/spec/unit/js_test_core/resources/runner_spec.rb +24 -0
  86. data/vendor/js-test-core/spec/unit/js_test_core/resources/runners/firefox_runner_spec.rb +197 -0
  87. data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_dir_spec.rb +79 -0
  88. data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_file_spec.rb +42 -0
  89. data/vendor/js-test-core/spec/unit/js_test_core/resources/suite_finish_spec.rb +94 -0
  90. data/vendor/js-test-core/spec/unit/js_test_core/resources/suite_spec.rb +44 -0
  91. data/vendor/js-test-core/spec/unit/js_test_core/resources/web_root_spec.rb +103 -0
  92. data/vendor/js-test-core/spec/unit/js_test_core/server_spec.rb +131 -0
  93. data/vendor/js-test-core/spec/unit/thin/js_test_core_connection_spec.rb +92 -0
  94. data/vendor/js-test-core/spec/unit/unit_spec_helper.rb +125 -0
  95. data/vendor/js-test-core/spec/unit_suite.rb +10 -0
  96. metadata +186 -0
@@ -0,0 +1,94 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ describe SuiteFinish do
6
+ attr_reader :stdout, :suite_finish, :suite
7
+ before do
8
+ @stdout = StringIO.new
9
+ SuiteFinish.const_set(:STDOUT, stdout)
10
+ end
11
+
12
+ after do
13
+ SuiteFinish.__send__(:remove_const, :STDOUT)
14
+ end
15
+
16
+ describe ".post" do
17
+ describe "when Suite#id == 'user'" do
18
+ before do
19
+ @suite = Suite.new('user')
20
+ @suite_finish = SuiteFinish.new(suite)
21
+ end
22
+
23
+ it "writes the body of the request to stdout" do
24
+ body = "The text in the POST body"
25
+ request = Rack::Request.new({'rack.input' => StringIO.new("text=#{body}")})
26
+ request.body.string.should == "text=#{body}"
27
+ response = Rack::Response.new
28
+
29
+ suite_finish.post(request, response)
30
+ stdout.string.should == "#{body}\n"
31
+ end
32
+
33
+ it "sets the Content-Length to be 0" do
34
+ request = Rack::Request.new('rack.input' => StringIO.new(""))
35
+ response = Rack::Response.new
36
+
37
+ response.headers["Content-Length"].should be_nil
38
+ suite_finish.post(request, response)
39
+ response.headers["Content-Length"].should == "0"
40
+ end
41
+ end
42
+
43
+ describe "when Suite#id is not 'user'" do
44
+ attr_reader :request, :response, :runner, :suite_id, :driver
45
+ before do
46
+ runner_request = Rack::Request.new( Rack::MockRequest.env_for('/runners/firefox') )
47
+ runner_response = Rack::Response.new
48
+ @suite_id = '12345'
49
+ @driver = "Selenium Driver"
50
+ stub(Selenium::SeleniumDriver).new('localhost', 4444, '*firefox', 'http://0.0.0.0:8080') do
51
+ driver
52
+ end
53
+ stub(driver).start
54
+ stub(driver).open
55
+ stub(driver).session_id {suite_id}
56
+ stub(Thread).start.yields
57
+ Thread.current[:connection] = connection
58
+
59
+ @runner = Runners::FirefoxRunner.new
60
+ runner.post(runner_request, runner_response)
61
+
62
+ @suite = Suite.new(suite_id)
63
+ @suite_finish = SuiteFinish.new(suite)
64
+ end
65
+
66
+ it "resumes the FirefoxRunner" do
67
+ body = "The text in the POST body"
68
+ request = Rack::Request.new({'rack.input' => StringIO.new("text=#{body}")})
69
+ response = Rack::Response.new
70
+ mock.proxy(Runners::FirefoxRunner).resume(suite_id, body)
71
+ mock(driver).stop
72
+ stub(connection).send_data.once
73
+ stub(connection).close_connection.once
74
+
75
+ suite_finish.post(request, response)
76
+ end
77
+
78
+ it "sets the Content-Length to be 0" do
79
+ request = Rack::Request.new('rack.input' => StringIO.new(""))
80
+ response = Rack::Response.new
81
+ stub(Runners::FirefoxRunner).resume
82
+ stub(driver).stop
83
+ stub(connection).send_data
84
+ stub(connection).close_connection
85
+
86
+ response.headers["Content-Length"].should be_nil
87
+ suite_finish.post(request, response)
88
+ response.headers["Content-Length"].should == "0"
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ describe Suite do
6
+ attr_reader :stdout
7
+ before do
8
+ @stdout = StringIO.new
9
+ Suite.const_set(:STDOUT, stdout)
10
+ end
11
+
12
+ after do
13
+ Suite.__send__(:remove_const, :STDOUT)
14
+ end
15
+
16
+ describe ".locate" do
17
+ it "when passed an identifier, returns an instance of Suite with the identifier" do
18
+ instance = Suite.locate('foobar')
19
+ instance.class.should == Suite
20
+ instance.id.should == 'foobar'
21
+ end
22
+ end
23
+
24
+ describe "#locate" do
25
+ attr_reader :suite
26
+ before do
27
+ @suite = Suite.new('foobar')
28
+ end
29
+
30
+ it "when passed 'finish', returns a SuiteFinish that has access to the suite" do
31
+ suite_finish = suite.locate('finish')
32
+ suite_finish.class.should == SuiteFinish
33
+ suite_finish.suite.should == suite
34
+ end
35
+
36
+ it "when not passed 'finish', raises ArgumentError" do
37
+ lambda do
38
+ suite.locate('invalid')
39
+ end.should raise_error(ArgumentError, "Invalid path: invalid")
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,103 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ describe WebRoot do
6
+ attr_reader :web_root
7
+ before(:each) do
8
+ @web_root = WebRoot.new(public_path)
9
+ end
10
+
11
+ describe "#locate" do
12
+ describe "when passed ''" do
13
+ it "returns self" do
14
+ web_root.locate('').should == web_root
15
+ end
16
+ end
17
+
18
+ describe "when passed 'core'" do
19
+ it "returns a Dir representing the JsTestCore core directory" do
20
+ runner = web_root.locate('core')
21
+ runner.should == Resources::Dir.new(JsTestCore::Server.core_path, '/core')
22
+ end
23
+ end
24
+
25
+ describe "when passed 'implementations'" do
26
+ it "returns a Dir representing the javascript implementations directory" do
27
+ runner = web_root.locate('implementations')
28
+ runner.should == Resources::Dir.new(JsTestCore::Server.implementation_root_path, '/implementations')
29
+ end
30
+ end
31
+
32
+ describe "when passed 'results'" do
33
+ it "returns a Suite" do
34
+ runner = web_root.locate('suites')
35
+ runner.should == Resources::Suite
36
+ end
37
+ end
38
+
39
+ describe "when passed 'runners'" do
40
+ it "returns a Runner" do
41
+ runner = web_root.locate('runners')
42
+ runner.should be_instance_of(Resources::Runners)
43
+ end
44
+ end
45
+
46
+ describe "when passed a directory that is in the public_path" do
47
+ it "returns a Dir representing that directory" do
48
+ runner = web_root.locate('stylesheets')
49
+ runner.should == Resources::Dir.new("#{JsTestCore::Server.public_path}/stylesheets", '/stylesheets')
50
+ end
51
+ end
52
+
53
+ describe "when passed a file that is in the public_path" do
54
+ it "returns a File representing that file" do
55
+ runner = web_root.locate('robots.txt')
56
+ runner.should == Resources::File.new("#{JsTestCore::Server.public_path}/robots.txt", '/robots.txt')
57
+ end
58
+ end
59
+
60
+ describe "when passed an invalid option" do
61
+ it "returns a 404 response" do
62
+ resource = web_root.locate('invalid')
63
+
64
+ end
65
+ end
66
+ end
67
+
68
+ describe ".dispatch_specs" do
69
+ describe "#get" do
70
+ attr_reader :request, :response
71
+ before do
72
+ @request = Rack::Request.new({'rack.input' => StringIO.new("")})
73
+ @response = Rack::Response.new
74
+ end
75
+
76
+ it "redirects to /specs" do
77
+ WebRoot.dispatch_specs
78
+
79
+ web_root.get(request, response)
80
+ response.should be_redirect
81
+ response.headers["Location"].should == "/specs"
82
+ end
83
+ end
84
+
85
+ describe "#locate /specs" do
86
+ it "dispatches to a Spec::SpecDir" do
87
+ WebRoot.dispatch_specs
88
+
89
+ resource = web_root.locate('specs')
90
+ resource.should == spec_dir('')
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ describe "when .dispatch_specs is not called" do
97
+ it "does not cause #locate to dispatch to /specs" do
98
+ web_root.locate('specs').should be_instance_of(FileNotFound)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,131 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ describe Server do
5
+ attr_reader :result
6
+
7
+ before do
8
+ @result = ""
9
+ stub(EventMachine).send_data do |signature, data, data_length|
10
+ @result << data
11
+ end
12
+ stub(EventMachine).close_connection
13
+ end
14
+
15
+ describe "HTTP GET" do
16
+ specify "'/core/JsTestCore.js', returns the contents of the file" do
17
+ response = get("/core/JsTestCore.js")
18
+ response.body.should == ::File.read("#{Server.core_path}/JsTestCore.js")
19
+ end
20
+
21
+ specify "'/stylesheets/example.css', returns the contents of the file" do
22
+ response = get("/stylesheets/example.css")
23
+ response.body.should == ::File.read("#{Server.public_path}/stylesheets/example.css")
24
+ end
25
+
26
+ specify "'/invalid/path', shows the full invalid path in the error message" do
27
+ lambda do
28
+ get("/invalid/path")
29
+ end.should raise_error(Exception, Regexp.new("/invalid/path"))
30
+ end
31
+ end
32
+
33
+ describe ".run" do
34
+ attr_reader :server_instance
35
+ before do
36
+ @server_instance = Server.instance
37
+ Server.instance = nil
38
+ end
39
+
40
+ it "instantiates an instance of Server and starts a Rack Thin handler" do
41
+ host = DEFAULT_HOST
42
+ port = DEFAULT_PORT
43
+
44
+ mock(EventMachine).run.yields
45
+ mock(EventMachine).start_server(host, port, ::Thin::JsTestCoreConnection)
46
+
47
+ Server.run(spec_root_path, implementation_root_path, public_path)
48
+ end
49
+
50
+ it "when passed a custom host and port, sets the host and port to the passed in value" do
51
+ host = 'foobar.com'
52
+ port = 80
53
+
54
+ mock(EventMachine).run.yields
55
+ mock(EventMachine).start_server(host, port, ::Thin::JsTestCoreConnection)
56
+
57
+ Server.run(spec_root_path, implementation_root_path, public_path, {:Host => host, :Port => port})
58
+ end
59
+ end
60
+
61
+ describe ".spec_root" do
62
+ it "returns the Dir " do
63
+ Server.spec_root_path.should == spec_root_path
64
+ end
65
+ end
66
+
67
+ describe ".spec_root_path" do
68
+ it "returns the absolute path of the specs root directory" do
69
+ Server.spec_root_path.should == spec_root_path
70
+ end
71
+ end
72
+
73
+ describe ".public_path" do
74
+ it "returns the expanded path of the public path" do
75
+ Server.public_path.should == public_path
76
+ end
77
+ end
78
+
79
+ describe ".core_path" do
80
+ it "returns the expanded path to the JsTestCore core directory" do
81
+ Server.core_path.should == core_path
82
+ end
83
+ end
84
+
85
+ describe ".implementation_root_path" do
86
+ it "returns the expanded path to the JsTestCore implementations directory" do
87
+ dir = ::File.dirname(__FILE__)
88
+ Server.implementation_root_path.should == implementation_root_path
89
+ end
90
+ end
91
+
92
+ describe "#call" do
93
+ describe "when there is an error" do
94
+ attr_reader :top_line_of_backtrace
95
+ before do
96
+ @top_line_of_backtrace = __LINE__ + 2
97
+ stub.instance_of(Resources::WebRoot).locate('somedir') do
98
+ raise "Foobar"
99
+ end
100
+ end
101
+
102
+ it "shows the full request path in the error message" do
103
+ lambda do
104
+ get('/somedir')
105
+ end.should raise_error(Exception, Regexp.new("/somedir"))
106
+ end
107
+
108
+ it "uses the backtrace from where the original error was raised" do
109
+ no_error = true
110
+ begin
111
+ get('/somedir')
112
+ rescue Exception => e
113
+ no_error = false
114
+ top_of_backtrace = e.backtrace.first.split(":")
115
+ backtrace_file = ::File.expand_path(top_of_backtrace[0])
116
+ backtrace_line = Integer(top_of_backtrace[1])
117
+ backtrace_file.should == __FILE__
118
+ backtrace_line.should == top_line_of_backtrace
119
+ end
120
+ raise "There should have been an error" if no_error
121
+ end
122
+ end
123
+ end
124
+
125
+ describe "#root_url" do
126
+ it "returns the url of the site's root" do
127
+ server.root_url.should == "http://#{server.host}:#{server.port}"
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,92 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../unit_spec_helper")
2
+
3
+ module Thin
4
+ describe JsTestCoreConnection do
5
+ describe "#process" do
6
+ attr_reader :connection, :result
7
+ before do
8
+ @connection = JsTestCoreConnection.new('signature')
9
+ stub(connection).socket_address {'0.0.0.0'}
10
+
11
+ @result = ""
12
+ stub(EventMachine).send_data do |signature, data, data_length|
13
+ result << data
14
+ end
15
+ end
16
+
17
+ describe "and the call is successful" do
18
+ describe "and the body is not empty" do
19
+ before do
20
+ mock(app = Object.new).call(is_a(Hash)) do
21
+ [200, {}, 'The Body']
22
+ end
23
+ connection.app = app
24
+ end
25
+
26
+ it "sends the response to the socket and closes the connection" do
27
+ mock(connection).close_connection_after_writing
28
+ connection.receive_data "GET /specs HTTP/1.1\r\nHost: _\r\n\r\n"
29
+ result.should include("The Body")
30
+ end
31
+ end
32
+
33
+ describe "and the body is empty" do
34
+ describe "and the Content-Length header is 0" do
35
+ before do
36
+ mock(app = Object.new).call(is_a(Hash)) do
37
+ [200, {"Content-Length" => '0'}, []]
38
+ end
39
+ connection.app = app
40
+ end
41
+
42
+ it "sends the response to the socket and closes the connection" do
43
+ mock(connection).close_connection_after_writing
44
+ connection.receive_data "GET /specs HTTP/1.1\r\nHost: _\r\n\r\n"
45
+ end
46
+ end
47
+
48
+ describe "and the Content-Length header is > 0" do
49
+ before do
50
+ mock(app = Object.new).call(is_a(Hash)) do
51
+ [200, {"Content-Length" => '55'}, []]
52
+ end
53
+ connection.app = app
54
+ end
55
+
56
+ it "keeps the connection open" do
57
+ dont_allow(connection).close_connection_after_writing
58
+ connection.receive_data "GET /specs HTTP/1.1\r\nHost: _\r\n\r\n"
59
+ end
60
+ end
61
+
62
+ describe "and the Content-Length header is not passed in" do
63
+ before do
64
+ mock(app = Object.new).call(is_a(Hash)) do
65
+ [200, {}, []]
66
+ end
67
+ connection.app = app
68
+ end
69
+
70
+ it "keeps the connection open" do
71
+ dont_allow(connection).close_connection_after_writing
72
+ connection.receive_data "GET /specs HTTP/1.1\r\nHost: _\r\n\r\n"
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "and the call raises an error" do
79
+ it "logs the error and closes the connection" do
80
+ mock(app = Object.new).call(is_a(Hash)) do
81
+ raise "An Error"
82
+ end
83
+ connection.app = app
84
+ mock(connection).log(anything).at_least(1)
85
+ mock(connection).close_connection
86
+
87
+ connection.receive_data "GET /specs HTTP/1.1\r\nHost: _\r\n\r\n"
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end