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.
Files changed (127) hide show
  1. data/CHANGES +21 -0
  2. data/README.markdown +354 -0
  3. data/Rakefile +39 -0
  4. data/VERSION.yml +4 -0
  5. data/bin/screw_unit +6 -0
  6. data/bin/screw_unit_server +10 -0
  7. data/core/CHANGES +10 -0
  8. data/core/EXAMPLE.html +68 -0
  9. data/core/LICENSE +22 -0
  10. data/core/README.markdown +307 -0
  11. data/core/example/models/cat.js +5 -0
  12. data/core/example/models/man.js +17 -0
  13. data/core/example/spec/matchers/have.js +8 -0
  14. data/core/example/spec/models/cat_spec.js +31 -0
  15. data/core/example/spec/models/man_spec.js +34 -0
  16. data/core/example/spec/spec_helper.js +5 -0
  17. data/core/example/spec/suite.html +25 -0
  18. data/core/lib/jquery-1.3.2.js +4376 -0
  19. data/core/lib/jquery.fn.js +30 -0
  20. data/core/lib/jquery.print.js +109 -0
  21. data/core/lib/screw.behaviors.js +93 -0
  22. data/core/lib/screw.builder.js +94 -0
  23. data/core/lib/screw.css +90 -0
  24. data/core/lib/screw.events.js +45 -0
  25. data/core/lib/screw.matchers.js +244 -0
  26. data/core/spec/behaviors_spec.js +188 -0
  27. data/core/spec/matchers_spec.js +372 -0
  28. data/core/spec/print_spec.js +158 -0
  29. data/core/spec/spec_helper.js +0 -0
  30. data/core/spec/suite.html +19 -0
  31. data/core/spec/with_screw_context_spec.js +9 -0
  32. data/init.rb +0 -0
  33. data/lib/screw_unit/representations/spec.html.rb +117 -0
  34. data/lib/screw_unit/representations.rb +2 -0
  35. data/lib/screw_unit.rb +19 -0
  36. data/spec/functional/functional_spec.rb +25 -0
  37. data/spec/functional/functional_spec_helper.rb +34 -0
  38. data/spec/functional/functional_spec_server_starter.rb +63 -0
  39. data/spec/functional_suite.rb +10 -0
  40. data/spec/spec_suite.rb +3 -0
  41. data/spec/unit/js_test_core/specs/spec_dir_spec.rb +39 -0
  42. data/spec/unit/js_test_core/specs/spec_file_spec.rb +35 -0
  43. data/spec/unit/unit_spec_helper.rb +119 -0
  44. data/spec/unit_suite.rb +10 -0
  45. data/vendor/js-test-core/CHANGES +25 -0
  46. data/vendor/js-test-core/README +12 -0
  47. data/vendor/js-test-core/Rakefile +73 -0
  48. data/vendor/js-test-core/lib/js_test_core/client.rb +129 -0
  49. data/vendor/js-test-core/lib/js_test_core/extensions/time.rb +6 -0
  50. data/vendor/js-test-core/lib/js_test_core/extensions.rb +3 -0
  51. data/vendor/js-test-core/lib/js_test_core/rack/commonlogger.rb +5 -0
  52. data/vendor/js-test-core/lib/js_test_core/rack.rb +2 -0
  53. data/vendor/js-test-core/lib/js_test_core/rails_server.rb +22 -0
  54. data/vendor/js-test-core/lib/js_test_core/representations/spec.html.rb +23 -0
  55. data/vendor/js-test-core/lib/js_test_core/representations.rb +9 -0
  56. data/vendor/js-test-core/lib/js_test_core/resources/dir.rb +67 -0
  57. data/vendor/js-test-core/lib/js_test_core/resources/file.rb +42 -0
  58. data/vendor/js-test-core/lib/js_test_core/resources/runner.rb +107 -0
  59. data/vendor/js-test-core/lib/js_test_core/resources/session.rb +44 -0
  60. data/vendor/js-test-core/lib/js_test_core/resources/session_finish.rb +17 -0
  61. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec.rb +32 -0
  62. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_dir.rb +50 -0
  63. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_file.rb +21 -0
  64. data/vendor/js-test-core/lib/js_test_core/resources/web_root.rb +66 -0
  65. data/vendor/js-test-core/lib/js_test_core/resources.rb +17 -0
  66. data/vendor/js-test-core/lib/js_test_core/selenium/client/driver.rb +7 -0
  67. data/vendor/js-test-core/lib/js_test_core/selenium.rb +2 -0
  68. data/vendor/js-test-core/lib/js_test_core/selenium_server_configuration.rb +48 -0
  69. data/vendor/js-test-core/lib/js_test_core/server.rb +50 -0
  70. data/vendor/js-test-core/lib/js_test_core/thin/backends/js_test_core_server.rb +9 -0
  71. data/vendor/js-test-core/lib/js_test_core/thin/js_test_core_connection.rb +8 -0
  72. data/vendor/js-test-core/lib/js_test_core/thin.rb +3 -0
  73. data/vendor/js-test-core/lib/js_test_core.rb +41 -0
  74. data/vendor/js-test-core/spec/example_core/JsTestCore.css +0 -0
  75. data/vendor/js-test-core/spec/example_core/JsTestCore.js +0 -0
  76. data/vendor/js-test-core/spec/example_public/favicon.ico +0 -0
  77. data/vendor/js-test-core/spec/example_public/javascripts/foo.js +3 -0
  78. data/vendor/js-test-core/spec/example_public/javascripts/large_file.js +59 -0
  79. data/vendor/js-test-core/spec/example_public/javascripts/subdir/bar.js +1 -0
  80. data/vendor/js-test-core/spec/example_public/robots.txt +0 -0
  81. data/vendor/js-test-core/spec/example_public/stylesheets/example.css +3 -0
  82. data/vendor/js-test-core/spec/example_specs/custom_dir_and_suite/passing_spec.js +6 -0
  83. data/vendor/js-test-core/spec/example_specs/custom_dir_and_suite.html +9 -0
  84. data/vendor/js-test-core/spec/example_specs/custom_suite.html +8 -0
  85. data/vendor/js-test-core/spec/example_specs/failing_spec.js +5 -0
  86. data/vendor/js-test-core/spec/example_specs/foo/failing_spec.js +6 -0
  87. data/vendor/js-test-core/spec/example_specs/foo/passing_spec.js +6 -0
  88. data/vendor/js-test-core/spec/spec_suite.rb +2 -0
  89. data/vendor/js-test-core/spec/specs/failing_spec.js +0 -0
  90. data/vendor/js-test-core/spec/unit/js_test_core/client_spec.rb +192 -0
  91. data/vendor/js-test-core/spec/unit/js_test_core/rails_server_spec.rb +45 -0
  92. data/vendor/js-test-core/spec/unit/js_test_core/resources/dir_spec.rb +53 -0
  93. data/vendor/js-test-core/spec/unit/js_test_core/resources/file_not_found_spec.rb +16 -0
  94. data/vendor/js-test-core/spec/unit/js_test_core/resources/file_spec.rb +90 -0
  95. data/vendor/js-test-core/spec/unit/js_test_core/resources/runners/runner_spec.rb +303 -0
  96. data/vendor/js-test-core/spec/unit/js_test_core/resources/session_finish_spec.rb +79 -0
  97. data/vendor/js-test-core/spec/unit/js_test_core/resources/session_spec.rb +82 -0
  98. data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_dir_spec.rb +104 -0
  99. data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_file_spec.rb +41 -0
  100. data/vendor/js-test-core/spec/unit/js_test_core/resources/web_root_spec.rb +32 -0
  101. data/vendor/js-test-core/spec/unit/js_test_core/selenium_server_configuration_spec.rb +49 -0
  102. data/vendor/js-test-core/spec/unit/js_test_core/server_spec.rb +117 -0
  103. data/vendor/js-test-core/spec/unit/thin/js_test_core_connection_spec.rb +6 -0
  104. data/vendor/js-test-core/spec/unit/unit_spec_helper.rb +161 -0
  105. data/vendor/js-test-core/spec/unit_suite.rb +10 -0
  106. data/vendor/js-test-core/vendor/thin-rest/CHANGES +2 -0
  107. data/vendor/js-test-core/vendor/thin-rest/README +0 -0
  108. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/connection.rb +117 -0
  109. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/extensions/object.rb +21 -0
  110. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/extensions.rb +3 -0
  111. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations/internal_error.html.rb +19 -0
  112. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations/page.html.rb +41 -0
  113. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations/resource_not_found.html.rb +18 -0
  114. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/representations.rb +4 -0
  115. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources/internal_error.rb +11 -0
  116. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources/resource.rb +105 -0
  117. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources/resource_not_found.rb +19 -0
  118. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/resources.rb +4 -0
  119. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest/routing_error.rb +5 -0
  120. data/vendor/js-test-core/vendor/thin-rest/lib/thin_rest.rb +10 -0
  121. data/vendor/js-test-core/vendor/thin-rest/spec/spec_suite.rb +5 -0
  122. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/connection_spec.rb +205 -0
  123. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resources/resource_not_found_spec.rb +16 -0
  124. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resources/resource_spec.rb +135 -0
  125. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest/resources/root_spec.rb +16 -0
  126. data/vendor/js-test-core/vendor/thin-rest/spec/thin_rest_spec_helper.rb +133 -0
  127. 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,6 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../unit_spec_helper")
2
+
3
+ module Thin
4
+ describe JsTestCoreConnection do
5
+ end
6
+ 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
@@ -0,0 +1,10 @@
1
+ class UnitSuite
2
+ def run
3
+ dir = File.dirname(__FILE__)
4
+ Dir["#{dir}/unit/**/*_spec.rb"].each do |file|
5
+ require file
6
+ end
7
+ end
8
+ end
9
+
10
+ UnitSuite.new.run
@@ -0,0 +1,2 @@
1
+ - Resource.property creates a reader that reads directly from the env hash
2
+ - Resource.property creates a writer that updates the env hash directly
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
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/extensions/*.rb"].each do |file|
2
+ require file
3
+ end