telvue-rsolr 2.2.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,48 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RSolr::Document do
4
+ describe RSolr::Field do
5
+ describe ".instance" do
6
+ subject { RSolr::Field }
7
+
8
+ it "uses the class name of the field value" do
9
+ expect(subject.instance({}, Time.new)).to be_a_kind_of(RSolr::TimeField)
10
+ end
11
+
12
+ it "uses the provided type option when it is a class" do
13
+ expect(subject.instance({:type => RSolr::TimeField}, nil)).to be_a_kind_of(RSolr::TimeField)
14
+ end
15
+
16
+ it "uses the provided type option when it is a string" do
17
+ expect(subject.instance({:type => 'Time'}, nil)).to be_a_kind_of(RSolr::TimeField)
18
+ end
19
+
20
+ it "falls back to the base Field class" do
21
+ expect(subject.instance({:type => 'UndefinedType'}, nil)).to be_a_kind_of(RSolr::Field)
22
+ end
23
+
24
+ it "defaults to the base Field class" do
25
+ expect(subject.instance({}, nil)).to be_a_kind_of(RSolr::Field)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe RSolr::TimeField do
31
+ it "convert value to string" do
32
+ time_value = Time.utc(2013, 9, 11, 18, 10, 0)
33
+ expect(RSolr::Field.instance({}, time_value).value).to eq '2013-09-11T18:10:00Z'
34
+ end
35
+
36
+ it "convert time to UTC" do
37
+ time_value = Time.new(2013, 9, 11, 18, 10, 0, '+02:00')
38
+ expect(RSolr::Field.instance({}, time_value).value).to eq '2013-09-11T16:10:00Z'
39
+ end
40
+ end
41
+
42
+ describe RSolr::DateField do
43
+ it "convert value to string" do
44
+ date_value = Date.new(2013, 9, 11)
45
+ expect(RSolr::Field.instance({}, date_value).value).to eq '2013-09-11T00:00:00Z'
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RSolr::Error do
4
+ def generate_error_with_backtrace(request, response)
5
+ raise RSolr::Error::Http.new request, response
6
+ rescue RSolr::Error::Http => exception
7
+ exception
8
+ end
9
+ let (:response_lines) { (1..15).to_a.map { |i| "line #{i}" } }
10
+ let(:request) { double :[] => "mocked" }
11
+ let(:response_body) { response_lines.join("\n") }
12
+ let(:response) {{
13
+ :body => response_body,
14
+ :status => 400
15
+ }}
16
+ subject { generate_error_with_backtrace(request, response).to_s }
17
+
18
+ context "when the response body is wrapped in a <pre> element" do
19
+ let(:response_body) { "<pre>" + response_lines.join("\n") + "</pre>" }
20
+
21
+ it "only shows the first eleven lines of the response" do
22
+ expect(subject).to match(/line 1\n.+line 11\n\n/m)
23
+ end
24
+
25
+ context "when the response is one line long" do
26
+ let(:response_body) { "<pre>failed</pre>" }
27
+ it { should match(/Error: failed/) }
28
+ end
29
+ end
30
+
31
+ context "when the response body is not wrapped in a <pre> element" do
32
+
33
+ it "only shows the first eleven lines of the response" do
34
+ expect(subject).to match(/line 1\n.+line 11\n\n/m)
35
+ end
36
+
37
+ context "when the response is one line long" do
38
+ let(:response_body) { 'failed' }
39
+ it { should match(/Error: failed/) }
40
+ end
41
+ context "when the response body contains a msg key" do
42
+ let(:msg) { "'org.apache.solr.search.SyntaxError: Cannot parse \\':false\\': Encountered \" \":\" \": \"\" at line 1, column 0.'" }
43
+ let(:response_body) { (response_lines << "'error'=>{'msg'=> #{msg}").join("\n") }
44
+ it { should include msg }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,198 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RSolr::JSON do
4
+
5
+ let(:generator){ RSolr::JSON::Generator.new }
6
+
7
+ context :add do
8
+ # add a single hash ("doc")
9
+ it 'should create an add from a hash' do
10
+ data = {
11
+ :id=>"1",
12
+ :name=>'matt'
13
+ }
14
+ message = JSON.parse(generator.add(data), symbolize_names: true)
15
+ expect(message.length).to eq 1
16
+ expect(message.first).to eq data
17
+ end
18
+
19
+ # add an array of hashes
20
+ it 'should create many adds from an array of hashes' do
21
+ data = [
22
+ {
23
+ :id=>"1",
24
+ :name=>'matt'
25
+ },
26
+ {
27
+ :id=>"2",
28
+ :name=>'sam'
29
+ }
30
+ ]
31
+ message = JSON.parse(generator.add(data), symbolize_names: true)
32
+ expect(message).to eq data
33
+ end
34
+
35
+ it 'should yield a Document object when #add is called with a block' do
36
+ documents = [{:id=>1, :name=>'sam', :cat=>['cat 1', 'cat 2']}]
37
+ result = generator.add(documents) do |doc|
38
+ doc.field_by_name(:name).attrs[:boost] = 10
39
+ end
40
+
41
+ message = JSON.parse(result, symbolize_names: true)
42
+
43
+ expect(message.length).to eq 1
44
+ expect(message.first).to include name: { boost: 10, value: 'sam' }
45
+ end
46
+
47
+ context 'with add_attr' do
48
+ it 'should create an add command with the attributes from a hash' do
49
+ data = {
50
+ :id=>"1",
51
+ :name=>'matt'
52
+ }
53
+ message = JSON.parse(generator.add(data, boost: 1), symbolize_names: true)
54
+ expect(message).to include :add
55
+ expect(message[:add][:doc]).to eq data
56
+ expect(message[:add][:boost]).to eq 1
57
+ end
58
+
59
+ it 'should create multiple add command with the attributes from a hash' do
60
+ data = [
61
+ {
62
+ :id=>"1",
63
+ :name=>'matt'
64
+ },
65
+ {
66
+ :id=>"2",
67
+ :name=>'sam'
68
+ },
69
+ ]
70
+
71
+ # custom JSON object class to handle Solr's non-standard JSON command format
72
+ tmp = Class.new do
73
+ def initialize
74
+ @source ||= {}
75
+ end
76
+
77
+ def []=(k, v)
78
+ if k == :add
79
+ @source[k] ||= []
80
+ @source[k] << v.to_h
81
+ elsif v.class == self.class
82
+ @source[k] = v.to_h
83
+ else
84
+ @source[k] = v
85
+ end
86
+ end
87
+
88
+ def to_h
89
+ @source
90
+ end
91
+ end
92
+
93
+ request = generator.add(data, boost: 1)
94
+ message = JSON.parse(request, object_class: tmp, symbolize_names: true).to_h
95
+ expect(message[:add].length).to eq 2
96
+ expect(message[:add].map { |x| x[:doc] }).to eq data
97
+ end
98
+ end
99
+
100
+ it 'allows for atomic updates' do
101
+ data = {
102
+ foo: { set: 'Bar' }
103
+ }
104
+
105
+ message = JSON.parse(generator.add(data), symbolize_names: true)
106
+ expect(message.length).to eq 1
107
+ expect(message.first).to eq data
108
+ end
109
+
110
+ it 'supports nested child documents' do
111
+ data = {
112
+ _childDocuments_: [
113
+ {
114
+ id: 1
115
+ },
116
+ {
117
+ id: 2
118
+ }
119
+ ]
120
+ }
121
+
122
+ message = JSON.parse(generator.add(data), symbolize_names: true)
123
+ expect(message.length).to eq 1
124
+ expect(message.first).to eq data
125
+ end
126
+
127
+ it 'supports nested child documents with only a single document' do
128
+ data = {
129
+ _childDocuments_: [
130
+ {
131
+ id: 1
132
+ }
133
+ ]
134
+ }
135
+
136
+ message = JSON.parse(generator.add(data), symbolize_names: true)
137
+ expect(message.length).to eq 1
138
+ expect(message.first).to eq data
139
+ end
140
+ end
141
+
142
+ it 'should create multiple fields from array values' do
143
+ data = {
144
+ :id => "1",
145
+ :name => ['matt1', 'matt2']
146
+ }
147
+ message = JSON.parse(generator.add(data), symbolize_names: true)
148
+ expect(message.length).to eq 1
149
+ expect(message.first).to eq data
150
+ end
151
+
152
+ it 'should create multiple fields from array values with options' do
153
+ test_values = [nil, 'matt1', 'matt2']
154
+ message = JSON.parse(
155
+ generator.add(id: '1') { |doc| doc.add_field(:name, test_values, boost: 3) },
156
+ symbolize_names: true
157
+ )
158
+ expect(message).to eq [{ id: '1', name: { boost: 3, value: test_values } }]
159
+ end
160
+
161
+ describe '#commit' do
162
+ it 'generates a commit command' do
163
+ expect(JSON.parse(generator.commit, symbolize_names: true)).to eq(commit: {})
164
+ end
165
+ end
166
+
167
+ describe '#optimize' do
168
+ it 'generates a optimize command' do
169
+ expect(JSON.parse(generator.optimize, symbolize_names: true)).to eq(optimize: {})
170
+ end
171
+ end
172
+
173
+ describe '#rollback' do
174
+ it 'generates a rollback command' do
175
+ expect(JSON.parse(generator.rollback, symbolize_names: true)).to eq(rollback: {})
176
+ end
177
+ end
178
+
179
+ describe '#delete_by_id' do
180
+ it 'generates a delete_by_id command for single documents' do
181
+ expect(JSON.parse(generator.delete_by_id('x'), symbolize_names: true)).to eq(delete: 'x')
182
+ end
183
+
184
+ it 'generates a delete_by_id command for an array of documents' do
185
+ expect(JSON.parse(generator.delete_by_id(%w(a b c)), symbolize_names: true)).to eq(delete: %w(a b c))
186
+ end
187
+ end
188
+
189
+ describe '#delete_by_query' do
190
+ it 'generates a delete_by_id command for single documents' do
191
+ expect(JSON.parse(generator.delete_by_query('id:x'), symbolize_names: true)).to eq(delete: { query: 'id:x'})
192
+ end
193
+
194
+ it 'generates a delete_by_id command for an array of documents' do
195
+ expect(JSON.parse(generator.delete_by_id(%w(a b c)), symbolize_names: true)).to eq(delete: %w(a b c))
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RSolr::Client do
4
+ context "build_paginated_request" do
5
+ it "should create the proper solr params and query string" do
6
+ c = RSolr::Client.new(nil, {})#.extend(RSolr::Pagination::Client)
7
+ r = c.build_paginated_request 3, 25, "select", {:params => {:q => "test"}}
8
+ #r[:page].should == 3
9
+ #r[:per_page].should == 25
10
+ expect(r[:params]["start"]).to eq(50)
11
+ expect(r[:params]["rows"]).to eq(25)
12
+ expect(r[:uri].query).to match(/rows=25/)
13
+ expect(r[:uri].query).to match(/start=50/)
14
+ end
15
+ end
16
+ context "paginate" do
17
+ it "should build a paginated request context and call execute" do
18
+ c = RSolr::Client.new(nil, {})#.extend(RSolr::Pagination::Client)
19
+ expect(c).to receive(:execute).with(hash_including({
20
+ #:page => 1,
21
+ #:per_page => 10,
22
+ :params => {
23
+ "rows" => 10,
24
+ "start" => 0,
25
+ :wt => :json
26
+ }
27
+ }))
28
+ c.paginate 1, 10, "select"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RSolr do
4
+
5
+ it "has a version that can be read via #version or VERSION" do
6
+ expect(RSolr.version).to eq(RSolr::VERSION)
7
+ end
8
+
9
+ context "connect" do
10
+ it "should return a RSolr::Client instance" do
11
+ expect(RSolr.connect).to be_a(RSolr::Client)
12
+ end
13
+ end
14
+
15
+ context '.solr_escape' do
16
+ it "adds backslash to Solr query syntax chars" do
17
+ # per http://lucene.apache.org/core/4_0_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Escaping_Special_Characters
18
+ special_chars = [ "+", "-", "&", "|", "!", "(", ")", "{", "}", "[", "]", "^", '"', "~", "*", "?", ":", "\\", "/" ]
19
+ escaped_str = RSolr.solr_escape("aa#{special_chars.join('aa')}aa")
20
+ special_chars.each { |c|
21
+ # note that the ruby code sending the query to Solr will un-escape the backslashes
22
+ # so the result sent to Solr is ultimately a single backslash in front of the particular character
23
+ expect(escaped_str).to match "\\#{c}"
24
+ }
25
+ end
26
+ it "leaves other chars alone" do
27
+ str = "nothing to see here; let's move along people."
28
+ expect(RSolr.solr_escape(str)).to eq str
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RSolr::Uri do
4
+
5
+ let(:uri) { RSolr::Uri }
6
+
7
+ context '.params_to_solr' do
8
+ it "converts Hash to Solr query string w/o a starting ?" do
9
+ hash = {:q => "gold", :fq => ["mode:one", "level:2"]}
10
+ query = uri.params_to_solr hash
11
+ expect(query[0]).not_to eq(??)
12
+ [/q=gold/, /fq=mode%3Aone/, /fq=level%3A2/].each do |p|
13
+ expect(query).to match p
14
+ end
15
+ expect(query.split('&').size).to eq(3)
16
+ end
17
+ it 'should URL escape &' do
18
+ expect(uri.params_to_solr(:fq => "&")).to eq('fq=%26')
19
+ end
20
+
21
+ it 'should convert spaces to +' do
22
+ expect(uri.params_to_solr(:fq => "me and you")).to eq('fq=me+and+you')
23
+ end
24
+
25
+ it 'should URL escape complex queries, part 1' do
26
+ my_params = {'fq' => '{!raw f=field_name}crazy+\"field+value'}
27
+ expected = 'fq=%7B%21raw+f%3Dfield_name%7Dcrazy%2B%5C%22field%2Bvalue'
28
+ expect(uri.params_to_solr(my_params)).to eq(expected)
29
+ end
30
+
31
+ it 'should URL escape complex queries, part 2' do
32
+ my_params = {'q' => '+popularity:[10 TO *] +section:0'}
33
+ expected = 'q=%2Bpopularity%3A%5B10+TO+*%5D+%2Bsection%3A0'
34
+ expect(uri.params_to_solr(my_params)).to eq(expected)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,255 @@
1
+ require 'spec_helper'
2
+ require 'builder'
3
+ require 'nokogiri'
4
+
5
+ RSpec.describe RSolr::Xml do
6
+ let(:generator){ RSolr::Xml::Generator.new }
7
+
8
+ builder_engines = {
9
+ :builder => { :val => false, :class => Builder::XmlMarkup, :engine => Builder::XmlMarkup.new(:indent => 0, :margin => 0, :encoding => 'UTF-8') },
10
+ :nokogiri => { :val => true, :class => Nokogiri::XML::Builder, :engine => Nokogiri::XML::Builder.new }
11
+ }
12
+
13
+ [:builder,:nokogiri].each do |engine_name|
14
+ describe engine_name do
15
+ before :all do
16
+ @engine = builder_engines[engine_name]
17
+ @old_ng_setting = RSolr::Xml::Generator.use_nokogiri
18
+ RSolr::Xml::Generator.use_nokogiri = @engine[:val]
19
+ end
20
+
21
+ after :all do
22
+ RSolr::Xml::Generator.use_nokogiri = @old_ng_setting
23
+ end
24
+
25
+ before :each do
26
+ builder_engines.each_pair do |name,spec|
27
+ expect(spec[:class]).not_to receive(:new) unless name == engine_name
28
+ end
29
+ end
30
+
31
+ context :xml_engine do
32
+ it "should use #{engine_name}" do
33
+ expect(@engine[:class]).to receive(:new).and_return(@engine[:engine])
34
+ generator.send(:commit)
35
+ end
36
+ end
37
+
38
+ # call all of the simple methods...
39
+ # make sure the xml string is valid
40
+ # ensure the class is actually Solr::XML
41
+ [:optimize, :rollback, :commit].each do |meth|
42
+ it "#{meth} should generator xml" do
43
+ result = generator.send(meth)
44
+ expect(result).to eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><#{meth}/>")
45
+ end
46
+ end
47
+
48
+ context :add do
49
+
50
+ it 'should yield a Message::Document object when #add is called with a block' do
51
+ documents = [{:id=>1, :name=>'sam', :cat=>['cat 1', 'cat 2']}]
52
+ add_attrs = {:boost=>200.00}
53
+ result = generator.add(documents, add_attrs) do |doc|
54
+ doc.field_by_name(:name).attrs[:boost] = 10
55
+ end
56
+ expect(result).to match(%r(name="cat">cat 1</field>))
57
+ expect(result).to match(%r(name="cat">cat 2</field>))
58
+ expect(result).to match(%r(<add boost="200.0">))
59
+ expect(result).to match(%r(boost="10"))
60
+ expect(result).to match(%r(<field name="id">1</field>))
61
+ end
62
+
63
+ it 'should work for values that yield enumerators' do
64
+ documents = [{id: 1, cat: ['cat 1', 'cat 2'].to_enum}]
65
+ result = generator.add(documents)
66
+
67
+ expect(result).to match(%r(name="cat">cat 1</field>))
68
+ expect(result).to match(%r(name="cat">cat 2</field>))
69
+ end
70
+
71
+ # add a single hash ("doc")
72
+ it 'should create an add from a hash' do
73
+ data = {
74
+ :id=>1,
75
+ :name=>'matt'
76
+ }
77
+ result = generator.add(data)
78
+ expect(result).to match(/<field name="name">matt<\/field>/)
79
+ expect(result).to match(/<field name="id">1<\/field>/)
80
+ end
81
+
82
+ # add a single hash ("doc")
83
+ it 'should create an add from a hash formatted for atomic updates' do
84
+ data = {
85
+ :id=>1,
86
+ :name=> { set: 'matt' }
87
+ }
88
+ result = generator.add(data)
89
+ expect(result).to match(/<field name="name" update="set">matt<\/field>/)
90
+ expect(result).to match(/<field name="id">1<\/field>/)
91
+ end
92
+ it 'should remove a field from a hash formatted for atomic updates' do
93
+ data = {
94
+ :id => 1,
95
+ :name => nil
96
+ }
97
+ result = generator.add(data)
98
+ expect(result).to match(%r{<field name="name" null="true"})
99
+ expect(result).to match(/<field name="id">1<\/field>/)
100
+ end
101
+
102
+ # add an array of hashes
103
+ it 'should create many adds from an array of hashes' do
104
+ data = [
105
+ {
106
+ :id=>1,
107
+ :name=>'matt'
108
+ },
109
+ {
110
+ :id=>2,
111
+ :name=>'sam'
112
+ }
113
+ ]
114
+ message = generator.add(data)
115
+ expect(message).to match %r{<field name="name">matt</field>}
116
+ expect(message).to match %r{<field name="name">sam</field>}
117
+ end
118
+
119
+ # multiValue field support test, thanks to Fouad Mardini!
120
+ it 'should create multiple fields from array values' do
121
+ data = {
122
+ :id => 1,
123
+ :name => ['matt1', 'matt2']
124
+ }
125
+ result = generator.add(data)
126
+ expect(result).to match(/<field name="name">matt1<\/field>/)
127
+ expect(result).to match(/<field name="name">matt2<\/field>/)
128
+ end
129
+
130
+ it 'should allow for objects which can be casted to an array' do
131
+ name = double("name", to_ary: ['matt1', 'matt2'])
132
+ data = {
133
+ :id => 1,
134
+ :name => name
135
+ }
136
+ result = generator.add(data)
137
+ expect(result).to match(/<field name="name">matt1<\/field>/)
138
+ expect(result).to match(/<field name="name">matt2<\/field>/)
139
+ end
140
+
141
+ it 'should create an add from a single Message::Document' do
142
+ document = RSolr::Document.new
143
+ document.add_field('id', 1)
144
+ document.add_field('name', 'matt', :boost => 2.0)
145
+ result = generator.add(document)
146
+ expect(result).to match(Regexp.escape('<?xml version="1.0" encoding="UTF-8"?>'))
147
+ expect(result).to match(/<field name="id">1<\/field>/)
148
+ expect(result).to match Regexp.escape('boost="2.0"')
149
+ expect(result).to match Regexp.escape('name="name"')
150
+ expect(result).to match Regexp.escape('matt</field>')
151
+ end
152
+
153
+ it 'should create adds from multiple Message::Documents' do
154
+ documents = (1..2).map do |i|
155
+ doc = RSolr::Document.new
156
+ doc.add_field('id', i)
157
+ doc.add_field('name', "matt#{i}")
158
+ doc
159
+ end
160
+ result = generator.add(documents)
161
+ expect(result).to match(/<field name="name">matt1<\/field>/)
162
+ expect(result).to match(/<field name="name">matt2<\/field>/)
163
+ end
164
+
165
+ it 'supports nested child documents' do
166
+ data = {
167
+ :_childDocuments_ => [
168
+ {
169
+ :id => 1
170
+ },
171
+ {
172
+ :id => 2
173
+ }
174
+ ]
175
+ }
176
+
177
+ result = generator.add(data)
178
+ expect(result).to match(%r{<add><doc><doc>})
179
+ expect(result).to match(%r{<doc><field name="id">1</field></doc>})
180
+ expect(result).to match(%r{<doc><field name="id">2</field></doc>})
181
+ end
182
+ end
183
+
184
+ context :delete_by_id do
185
+
186
+ it 'should create a doc id delete' do
187
+ expect(generator.delete_by_id(10)).to eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><id>10</id></delete>")
188
+ end
189
+
190
+ it 'should create many doc id deletes' do
191
+ expect(generator.delete_by_id([1, 2, 3])).to eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><id>1</id><id>2</id><id>3</id></delete>")
192
+ end
193
+
194
+ end
195
+
196
+ context :delete_by_query do
197
+ it 'should create a query delete' do
198
+ expect(generator.delete_by_query('status:"LOST"')).to eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><query>status:\"LOST\"</query></delete>")
199
+ end
200
+
201
+ it 'should create many query deletes' do
202
+ expect(generator.delete_by_query(['status:"LOST"', 'quantity:0'])).to eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><query>status:\"LOST\"</query><query>quantity:0</query></delete>")
203
+ end
204
+ end
205
+
206
+ end
207
+ end
208
+
209
+ context :formatting do
210
+ it 'should format date objects into ISO 8601' do
211
+ data = {
212
+ dt: Date.new(1992, 03, 15)
213
+ }
214
+ result = generator.add(data)
215
+ expect(result).to match(/<field name="dt">1992-03-15T00:00:00Z<\/field>/)
216
+ end
217
+
218
+ it 'should format time objects into ISO 8601' do
219
+ data = {
220
+ dt: Time.new(1992, 03, 15, 16, 23, 55, 3600)
221
+ }
222
+ result = generator.add(data)
223
+ expect(result).to match(/<field name="dt">1992-03-15T15:23:55Z<\/field>/)
224
+ end
225
+
226
+ it 'should format datetime objects into ISO 8601' do
227
+ data = {
228
+ dt: DateTime.new(1992, 03, 15, 16, 23, 55, '+1')
229
+ }
230
+ result = generator.add(data)
231
+ expect(result).to match(/<field name="dt">1992-03-15T15:23:55Z<\/field>/)
232
+ end
233
+
234
+ it 'passes through other values' do
235
+ data = {
236
+ whatever: 'some string'
237
+ }
238
+
239
+ result = generator.add(data)
240
+ expect(result).to match(/<field name="whatever">some string<\/field>/)
241
+ end
242
+
243
+ # rails monkey-patches String to add a #to_time casting..
244
+ context 'with rails monkey patching' do
245
+ it 'passes through string values' do
246
+ data = {
247
+ whatever: double(to_s: 'some string', to_time: nil)
248
+ }
249
+
250
+ result = generator.add(data)
251
+ expect(result).to match(/<field name="whatever">some string<\/field>/)
252
+ end
253
+ end
254
+ end
255
+ end