screw-unit-server 0.3.0 → 0.5.3

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 (124) hide show
  1. data/CHANGES +23 -1
  2. data/README.markdown +10 -3
  3. data/Rakefile +27 -55
  4. data/VERSION.yml +4 -0
  5. data/bin/screw_unit_server +14 -4
  6. data/core/CHANGES +10 -0
  7. data/core/EXAMPLE.html +4 -4
  8. data/core/README.markdown +7 -7
  9. data/core/example/models/man.js +2 -2
  10. data/core/example/spec/suite.html +1 -1
  11. data/core/lib/jquery-1.3.2.js +4376 -0
  12. data/core/lib/jquery.fn.js +2 -1
  13. data/core/lib/jquery.print.js +13 -12
  14. data/core/lib/screw.behaviors.js +11 -9
  15. data/core/lib/screw.builder.js +26 -11
  16. data/core/lib/screw.css +2 -2
  17. data/core/lib/screw.events.js +11 -4
  18. data/core/lib/screw.matchers.js +192 -13
  19. data/core/spec/behaviors_spec.js +11 -1
  20. data/core/spec/matchers_spec.js +288 -9
  21. data/core/spec/print_spec.js +47 -8
  22. data/core/spec/suite.html +2 -1
  23. data/core/spec/with_screw_context_spec.js +9 -0
  24. data/lib/screw_unit.rb +13 -16
  25. data/lib/screw_unit/representations.rb +2 -0
  26. data/lib/screw_unit/representations/spec.html.rb +117 -0
  27. data/spec/functional/functional_spec.rb +14 -3
  28. data/spec/functional/functional_spec_helper.rb +22 -34
  29. data/spec/functional/functional_spec_server_starter.rb +68 -0
  30. data/spec/unit/js_test_core/specs/spec_file_spec.rb +45 -20
  31. data/spec/unit/unit_spec_helper.rb +24 -93
  32. data/vendor/js-test-core/CHANGES +19 -0
  33. data/vendor/js-test-core/Rakefile +2 -1
  34. data/vendor/js-test-core/lib/js_test_core.rb +26 -10
  35. data/vendor/js-test-core/lib/js_test_core/app.rb +12 -0
  36. data/vendor/js-test-core/lib/js_test_core/client.rb +97 -18
  37. data/vendor/js-test-core/lib/js_test_core/configuration.rb +35 -0
  38. data/vendor/js-test-core/lib/js_test_core/extensions.rb +3 -0
  39. data/vendor/js-test-core/lib/js_test_core/extensions/selenium/client/driver.rb +7 -0
  40. data/vendor/js-test-core/lib/js_test_core/extensions/time.rb +6 -0
  41. data/vendor/js-test-core/lib/js_test_core/models.rb +8 -0
  42. data/vendor/js-test-core/lib/js_test_core/models/selenium_session.rb +80 -0
  43. data/vendor/js-test-core/lib/js_test_core/representations.rb +11 -0
  44. data/vendor/js-test-core/lib/js_test_core/representations/dir.html.rb +24 -0
  45. data/vendor/js-test-core/lib/js_test_core/representations/not_found.html.rb +15 -0
  46. data/vendor/js-test-core/lib/js_test_core/representations/page.html.rb +41 -0
  47. data/vendor/js-test-core/lib/js_test_core/representations/spec.html.rb +24 -0
  48. data/vendor/js-test-core/lib/js_test_core/resources.rb +13 -8
  49. data/vendor/js-test-core/lib/js_test_core/resources/core_file.rb +19 -0
  50. data/vendor/js-test-core/lib/js_test_core/resources/file.rb +44 -14
  51. data/vendor/js-test-core/lib/js_test_core/resources/implementations_deprecation.rb +12 -0
  52. data/vendor/js-test-core/lib/js_test_core/resources/not_found.rb +35 -0
  53. data/vendor/js-test-core/lib/js_test_core/resources/resource.rb +16 -0
  54. data/vendor/js-test-core/lib/js_test_core/resources/selenium_session.rb +104 -0
  55. data/vendor/js-test-core/lib/js_test_core/resources/spec_file.rb +63 -0
  56. data/vendor/js-test-core/lib/js_test_core/resources/web_root.rb +5 -56
  57. data/vendor/js-test-core/lib/js_test_core/selenium_server_configuration.rb +48 -0
  58. data/vendor/js-test-core/spec/example_core/subdir/SubDirFile.js +0 -0
  59. data/vendor/js-test-core/spec/example_public/javascripts/large_file.js +59 -0
  60. data/vendor/js-test-core/spec/example_public/javascripts/subdir/bar.js +1 -0
  61. data/vendor/js-test-core/spec/example_specs/custom_dir_and_suite/passing_spec.js +6 -0
  62. data/vendor/js-test-core/spec/example_specs/custom_suite.html +8 -0
  63. data/vendor/js-test-core/spec/example_specs/foo/failing_spec.js +1 -1
  64. data/vendor/js-test-core/spec/example_specs/foo/passing_spec.js +1 -1
  65. data/vendor/js-test-core/spec/spec_helpers/be_http.rb +32 -0
  66. data/vendor/js-test-core/spec/spec_helpers/example_group.rb +36 -0
  67. data/vendor/js-test-core/spec/spec_helpers/fake_selenium_driver.rb +27 -0
  68. data/vendor/js-test-core/spec/spec_helpers/show_test_exceptions.rb +22 -0
  69. data/vendor/js-test-core/spec/unit/js_test_core/client_spec.rb +140 -85
  70. data/vendor/js-test-core/spec/unit/js_test_core/configuration_spec.rb +44 -0
  71. data/vendor/js-test-core/spec/unit/js_test_core/models/selenium_session_spec.rb +85 -0
  72. data/vendor/js-test-core/spec/unit/js_test_core/resources/core_file_spec.rb +60 -0
  73. data/vendor/js-test-core/spec/unit/js_test_core/resources/file_spec.rb +61 -68
  74. data/vendor/js-test-core/spec/unit/js_test_core/resources/implementations_deprecation_spec.rb +18 -0
  75. data/vendor/js-test-core/spec/unit/js_test_core/resources/not_found_spec.rb +51 -0
  76. data/vendor/js-test-core/spec/unit/js_test_core/resources/selenium_session_spec.rb +362 -0
  77. data/vendor/js-test-core/spec/unit/js_test_core/resources/spec_file_spec.rb +120 -0
  78. data/vendor/js-test-core/spec/unit/js_test_core/resources/web_root_spec.rb +14 -89
  79. data/vendor/js-test-core/spec/unit/js_test_core/selenium_server_configuration_spec.rb +49 -0
  80. data/vendor/js-test-core/spec/unit/unit_spec_helper.rb +16 -113
  81. data/vendor/js-test-core/vendor/lucky-luciano/README.markdown +7 -0
  82. data/vendor/js-test-core/vendor/lucky-luciano/lib/lucky_luciano.rb +4 -0
  83. data/vendor/js-test-core/vendor/lucky-luciano/lib/lucky_luciano/resource.rb +135 -0
  84. data/vendor/js-test-core/vendor/lucky-luciano/lib/lucky_luciano/rspec.rb +4 -0
  85. data/vendor/js-test-core/vendor/lucky-luciano/lib/lucky_luciano/rspec/be_http.rb +32 -0
  86. data/vendor/js-test-core/vendor/lucky-luciano/spec/lucky_luciano/resource_spec.rb +231 -0
  87. data/vendor/js-test-core/vendor/lucky-luciano/spec/spec_helper.rb +48 -0
  88. data/vendor/js-test-core/vendor/lucky-luciano/spec/spec_suite.rb +4 -0
  89. metadata +143 -129
  90. data/core/TODO +0 -2
  91. data/core/lib/jquery-1.2.3.js +0 -3408
  92. data/core/lib/screw.assets.js +0 -36
  93. data/core/lib/screw.server.js +0 -21
  94. data/lib/screw_unit/resources.rb +0 -2
  95. data/lib/screw_unit/resources/spec.rb +0 -37
  96. data/spec/unit/js_test_core/specs/spec_dir_spec.rb +0 -43
  97. data/vendor/js-test-core/lib/js_test_core/rack.rb +0 -2
  98. data/vendor/js-test-core/lib/js_test_core/rack/commonlogger.rb +0 -5
  99. data/vendor/js-test-core/lib/js_test_core/rails_server.rb +0 -22
  100. data/vendor/js-test-core/lib/js_test_core/resources/dir.rb +0 -52
  101. data/vendor/js-test-core/lib/js_test_core/resources/file_not_found.rb +0 -15
  102. data/vendor/js-test-core/lib/js_test_core/resources/runners.rb +0 -15
  103. data/vendor/js-test-core/lib/js_test_core/resources/runners/firefox_runner.rb +0 -75
  104. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_dir.rb +0 -50
  105. data/vendor/js-test-core/lib/js_test_core/resources/specs/spec_file.rb +0 -17
  106. data/vendor/js-test-core/lib/js_test_core/resources/suite.rb +0 -24
  107. data/vendor/js-test-core/lib/js_test_core/resources/suite_finish.rb +0 -19
  108. data/vendor/js-test-core/lib/js_test_core/selenium.rb +0 -2
  109. data/vendor/js-test-core/lib/js_test_core/selenium/selenium_driver.rb +0 -5
  110. data/vendor/js-test-core/lib/js_test_core/server.rb +0 -111
  111. data/vendor/js-test-core/lib/js_test_core/thin.rb +0 -3
  112. data/vendor/js-test-core/lib/js_test_core/thin/backends/js_test_core_server.rb +0 -9
  113. data/vendor/js-test-core/lib/js_test_core/thin/js_test_core_connection.rb +0 -42
  114. data/vendor/js-test-core/spec/unit/js_test_core/rails_server_spec.rb +0 -45
  115. data/vendor/js-test-core/spec/unit/js_test_core/resources/dir_spec.rb +0 -42
  116. data/vendor/js-test-core/spec/unit/js_test_core/resources/file_not_found_spec.rb +0 -26
  117. data/vendor/js-test-core/spec/unit/js_test_core/resources/runner_spec.rb +0 -24
  118. data/vendor/js-test-core/spec/unit/js_test_core/resources/runners/firefox_runner_spec.rb +0 -197
  119. data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_dir_spec.rb +0 -79
  120. data/vendor/js-test-core/spec/unit/js_test_core/resources/specs/spec_file_spec.rb +0 -42
  121. data/vendor/js-test-core/spec/unit/js_test_core/resources/suite_finish_spec.rb +0 -94
  122. data/vendor/js-test-core/spec/unit/js_test_core/resources/suite_spec.rb +0 -44
  123. data/vendor/js-test-core/spec/unit/js_test_core/server_spec.rb +0 -131
  124. data/vendor/js-test-core/spec/unit/thin/js_test_core_connection_spec.rb +0 -92
