merb-core 0.9.2 → 0.9.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 (104) hide show
  1. data/Rakefile +61 -11
  2. data/bin/merb +5 -1
  3. data/lib/merb-core.rb +202 -25
  4. data/lib/merb-core/autoload.rb +19 -17
  5. data/lib/merb-core/bootloader.rb +84 -71
  6. data/lib/merb-core/config.rb +19 -14
  7. data/lib/merb-core/controller/abstract_controller.rb +16 -17
  8. data/lib/merb-core/controller/exceptions.rb +115 -70
  9. data/lib/merb-core/controller/merb_controller.rb +62 -38
  10. data/lib/merb-core/controller/mime.rb +1 -1
  11. data/lib/merb-core/controller/mixins/authentication.rb +87 -0
  12. data/lib/merb-core/controller/mixins/controller.rb +16 -15
  13. data/lib/merb-core/controller/mixins/render.rb +113 -19
  14. data/lib/merb-core/controller/mixins/responder.rb +8 -2
  15. data/lib/merb-core/controller/template.rb +1 -1
  16. data/lib/merb-core/core_ext.rb +1 -0
  17. data/lib/merb-core/core_ext/class.rb +113 -6
  18. data/lib/merb-core/core_ext/hash.rb +43 -39
  19. data/lib/merb-core/core_ext/kernel.rb +75 -38
  20. data/lib/merb-core/core_ext/mash.rb +4 -4
  21. data/lib/merb-core/core_ext/object.rb +18 -7
  22. data/lib/merb-core/core_ext/set.rb +9 -4
  23. data/lib/merb-core/core_ext/string.rb +29 -9
  24. data/lib/merb-core/core_ext/time.rb +13 -0
  25. data/lib/merb-core/dispatch/cookies.rb +1 -2
  26. data/lib/merb-core/dispatch/dispatcher.rb +18 -10
  27. data/lib/merb-core/dispatch/exceptions.html.erb +1 -1
  28. data/lib/merb-core/dispatch/request.rb +3 -0
  29. data/lib/merb-core/dispatch/router.rb +10 -7
  30. data/lib/merb-core/dispatch/router/behavior.rb +36 -27
  31. data/lib/merb-core/dispatch/router/route.rb +7 -2
  32. data/lib/merb-core/dispatch/session/cookie.rb +4 -4
  33. data/lib/merb-core/dispatch/session/memcached.rb +17 -5
  34. data/lib/merb-core/logger.rb +2 -2
  35. data/lib/merb-core/plugins.rb +16 -4
  36. data/lib/merb-core/rack/adapter/ebb.rb +4 -1
  37. data/lib/merb-core/rack/adapter/evented_mongrel.rb +2 -0
  38. data/lib/merb-core/rack/adapter/fcgi.rb +1 -0
  39. data/lib/merb-core/rack/adapter/mongrel.rb +1 -0
  40. data/lib/merb-core/rack/adapter/runner.rb +1 -0
  41. data/lib/merb-core/rack/adapter/thin.rb +3 -1
  42. data/lib/merb-core/rack/adapter/webrick.rb +1 -0
  43. data/lib/merb-core/rack/application.rb +17 -1
  44. data/lib/merb-core/server.rb +78 -28
  45. data/lib/merb-core/test/helpers/multipart_request_helper.rb +3 -3
  46. data/lib/merb-core/test/helpers/request_helper.rb +81 -27
  47. data/lib/merb-core/test/helpers/view_helper.rb +1 -1
  48. data/lib/merb-core/test/matchers/controller_matchers.rb +55 -5
  49. data/lib/merb-core/test/matchers/route_matchers.rb +8 -17
  50. data/lib/merb-core/test/matchers/view_matchers.rb +53 -11
  51. data/lib/merb-core/test/run_specs.rb +22 -14
  52. data/lib/merb-core/test/tasks/spectasks.rb +54 -33
  53. data/lib/merb-core/vendor/facets/inflect.rb +91 -2
  54. data/lib/merb-core/version.rb +2 -2
  55. data/spec/private/config/config_spec.rb +54 -26
  56. data/spec/private/core_ext/class_spec.rb +22 -0
  57. data/spec/private/core_ext/hash_spec.rb +70 -54
  58. data/spec/private/core_ext/kernel_spec.rb +149 -14
  59. data/spec/private/core_ext/object_spec.rb +92 -10
  60. data/spec/private/core_ext/string_spec.rb +162 -4
  61. data/spec/private/core_ext/time_spec.rb +16 -0
  62. data/spec/private/dispatch/bootloader_spec.rb +24 -0
  63. data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +1 -1
  64. data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +1 -1
  65. data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +1 -1
  66. data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +1 -1
  67. data/spec/private/dispatch/fixture/config/black_hole.rb +12 -0
  68. data/spec/private/dispatch/fixture/log/merb_test.log +138 -0
  69. data/spec/private/plugins/plugin_spec.rb +79 -8
  70. data/spec/private/rack/application_spec.rb +1 -1
  71. data/spec/public/abstract_controller/controllers/filters.rb +26 -0
  72. data/spec/public/abstract_controller/controllers/helpers.rb +2 -2
  73. data/spec/public/abstract_controller/controllers/partial.rb +2 -2
  74. data/spec/public/abstract_controller/controllers/render.rb +16 -4
  75. data/spec/public/abstract_controller/filter_spec.rb +8 -0
  76. data/spec/public/abstract_controller/render_spec.rb +12 -0
  77. data/spec/public/controller/authentication_spec.rb +103 -0
  78. data/spec/public/controller/base_spec.rb +4 -3
  79. data/spec/public/controller/controllers/authentication.rb +47 -0
  80. data/spec/public/controller/controllers/base.rb +1 -0
  81. data/spec/public/controller/controllers/display.rb +30 -0
  82. data/spec/public/controller/controllers/views/layout/custom_arg.html.erb +1 -0
  83. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template_argument/index.html.erb +1 -0
  84. data/spec/public/controller/display_spec.rb +17 -0
  85. data/spec/public/controller/spec_helper.rb +1 -0
  86. data/spec/public/controller/url_spec.rb +25 -7
  87. data/spec/public/core/merb_core_spec.rb +34 -0
  88. data/spec/public/directory_structure/directory/app/controllers/custom.rb +2 -2
  89. data/spec/public/directory_structure/directory/log/merb_test.log +48 -0
  90. data/spec/public/logger/logger_spec.rb +10 -4
  91. data/spec/public/reloading/directory/app/controllers/reload.rb +1 -1
  92. data/spec/public/reloading/directory/log/merb_test.log +13 -0
  93. data/spec/public/reloading/reload_spec.rb +23 -22
  94. data/spec/public/request/request_spec.rb +2 -0
  95. data/spec/public/router/nested_resources_spec.rb +7 -0
  96. data/spec/public/router/resources_spec.rb +46 -1
  97. data/spec/public/router/special_spec.rb +5 -1
  98. data/spec/public/test/controller_matchers_spec.rb +25 -1
  99. data/spec/public/test/controllers/spec_helper_controller.rb +8 -0
  100. data/spec/public/test/request_helper_spec.rb +52 -1
  101. data/spec/public/test/route_matchers_spec.rb +27 -25
  102. data/spec/public/test/view_helper_spec.rb +1 -1
  103. data/spec/public/test/view_matchers_spec.rb +148 -72
  104. metadata +23 -3
