excalibur 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ require 'rails/generators/base'
2
+
3
+ module Excalibur
4
+ module Generators
5
+ # the install generator allows you to get a free to use and fully
6
+ # documented initializer file for your rails app by running:
7
+ # rails g excalibur:install
8
+ class InstallGenerator < Rails::Generators::Base
9
+ source_root File.expand_path('../../templates', __FILE__)
10
+
11
+ desc 'Creates a Excalibur initializer.'
12
+
13
+ def copy_initializer
14
+ template 'excalibur.rb', 'config/initializers/excalibur.rb'
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,75 @@
1
+ class Excalibur::<%= class_name %>Decorator < Excalibur::Decorator
2
+ # ==> Full custom configuration
3
+ # it is possible to force a new config onto over the application wide
4
+ # default set in the initializer.
5
+ #
6
+ # You can pass a custom configuration in like so:
7
+ # excalibur_init @my_custom_config
8
+ #
9
+ # or start with a blank configuration like so:
10
+ # excalibur_init Excalibur::Configuration.new
11
+ #
12
+ # The last method is easiest as all configuration options are available in
13
+ # this decorator through a DSL instead of building the object from scratch.
14
+
15
+ # ==> Title and Description settings
16
+ # Titles and descriptions act mostly the same way within Excalibur. They
17
+ # share the same DSL with the small difference in method name. Below the
18
+ # description is for title but it applies to description as well.
19
+ #
20
+ # => Set content
21
+ # the excalibur_set_title_content method takes two parameters to change the
22
+ # content of a title. By defaults you can set a :prefix, :body and :suffix.
23
+ # All of these can be a string or a Proc.
24
+ #
25
+ # as an example:
26
+ # excalibur_set_title_content :body, 'my class specific title body'
27
+ #
28
+ # => Set option
29
+ # the excalibur_set_title_option method takes two arguments to change the
30
+ # options of a title. By defaults you can set a :length, :omission and
31
+ # :separator.
32
+ #
33
+ # :length takes any integer to indicate the length limit of the title.
34
+ # :omission is what fills the end of the line when the body is truncated
35
+ # below the limited length of the title :body.
36
+ # :separator determines what character the :body will be truncated on. with
37
+ # a single space (' ') it will break on words and with no-space ('') it
38
+ # will break on any character.
39
+ #
40
+ # as an examples:
41
+ # excalibur_set_title_content :length, 42
42
+ # excalibur_set_title_content :omission, '... (continued)'
43
+ #
44
+ # => set combinator
45
+ # the excalibur_set_title_combinator takes one argument and it should be a
46
+ # Proc. The proc is passed the decorated object so you have access to the
47
+ # object and the configuration of required. It needs to result in a string.
48
+ #
49
+ # excalibur_set_title_combinator(proc { |obj|
50
+ # # your code here
51
+ # })
52
+
53
+ # ==> Meta tag settings
54
+ # the excalibur_set_meta_tag method takes three arguments to set the content
55
+ # for a meta tag. The first and second arguments are about the type of meta
56
+ # tag while the third is used for the content.
57
+ #
58
+ # A description meta tag would look like this:
59
+ # excalibur_set_meta_tag :name, :description, 'Some description content'
60
+ #
61
+ # The content of a meta tag can be anything that prints nicely into a
62
+ # string, a Proc or an Array. The Proc may also result in an array and is
63
+ # passed the decorated object for access to the objects attributes and the
64
+ # excalibur configuration acting for the object.
65
+
66
+ # ==> Recommended use
67
+ # Because the title, description and the meta tags all allow for a Proc to
68
+ # be passed it gives you a lot of freedom. However like any freedom it is to
69
+ # be used with some warning. It is recommended when doing larger amounts of
70
+ # work in code of a proc to use the decorator to delegate that
71
+ # responsibility. The decorator becomes easier to test and it is also a lot
72
+ # cleaner.
73
+ #
74
+ # TODO: An article about how to do it properly will come soon!
75
+ end
@@ -0,0 +1,151 @@
1
+ # Use this to set up your default
2
+ Excalibur.configure do |config|
3
+ # ==> Your sane defaults:
4
+
5
+ # => Title content
6
+ # config.title.update_content :prefix, 'prefix - '
7
+ config.title.update_content :body, 'My website has a title by Excalibur'
8
+
9
+ # => Title options
10
+ # config.title.update_option :length, 69
11
+ # config.title.update_option :omission, '...'
12
+ # config.title.update_option :separator, ''
13
+
14
+ # => Description content
15
+ config.description.update_content :body, 'Excalibur gave me a description!'
16
+
17
+ # => Description options
18
+ # config.description.update_option :length, 155
19
+ # config.description.update_option :omission, '...'
20
+ # config.description.update_option :separator, ' '
21
+
22
+ # => Meta tags
23
+ config.set_meta_tag :name, :viewport, 'width=device-width, initial-scale=1'
24
+
25
+ # ==> Configuration DSL:
26
+ #
27
+ # Both the title and description are configurable in the same way;
28
+ # config.title for the title and config.description for the description.
29
+ # They both consist out of three elements; content, options and the
30
+ # combinator. The meta tags have their own interface as they are slightly
31
+ # different. Both the content in the title/description and the content in
32
+ # the meta tags can be given a Proc in order for on-render computation to
33
+ # occur.
34
+
35
+ # => Title/Description content
36
+ # The default of the gem tries to combine 3 parts; :prefix,
37
+ # :body and :suffix. They are put together in that order by the default
38
+ # combinator.
39
+ #
40
+ # To set these add:
41
+ # config.title.update_content :prefix, 'CNN.com - '
42
+ # config.title.update_content :body, 'Breaking, World, Business, Sports and
43
+ # Entertainment News'
44
+ #
45
+ # this will result in a title like 'CNN.com - Breaking, World, Business,
46
+ # Sports and Entertainment News'
47
+ #
48
+ # > Title Defaults:
49
+ # prefix: ''
50
+ # body: 'Excalibur'
51
+ # suffix: ''
52
+ #
53
+ # > Description Defaults:
54
+ # prefix: ''
55
+ # body: 'Excalibur; a worthy title for a gem about titles.'
56
+ # suffix: ''
57
+
58
+ # => Title/Description options
59
+ # The default of the gem uses the options to truncate the content
60
+ # components in the correct way. :length is the length the content will be
61
+ # truncated to. :omission is used to indicate that the content is truncated
62
+ # and is added behind the section that has been truncated. :separator
63
+ # determines if truncation happens on a character or not,
64
+ # '' for every letter and ' ' for a space as it allows for breaking on words
65
+ # or characters.
66
+ #
67
+ # To set these add:
68
+ # config.title.update_option :length, 42
69
+ # config.title.update_option :omission, '... (continued)'
70
+ #
71
+ # > Title Defaults:
72
+ # length: 69
73
+ # omission: '...'
74
+ # separator: ''
75
+ #
76
+ # > Description Defaults:
77
+ # length: 155
78
+ # omission: '...'
79
+ # separator: ' '
80
+
81
+ # => Title/Description combinator
82
+ # The combinator is by default a proc that combines the content elements
83
+ # together and truncates them according to what the options have specified.
84
+ # If your not into it yet the combinator is to be changed with caution.
85
+ #
86
+ # Change the combinator by:
87
+ # config.title.update_combinator(
88
+ # proc do |object|
89
+ # # your code here
90
+ # #
91
+ # # the object var is passed when rendering and contains an object
92
+ # # with the current configuration for that render. It's advised when
93
+ # # using data from that configuration to use object.configuration to
94
+ # # access it.
95
+ # end
96
+ # )
97
+ #
98
+ # > Default behavior
99
+ # By default the combinator takes the 3 content sections but only truncates
100
+ # the :body section. This does take into account the length of the :prefix
101
+ # and :suffix when truncating the content so the overall length of the
102
+ # title stays within the length set in the options.
103
+ #
104
+ # > Title/Description configuration examples:
105
+ # content:
106
+ # prefix: 'Excalibur | '
107
+ # body: 'The Object oriented way of setting SEO and meta information'
108
+ # options:
109
+ # length: 69
110
+ # omission: '...'
111
+ # separator: ''
112
+ # result: 'Excalibur | The Object oriented way of setting SEO and meta
113
+ # inform...'
114
+ #
115
+ # options:
116
+ # separator: ' '
117
+ # result: 'Excalibur | The Object oriented way of setting SEO and meta...'
118
+ #
119
+ # content:
120
+ # body: 'Just another website'
121
+ # suffix: ' - site ID'
122
+ # result: 'Just another website - site ID'
123
+
124
+ # => Meta tags
125
+ # Meta tags are basically represented in the configuration as a double
126
+ # layered hash. The hash is converted to meta tags types and the values are
127
+ # the content of the meta tag.
128
+ #
129
+ # These can be easily set using:
130
+ # config.set_meta_tag(
131
+ # :name,
132
+ # :viewport,
133
+ # 'width=device-width, initial-scale=1')
134
+
135
+ # => General configuration:
136
+ # it is possible to roll your own configuration without using the accessors
137
+ # provided in the DSL. You can use the Excalibur::Configuration class to
138
+ # create your own config. Have a look at the code how to do so!
139
+ #
140
+ # you can set it by simply:
141
+ # config = MyCustomConfiguration.new
142
+ #
143
+ # If you want to keep using parts of the default configuration but want to
144
+ # replace others configuration has a #merge! method to merge another
145
+ # Excalibur::Configuration object into the default. Note that this will only
146
+ # work if the supplied object is a Excalibur::Configuration or an inherited
147
+ # object.
148
+ #
149
+ # use this by:
150
+ # config.merge!(MyCustomConfiguration.new)
151
+ end
@@ -0,0 +1,215 @@
1
+ require 'spec_helper'
2
+
3
+ module Excalibur
4
+ describe Configuration do
5
+ describe '#new' do
6
+ context 'when creating a configuration without parameters' do
7
+ let(:config) { Configuration.new }
8
+
9
+ it 'should create a title' do
10
+ expect(config.title).to be_instance_of TruncateableContent
11
+ end
12
+
13
+ it 'should create a describe' do
14
+ expect(config.description).to be_instance_of TruncateableContent
15
+ end
16
+
17
+ it 'should create an empty meta tags hash' do
18
+ expect(config.meta_tags).to be_instance_of ::HashWithIndifferentAccess
19
+ expect(config.meta_tags).to be_empty
20
+ end
21
+ end
22
+
23
+ context 'when supplying parameters' do
24
+ let(:config) { Configuration.new('foo', 'bar', 'baz') }
25
+
26
+ it 'should set the right values' do
27
+ expect(config.title).to eq('foo')
28
+ expect(config.description).to eq('bar')
29
+ expect(config.meta_tags).to eq('baz')
30
+ end
31
+ end
32
+ end
33
+
34
+ describe '#merge!' do
35
+ context 'when trying to merge with the wrong type of object' do
36
+ let(:obj) { Configuration.new }
37
+
38
+ it 'should raise a TypeError' do
39
+ expect { obj.merge!('foo') }.to raise_error(TypeError, 'can only merge two Excalibur::Configuration objects')
40
+ end
41
+ end
42
+
43
+ context 'when merging two configurations' do
44
+ let(:obj_a) { Configuration.new(TruncateableContent.new, TruncateableContent.new) }
45
+ let(:obj_b) { Configuration.new(TruncateableContent.new, false, nil) }
46
+
47
+ context 'instance result' do
48
+ after do
49
+ obj_a.merge!(obj_b)
50
+ end
51
+
52
+ it 'should merge the instance variables' do
53
+ expect(obj_a).to receive(:merge_instance).exactly(3).times
54
+ end
55
+ end
56
+
57
+ context 'function result' do
58
+ it 'should return itself' do
59
+ expect(obj_a.merge!(obj_b)).to be_instance_of Configuration
60
+ end
61
+ end
62
+ end
63
+
64
+ describe 'when merging content merging' do
65
+ let(:a) { 'foobar' }
66
+ let(:b) { 'baz' }
67
+ let(:config) { Configuration.new(a) }
68
+ let(:new_config) { Configuration.new(b) }
69
+
70
+ before do
71
+ config.merge!(new_config)
72
+ end
73
+
74
+ context 'when the objects are different classes' do
75
+ context 'when the new object is nil' do
76
+ let(:new_config) { Configuration.new(nil) }
77
+
78
+ it 'should not change the config variable' do
79
+ expect( config.title ).to eq(config.title)
80
+ end
81
+ end
82
+
83
+ context 'when the new object is a value' do
84
+ let(:new_config) { Configuration.new(true) }
85
+
86
+ it 'should change the config variable' do
87
+ expect( config.title ).to eq(true)
88
+ end
89
+ end
90
+ end
91
+
92
+ context 'when the objects are the same class' do
93
+ context 'when merging two hashes' do
94
+ let(:a) { {foo: {bar: 'baz', other: 'old'}} }
95
+ let(:b) { {foo: {other: 'new'}} }
96
+
97
+ it 'should deep merge the two hashes' do
98
+ expect(config.title).to eq( { foo: {bar: 'baz', other: 'new'} } )
99
+ end
100
+ end
101
+
102
+ context 'when merging two TruncatableContent' do
103
+ let(:config) { Configuration.new }
104
+ let(:b) { TruncateableContent.new({foo: 'bar'}, {foo: 'bar'}, 'foobar') }
105
+
106
+ it 'should merge the two TruncatableContent' do
107
+ expect(config.title.content).to eq( b.content )
108
+ expect(config.title.options).to eq( b.options )
109
+ expect(config.title.combinator).to eq( b.combinator )
110
+ end
111
+ end
112
+
113
+ context 'when merging two strings' do
114
+ let(:a) { 'foo' }
115
+ let(:b) { 'bar' }
116
+
117
+ it 'should concatenate the two strings' do
118
+ expect(config.title).to eq('foobar')
119
+ end
120
+ end
121
+
122
+ context 'when merging something else' do
123
+ let(:a) { true }
124
+ let(:b) { false }
125
+
126
+ it 'should replace it' do
127
+ expect(config.title).to eq(false)
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ describe '#dup' do
135
+ it 'should create a duplicate of the object and the attributes' do
136
+ expect(Excalibur.configuration.title).to receive(:dup)
137
+ expect(Excalibur.configuration.description).to receive(:dup)
138
+ expect(Excalibur.configuration.meta_tags).to receive(:dup)
139
+
140
+ Excalibur.configuration.dup
141
+ end
142
+
143
+ it 'should create a duplicate of the object and the attributes' do
144
+ expect(Excalibur.configuration).to receive(:dup_instance).exactly(3).times
145
+
146
+ Excalibur.configuration.dup
147
+ end
148
+ end
149
+
150
+ describe '#set_meta_tag' do
151
+ let(:config) do
152
+ c = Configuration.new
153
+ c.meta_tags = ::HashWithIndifferentAccess.new( name: ::HashWithIndifferentAccess.new( description: 'old' ) )
154
+ c
155
+ end
156
+
157
+ it 'should overwrite a tag' do
158
+ config.set_meta_tag(:name, :description, 'Description content')
159
+
160
+ expect(config.meta_tags).to eq(::HashWithIndifferentAccess.new(
161
+ name: ::HashWithIndifferentAccess.new( description: 'Description content' ))
162
+ )
163
+ end
164
+
165
+ it 'should create a new tag type when required' do
166
+ config.set_meta_tag(:foo, :bar, 'baz')
167
+
168
+ expect(config.meta_tags).to have_key(:foo)
169
+ expect(config.meta_tags[:foo]).to have_key(:bar)
170
+ expect(config.meta_tags[:foo]).to be_instance_of ::HashWithIndifferentAccess
171
+ expect(config.meta_tags[:foo][:bar]).to eq('baz')
172
+ end
173
+ end
174
+
175
+ describe '#remove_meta_tag' do
176
+ let(:config) do
177
+ c = Configuration.new
178
+ c.meta_tags = {
179
+ name: {
180
+ description: 'content',
181
+ other: 'content'
182
+ },
183
+ foo: {
184
+ bar: 'baz'
185
+ }
186
+ }
187
+ c
188
+ end
189
+
190
+ context 'when the type still has values left' do
191
+ before do
192
+ config.remove_meta_tag(:name, :other)
193
+ end
194
+
195
+ it 'should have removed the name' do
196
+ expect(config.meta_tags[:name]).to_not have_key(:other)
197
+ end
198
+
199
+ it 'should still have the type' do
200
+ expect(config.meta_tags).to have_key(:name)
201
+ end
202
+ end
203
+
204
+ context 'when the type still has values left' do
205
+ before do
206
+ config.remove_meta_tag(:foo, :bar)
207
+ end
208
+
209
+ it 'should have removed the type' do
210
+ expect(config.meta_tags).to_not have_key(:foo)
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,224 @@
1
+ require 'spec_helper'
2
+
3
+ module Excalibur
4
+ class Dummy; end
5
+ class DummyDecorator < Decorator; end
6
+
7
+ describe Decorator do
8
+ before do
9
+ Excalibur.reset
10
+ DummyDecorator.configuration = nil
11
+ end
12
+
13
+ after do
14
+ DummyDecorator.configuration = nil
15
+ end
16
+
17
+ describe '#new' do
18
+ context 'when creating it without options' do
19
+ let(:obj) { DummyDecorator.decorate(Dummy.new) }
20
+
21
+ it { expect(obj.context).to be_empty }
22
+ it { expect(obj.configuration).to be_present }
23
+ end
24
+
25
+ context 'when creating it with options' do
26
+ context 'when providing context' do
27
+ let(:obj) { DummyDecorator.decorate(Dummy.new, context: {foo: 'bar'}) }
28
+
29
+ it { expect(obj.context).to_not be_empty }
30
+ it { expect(obj.context).to eq({foo: 'bar'}) }
31
+ end
32
+
33
+ context 'when providing config' do
34
+ let(:config) { Configuration.new }
35
+ let(:obj) { DummyDecorator.decorate(Dummy.new, config: config) }
36
+
37
+ it 'should try and merge the configuration' do
38
+ expect_any_instance_of(Configuration).to receive(:merge!).with(config)
39
+
40
+ obj
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ context 'when configuring a decorator with mixed methods' do
47
+ before do
48
+ DummyDecorator.configuration = nil
49
+
50
+ class DummyDecorator < Decorator
51
+ excalibur_set_meta_tag(:foo, :bar, proc { |obj| 'content' })
52
+ excalibur_set_meta_tag(:name, :other, 'content')
53
+
54
+ excalibur_set_title_content(:prefix, 'Exc / ')
55
+ excalibur_set_title_content(:body, 'title body')
56
+ excalibur_set_title_option(:length, 42)
57
+ excalibur_set_title_combinator proc{ |obj| "result #{obj}" }
58
+
59
+ excalibur_set_description_content(:body, 'title body')
60
+ excalibur_set_description_option(:length, 42)
61
+ excalibur_set_description_combinator proc{ |obj| "result #{obj}" }
62
+ end
63
+ end
64
+
65
+ it { expect(DummyDecorator.configuration.meta_tags).to have_key(:name) }
66
+ it { expect(DummyDecorator.configuration.meta_tags[:name]).to have_key(:other) }
67
+ it { expect(DummyDecorator.configuration.meta_tags).to have_key(:foo) }
68
+ it { expect(DummyDecorator.configuration.meta_tags[:foo]).to have_key(:bar) }
69
+
70
+ it { expect(DummyDecorator.configuration.title.content[:prefix]).to eq 'Exc / ' }
71
+ it { expect(DummyDecorator.configuration.title.content[:body]).to eq 'title body' }
72
+ it { expect(DummyDecorator.configuration.title.options[:length]).to eq 42 }
73
+ it { expect(DummyDecorator.configuration.title.combinator).to be_instance_of Proc }
74
+ it { expect(DummyDecorator.configuration.title.combinator.call('foobar')).to eq('result foobar') }
75
+
76
+ it { expect(DummyDecorator.configuration.description.content[:body]).to eq 'title body' }
77
+ it { expect(DummyDecorator.configuration.description.options[:length]).to eq 42 }
78
+ it { expect(DummyDecorator.configuration.description.combinator).to be_instance_of Proc }
79
+ it { expect(DummyDecorator.configuration.description.combinator.call('foobar')).to eq('result foobar') }
80
+ end
81
+
82
+ describe '::excalibur_init' do
83
+ context 'when creating a decorator' do
84
+ context 'when setting the config without a value' do
85
+ before do
86
+ class DummyDecorator < Decorator
87
+ excalibur_init
88
+ end
89
+ end
90
+
91
+ it { expect(DummyDecorator.configuration).to be_present }
92
+ it { expect(DummyDecorator.configuration).to be_instance_of Configuration }
93
+ end
94
+
95
+ context 'when setting the config with a value' do
96
+ before do
97
+ class DummyDecorator < Decorator
98
+ excalibur_init true
99
+ end
100
+ end
101
+
102
+ it { expect(DummyDecorator.configuration).to be_present }
103
+ it { expect(DummyDecorator.configuration).to eq(true) }
104
+ end
105
+ end
106
+ end
107
+
108
+ describe '::configuration' do
109
+ it 'should duplicate the system wide configuration' do
110
+ expect( Excalibur.configuration ).to receive(:dup)
111
+
112
+ DummyDecorator.configuration
113
+ end
114
+
115
+ it 'should only duplicate the system wide configuration once' do
116
+ DummyDecorator.configuration
117
+
118
+ expect( Excalibur.configuration ).to_not receive(:dup)
119
+
120
+ DummyDecorator.configuration
121
+ end
122
+ end
123
+
124
+ describe '::excalibur_set' do
125
+ describe '_title' do
126
+ describe '_content' do
127
+ it 'should change the title content' do
128
+ expect {
129
+ DummyDecorator.excalibur_set_title_content(:foo, 'bar')
130
+ }.to change(DummyDecorator.configuration.title, :content).to(body: 'Excalibur', foo: 'bar')
131
+ end
132
+ end
133
+
134
+ describe '_option' do
135
+ it 'should change the title options' do
136
+ expect {
137
+ DummyDecorator.excalibur_set_title_option(:foo, 'bar')
138
+ }.to change(DummyDecorator.configuration.title, :options).to(length: 69, omission: '...', separator: '', foo: 'bar')
139
+ end
140
+ end
141
+
142
+ describe '_combinator' do
143
+ it 'should change the title combinator' do
144
+ expect {
145
+ DummyDecorator.excalibur_set_title_combinator(true)
146
+ }.to change(DummyDecorator.configuration.title, :combinator).to(true)
147
+ end
148
+ end
149
+ end
150
+
151
+ describe '_description' do
152
+ describe '_content' do
153
+ it 'should change the description content' do
154
+ expect {
155
+ DummyDecorator.excalibur_set_description_content(:foo, 'bar')
156
+ }.to change(DummyDecorator.configuration.description, :content).to(body: 'Excalibur; a worthy title for a gem about titles.', foo: 'bar')
157
+ end
158
+ end
159
+
160
+ describe '_option' do
161
+ it 'should change the description options' do
162
+ expect {
163
+ DummyDecorator.excalibur_set_description_option(:foo, 'bar')
164
+ }.to change(DummyDecorator.configuration.description, :options).to(length: 155, omission: '...', separator: ' ', foo: 'bar')
165
+ end
166
+ end
167
+
168
+ describe '_combinator' do
169
+ it 'should change the description combinator' do
170
+ expect {
171
+ DummyDecorator.excalibur_set_description_combinator(true)
172
+ }.to change(DummyDecorator.configuration.description, :combinator).to(true)
173
+ end
174
+ end
175
+ end
176
+
177
+ describe '_meta_tag' do
178
+ it 'should change the meta tags' do
179
+ expect(DummyDecorator.configuration).to receive(:set_meta_tag).with(:name, :description, 'foobar')
180
+
181
+ DummyDecorator.excalibur_set_meta_tag(:name, :description, 'foobar')
182
+ end
183
+ end
184
+ end
185
+
186
+ describe '#configuration' do
187
+ let(:obj) { DummyDecorator.decorate(Dummy.new) }
188
+
189
+ it "should duplicate the decorator's configuration" do
190
+ expect(obj.class.configuration).to receive(:dup)
191
+
192
+ obj.configuration
193
+ end
194
+
195
+ it 'should return a configuration' do
196
+ expect(obj.configuration).to be_instance_of Configuration
197
+ end
198
+ end
199
+
200
+ describe '#customize_configuration' do
201
+ let(:obj) { DummyDecorator.decorate(Dummy.new) }
202
+
203
+ it 'should merge the input with the configuration' do
204
+ expect(obj.configuration).to receive(:merge!).with('foobar')
205
+
206
+ obj.customize_configuration('foobar')
207
+ end
208
+ end
209
+
210
+ describe '#render_title' do
211
+ let(:obj) { DummyDecorator.decorate(Dummy.new) }
212
+
213
+ context 'when using the default settings' do
214
+ it { expect(obj.render_title).to eq('Excalibur') }
215
+
216
+ it 'should call to_s in the title' do
217
+ expect(obj.configuration.title).to receive(:to_s)
218
+
219
+ obj.render_title
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end