@@ -0,0 +1,120 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
2
+
3
+ module JsTestCore
4
+ module Resources
5
+ describe SpecFile do
6
+ describe "Files" do
7
+ describe "GET /specs/failing_spec" do
8
+ it "renders a suite only for failing_spec.js as text/html" do
9
+ absolute_path = "#{spec_root_path}/failing_spec.js"
10
+
11
+ response = get(SpecFile.path("failing_spec"))
12
+ response.should be_http(
13
+ 200,
14
+ {
15
+ "Content-Type" => "text/html",
16
+ "Last-Modified" => ::File.mtime(absolute_path).rfc822
17
+ },
18
+ ""
19
+ )
20
+ doc = Nokogiri::HTML(response.body)
21
+ js_files = doc.search("script").map {|script| script["src"]}
22
+ js_files.should include("/specs/failing_spec.js")
23
+ end
24
+ end
25
+
26
+ describe "GET /specs/failing_spec.js" do
27
+ it "renders the contents of failing_spec.js as text/javascript" do
28
+ absolute_path = "#{spec_root_path}/failing_spec.js"
29
+
30
+ response = get(SpecFile.path("failing_spec.js"))
31
+ response.should be_http(
32
+ 200,
33
+ {
34
+ "Content-Type" => "text/javascript",
35
+ "Last-Modified" => ::File.mtime(absolute_path).rfc822
36
+ },
37
+ ::File.read(absolute_path)
38
+ )
39
+ end
40
+ end
41
+
42
+ describe "GET /specs/custom_suite" do
43
+ it "renders the custom_suite.html file" do
44
+ path = "#{spec_root_path}/custom_suite.html"
45
+
46
+ response = get(SpecFile.path("custom_suite.html"))
47
+ response.should be_http(
48
+ 200,
49
+ {
50
+ "Content-Type" => "text/html",
51
+ "Last-Modified" => ::File.mtime(path).rfc822
52
+ },
53
+ ::File.read(path)
54
+ )
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "Directories" do
60
+ describe "GET /specs" do
61
+ macro "renders a suite for all specs" do |relative_path|
62
+ it "renders a suite for all specs" do
63
+ path = "#{spec_root_path}"
64
+
65
+ response = get(relative_path)
66
+ response.should be_http(
67
+ 200,
68
+ {
69
+ "Content-Type" => "text/html",
70
+ "Last-Modified" => ::File.mtime(path).rfc822
71
+ },
72
+ ""
73
+ )
74
+ doc = Nokogiri::HTML(response.body)
75
+ js_files = doc.search("script").map {|script| script["src"]}
76
+ js_files.should include("/specs/failing_spec.js")
77
+ js_files.should include("/specs/custom_dir_and_suite/passing_spec.js")
78
+ js_files.should include("/specs/foo/passing_spec.js")
79
+ js_files.should include("/specs/foo/failing_spec.js")
80
+ end
81
+ end
82
+
83
+ send("renders a suite for all specs", SpecFile.path)
84
+ send("renders a suite for all specs", SpecFile.path("/"))
85
+ end
86
+
87
+ describe "GET /specs/foo" do
88
+ it "renders a spec suite that includes all of the javascript spec files in the directory" do
89
+ path = "#{spec_root_path}/foo"
90
+
91
+ response = get(SpecFile.path("foo"))
92
+ response.should be_http(
93
+ 200,
94
+ {
95
+ "Content-Type" => "text/html",
96
+ "Last-Modified" => ::File.mtime(path).rfc822
97
+ },
98
+ ""
99
+ )
100
+ doc = Nokogiri::HTML(response.body)
101
+ js_files = doc.search("script").map {|script| script["src"]}
102
+ js_files.should include("/specs/foo/passing_spec.js")
103
+ js_files.should include("/specs/foo/failing_spec.js")
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "GET /specs/i_dont_exist" do
109
+ it "renders a 404" do
110
+ response = get(SpecFile.path("i_dont_exist"))
111
+ response.should be_http(
112
+ 404,
113
+ {},
114
+ "/specs/i_dont_exist not found"
115
+ )
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -3,100 +3,25 @@ require File.expand_path("#{File.dirname(__FILE__)}/../../unit_spec_helper")
3
3
  module JsTestCore
