excalibur 0.0.2

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.
@@ -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