js-test-server 0.2.1 → 0.2.6
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 +3 -2
- data/Rakefile +12 -5
- data/lib/js_test_server/configuration.rb +2 -2
- data/lib/js_test_server/server.rb +1 -1
- data/lib/js_test_server/server/resources/file.rb +1 -1
- data/lib/js_test_server/server/resources/not_found.rb +1 -1
- data/lib/js_test_server/server/resources/remote_control.rb +1 -1
- data/lib/js_test_server/server/resources/spec_file.rb +1 -1
- data/lib/js_test_server/server/runner.rb +15 -0
- data/lib/js_test_server/server/standalone.ru +1 -0
- data/lib/js_test_server/server/views.rb +12 -0
- data/lib/js_test_server/server/{representations → views}/dir.html.rb +1 -1
- data/lib/js_test_server/server/{representations → views}/frameworks.rb +0 -0
- data/lib/js_test_server/server/{representations → views}/not_found.html.rb +1 -1
- data/lib/js_test_server/server/{representations → views}/page.html.rb +1 -1
- data/lib/js_test_server/server/{representations → views}/remote_control_subscriber.rb +2 -2
- data/lib/js_test_server/server/{representations → views}/suite.html.rb +1 -1
- data/lib/js_test_server/server/{representations → views}/suites.rb +1 -1
- data/lib/js_test_server/server/{representations → views}/suites/jasmine.html.rb +2 -2
- data/lib/js_test_server/server/{representations → views}/suites/screw_unit.html.rb +6 -7
- data/public/js_test_server.js +568 -0
- data/public/js_test_server/jasmine_driver.js +62 -0
- data/public/js_test_server/remote_control.js +28 -0
- data/public/js_test_server/screw_unit_driver.js +31 -0
- data/spec/unit/js_test_core/resources/spec_file_spec.rb +4 -4
- data/spec/unit/js_test_core/server/server_spec.rb +38 -2
- data/vendor/lucky-luciano/lib/lucky_luciano.rb +5 -0
- data/vendor/lucky-luciano/lib/lucky_luciano/resource.rb +142 -0
- data/vendor/lucky-luciano/lib/lucky_luciano/resource/path.rb +24 -0
- data/vendor/lucky-luciano/lib/lucky_luciano/rspec.rb +4 -0
- data/vendor/lucky-luciano/lib/lucky_luciano/rspec/be_http.rb +32 -0
- data/vendor/lucky-luciano/spec/lucky_luciano/resource_spec.rb +276 -0
- data/vendor/lucky-luciano/spec/spec_helper.rb +48 -0
- data/vendor/lucky-luciano/spec/spec_suite.rb +4 -0
- metadata +60 -28
- data/lib/js_test_server/server/representations.rb +0 -12
@@ -0,0 +1,62 @@
|
|
1
|
+
JsTestServer.JasmineDriver = {};
|
2
|
+
|
3
|
+
JsTestServer.JasmineDriver.init = function() {
|
4
|
+
JsTestServer.JasmineDriver.instance = new JsTestServer.JasmineDriver.Instance();
|
5
|
+
JsTestServer.JasmineDriver.instance.start();
|
6
|
+
};
|
7
|
+
|
8
|
+
JsTestServer.JasmineDriver.Instance = function() {
|
9
|
+
};
|
10
|
+
|
11
|
+
(function(Instance) {
|
12
|
+
var jsTestServerConsole = "";
|
13
|
+
var reporter;
|
14
|
+
|
15
|
+
Instance.prototype.start = function() {
|
16
|
+
this.addJasmineReporter();
|
17
|
+
this.defineStatusMethod();
|
18
|
+
this.startJasmine();
|
19
|
+
};
|
20
|
+
|
21
|
+
Instance.prototype.addJasmineReporter = function() {
|
22
|
+
reporter = new JsTestServer.JasmineDriver.Reporter();
|
23
|
+
jasmine.getEnv().addReporter(reporter);
|
24
|
+
};
|
25
|
+
|
26
|
+
Instance.prototype.defineStatusMethod = function() {
|
27
|
+
JsTestServer.status = function() {
|
28
|
+
var runnerState;
|
29
|
+
if(jasmine.getEnv().currentRunner.finished) {
|
30
|
+
if(jasmine.getEnv().currentRunner.getResults().failedCount == 0) {
|
31
|
+
runnerState = "passed";
|
32
|
+
} else {
|
33
|
+
runnerState = "failed";
|
34
|
+
}
|
35
|
+
} else {
|
36
|
+
runnerState = "running";
|
37
|
+
}
|
38
|
+
|
39
|
+
return JsTestServer.JSON.stringify({
|
40
|
+
"runner_state": runnerState,
|
41
|
+
"console": jsTestServerConsole
|
42
|
+
});
|
43
|
+
};
|
44
|
+
};
|
45
|
+
|
46
|
+
Instance.prototype.startJasmine = function() {
|
47
|
+
var jasmineEnv = jasmine.getEnv();
|
48
|
+
var jsApiReporter = new jasmine.JsApiReporter();
|
49
|
+
jasmineEnv.addReporter(jsApiReporter);
|
50
|
+
jasmineEnv.addReporter(new jasmine.TrivialReporter());
|
51
|
+
window.onload = function() {
|
52
|
+
jasmineEnv.execute();
|
53
|
+
};
|
54
|
+
};
|
55
|
+
|
56
|
+
JsTestServer.JasmineDriver.Reporter = function() {
|
57
|
+
};
|
58
|
+
JsTestServer.JasmineDriver.Reporter.prototype.log = function(str) {
|
59
|
+
jsTestServerConsole += str;
|
60
|
+
jsTestServerConsole += "\n";
|
61
|
+
};
|
62
|
+
})(JsTestServer.JasmineDriver.Instance);
|
@@ -0,0 +1,28 @@
|
|
1
|
+
(function() {
|
2
|
+
JsTestServer.RemoteControl = function() {
|
3
|
+
};
|
4
|
+
|
5
|
+
JsTestServer.RemoteControl.start = function() {
|
6
|
+
var instance = new JsTestServer.RemoteControl();
|
7
|
+
instance.start();
|
8
|
+
};
|
9
|
+
|
10
|
+
JsTestServer.RemoteControl.prototype.start = function() {
|
11
|
+
this.poll();
|
12
|
+
};
|
13
|
+
|
14
|
+
JsTestServer.RemoteControl.prototype.poll = function() {
|
15
|
+
var self = this;
|
16
|
+
JsTestServer.xhrGet("/remote_control/commands", function(request) {
|
17
|
+
if(request.status == 200) {
|
18
|
+
var messages = eval(request.responseText);
|
19
|
+
for(var i=0; i < messages.length; i++) {
|
20
|
+
eval(messages[i].javascript);
|
21
|
+
}
|
22
|
+
setTimeout(function() {
|
23
|
+
self.poll();
|
24
|
+
}, 100);
|
25
|
+
};
|
26
|
+
});
|
27
|
+
};
|
28
|
+
})();
|
@@ -0,0 +1,31 @@
|
|
1
|
+
(function($) {
|
2
|
+
var jsTestServerStatus = {"runner_state": "running", "console": ""};
|
3
|
+
|
4
|
+
JsTestServer.status = function() {
|
5
|
+
return JsTestServer.JSON.stringify(jsTestServerStatus);
|
6
|
+
};
|
7
|
+
|
8
|
+
$(Screw).bind('after', function() {
|
9
|
+
var error_text = $(".error").map(function(_i, error_element) {
|
10
|
+
var element = $(error_element);
|
11
|
+
|
12
|
+
var parent_descriptions = element.parents("li.describe");
|
13
|
+
var parent_description_text = [];
|
14
|
+
|
15
|
+
for(var i=parent_descriptions.length-1; i >= 0; i--) {
|
16
|
+
parent_description_text.push($(parent_descriptions[i]).find("h1").text());
|
17
|
+
}
|
18
|
+
|
19
|
+
var it_text = element.parents("li.it").find("h2").text();
|
20
|
+
|
21
|
+
return parent_description_text.join(" ") + " " + it_text + ": " + element.text();
|
22
|
+
}).get().join("\\n");
|
23
|
+
|
24
|
+
jsTestServerStatus["console"] = error_text;
|
25
|
+
if(error_text) {
|
26
|
+
jsTestServerStatus["runner_state"] = "failed";
|
27
|
+
} else {
|
28
|
+
jsTestServerStatus["runner_state"] = "passed";
|
29
|
+
}
|
30
|
+
});
|
31
|
+
})(jQuery);
|
@@ -6,8 +6,8 @@ module JsTestServer::Server::Resources
|
|
6
6
|
attr_reader :doc
|
7
7
|
before do
|
8
8
|
JsTestServer.framework_name = "screw-unit"
|
9
|
-
JsTestServer::Server::
|
10
|
-
JsTestServer::Server::
|
9
|
+
JsTestServer::Server::Views::Suite.project_js_files += ["/javascripts/test_file_1.js", "/javascripts/test_file_2.js"]
|
10
|
+
JsTestServer::Server::Views::Suite.project_css_files += ["/stylesheets/test_file_1.css", "/stylesheets/test_file_2.css"]
|
11
11
|
|
12
12
|
response = get(SpecFile.path("/failing_spec"))
|
13
13
|
response.should be_http( 200, {}, "" )
|
@@ -16,8 +16,8 @@ module JsTestServer::Server::Resources
|
|
16
16
|
end
|
17
17
|
|
18
18
|
after do
|
19
|
-
JsTestServer::Server::
|
20
|
-
JsTestServer::Server::
|
19
|
+
JsTestServer::Server::Views::Suite.project_js_files.clear
|
20
|
+
JsTestServer::Server::Views::Suite.project_css_files.clear
|
21
21
|
end
|
22
22
|
|
23
23
|
it "renders project js files" do
|
@@ -21,7 +21,7 @@ module JsTestServer::Server
|
|
21
21
|
|
22
22
|
|
23
23
|
context "when the --framework-name and --framework-path are set" do
|
24
|
-
it "starts the server and sets SpecFile::
|
24
|
+
it "starts the server and sets SpecFile::suite_view_class to be the ScrewUnit suite" do
|
25
25
|
project_spec_dir = File.expand_path("#{File.dirname(__FILE__)}/../../..")
|
26
26
|
|
27
27
|
mock.proxy(Thin::Runner).new(["--port", "8081", "--rackup", rackup_path, "start"]) do |runner|
|
@@ -43,7 +43,43 @@ module JsTestServer::Server
|
|
43
43
|
"--port", "8081"
|
44
44
|
)
|
45
45
|
|
46
|
-
JsTestServer::Configuration.instance.
|
46
|
+
JsTestServer::Configuration.instance.suite_view_class.should == JsTestServer::Server::Views::Suites::ScrewUnit
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when --javascript-files and --css-files are set" do
|
51
|
+
it "causes the suite_view_class to load the javascript and css files" do
|
52
|
+
project_spec_dir = File.expand_path("#{File.dirname(__FILE__)}/../../..")
|
53
|
+
|
54
|
+
mock.proxy(Thin::Runner).new(["--port", "8081", "--rackup", rackup_path, "start"]) do |runner|
|
55
|
+
mock(runner).run!
|
56
|
+
end
|
57
|
+
|
58
|
+
stub.proxy(Rack::Builder).new do |builder|
|
59
|
+
mock.proxy(builder).use(JsTestServer::Server::App)
|
60
|
+
stub.proxy(builder).use
|
61
|
+
mock(builder).run(is_a(JsTestServer::Server::App))
|
62
|
+
mock(builder).run(is_a(Sinatra::Application))
|
63
|
+
end
|
64
|
+
|
65
|
+
server.cli(
|
66
|
+
"--framework-name", "screw-unit",
|
67
|
+
"--framework-path", "#{project_spec_dir}/example_framework",
|
68
|
+
"--root-path", "#{project_spec_dir}/example_root",
|
69
|
+
"--spec-path", "#{project_spec_dir}/example_spec",
|
70
|
+
"--port", "8081",
|
71
|
+
"--javascript-files", "/javascripts/foo.js,/javascipts/large_file.js,/specs/spec_helper.js",
|
72
|
+
"--css-files", "/stylesheets/example.css"
|
73
|
+
)
|
74
|
+
|
75
|
+
JsTestServer::Configuration.instance.suite_view_class.project_js_files.should == [
|
76
|
+
"/javascripts/foo.js",
|
77
|
+
"/javascipts/large_file.js",
|
78
|
+
"/specs/spec_helper.js"
|
79
|
+
]
|
80
|
+
JsTestServer::Configuration.instance.suite_view_class.project_css_files.should == [
|
81
|
+
"/stylesheets/example.css",
|
82
|
+
]
|
47
83
|
end
|
48
84
|
end
|
49
85
|
|
@@ -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,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
|