4
4
  module Resources
5
5
  describe WebRoot do
6
- attr_reader :web_root
7
- before(:each) do
8
- @web_root = WebRoot.new(public_path)
9
- end
10
-
11
- describe "#locate" do
12
- describe "when passed ''" do
13
- it "returns self" do
14
- web_root.locate('').should == web_root
15
- end
16
- end
17
-
18
- describe "when passed 'core'" do
19
- it "returns a Dir representing the JsTestCore core directory" do
20
- runner = web_root.locate('core')
21
- runner.should == Resources::Dir.new(JsTestCore::Server.core_path, '/core')
22
- end
23
- end
24
-
25
- describe "when passed 'implementations'" do
26
- it "returns a Dir representing the javascript implementations directory" do
27
- runner = web_root.locate('implementations')
28
- runner.should == Resources::Dir.new(JsTestCore::Server.implementation_root_path, '/implementations')
29
- end
30
- end
31
-
32
- describe "when passed 'results'" do
33
- it "returns a Suite" do
34
- runner = web_root.locate('suites')
35
- runner.should == Resources::Suite
36
- end
37
- end
38
-
39
- describe "when passed 'runners'" do
40
- it "returns a Runner" do
41
- runner = web_root.locate('runners')
42
- runner.should be_instance_of(Resources::Runners)
43
- end
44
- end
45
-
46
- describe "when passed a directory that is in the public_path" do
47
- it "returns a Dir representing that directory" do
48
- runner = web_root.locate('stylesheets')
49
- runner.should == Resources::Dir.new("#{JsTestCore::Server.public_path}/stylesheets", '/stylesheets')
50
- end
51
- end
52
-
53
- describe "when passed a file that is in the public_path" do
54
- it "returns a File representing that file" do
55
- runner = web_root.locate('robots.txt')
56
- runner.should == Resources::File.new("#{JsTestCore::Server.public_path}/robots.txt", '/robots.txt')
57
- end
58
- end
59
-
60
- describe "when passed an invalid option" do
61
- it "returns a 404 response" do
62
- resource = web_root.locate('invalid')
63
-
64
- end
6
+ macro("includes a link to the spec suite") do |relative_path|
7
+ it "includes a link to the spec suite" do
8
+ response = get(relative_path)
9
+ response.should be_http(
10
+ 200,
11
+ {},
12
+ ""
13
+ )
14
+ doc = Nokogiri::HTML(response.body)
15
+ doc.css("a[href='/specs']").should_not be_nil
65
16
  end