@@ -1,11 +1,9 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
-
4
3
  describe "Kernel#require" do
5
-
6
4
  before do
7
5
  @logger = StringIO.new
8
- Merb.logger = Merb::Logger.new(@logger)
6
+ Merb.logger = Merb::Logger.new(@logger)
9
7
  end
10
8
 
11
9
  it "should be able to require and throw a useful error message" do
@@ -13,34 +11,171 @@ describe "Kernel#require" do
13
11
  Merb.logger.should_receive(:error!).with("foo")
14
12
  Kernel.rescue_require("redcloth", "foo")
15
13
  end
16
-
17
-
18
14
  end
19
15
 
16
+
17
+
20
18
  describe "Kernel#caller" do
21
-
22
19
  it "should be able to determine caller info" do
23
20
  __caller_info__.should be_kind_of(Array)
24
21
  end
25
-
22
+
26
23
  it "should be able to get caller lines" do
27
24
  __caller_lines__(__caller_info__[0], __caller_info__[1], 4).length.should == 9
28
25
  __caller_lines__(__caller_info__[0], __caller_info__[1], 4).should be_kind_of(Array)
29
26
  end
30
-
31
27
  end
32
28
 
33
- describe "Kernel misc." do
29
+
30
+
31
+ describe "Kernel#extract_options_from_args!" do
34
32
  it "should extract options from args" do
