honkster-js-test-server 0.2.9

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 (78) hide show
  1. data/CHANGES +40 -0
  2. data/Gemfile +21 -0
  3. data/Gemfile.lock +60 -0
  4. data/README.markdown +9 -0
  5. data/Rakefile +67 -0
  6. data/bin/jasmine-server +9 -0
  7. data/bin/js-test-client +8 -0
  8. data/bin/js-test-server +9 -0
  9. data/bin/screw-unit-server +9 -0
  10. data/lib/js_test_server.rb +29 -0
  11. data/lib/js_test_server/client.rb +23 -0
  12. data/lib/js_test_server/client/runner.rb +130 -0
  13. data/lib/js_test_server/configuration.rb +69 -0
  14. data/lib/js_test_server/server.rb +14 -0
  15. data/lib/js_test_server/server/app.rb +10 -0
  16. data/lib/js_test_server/server/resources.rb +14 -0
  17. data/lib/js_test_server/server/resources/file.rb +58 -0
  18. data/lib/js_test_server/server/resources/framework_file.rb +15 -0
  19. data/lib/js_test_server/server/resources/implementations_deprecation.rb +8 -0
  20. data/lib/js_test_server/server/resources/not_found.rb +25 -0
  21. data/lib/js_test_server/server/resources/remote_control.rb +80 -0
  22. data/lib/js_test_server/server/resources/resource.rb +12 -0
  23. data/lib/js_test_server/server/resources/spec_file.rb +47 -0
  24. data/lib/js_test_server/server/resources/web_root.rb +17 -0
  25. data/lib/js_test_server/server/runner.rb +77 -0
  26. data/lib/js_test_server/server/standalone.ru +1 -0
  27. data/lib/js_test_server/server/views.rb +12 -0
  28. data/lib/js_test_server/server/views/dir.html.rb +22 -0
  29. data/lib/js_test_server/server/views/frameworks.rb +3 -0
  30. data/lib/js_test_server/server/views/not_found.html.rb +13 -0
  31. data/lib/js_test_server/server/views/page.html.rb +40 -0
  32. data/lib/js_test_server/server/views/remote_control_subscriber.rb +17 -0
  33. data/lib/js_test_server/server/views/suite.html.rb +54 -0
  34. data/lib/js_test_server/server/views/suites.rb +6 -0
  35. data/lib/js_test_server/server/views/suites/jasmine.html.rb +30 -0
  36. data/lib/js_test_server/server/views/suites/screw_unit.html.rb +44 -0
  37. data/public/js_test_server.js +565 -0
  38. data/public/js_test_server/jasmine_driver.js +63 -0
  39. data/public/js_test_server/remote_control.js +28 -0
  40. data/public/js_test_server/screw_unit_driver.js +31 -0
  41. data/scratch.rb +8 -0
  42. data/spec/frameworks/jasmine/cruise_config.rb +21 -0
  43. data/spec/frameworks/jasmine/spec/jasmine_helper.rb +44 -0
  44. data/spec/frameworks/jasmine/spec/jasmine_spec.rb +31 -0
  45. data/spec/functional/functional_spec_helper.rb +55 -0
  46. data/spec/functional/functional_spec_server_starter.rb +69 -0
  47. data/spec/functional/jasmine/jasmine_functional_spec.rb +27 -0
  48. data/spec/functional/screw-unit/screw_unit_functional_spec.rb +27 -0
  49. data/spec/functional_suite.rb +16 -0
  50. data/spec/spec_helpers/be_http.rb +32 -0
  51. data/spec/spec_helpers/example_group.rb +41 -0
  52. data/spec/spec_helpers/fake_deferrable.rb +3 -0
  53. data/spec/spec_helpers/fake_selenium_driver.rb +16 -0
  54. data/spec/spec_helpers/mock_session.rb +30 -0
  55. data/spec/spec_helpers/show_test_exceptions.rb +22 -0
  56. data/spec/spec_helpers/wait_for.rb +11 -0
  57. data/spec/spec_suite.rb +3 -0
  58. data/spec/unit/js_test_core/client/runner_spec.rb +198 -0
  59. data/spec/unit/js_test_core/configuration_spec.rb +44 -0
  60. data/spec/unit/js_test_core/resources/file_spec.rb +79 -0
  61. data/spec/unit/js_test_core/resources/framework_file_spec.rb +58 -0
  62. data/spec/unit/js_test_core/resources/implementations_deprecation_spec.rb +16 -0
  63. data/spec/unit/js_test_core/resources/not_found_spec.rb +49 -0
  64. data/spec/unit/js_test_core/resources/remote_control_spec.rb +117 -0
  65. data/spec/unit/js_test_core/resources/spec_file_spec.rb +147 -0
  66. data/spec/unit/js_test_core/resources/web_root_spec.rb +26 -0
  67. data/spec/unit/js_test_core/server/server_spec.rb +103 -0
  68. data/spec/unit/unit_spec_helper.rb +34 -0
  69. data/spec/unit_suite.rb +10 -0
  70. data/vendor/lucky-luciano/lib/lucky_luciano.rb +5 -0
  71. data/vendor/lucky-luciano/lib/lucky_luciano/resource.rb +142 -0
  72. data/vendor/lucky-luciano/lib/lucky_luciano/resource/path.rb +24 -0
  73. data/vendor/lucky-luciano/lib/lucky_luciano/rspec.rb +4 -0
  74. data/vendor/lucky-luciano/lib/lucky_luciano/rspec/be_http.rb +32 -0
  75. data/vendor/lucky-luciano/spec/lucky_luciano/resource_spec.rb +276 -0
  76. data/vendor/lucky-luciano/spec/spec_helper.rb +48 -0
  77. data/vendor/lucky-luciano/spec/spec_suite.rb +4 -0
  78. metadata +146 -0
