pivotal-screw-unit 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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