35
33
  args = ["foo", "bar", {:baz => :bar}]
36
34
  Kernel.extract_options_from_args!(args).should == {:baz => :bar}
37
35
  args.should == ["foo", "bar"]
38
36
  end
39
-
37
+ end
38
+
39
+
40
+
41
+ describe "Kernel#debugger" do
40
42
  it "should throw a useful error if there's no debugger" do
41
- Merb.logger.should_receive(:info!).with "\n***** Debugger requested, but was not " +
42
- "available: Start server with --debugger " +
43
- "to enable *****\n"
43
+ Merb.logger.should_receive(:info!).with "\n***** Debugger requested, but was not " +
44
+ "available: Start server with --debugger " +
45
+ "to enable *****\n"
44
46
  Kernel.debugger
45
47
  end
46
- end
48
+ end
49
+
50
+
51
+ describe "Kernel#dependency" do
52
+ it "adds dependency to the list" do
53
+ lambda { dependency("dm_merb", ">= 0.9") }.should change(Merb::BootLoader::Dependencies.dependencies, :size)
54
+ end
55
+
56
+ it "deferres load to boot loader run" do
57
+ Object.should_not_receive(:full_const_get)
58
+ dependency("dm_merb", ">= 0.9")
59
+ end
60
+ end
61
+
62
+
63
+ describe "Kernel#load_dependency" do
64
+ before :each do
65
+
66
+ end
67
+
68
+ it "DOES NOT add dependency to the list" do
69
+ lambda {
70
+ begin
71
+ load_dependency("rspec", ">= 1.1.2")
72
+ rescue LoadError => e
73
+ # some people may have no RSpec gem
74
+ end
75
+ }.should_not change(Merb::BootLoader::Dependencies.dependencies, :size)
76
+ end
77
+
78
+ it "DOES NOT defer load to boot loader run and requires it right away" do
79
+ self.should_receive(:require)
80
+
81
+ begin
82
+ load_dependency("rspec", ">= 1.1.2")
83
+ rescue LoadError => e
84
+ # some people may have no RSpec gem
85
+ end
86
+ end
87
+
88
+ it "logs on events using info level" do
89
+ self.should_receive(:require)
90
+ Merb.logger.should_receive(:info!)
91
+
92
+ begin
93
+ load_dependency("rspec", ">= 1.1.2")
94
+ rescue LoadError => e
95
+ # some people may have no RSpec gem
96
+ end
97
+ end
98
+
99
+ it "tries to be smart by checking if Merb is frozen" do
100
+ self.should_receive(:require)
101
+ Merb.should_receive(:frozen?).and_return(true)
102
+
103
+ begin
104
+ load_dependency("merb-core")
105
+ rescue LoadError => e
106
+ # some people may have no RSpec gem
107
+ end
108
+ end
109
+ end
110
+
111
+
112
+
113
+ describe "Kernel#dependencies" do
114
+ it "deferres load of dependencies given as String" do
115
+ self.should_receive(:dependency).with("hpricot").and_return(true)
116
+
117
+ begin
118
+ dependencies("hpricot")
119
+ rescue LoadError => e
120
+ # sanity check, should never happen
121
+ end
122
+ end
123
+
124
+ it "deferres load of dependencies given as Array" do
125
+ self.should_receive(:dependency).with("hpricot").and_return(true)
126
+ self.should_receive(:dependency).with("rake").and_return(true)
127
+
128
+ begin
129
+ dependencies("hpricot", "rake")
130
+ rescue LoadError => e
131
+ # sanity check, should never happen
132
+ end
133
+ end
134
+
135
+ it "deferres load of dependencies given as Hash" do
136
+ self.should_receive(:dependency).with("hpricot", "0.6").and_return(true)
137
+ self.should_receive(:dependency).with("rake", "0.8.1").and_return(true)
138
+
139
+ begin
140
+ dependencies("hpricot" => "0.6", "rake" => "0.8.1")
141
+ rescue LoadError => e
142
+ # sanity check, should never happen
143
+ end
144
+ end
145
+ end
146
+
147
+
148
+
149
+ describe "Kernel#load_dependencies" do
150
+ it "loads dependencies given as String immediately" do
151
+ self.should_receive(:load_dependency).with("hpricot").and_return(true)
152
+
153
+ begin
154
+ load_dependencies("hpricot")
155
+ rescue LoadError => e
156
+ # sanity check, should never happen
157
+ end
158
+ end
159
+
160
+ it "loads dependencies given as Array immediately" do
161
+ self.should_receive(:load_dependency).with("hpricot").and_return(true)
162
+ self.should_receive(:load_dependency).with("rake").and_return(true)
163
+
164
+ begin
165
+ load_dependencies("hpricot", "rake")
166
+ rescue LoadError => e
167
+ # sanity check, should never happen
168
+ end
169
+ end
170
+
171
+ it "loads dependencies given as Hash immediately" do
172
+ self.should_receive(:load_dependency).with("hpricot", "0.6").and_return(true)
173
+ self.should_receive(:load_dependency).with("rake", "0.8.1").and_return(true)
174
+
175
+ begin
176
+ load_dependencies("hpricot" => "0.6", "rake" => "0.8.1")
177
+ rescue LoadError => e
178
+ # sanity check, should never happen
179
+ end
180
+ end
181
+ end
@@ -1,39 +1,121 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
  class Foo