@@ -0,0 +1,34 @@
1
+ require "rubygems"
2
+ require "spec"
3
+ require "spec/autorun"
4
+ require "rack/test"
5
+ require "rr"
6
+ ARGV.push("-b", "--format", "nested")
7
+
8
+ dir = File.dirname(__FILE__)
9
+ LIBRARY_ROOT_DIR = File.expand_path("#{dir}/../..")
10
+ $LOAD_PATH.unshift File.expand_path("#{LIBRARY_ROOT_DIR}/lib")
11
+ require "js_test_server"
12
+ require "nokogiri"
13
+ require "guid"
14
+ require "thin"
15
+ require "js_test_server"
16
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/be_http"
17
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/wait_for"
18
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/example_group"
19
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/fake_selenium_driver"
20
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/show_test_exceptions"
21
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/fake_deferrable"
22
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/mock_session"
23
+
24
+ Spec::Runner.configure do |config|
25
+ config.mock_with RR::Adapters::Rspec
26
+ end
27
+
28
+ Sinatra::Application.use ShowTestExceptions
29
+ Sinatra::Application.set :raise_errors, true
30
+ Sinatra::Application.set :show_exceptions, false
31
+ JsTestServer::Server::App.set :raise_errors, true
32
+ JsTestServer::Server::App.set :show_exceptions, false
33
+
34
+ Sinatra::Application.use(JsTestServer::Server::App)
@@ -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,5 @@
1
+ require "sinatra/base"
2
+
3
+ dir = File.dirname(__FILE__)
4
+ require "#{dir}/lucky_luciano/resource"
5
+ require "#{dir}/lucky_luciano/resource/path"
@@ -0,0 +1,142 @@
1
+ module LuckyLuciano
2
+ class Resource
3
+ class << self
4
+ attr_reader :base_path_definition
5
+
6
+ def map(base_path_definition)
7
+ @base_path_definition = base_path_definition
8
+ end
9
+
10
+ def recorded_http_handlers
11
+ @recorded_http_handlers ||= []
12
+ end
13
+
14
+ def route_handler
15
+ create_sinatra_handler
16
+ end
17
+
18
+ ["get", "put", "post", "delete"].each do |http_verb|
19
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
20
+ def #{http_verb}(relative_path, opts={}, &block)
21
+ recorded_http_handlers << [:#{http_verb}, relative_path, opts, block]
22
+ end
23
+ RUBY
24
+ end
25
+
26
+ def [](sub_path=nil)
27
+ Path.new(self, sub_path)
28
+ end
29
+
30
+ def path(*sub_paths)
31
+ params = sub_paths.last.is_a?(Hash) ? sub_paths.pop : {}
32
+
33
+ sub_path_definition = sub_paths.join("/")
34
+
35
+ full_path = normalize_seperators("#{base_path(params)}/#{path_from_definition(sub_path_definition, params)}").gsub(/\/$/, "")
36
+
37
+ base_path_param_keys = param_keys_from(base_path_definition)
38
+ query_params = params.delete_if do |key, value|
39
+ base_path_param_keys.include?(key)
40
+ end
41
+
42
+ sub_path_param_keys = param_keys_from(sub_path_definition)
43
+ query_params = params.delete_if do |key, value|
44
+ sub_path_param_keys.include?(key)
45
+ end
46
+
47
+ if query_params.empty?
48
+ full_path
49
+ else
50
+ query = build_query(query_params)
51
+ "#{full_path}?#{query}"
52
+ end
53
+ end
54
+
55
+ def base_path(params={})
56
+ path_from_definition(base_path_definition, params)
57
+ end
58
+
59
+ def normalize_seperators(url)
60
+ url.gsub(Regexp.new("//+"), '/')
61
+ end
62
+
63
+ protected
64
+
65
+ def path_from_definition(definition, params={})
66
+ param_keys = param_keys_from(definition)
67
+ if param_keys.empty?
68
+ definition.dup
69
+ else
70
+ param_keys.each do |base_path_param|
71
+ unless params.include?(base_path_param.to_sym)
72
+ raise ArgumentError, "Expected #{base_path_param.inspect} to have a value"
73
+ end
74
+ end
75
+ definition.split("/").map do |segment|
76
+ if param_key = segment_param_key(segment)
77
+ params[param_key]
78
+ else
79
+ segment
80
+ end
81
+ end.join("/")
82
+ end
83
+ end
84
+
85
+ def param_keys_from(definition)
86
+ definition.split("/").find_all do |segment|
87
+ segment_param_key(segment)
88
+ end.map do |param|
89
+ param[1..-1].to_sym
90
+ end
91
+ end
92
+
93
+ def segment_param_key(segment)
94
+ segment[0..0] == ':' ? segment[1..-1].to_sym : nil
95
+ end
96
+
97
+ def build_query(params)
98
+ params.to_a.inject([]) do |splatted_params, (key, value)|
99
+ [value].flatten.each do |value_in_param|
100
+ splatted_params << "#{URI.escape(key.to_s)}=#{URI.escape(value_in_param.to_s)}"
101
+ end
102
+ splatted_params
103
+ end.join("&")
104
+ end
105
+
106
+ def create_sinatra_handler
107
+ resource_class = self
108
+ Module.new do
109
+ (class << self; self; end).class_eval do
110
+ define_method(:registered) do |app|
111
+ resource_class.recorded_http_handlers.each do |handler|
112
+ verb, relative_path, opts, block = handler
113
+ full_path = resource_class.normalize_seperators(
114
+ "#{resource_class.base_path_definition}/#{relative_path}"
115
+ ).gsub(%r{^.+/$}) do |match|
116
+ match.gsub(%r{/$}, "")
117
+ end
118
+ app.send(verb, full_path, opts) do
119
+ resource_class.new(self).instance_eval(&block)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ attr_reader :app
129
+
130
+ def initialize(app)
131
+ @app = app
132
+ end
133
+
134
+ def method_missing(method_name, *args, &block)
135
+ if app.respond_to?(method_name)
136
+ app.send(method_name, *args, &block)
137
+ else
138
+ super
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,24 @@
1
+ class LuckyLuciano::Resource::Path
2
+ attr_reader :resource, :sub_paths
3
+ def initialize(resource, *sub_paths)
4
+ @resource = resource
5
+ @sub_paths = sub_paths
6
+ end
7
+
8
+ def =~(other)
9
+ to_s =~ other
10
+ end
11
+
12
+ def [](*additional_sub_paths)
13
+ sub_paths.push(*additional_sub_paths)
14
+ self
15
+ end
16
+
17
+ def to_s
18
+ resource.path(*sub_paths)
19
+ end
20
+
21
+ def ==(other)
22
+ to_s == other.to_s
23
+ end
24
+ end
@@ -0,0 +1,4 @@
1
+ dir = File.dirname(__FILE__)
2
+ Dir["#{dir}/rspec/**/*.rb"].each do |file|
3
+ require file
4
+ end
@@ -0,0 +1,32 @@
1
+ module BeHttp
2
+ include Spec::Matchers
3
+ def be_http(status, headers, body)
4
+ SimpleMatcher.new(nil) do |given, matcher|
5
+ description = (<<-DESC).gsub(/^ +/, "")
6
+ be an http of
7
+ expected status: #{status.inspect}
8
+ actual status : #{given.status.inspect}
9
+
10
+ expected headers containing: #{headers.inspect}
11
+ actual headers : #{given.headers.inspect}
12
+
13
+ expected body containing: #{body.inspect}
14
+ actual body : #{given.body.inspect}
15
+ DESC
16
+ matcher.failure_message = description
17
+ matcher.negative_failure_message = "not #{description}"
18
+
19
+ passed = true
20
+ unless given.status == status
21
+ passed = false
22
+ end
23
+ unless headers.all?{|k, v| given.headers[k] == headers[k]}
24
+ passed = false
25
+ end
26
+ unless body.is_a?(Regexp) ? given.body =~ body : given.body.include?(body)
27
+ passed = false
28
+ end
29
+ passed
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,276 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module LuckyLuciano
4
+ module ResourceSpec
5
+ class Root < Resource
6
+ map "/"
7
+ end
8
+
9
+ class ResourceFixture < Resource
10
+ map "/foobar"
11
+ end
12
+
13
+ class ResourceFixtureWithSubPaths < Resource
14
+ map "/foobar/"
15
+
16
+ get "/baz" do
17
+ "Response from /foobar/baz"
18
+ end
19
+
20
+ get "/users/:user_id" do
21
+ "User id is #{params[:user_id]}"
22
+ end
23
+ end
24
+
25
+ class User < Resource
26
+ map "/users/:user_id"
27
+
28
+ get "/friends" do
29
+ "User #{params['user_id']} friends"
30
+ end
31
+ end
32
+
33
+ describe Resource do
34
+ include ResourceSpec
35
+
36
+ before do
37
+ ResourceFixture.recorded_http_handlers.clear
38
+ end
39
+
40
+ macro("http verb") do |verb|
41
+ describe ".#{verb}" do
42
+ context "" do
43
+ before do
44
+ ResourceFixture.send(verb, "/") do
45
+ "He sleeps with the fishes"
46
+ end
47
+ end
48
+
49
+ it "creates a route to #{verb.upcase} the given path that executes the given block" do
50
+ app.register(ResourceFixture.route_handler)
51
+ response = send(verb, "/foobar")
52
+ response.should be_http( 200, {}, "He sleeps with the fishes" )
53
+ end
54
+ end
55
+
56
+ context "when the base path is blank and the relative path is blank" do
57
+ before do
58
+ Root.send(verb, "") do
59
+ "Response from /"
60
+ end
61
+ end
62
+
63
+ it "creates a route to /" do
64
+ app.register(Root.route_handler)
65
+ response = send(verb, "/")
66
+ response.should be_http( 200, {}, "Response from /" )
67
+ end
68
+ end
69
+
70
+ context "when the relative path does not have a leading slash" do
71
+ before do
72
+ ResourceFixtureWithSubPaths.send(verb, "no_leading_slash") do
73
+ "Response from /foobar/no_leading_slash"
74
+ end
75
+ end
76
+
77
+ it "creates a route to #{verb.upcase} the given path that executes the given block" do
78
+ app.register(ResourceFixtureWithSubPaths.route_handler)
79
+ response = send(verb, "/foobar/no_leading_slash")
80
+ response.should be_http( 200, {}, "Response from /foobar/no_leading_slash" )
81
+ end
82
+ end
83
+
84
+
85
+ it "does not respond to another type of http request" do
86
+ ResourceFixture.send(verb, "/") do
87
+ ""
88
+ end
89
+ app.register(ResourceFixture.route_handler)
90
+ get("/foobar").status.should == 404 unless verb == "get"
91
+ put("/foobar").status.should == 404 unless verb == "put"
92
+ post("/foobar").status.should == 404 unless verb == "post"
93
+ delete("/foobar").status.should == 404 unless verb == "delete"
94
+ end
95
+
96
+ describe "Instance behavior" do
97
+ attr_reader :evaluation_target
98
+ before do
99
+ evaluation_target = nil
100
+ ResourceFixture.send(verb, "/") do
101
+ evaluation_target = self
102
+ ""
103
+ end
104
+ app.register(ResourceFixture.route_handler)
105
+
106
+ send(verb, "/foobar")
107
+ @evaluation_target = evaluation_target
108
+ end
109
+
110
+ it "evaluates the block in as a Resource" do
111
+ evaluation_target.class.should == ResourceFixture
112
+ end
113
+
114
+ it "sets app to be the Sinatra context" do
115
+ evaluation_target.app.class.should == Sinatra::Application
116
+ end
117
+
118
+ it "delegates methods to the #app" do
119
+ return_value = nil
120
+ mock.proxy(evaluation_target.app).params {|val| return_value = val}
121
+ evaluation_target.params.should == return_value
122
+ end
123
+
124
+ context "when the #app does not respond to the method" do
125
+ it "raises a NoMethodError from the Resource's perspective" do
126
+ lambda do
127
+ evaluation_target.i_dont_exist
128
+ end.should raise_error(NoMethodError, /ResourceFixture/)
129
+ end
130
+ end
131
+ end
132
+
133
+ end
134
+ end
135
+
136
+ send("http verb", "get")
137
+ send("http verb", "put")
138
+ send("http verb", "post")
139
+ send("http verb", "delete")
140
+
141
+ describe ".[][]" do
142
+ context "when passed nothing" do
143
+ it "returns the base_path" do
144
+ ResourceFixture[].should == "/foobar"
145
+ ResourceFixture[][].should == "/foobar"
146
+ end
147
+ end
148
+
149
+ context "when passed a sub path" do
150
+ it "merges the base_path into the sub path, regardless of a / in front" do
151
+ ResourceFixtureWithSubPaths["/baz"].to_s.should == "/foobar/baz"
152
+ ResourceFixtureWithSubPaths["baz"].to_s.should == "/foobar/baz"
153
+ end
154
+
155
+ context "when passed a multiple sub paths" do
156
+ it "joins the sub paths with '/'" do
157
+ ResourceFixtureWithSubPaths["users"][99].should == "/foobar/users/99"
158
+ end
159
+ end
160
+
161
+ context "when passed a hash as the last argument" do
162
+ context "when using a single path argument" do
163
+ it "creates url params from the hash" do
164
+ path = ResourceFixtureWithSubPaths["/users/:user_id"][:user_id => 99, :single_value_param => "single_value_param_value", 'multiple_value_param[]' => [1,2,3]]
165
+ path.should be_url("/foobar/users/99", [
166
+ "multiple_value_param[]=1",
167
+ "multiple_value_param[]=2",
168
+ "multiple_value_param[]=3",
169
+ "single_value_param=single_value_param_value",
170
+ ])
171
+ end
172
+ end
173
+
174
+ context "when using multiple path arguments" do
175
+ it "creates url params from the hash" do
176
+ path = ResourceFixtureWithSubPaths["users"][99][:single_value_param => "single_value_param_value", 'multiple_value_param[]' => [1,2,3]]
177
+ path.should be_url("/foobar/users/99", [
178
+ "multiple_value_param[]=1",
179
+ "multiple_value_param[]=2",
180
+ "multiple_value_param[]=3",
181
+ "single_value_param=single_value_param_value",
182
+ ])
183
+ end
184
+ end
185
+
186
+ def be_url(expected_path, expected_query_parts)
187
+ Spec::Matchers::SimpleMatcher.new("match url") do |actual|
188
+ uri = URI.parse(actual.to_s)
189
+ uri.path.should == expected_path
190
+ query_parts = uri.query.split("&")
191
+ query_parts.should =~ expected_query_parts
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ describe ".path" do
199
+ context "when passed nothing" do
200
+ it "returns the base_path" do
201
+ ResourceFixture.path.should == "/foobar"
202
+ end
203
+ end
204
+
205
+ context "when passed a sub path" do
206
+ it "merges the base_path into the sub path, regardless of a / in front" do
207
+ ResourceFixtureWithSubPaths.path("/baz").should == "/foobar/baz"
208
+ ResourceFixtureWithSubPaths.path("baz").should == "/foobar/baz"
209
+ end
210
+
211
+ context "when passed a multiple sub paths" do
212
+ it "joins the sub paths with '/'" do
213
+ ResourceFixtureWithSubPaths.path("users", 99).should == "/foobar/users/99"
214
+ end
215
+ end
216
+
217
+ context "when passed a hash as the last argument" do
218
+ context "when using a single path argument" do
219
+ it "creates url params from the hash" do
220
+ path = ResourceFixtureWithSubPaths.path(
221
+ "/users/:user_id", {:user_id => 99, :single_value_param => "single_value_param_value", 'multiple_value_param[]' => [1,2,3]}
222
+ )
223
+ uri = URI.parse(path)
224
+ uri.path.should == "/foobar/users/99"
225
+ query_parts = uri.query.split("&")
226
+ query_parts.should =~ [
227
+ "multiple_value_param[]=1",
228
+ "multiple_value_param[]=2",
229
+ "multiple_value_param[]=3",
230
+ "single_value_param=single_value_param_value",
231
+ ]
232
+ end
233
+ end
234
+
235
+ context "when using multiple path arguments" do
236
+ it "creates url params from the hash" do
237
+ path = ResourceFixtureWithSubPaths.path(
238
+ "users", 99, {:single_value_param => "single_value_param_value", 'multiple_value_param[]' => [1,2,3]}
239
+ )
240
+ uri = URI.parse(path)
241
+ uri.path.should == "/foobar/users/99"
242
+ query_parts = uri.query.split("&")
243
+ query_parts.should =~ [
244
+ "multiple_value_param[]=1",
245
+ "multiple_value_param[]=2",
246
+ "multiple_value_param[]=3",
247
+ "single_value_param=single_value_param_value",
248
+ ]
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ context "when the base_path contains a parameter" do
255
+ context "when not passed" do
256
+ it "raises an ArgumentError" do
257
+ lambda do
258
+ User.path
259
+ end.should raise_error(
260
+ ArgumentError,
261
+ %r{Expected :user_id to have a value}
262
+ )
263
+ end
264
+ end
265
+
266
+ context "when first argument is a hash" do
267
+ it "returns the full path with the base path param value" do
268
+ User.path("friends", :user_id => 99).should == "/users/99/friends"
269
+ end
270
+ end
271
+ end
272
+ end
273
+ end
274
+ end
275
+
276
+ end