66
17
  end
67
18
 
68
- describe ".dispatch_specs" do
69
- describe "#get" do
70
- attr_reader :request, :response
71
- before do
72
- @request = Rack::Request.new({'rack.input' => StringIO.new("")})
73
- @response = Rack::Response.new
74
- end
75
-
76
- it "redirects to /specs" do
77
- WebRoot.dispatch_specs
78
-
79
- web_root.get(request, response)
80
- response.should be_redirect
81
- response.headers["Location"].should == "/specs"
82
- end
83
- end
84
-
85
- describe "#locate /specs" do
86
- it "dispatches to a Spec::SpecDir" do
87
- WebRoot.dispatch_specs
88
-
89
- resource = web_root.locate('specs')
90
- resource.should == spec_dir('')
91
- end
92
- end
93
-
19
+ describe "GET " do
20
+ send("includes a link to the spec suite", "")
94
21
  end
95
22
 
96
- describe "when .dispatch_specs is not called" do
97
- it "does not cause #locate to dispatch to /specs" do
98
- web_root.locate('specs').should be_instance_of(FileNotFound)
99
- end
23
+ describe "GET /" do
24
+ send("includes a link to the spec suite", "/")
100
25
  end
101
26
  end
102
27
  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
@@ -1,125 +1,28 @@
1
1
  require "rubygems"