3
-
4
3
  end
5
4
 
6
- describe Object do
7
5
 
8
-
6
+ describe Object do
9
7
  it "should treat an empty string as blank" do
10
8
  "".should be_blank
11
9
  end
12
-
10
+
13
11
  it "should treat a string with just spaces as blank" do
14
12
  " ".should be_blank
15
13
  end
16
-
14
+
17
15
  it "should treat an empty array as blank" do
18
16
  [].should be_blank
19
17
  end
20
-
18
+
21
19
  it "should treat boolean false as blank" do
22
20
  false.should be_blank
23
21
  end
24
-
25
22
  end
26
23
 
24
+
25
+
27
26
  describe Object, "#quacks_like" do
28
27
  it "use respond_to? to determine quacks_like :symbol" do
29
28
  "Foo".should be_quacks_like(:strip)
30
29
  end
31
-
30
+
32
31
  it "should return true if any of the elements in the Array are true" do
33
32
  "Foo".should be_quacks_like([String, Array])
34
33
  end
35
-
34
+
36
35
  it "should return false if an invalid value is passed in" do
37
36
  "Foo".should_not be_quacks_like({})
38
37
  end
39
- end
38
+ end
39
+
40
+
41
+
42
+ describe Object, "#full_const_get" do
43
+ class April
44
+ class In
45
+ class Paris
46
+ PERFORMER = "Ella Fitzgerald"
47
+ end
48
+ end
49
+ end
50
+
51
+ module Succubus
52
+ module In
53
+ module Rapture
54
+ PERFORMER = "Dimmu Borgir"
55
+ end
56
+ end
57
+ end
58
+
59
+ it "returns constant corresponding to the name" do
60
+ self.full_const_get("April").should == April
61
+ end
62
+
63
+ it "handles nested classes" do
64
+ self.full_const_get("April::In::Paris").should == April::In::Paris
65
+ end
66
+
67
+ it "handles nested modules" do
68
+ self.full_const_get("Succubus::In::Rapture").should == Succubus::In::Rapture
69
+ end
70
+
71
+ it "handles in-scoped constants in modules" do
72
+ self.full_const_get("Succubus::In::Rapture::PERFORMER").should == "Dimmu Borgir"
73
+ end
74
+
75
+ it "handles in-scoped constants in classes" do
76
+ self.full_const_get("April::In::Paris::PERFORMER").should == "Ella Fitzgerald"
77
+ end
78
+
79
+ it "acts as a global function" do
80
+ lambda { April::In::Paris.full_const_get("PERFORMER") }.should raise_error(NameError)
81
+ end
82
+
83
+ it "raises an exception if constant is undefined" do
84
+ lambda { self.full_const_get("We::May::Never::Meet::Again") }.should raise_error(NameError)
85
+ end
86
+ end
87
+
88
+
89
+
90
+ describe Object, "#make_module" do
91
+ it "defines module from a string name" do
92
+ Object.make_module("Cant::Take::That::Away::From::Me")
93
+
94
+ defined?(Cant::Take::That::Away::From::Me).should == "constant"
95
+ end
96
+
97
+ it "is OK if module already defined" do
98
+ module Merb
99
+ module Is
100
+ module Modular
101
+ end
102
+ end
103
+ end
104
+
105
+ lambda { Object.make_module("Merb::Is::Modular") }.should_not raise_error
106
+ end
107
+ end
108
+
109
+ describe Object, "#in?" do
110
+ it "should be true if the argument includes self" do
111
+ 4.in?([1,2,4,5]).should be_true
112
+ end
113
+
114
+ it "should be false if the argument does not include self" do
115
+ 4.in?([1,2,3,5]).should be_false
116
+ end
117
+
118
+ it "should splat the args so [] are not required" do
119
+ 4.in?(1,2,3,4,5).should be_true
120
+ end
121
+ end
@@ -1,9 +1,167 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
- describe String, "to_const_string" do
4
-
5
- it "should convert a path into a constant string" do
3
+ describe String, "#to_const_string" do
4
+ it "swaps slashes with ::" do
5
+ "foo/bar".to_const_string.should == "Foo::Bar"
6
+ end
7
+
8
+ it "replaces snake_case with CamelCase" do
6
9
  "foo/bar/baz_bat".to_const_string.should == "Foo::Bar::BazBat"
