pivotal-screw-unit 0.4.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.
- data/CHANGES +21 -0
- data/README.markdown +354 -0
- data/Rakefile +39 -0
- data/VERSION.yml +4 -0
- data/bin/screw_unit +6 -0
- data/bin/screw_unit_server +10 -0
- data/core/CHANGES +10 -0
- data/core/EXAMPLE.html +68 -0
- data/core/LICENSE +22 -0
- data/core/README.markdown +307 -0
- data/core/example/models/cat.js +5 -0
- data/core/example/models/man.js +17 -0
- data/core/example/spec/matchers/have.js +8 -0
- data/core/example/spec/models/cat_spec.js +31 -0
- data/core/example/spec/models/man_spec.js +34 -0
- data/core/example/spec/spec_helper.js +5 -0
- data/core/example/spec/suite.html +25 -0
- data/core/lib/jquery-1.3.2.js +4376 -0
- data/core/lib/jquery.fn.js +30 -0
- data/core/lib/jquery.print.js +109 -0
- data/core/lib/screw.behaviors.js +93 -0
- data/core/lib/screw.builder.js +94 -0
- data/core/lib/screw.css +90 -0
- data/core/lib/screw.events.js +45 -0
- data/core/lib/screw.matchers.js +244 -0
- data/core/spec/behaviors_spec.js +188 -0
- data/core/spec/matchers_spec.js +372 -0
- data/core/spec/print_spec.js +158 -0
- data/core/spec/spec_helper.js +0 -0
- data/core/spec/suite.html +19 -0
- data/core/spec/with_screw_context_spec.js +9 -0
- data/init.rb +0 -0
- data/lib/screw_unit/representations/spec.html.rb +117 -0
- data/lib/screw_unit/representations.rb +2 -0
- data/lib/screw_unit.rb +19 -0
- data/spec/functional/functional_spec.rb +25 -0
- data/spec/functional/functional_spec_helper.rb +34 -0
- data/spec/functional/functional_spec_server_starter.rb +63 -0
- data/spec/functional_suite.rb +10 -0
- data/spec/spec_suite.rb +3 -0
- data/spec/unit/js_test_core/specs/spec_dir_spec.rb +39 -0
- data/spec/unit/js_test_core/specs/spec_file_spec.rb +35 -0
- data/spec/unit/unit_spec_helper.rb +119 -0
- data/spec/unit_suite.rb +10 -0
- data/vendor/js-test-core/CHANGES +25 -0
- data/vendor/js-test-core/README +12 -0
- data/vendor/js-test-core/Rakefile +73 -0
- data/vendor/js-test-core/lib/js_test_core/client.rb +129 -0
- data/vendor/js-test-core/lib/js_test_core/extensions/time.rb +6 -0
- data/vendor/js-test-core/lib/js_test_core/extensions.rb +3 -0
- data/vendor/js-test-core/lib/js_test_core/rack/commonlogger.rb +5 -0
- data/vendor/js-test-core/lib/js_test_core/rack.rb +2 -0
- data/vendor/js-test-core/lib/js_test_core/rails_server.rb +22 -0
- data/vendor/js-test-core/lib/js_test_core/representations/spec.html.rb +23 -0
- data/vendor/js-test-core/lib/js_test_core/representations.rb +9 -0
- data/vendor/js-test-core/lib/js_test_core/resources/dir.rb +67 -0
- data/vendor/js-test-core/lib/js_test_core/resources/file.rb +42 -0
- data/vendor/js-test-core/lib/js_test_core/resources/runner.rb +107 -0
- data/vendor/js-test-core/lib/js_test_core/resources/session.rb +44 -0
- data/vendor/js-test-core/lib/js_test_core/resources/session_finish.rb +17 -0
- data/vendor/js-test-core/lib/js_test_core/resources/specs/spec.rb +32 -0
- data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_dir.rb +50 -0
- data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_file.rb +21 -0
- data/vendor/js-test-core/lib/js_test_core/resources/web_root.rb +66 -0
- data/vendor/js-test-core/lib/js_test_core/resources.rb +17 -0
- data/vendor/js-test-core/lib/js_test_core/selenium/client/driver.rb +7 -0
- data/vendor/js-test-core/lib/js_test_core/selenium.rb +2 -0
- data/vendor/js-test-core/lib/js_test_core/selenium_server_configuration.rb +48 -0
- data/vendor/js-test-core/lib/js_test_core/server.rb +50 -0
- data/vendor/js-test-core/lib/js_test_core/thin/backends/js_test_core_server.rb +9 -0
- data/vendor/js-test-core/lib/js_test_core/thin/js_test_core_connection.rb +8 -0
- data/vendor/js-test-core/lib/js_test_core/thin.rb +3 -0
- data/vendor/js-test-core/lib/js_test_core.rb +41 -0
- data/vendor/js-test-core/spec/example_core/JsTestCore.css +0 -0
- data/vendor/js-test-core/spec/example_core/JsTestCore.js +0 -0
- data/vendor/js-test-core/spec/example_public/favicon.ico +0 -0
- data/vendor/js-test-core/spec/example_public/javascripts/foo.js +3 -0
- data/vendor/js-test-core/spec/example_public/javascripts/large_file.js +59 -0
- data/vendor/js-test-core/spec/example_public/javascripts/subdir/bar.js +1 -0
- data/vendor/js-test-core/spec/example_public/robots.txt +0 -0
- data/vendor/js-test-core/spec/example_public/stylesheets/example.css +3 -0
- data/vendor/js-test-core/spec/example_specs/custom_dir_and_suite/passing_spec.js +6 -0
- data/vendor/js-test-core/spec/example_specs/custom_dir_and_suite.html +9 -0
- data/vendor/js-test-core/spec/example_specs/custom_suite.html +8 -0
- data/vendor/js-test-core/spec/example_specs/failing_spec.js +5 -0
- data/vendor/js-test-core/spec/example_specs/foo/failing_spec.js +6 -0
- data/vendor/js-test-core/spec/example_specs/foo/passing_spec.js +6 -0
- data/vendor/js-test-core/spec/spec_suite.rb +2 -0
- data/vendor/js-test-core/spec/specs/failing_spec.js +0 -0
- data/vendor/js-test-core/spec/unit/js_test_core/client_spec.rb +192 -0
- data/vendor/js-test-core/spec/unit/js_test_core/rails_server_spec.rb +45 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/dir_spec.rb +53 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/file_not_found_spec.rb +16 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/file_spec.rb +90 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/runners/runner_spec.rb +303 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/session_finish_spec.rb +79 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/session_spec.rb +82 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_dir_spec.rb +104 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_file_spec.rb +41 -0
- data/vendor/js-test-core/spec/unit/js_test_core/resources/web_root_spec.rb +32 -0
- data/vendor/js-test-core/spec/unit/js_test_core/selenium_server_configuration_spec.rb +49 -0
- data/vendor/js-test-core/spec/unit/js_test_core/server_spec.rb +117 -0
- data/vendor/js-test-core/spec/unit/thin/js_test_core_connection_spec.rb +6 -0
- data/vendor/js-test-core/spec/unit/unit_spec_helper.rb +161 -0
- data/vendor/js-test-core/spec/unit_suite.rb +10 -0
- data/vendor/js-test-core/vendor/thin-rest/CHANGES +2 -0
- data/vendor/js-test-core/vendor/thin-rest/README +0 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/connection.rb +117 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/extensions/object.rb +21 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/extensions.rb +3 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations/internal_error.html.rb +19 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations/page.html.rb +41 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations/resource_not_found.html.rb +18 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations.rb +4 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources/internal_error.rb +11 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources/resource.rb +105 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources/resource_not_found.rb +19 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources.rb +4 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/routing_error.rb +5 -0
- data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest.rb +10 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/spec_suite.rb +5 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/connection_spec.rb +205 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resources/resource_not_found_spec.rb +16 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resources/resource_spec.rb +135 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resources/root_spec.rb +16 -0
- data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest_spec_helper.rb +133 -0
- metadata +184 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../../unit_spec_helper")
|
|
2
|
+
|
|
3
|
+
module JsTestCore
|
|
4
|
+
module Resources
|
|
5
|
+
module Specs
|
|
6
|
+
describe SpecDir do
|
|
7
|
+
attr_reader :dir, :absolute_path, :relative_path
|
|
8
|
+
before do
|
|
9
|
+
@absolute_path = spec_root_path
|
|
10
|
+
@relative_path = "/specs"
|
|
11
|
+
@dir = Resources::Specs::SpecDir.new(:connection => connection, :absolute_path => absolute_path, :relative_path => relative_path)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "#locate" do
|
|
15
|
+
context "when passed the name with an extension" do
|
|
16
|
+
context "when file exists" do
|
|
17
|
+
it "returns a Resources::File representing it" do
|
|
18
|
+
file = dir.locate("failing_spec.js")
|
|
19
|
+
file.relative_path.should == "/specs/failing_spec.js"
|
|
20
|
+
file.absolute_path.should == "#{spec_root_path}/failing_spec.js"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "when file does not exist" do
|
|
25
|
+
it "raises error" do
|
|
26
|
+
lambda { dir.locate("nonexistent.js") }.should raise_error
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "when passed a name without an extension" do
|
|
32
|
+
context "when name corresponds to a subdirectory" do
|
|
33
|
+
it "returns a DirectoryRunner for the directory" do
|
|
34
|
+
subdir = dir.locate("foo")
|
|
35
|
+
subdir.should == spec_dir("/foo")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "when name corresponds to a .js file" do
|
|
40
|
+
it "returns a SpecFile for the .js file" do
|
|
41
|
+
spec_file_name = "failing_spec"
|
|
42
|
+
subdir = dir.locate(spec_file_name)
|
|
43
|
+
subdir.should == JsTestCore::Resources::Specs::SpecFile.new(
|
|
44
|
+
:connection => connection,
|
|
45
|
+
:absolute_path => "#{spec_root_path}/#{spec_file_name}.js",
|
|
46
|
+
:relative_path => "/specs/#{spec_file_name}.js"
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "when name does not correspond to a .js file or directory" do
|
|
52
|
+
it "raises an error" do
|
|
53
|
+
lambda do
|
|
54
|
+
dir.locate("nonexistent")
|
|
55
|
+
end.should raise_error
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "GET /specs/custom_dir_and_suite" do
|
|
62
|
+
it "renders the custom_dir_and_suite.html file" do
|
|
63
|
+
WebRoot.dispatch_specs
|
|
64
|
+
path = "#{spec_root_path}/custom_dir_and_suite.html"
|
|
65
|
+
mock(connection).send_head(200, 'Content-Type' => "text/html", 'Content-Length' => ::File.size(path), 'Last-Modified' => ::File.mtime(path).rfc822)
|
|
66
|
+
mock(connection).send_data(::File.read(path))
|
|
67
|
+
|
|
68
|
+
connection.receive_data("GET /specs/custom_dir_and_suite.html HTTP/1.1\r\nHost: _\r\n\r\n")
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe "GET /specs/foo" do
|
|
73
|
+
it "renders a custom spec suite that includes all of the javascript spec files in the directory" do
|
|
74
|
+
WebRoot.dispatch_specs
|
|
75
|
+
Thin::Logging.silent = true
|
|
76
|
+
path = "#{spec_root_path}/foo"
|
|
77
|
+
mock(connection).send_head(200, 'Content-Type' => "text/html", 'Last-Modified' => ::File.mtime(path).rfc822)
|
|
78
|
+
mock(connection).send_data(/Content-Length: /)
|
|
79
|
+
mock(connection).send_data(Regexp.new("Js Test Core Suite")) do |html|
|
|
80
|
+
doc = Nokogiri::HTML(html)
|
|
81
|
+
core_js_files = doc.search("script").map {|script| script["src"]}
|
|
82
|
+
core_js_files.should include("/specs/foo/passing_spec.js")
|
|
83
|
+
core_js_files.should include("/specs/foo/failing_spec.js")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
connection.receive_data("GET /specs/foo HTTP/1.1\r\nHost: _\r\n\r\n")
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe "GET /" do
|
|
91
|
+
context "when WebRoot.dispatch_specs has been invoked" do
|
|
92
|
+
it "renders a home page" do
|
|
93
|
+
WebRoot.dispatch_specs
|
|
94
|
+
mock(connection).send_head(200, :Location => '/specs')
|
|
95
|
+
mock(connection).send_body(is_a(String))
|
|
96
|
+
|
|
97
|
+
connection.receive_data("GET / HTTP/1.1\r\nHost: _\r\n\r\n")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../../unit_spec_helper")
|
|
2
|
+
|
|
3
|
+
module JsTestCore
|
|
4
|
+
module Resources
|
|
5
|
+
module Specs
|
|
6
|
+
describe SpecFile do
|
|
7
|
+
describe "GET" do
|
|
8
|
+
before do
|
|
9
|
+
WebRoot.dispatch_specs
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "GET /specs/custom_suite.html" do
|
|
13
|
+
it "renders the custom_suite.html file" do
|
|
14
|
+
path = "#{spec_root_path}/custom_suite.html"
|
|
15
|
+
mock(connection).send_head(200, 'Content-Type' => "text/html", 'Content-Length' => ::File.size(path), 'Last-Modified' => ::File.mtime(path).rfc822)
|
|
16
|
+
mock(connection).send_data(::File.read(path))
|
|
17
|
+
|
|
18
|
+
connection.receive_data("GET /specs/custom_suite.html HTTP/1.1\r\nHost: _\r\n\r\n")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "GET /specs/foo/passing_spec" do
|
|
23
|
+
it "renders a Representations::Spec with passing_spec.js as the spec file" do
|
|
24
|
+
path = "#{spec_root_path}/foo/passing_spec.js"
|
|
25
|
+
mock(connection).send_head(200, 'Content-Type' => "text/html", 'Last-Modified' => ::File.mtime(path).rfc822)
|
|
26
|
+
mock(connection).send_data(/Content-Length: /)
|
|
27
|
+
mock(connection).send_data(Regexp.new("Js Test Core Suite")) do |html|
|
|
28
|
+
doc = Nokogiri::HTML(html)
|
|
29
|
+
core_js_files = doc.search("script").map {|script| script["src"]}
|
|
30
|
+
core_js_files.should include("/specs/foo/passing_spec.js")
|
|
31
|
+
core_js_files.should_not include("/specs/foo/failing_spec.js")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
connection.receive_data("GET /specs/foo/passing_spec HTTP/1.1\r\nHost: _\r\n\r\n")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
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(:connection => connection, :public_path => public_path)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "GET /stylesheets" do
|
|
12
|
+
it "returns a page with a of files in the directory" do
|
|
13
|
+
mock(connection).send_head()
|
|
14
|
+
mock(connection).send_body(Regexp.new('<a href="example.css">example.css</a>'))
|
|
15
|
+
|
|
16
|
+
connection.receive_data("GET /stylesheets HTTP/1.1\r\nHost: _\r\n\r\n")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "GET /stylesheets/example.css" do
|
|
21
|
+
it "returns a page with a of files in the directory" do
|
|
22
|
+
path = "#{public_path}/stylesheets/example.css"
|
|
23
|
+
mock(connection).send_head(200, 'Content-Type' => "text/css", 'Content-Length' => ::File.size(path), 'Last-Modified' => ::File.mtime(path).rfc822)
|
|
24
|
+
mock(connection).send_data(::File.read(path))
|
|
25
|
+
stub(EventMachine).close_connection
|
|
26
|
+
|
|
27
|
+
connection.receive_data("GET /stylesheets/example.css HTTP/1.1\r\nHost: _\r\n\r\n")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../unit_spec_helper")
|
|
2
|
+
|
|
3
|
+
module JsTestCore
|
|
4
|
+
describe SeleniumServerConfiguration do
|
|
5
|
+
describe '#query_string' do
|
|
6
|
+
context "when not passed explicit options" do
|
|
7
|
+
it "defaults selenium_browser_start_command to '*firefox' and selenium_host to 'localhost' and selenium_port to 4444 and ignores spec_url" do
|
|
8
|
+
configuration = SeleniumServerConfiguration.new
|
|
9
|
+
configuration.query_string.should include("selenium_browser_start_command=#{CGI.escape("*firefox")}")
|
|
10
|
+
configuration.query_string.should include("selenium_host=localhost")
|
|
11
|
+
configuration.query_string.should include("selenium_port=4444")
|
|
12
|
+
configuration.query_string.should_not include("spec_url")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "when passed explicit options" do
|
|
17
|
+
attr_reader :configuration, :selenium_browser_start_command, :selenium_host, :selenium_port, :spec_url
|
|
18
|
+
before do
|
|
19
|
+
@selenium_browser_start_command = "*iexplore"
|
|
20
|
+
@selenium_host = "google.com"
|
|
21
|
+
@selenium_port = "4332"
|
|
22
|
+
@spec_url = "http://foobar.com/foo"
|
|
23
|
+
@configuration = SeleniumServerConfiguration.new(
|
|
24
|
+
:selenium_browser_start_command => selenium_browser_start_command,
|
|
25
|
+
:selenium_host => selenium_host,
|
|
26
|
+
:selenium_port => selenium_port,
|
|
27
|
+
:spec_url => spec_url
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "sets the selenium_browser_start_command option" do
|
|
32
|
+
configuration.query_string.should include("selenium_browser_start_command=#{CGI.escape(selenium_browser_start_command)}")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "sets the selenium_host option" do
|
|
36
|
+
configuration.query_string.should include("selenium_host=#{selenium_host}")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "sets the selenium_port option" do
|
|
40
|
+
configuration.query_string.should include("selenium_port=#{selenium_port}")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "sets the spec_url option" do
|
|
44
|
+
configuration.query_string.should include("spec_url=#{spec_url}")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
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 ".run" do
|
|
16
|
+
attr_reader :server_instance
|
|
17
|
+
before do
|
|
18
|
+
@server_instance = Server.instance
|
|
19
|
+
Server.instance = nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "instantiates an instance of Server and starts a Rack Thin handler" do
|
|
23
|
+
host = DEFAULT_HOST
|
|
24
|
+
port = DEFAULT_PORT
|
|
25
|
+
|
|
26
|
+
mock(EventMachine).run.yields
|
|
27
|
+
mock(EventMachine).start_server(host, port, ::Thin::JsTestCoreConnection)
|
|
28
|
+
|
|
29
|
+
Server.run(spec_root_path, implementation_root_path, public_path)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "when passed a custom host and port, sets the host and port to the passed in value" do
|
|
33
|
+
host = 'foobar.com'
|
|
34
|
+
port = 80
|
|
35
|
+
|
|
36
|
+
mock(EventMachine).run.yields
|
|
37
|
+
mock(EventMachine).start_server(host, port, ::Thin::JsTestCoreConnection)
|
|
38
|
+
|
|
39
|
+
Server.run(spec_root_path, implementation_root_path, public_path, {:Host => host, :Port => port})
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe ".spec_root" do
|
|
44
|
+
it "returns the Dir " do
|
|
45
|
+
Server.spec_root_path.should == spec_root_path
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe ".spec_root_path" do
|
|
50
|
+
it "returns the absolute path of the specs root directory" do
|
|
51
|
+
Server.spec_root_path.should == spec_root_path
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe ".public_path" do
|
|
56
|
+
it "returns the expanded path of the public path" do
|
|
57
|
+
Server.public_path.should == public_path
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe ".core_path" do
|
|
62
|
+
it "returns the expanded path to the JsTestCore core directory" do
|
|
63
|
+
Server.core_path.should == core_path
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe ".implementation_root_path" do
|
|
68
|
+
it "returns the expanded path to the JsTestCore implementations directory" do
|
|
69
|
+
dir = ::File.dirname(__FILE__)
|
|
70
|
+
Server.implementation_root_path.should == implementation_root_path
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe "#call" do
|
|
75
|
+
describe "when there is an error" do
|
|
76
|
+
attr_reader :top_line_of_backtrace
|
|
77
|
+
before do
|
|
78
|
+
@top_line_of_backtrace = __LINE__ + 2
|
|
79
|
+
stub.instance_of(Resources::WebRoot).locate('somedir') do
|
|
80
|
+
raise "Foobar"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "shows the full request path in the error message" do
|
|
85
|
+
error = nil
|
|
86
|
+
mock(connection).log_error(is_a(Exception)) do |error_arg|
|
|
87
|
+
error = error_arg
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
get('/somedir')
|
|
91
|
+
error.message.should =~ Regexp.new("/somedir")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "uses the backtrace from where the original error was raised" do
|
|
95
|
+
error = nil
|
|
96
|
+
mock(connection).log_error(is_a(Exception)) do |error_arg|
|
|
97
|
+
error = error_arg
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
get('/somedir')
|
|
101
|
+
no_error = false
|
|
102
|
+
top_of_backtrace = error.backtrace.first.split(":")
|
|
103
|
+
backtrace_file = ::File.expand_path(top_of_backtrace[0])
|
|
104
|
+
backtrace_line = Integer(top_of_backtrace[1])
|
|
105
|
+
backtrace_file.should == __FILE__
|
|
106
|
+
backtrace_line.should == top_line_of_backtrace
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe "#root_url" do
|
|
112
|
+
it "returns the url of the site's root" do
|
|
113
|
+
server.root_url.should == "http://#{server.host}:#{server.port}"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
require "rubygems"
|
|
2
|
+
require "spec"
|
|
3
|
+
|
|
4
|
+
dir = File.dirname(__FILE__)
|
|
5
|
+
$LOAD_PATH.unshift File.expand_path("#{dir}/../../lib")
|
|
6
|
+
require "js_test_core"
|
|
7
|
+
require "nokogiri"
|
|
8
|
+
require "guid"
|
|
9
|
+
|
|
10
|
+
Spec::Runner.configure do |config|
|
|
11
|
+
config.mock_with :rr
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module Spec
|
|
15
|
+
module Matchers
|
|
16
|
+
class Exist
|
|
17
|
+
def matches?(actual)
|
|
18
|
+
@actual = actual
|
|
19
|
+
!@actual.nil?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class JsTestCoreTestDir < JsTestCore::Resources::Dir
|
|
26
|
+
def get
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class Spec::ExampleGroup
|
|
32
|
+
class << self
|
|
33
|
+
def thin_logging
|
|
34
|
+
@thin_logging = true if @thin_logging.nil?
|
|
35
|
+
@thin_logging
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
attr_writer :thin_logging
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
attr_reader :core_path, :spec_root_path, :implementation_root_path, :public_path, :server, :connection
|
|
42
|
+
before(:all) do
|
|
43
|
+
dir = File.dirname(__FILE__)
|
|
44
|
+
@core_path = File.expand_path("#{dir}/../example_core")
|
|
45
|
+
JsTestCore.core_path = core_path
|
|
46
|
+
@spec_root_path = File.expand_path("#{dir}/../example_specs")
|
|
47
|
+
@implementation_root_path = File.expand_path("#{dir}/../example_public/javascripts")
|
|
48
|
+
@public_path = File.expand_path("#{dir}/../example_public")
|
|
49
|
+
stub(Thread).start.yields
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
before(:each) do
|
|
53
|
+
JsTestCore::Server.instance = JsTestCore::Server.new(spec_root_path, implementation_root_path, public_path)
|
|
54
|
+
stub(EventMachine).run do
|
|
55
|
+
raise "You need to mock calls to EventMachine.run or the process will hang"
|
|
56
|
+
end
|
|
57
|
+
stub(EventMachine).start_server do
|
|
58
|
+
raise "You need to mock calls to EventMachine.start_server or the process will hang"
|
|
59
|
+
end
|
|
60
|
+
stub(EventMachine).send_data do
|
|
61
|
+
raise "Calls to EventMachine.send_data must be mocked or stubbed"
|
|
62
|
+
end
|
|
63
|
+
@connection = create_connection
|
|
64
|
+
stub(EventMachine).send_data {raise "EventMachine.send_data must be handled"}
|
|
65
|
+
stub(EventMachine).close_connection {raise "EventMachine.close_connection must be handled"}
|
|
66
|
+
@server = JsTestCore::Server.instance
|
|
67
|
+
Thin::Logging.silent = !self.class.thin_logging
|
|
68
|
+
Thin::Logging.debug = self.class.thin_logging
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
after(:each) do
|
|
72
|
+
JsTestCore::Resources::WebRoot.dispatch_strategy = nil
|
|
73
|
+
Thin::Logging.silent = true
|
|
74
|
+
Thin::Logging.debug = false
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def create_connection(guid=Guid.new)
|
|
78
|
+
Thin::JsTestCoreConnection.new(Guid.new)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def get(url, params={})
|
|
82
|
+
request(:get, url, params)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def post(url, params={})
|
|
86
|
+
request(:post, url, params)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def put(url, params={})
|
|
90
|
+
request(:put, url, params)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def delete(url, params={})
|
|
94
|
+
request(:delete, url, params)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def env_for(method, url, params)
|
|
98
|
+
Rack::MockRequest.env_for(url, params.merge({:method => method.to_s.upcase, 'js_test_core.connection' => connection}))
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def create_request(method, path, params={})
|
|
102
|
+
body = params.map do |key, value|
|
|
103
|
+
"#{URI.escape(key)}=#{URI.escape(value)}"
|
|
104
|
+
end.join("&")
|
|
105
|
+
connection.receive_data "#{method.to_s.upcase} #{path} HTTP/1.1\r\nHost: _\r\nContent-Length: #{body.length}\r\n\r\n#{body}"
|
|
106
|
+
connection.response
|
|
107
|
+
end
|
|
108
|
+
alias_method :request, :create_request
|
|
109
|
+
|
|
110
|
+
def spec_dir(relative_path="")
|
|
111
|
+
absolute_path = spec_root_path + relative_path
|
|
112
|
+
JsTestCore::Resources::Specs::SpecDir.new(:connection => connection, :absolute_path => absolute_path, :relative_path => "/specs#{relative_path}")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def contain_spec_file_with_correct_paths(path_relative_to_spec_root)
|
|
116
|
+
expected_absolute_path = spec_root_path + path_relative_to_spec_root
|
|
117
|
+
expected_relative_path = "/specs" + path_relative_to_spec_root
|
|
118
|
+
|
|
119
|
+
::Spec::Matchers::SimpleMatcher.new(expected_relative_path) do |globbed_files|
|
|
120
|
+
file = globbed_files.find do |file|
|
|
121
|
+
file.absolute_path == expected_absolute_path
|
|
122
|
+
end
|
|
123
|
+
raise "Did not find file with absolute path of #{expected_absolute_path.inspect}" unless file
|
|
124
|
+
file.relative_path == expected_relative_path
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def stub_send_data
|
|
129
|
+
stub(EventMachine).send_data do |signature, data, data_length|
|
|
130
|
+
data_length
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
class FakeSeleniumDriver
|
|
136
|
+
SESSION_ID = "DEADBEEF"
|
|
137
|
+
attr_reader :session_id
|
|
138
|
+
|
|
139
|
+
def initialize
|
|
140
|
+
@session_id = nil
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def start
|
|
144
|
+
@session_id = SESSION_ID
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def stop
|
|
148
|
+
@session_id = nil
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def open(url)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def create_cookie(key_value, options="")
|
|
155
|
+
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def session_started?
|
|
159
|
+
!!@session_id
|
|
160
|
+
end
|
|
161
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
module ThinRest
|
|
2
|
+
class Connection < Thin::Connection
|
|
3
|
+
attr_reader :resource, :rack_request
|
|
4
|
+
|
|
5
|
+
def process
|
|
6
|
+
guard_against_errors do
|
|
7
|
+
method = rack_request.request_method.downcase.to_sym
|
|
8
|
+
@resource = get_resource
|
|
9
|
+
resource.send(method)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def rack_request
|
|
14
|
+
@rack_request ||= Rack::Request.new(@request.env)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def send_head(status=200, additional_parameters={})
|
|
18
|
+
send_data(head(status, additional_parameters))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def head(status, additional_parameters)
|
|
22
|
+
parameters = {}
|
|
23
|
+
parameters['Connection'] = "close" unless request.persistent?
|
|
24
|
+
parameters.merge!(additional_parameters)
|
|
25
|
+
head_output = parameters.inject("HTTP/1.1 #{status} OK\r\nServer: Thin Rest Server\r\n") do |header, parameter|
|
|
26
|
+
header << "#{parameter[0]}: #{parameter[1]}\r\n"
|
|
27
|
+
end
|
|
28
|
+
if additional_parameters[:'Content-Length'] || additional_parameters['Content-Length']
|
|
29
|
+
head_output << "\r\n"
|
|
30
|
+
end
|
|
31
|
+
head_output
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def send_body(data)
|
|
35
|
+
terminate_after_sending do
|
|
36
|
+
send_data("Content-Length: #{data.length}\r\n\r\n")
|
|
37
|
+
send_data(data)
|
|
38
|
+
yield(self) if block_given?
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def terminate_after_sending
|
|
43
|
+
yield
|
|
44
|
+
ensure
|
|
45
|
+
unless request.persistent?
|
|
46
|
+
close_connection_after_writing
|
|
47
|
+
end
|
|
48
|
+
terminate_request
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def unbind
|
|
52
|
+
super
|
|
53
|
+
resource.unbind if resource
|
|
54
|
+
rescue Exception => e
|
|
55
|
+
handle_error e
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def terminate_request
|
|
59
|
+
persistent = persistent?
|
|
60
|
+
@resource = nil
|
|
61
|
+
@rack_request = nil
|
|
62
|
+
@request.close rescue nil
|
|
63
|
+
@response.close rescue nil
|
|
64
|
+
|
|
65
|
+
# Prepare the connection for another request if the client
|
|
66
|
+
# supports HTTP pipelining (persistent connection).
|
|
67
|
+
if persistent
|
|
68
|
+
post_init
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def persistent?
|
|
73
|
+
request.persistent?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def handle_error(error)
|
|
77
|
+
log_error error
|
|
78
|
+
Resources::InternalError.new(:connection => self, :error => error).get
|
|
79
|
+
rescue Exception => unexpected_error
|
|
80
|
+
log_error unexpected_error
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
protected
|
|
84
|
+
def guard_against_errors
|
|
85
|
+
yield
|
|
86
|
+
rescue RoutingError => e
|
|
87
|
+
handle_error e
|
|
88
|
+
rescue Exception => e
|
|
89
|
+
wrapped_error = Exception.new("Error in #{rack_request.path_info} : #{e.message}")
|
|
90
|
+
wrapped_error.set_backtrace(e.backtrace)
|
|
91
|
+
handle_error wrapped_error
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def get_resource
|
|
95
|
+
path_parts.inject(root_resource) do |resource, child_resource_name|
|
|
96
|
+
resource.locate(child_resource_name)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def root_resource
|
|
101
|
+
raise NotImplementedError
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def path_parts
|
|
105
|
+
rack_request.path_info.split('/').reject { |part| part == "" }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def error_message(e)
|
|
109
|
+
output = "Error in Connection#receive_line\n"
|
|
110
|
+
output << "#{e.message}\n"
|
|
111
|
+
output << e.backtrace.join("\n\t")
|
|
112
|
+
output << "\n\nResource was:\n\t"
|
|
113
|
+
output << "#{resource.inspect}\n"
|
|
114
|
+
output
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# From Mauricio Fernandez.
|
|
2
|
+
class Object
|
|
3
|
+
module InstanceExecHelper; end
|
|
4
|
+
include InstanceExecHelper
|
|
5
|
+
def instance_exec(*args, &block)
|
|
6
|
+
begin
|
|
7
|
+
old_critical, Thread.critical = Thread.critical, true
|
|
8
|
+
n = 0
|
|
9
|
+
n += 1 while respond_to?(mname="__instance_exec#{n}")
|
|
10
|
+
InstanceExecHelper.module_eval{ define_method(mname, &block) }
|
|
11
|
+
ensure
|
|
12
|
+
Thread.critical = old_critical
|
|
13
|
+
end
|
|
14
|
+
begin
|
|
15
|
+
ret = send(mname, *args)
|
|
16
|
+
ensure
|
|
17
|
+
InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
|
|
18
|
+
end
|
|
19
|
+
ret
|
|
20
|
+
end
|
|
21
|
+
end
|