2
2
  require "spec"
3
+ require "spec/autorun"
4
+ require "rack/test"
5
+ ARGV.push("-b")
3
6
 
4
7
  dir = File.dirname(__FILE__)
5
- $LOAD_PATH.unshift "#{dir}/../../lib"
8
+ LIBRARY_ROOT_DIR = File.expand_path("#{dir}/../..")
9
+ $LOAD_PATH.unshift File.expand_path("#{LIBRARY_ROOT_DIR}/lib")
6
10
  require "js_test_core"
7
- require "hpricot"
11
+ require "nokogiri"
8
12
  require "guid"
13
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/be_http"
14
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/example_group"
15
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/fake_selenium_driver"
16
+ require "#{LIBRARY_ROOT_DIR}/spec/spec_helpers/show_test_exceptions"
9
17
 
10
18
  Spec::Runner.configure do |config|
11
19
  config.mock_with :rr
12
20
  end
13
21
 
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 Spec::Example::ExampleGroup
26
- class << self
27
- def thin_logging
28
- @thin_logging = true if @thin_logging.nil?
29
- @thin_logging
30
- end
31
-
32
- attr_writer :thin_logging
33
- end
34
- end
35
-
36
- class JsTestCoreTestDir < JsTestCore::Resources::Dir
37
- def get(request, response)
38
-
39
- end
40
- end
41
-
42
- module Spec::Example::ExampleMethods
43
- attr_reader :core_path, :spec_root_path, :implementation_root_path, :public_path, :server, :connection
44
- before(:all) do
45
- dir = File.dirname(__FILE__)
46
- @core_path = File.expand_path("#{dir}/../example_core")
47
- JsTestCore.core_path = core_path
48
- @spec_root_path = File.expand_path("#{dir}/../example_specs")
49
- @implementation_root_path = File.expand_path("#{dir}/../example_public/javascripts")
50
- @public_path = File.expand_path("#{dir}/../example_public")
51
- end
52
-
53
- before(:each) do
54
- JsTestCore::Server.instance = JsTestCore::Server.new(spec_root_path, implementation_root_path, public_path)
55
- stub(EventMachine).run do
56
- raise "You need to mock calls to EventMachine.run or the process will hang"
57
- end
58
- stub(EventMachine).start_server do
59
- raise "You need to mock calls to EventMachine.start_server or the process will hang"
60
- end
61
- stub(EventMachine).send_data do
62
- raise "Calls to EventMachine.send_data must be mocked or stubbed"
63
- end
64
- @connection = Thin::JsTestCoreConnection.new(Guid.new)
65
- stub(EventMachine).send_data {raise "EventMachine.send_data must be handled"}
66
- stub(EventMachine).close_connection {raise "EventMachine.close_connection must be handled"}
67
- @server = JsTestCore::Server.instance
68
- Thin::Logging.silent = !self.class.thin_logging
69
- Thin::Logging.debug = self.class.thin_logging
70
- end
71
-
72
- after(:each) do
73
- JsTestCore::Resources::WebRoot.dispatch_strategy = nil
74
- Thin::Logging.silent = true
75
- Thin::Logging.debug = false
76
- end
22
+ Sinatra::Application.use ShowTestExceptions
23
+ Sinatra::Application.set :raise_errors, true
24
+ Sinatra::Application.set :show_exceptions, false
25
+ JsTestCore::App.set :raise_errors, true
26
+ JsTestCore::App.set :show_exceptions, false
77
27
 