7
10
  end
8
11
 
9
- end
12
+ it "leaves constant string as is" do
13
+ "Merb::Test".to_const_string.should == "Merb::Test"
14
+ end
15
+ end
16
+
17
+
18
+
19
+ describe String, "#to_const_path" do
20
+ it "swaps :: with slash" do
21
+ "Foo::Bar".to_const_path.should == "foo/bar"
22
+ end
23
+
24
+ it "snake_cases string" do
25
+ "Merb::Test::ViewHelper".to_const_path.should == "merb/test/view_helper"
26
+ end
27
+
28
+ it "leaves slash-separated snake case string as is" do
29
+ "merb/test/view_helper".to_const_path.should == "merb/test/view_helper"
30
+ end
31
+ end
32
+
33
+
34
+
35
+ describe String, "#camel_case" do
36
+ it "handles lowercase without underscore" do
37
+ "merb".camel_case.should == "Merb"
38
+ end
39
+
40
+ it "handles lowercase with 1 underscore" do
41
+ "merb_core".camel_case.should == "MerbCore"
42
+ end
43
+
44
+ it "handles lowercase with more than 1 underscore" do
45
+ "so_you_want_contribute_to_merb_core".camel_case.should == "SoYouWantContributeToMerbCore"
46
+ end
47
+
48
+ it "handles lowercase with more than 1 underscore in a row" do
49
+ "__python__is__like__this".camel_case.should == "PythonIsLikeThis"
50
+ end
51
+
52
+ it "handle first capital letter with underscores" do
53
+ "Python__Is__Like__This".camel_case.should == "PythonIsLikeThis"
54
+ end
55
+
56
+ it "leaves CamelCase as is" do
57
+ "TestController".camel_case.should == "TestController"
58
+ end
59
+ end
60
+
61
+
62
+
63
+ describe String, "#snake_case" do
64
+ it "lowercases one word CamelCase" do
65
+ "Merb".snake_case.should == "merb"
66
+ end
67
+
68
+ it "makes one underscore snake_case two word CamelCase" do
69
+ "MerbCore".snake_case.should == "merb_core"
70
+ end
71
+
72
+ it "handles CamelCase with more than 2 words" do
73
+ "SoYouWantContributeToMerbCore".snake_case.should == "so_you_want_contribute_to_merb_core"
74
+ end
75
+
76
+ it "handles CamelCase with more than 2 capital letter in a row" do
77
+ "CNN".snake_case.should == "cnn"
78
+ "CNNNews".snake_case.should == "cnn_news"
79
+ "HeadlineCNNNews".snake_case.should == "headline_cnn_news"
80
+ end
81
+
82
+ it "does NOT change one word lowercase" do
83
+ "merb".snake_case.should == "merb"
84
+ end
85
+
86
+ it "leaves snake_case as is" do
87
+ "merb_core".snake_case.should == "merb_core"
88
+ end
89
+ end
90
+
91
+
92
+
93
+ describe String, "#escape_regexp" do
94
+ it "escapes all * in a string" do
95
+ "*and*".escape_regexp.should == "\\*and\\*"
96
+ end
97
+
98
+ it "escapes all ? in a string" do
99
+ "?and?".escape_regexp.should == "\\?and\\?"
100
+ end
101
+
102
+ it "escapes all { in a string" do
103
+ "{and{".escape_regexp.should == "\\{and\\{"
104
+ end
105
+
106
+ it "escapes all } in a string" do
107
+ "}and}".escape_regexp.should == "\\}and\\}"
108
+ end
109
+
110
+ it "escapes all . in a string" do
111
+ ".and.".escape_regexp.should == "\\.and\\."
112
+ end
113
+
114
+ it "escapes all regexp special characters used in a string" do
115
+ "*?{}.".escape_regexp.should == "\\*\\?\\{\\}\\."
116
+ end
117
+ end
118
+
119
+
120
+
121
+ describe String, "#unescape_regexp" do
122
+ it "unescapes all \\* in a string" do
123
+ "\\*and\\*".unescape_regexp.should == "*and*"
124
+ end
125
+
126
+ it "unescapes all \\? in a string" do
127
+ "\\?and\\?".unescape_regexp.should == "?and?"
128
+ end
129
+
130
+ it "unescapes all \\{ in a string" do
131
+ "\\{and\\{".unescape_regexp.should == "{and{"
132
+ end
133
+
134
+ it "unescapes all \\} in a string" do
135
+ "\\}and\\}".unescape_regexp.should == "}and}"
136
+ end
137
+
138
+ it "unescapes all \\. in a string" do
139
+ "\\.and\\.".unescape_regexp.should == ".and."
140
+ end
141
+
142
+ it "unescapes all regexp special characters used in a string" do
143
+ "\\*\\?\\{\\}\\.".unescape_regexp.should == "*?{}."
144
+ end
145
+ end
146
+
147
+
148
+
149
+ describe String, "#/" do
150
+ it "concanates operands with File::SEPARATOR" do
151
+ ("merb" / "core").should == "merb#{File::SEPARATOR}core"
152
+ end
153
+ end
154
+
155
+
156
+ require 'rbconfig'
157
+ describe String, "#relative_path_from" do
158
+ it "uses other operand as base for path calculation" do
159
+ site_dir = Config::CONFIG["sitedir"]
160
+
161
+ two_levels_up = site_dir.split(File::SEPARATOR)
162
+ 2.times { two_levels_up.pop } # remove two deepest directories
163
+ two_levels_up = File::SEPARATOR + two_levels_up.join(File::SEPARATOR)
164
+
165
+ two_levels_up.relative_path_from(site_dir).should == "../.."
166
+ end
167
+ end