78
- def get(url, params={})
79
- request(:get, url, params)
80
- end
81
-
82
- def post(url, params={})
83
- request(:post, url, params)
84
- end
85
-
86
- def put(url, params={})
87
- request(:put, url, params)
88
- end
89
-
90
- def delete(url, params={})
91
- request(:delete, url, params)
92
- end
93
-
94
- def env_for(method, url, params)
95
- Rack::MockRequest.env_for(url, params.merge({:method => method.to_s.upcase, 'js_test_core.connection' => connection}))
96
- end
97
-
98
- def create_request(method, url, params={})
99
- env = env_for(method, url, params)
100
- server.call(env)[2]
101
- end
102
- alias_method :request, :create_request
103
-
104
- def spec_file(relative_path)
105
- absolute_path = spec_root_path + relative_path
106
- JsTestCore::Resources::File.new(absolute_path, "/specs#{relative_path}")
107
- end
108
-
109
- def spec_dir(relative_path="")
110
- absolute_path = spec_root_path + relative_path
111
- JsTestCore::Resources::Specs::SpecDir.new(absolute_path, "/specs#{relative_path}")
112
- end
113
-
114
- def contain_spec_file_with_correct_paths(path_relative_to_spec_root)
115
- expected_absolute_path = spec_root_path + path_relative_to_spec_root
116
- expected_relative_path = "/specs" + path_relative_to_spec_root
117
-
118
- ::Spec::Matchers::SimpleMatcher.new(expected_relative_path) do |globbed_files|
119
- file = globbed_files.find do |file|
120
- file.absolute_path == expected_absolute_path
121
- end
122
- file && file.relative_path == expected_relative_path
123
- end
124
- end
125
- end
28
+ Sinatra::Application.use(JsTestCore::App)
@@ -0,0 +1,7 @@
1
+ Lucky Luciano, is a library that makes it easy to organize your Sinatra routes into Restful Resources.
2
+
3
+ ## Who was this Lucky Luciano person?
4
+
5
+ Lucky Luciano was a mob boss and an alleged friend of Frank Sinatra.
6
+
7
+ http://news.bbc.co.uk/2/hi/special_report/1998/05/98/sinatra/94360.stm
@@ -0,0 +1,4 @@
1
+ require "sinatra/base"
2
+
3
+ dir = File.dirname(__FILE__)
4
+ require "#{dir}/lucky_luciano/resource"
@@ -0,0 +1,135 @@
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 path(*sub_paths)
27
+ params = sub_paths.last.is_a?(Hash) ? sub_paths.pop : {}
28
+
29
+ sub_path_definition = sub_paths.join("/")
30
+
31
+ full_path = "#{base_path(params)}/#{path_from_definition(sub_path_definition, params)}".
32
+ gsub("//", "/").gsub(/\/$/, "")
33
+
34
+ base_path_param_keys = param_keys_from(base_path_definition)
35
+ query_params = params.delete_if do |key, value|
36
+ base_path_param_keys.include?(key)
37
+ end
38
+
39
+ sub_path_param_keys = param_keys_from(sub_path_definition)
40
+ query_params = params.delete_if do |key, value|
41
+ sub_path_param_keys.include?(key)
42
+ end
43
+
44
+ if query_params.empty?
45
+ full_path
46
+ else
47
+ query = build_query(query_params)
48
+ "#{full_path}?#{query}"
49
+ end
50
+ end
51
+
52
+ def base_path(params={})
53
+ path_from_definition(base_path_definition, params)
54
+ end
55
+
56
+ protected
57
+
58
+ def path_from_definition(definition, params={})
59
+ param_keys = param_keys_from(definition)
60
+ if param_keys.empty?
61
+ definition.dup
62
+ else
63
+ param_keys.each do |base_path_param|
64
+ unless params.include?(base_path_param.to_sym)
65
+ raise ArgumentError, "Expected #{base_path_param.inspect} to have a value"
66
+ end
67
+ end
68
+ definition.split("/").map do |segment|
69
+ if param_key = segment_param_key(segment)
70
+ params[param_key]
71
+ else
72
+ segment
73
+ end
74
+ end.join("/")
75
+ end
76
+ end
77
+
78
+ def param_keys_from(definition)
79
+ definition.split("/").find_all do |segment|
80
+ segment_param_key(segment)
81
+ end.map do |param|
82
+ param[1..-1].to_sym
83
+ end
84
+ end
85
+
86
+ def segment_param_key(segment)
87
+ segment[0..0] == ':' ? segment[1..-1].to_sym : nil
88
+ end
89
+
90
+ def build_query(params)
91
+ params.to_a.inject([]) do |splatted_params, (key, value)|
92
+ [value].flatten.each do |value_in_param|
93
+ splatted_params << "#{URI.escape(key.to_s)}=#{URI.escape(value_in_param.to_s)}"
94
+ end
95
+ splatted_params
96
+ end.join("&")
97
+ end
98
+
99
+ def create_sinatra_handler
100
+ handlers = recorded_http_handlers
101
+ resource_class = self
102
+ Module.new do
103
+ (class << self; self; end).class_eval do
104
+ define_method(:registered) do |app|
105
+ handlers.each do |handler|
106
+ verb, relative_path, opts, block = handler
107
+ full_path = "#{resource_class.base_path_definition}/#{relative_path}".
108
+ gsub("//", "/").gsub(%r{^.+/$}) do |match|
109
+ match.gsub(%r{/$}, "")
110
+ end
111
+ app.send(verb, full_path, opts) do
112
+ resource_class.new(self).instance_eval(&block)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ attr_reader :app
122
+
123
+ def initialize(app)
124
+ @app = app
125
+ end
126
+
127
+ def method_missing(method_name, *args, &block)
128
+ if app.respond_to?(method_name)
129
+ app.send(method_name, *args, &block)
130
+ else
131
+ super
132
+ end
133
+ end
134
+ end
135
+ end