active-fedora 11.0.0.rc7 → 11.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +2 -7
  4. data/.rubocop_todo.yml +40 -9
  5. data/active-fedora.gemspec +2 -2
  6. data/lib/active_fedora/associations/collection_association.rb +1 -1
  7. data/lib/active_fedora/associations/contained_finder.rb +2 -2
  8. data/lib/active_fedora/change_set.rb +6 -2
  9. data/lib/active_fedora/core.rb +18 -7
  10. data/lib/active_fedora/fedora_attributes.rb +1 -1
  11. data/lib/active_fedora/indexing_service.rb +0 -4
  12. data/lib/active_fedora/orders/ordered_list.rb +2 -2
  13. data/lib/active_fedora/relation/delegation.rb +4 -0
  14. data/lib/active_fedora/solr_hit.rb +0 -4
  15. data/lib/active_fedora/solr_query_builder.rb +16 -12
  16. data/lib/active_fedora/version.rb +1 -1
  17. data/spec/config_helper.rb +1 -1
  18. data/spec/integration/autosave_association_spec.rb +1 -1
  19. data/spec/integration/base_spec.rb +1 -1
  20. data/spec/integration/file_spec.rb +1 -1
  21. data/spec/integration/indexing_spec.rb +1 -1
  22. data/spec/integration/query_result_builder_spec.rb +1 -1
  23. data/spec/integration/relation_delegation_spec.rb +1 -3
  24. data/spec/integration/versionable_spec.rb +4 -4
  25. data/spec/spec_helper.rb +52 -3
  26. data/spec/unit/active_fedora_spec.rb +1 -1
  27. data/spec/unit/association_hash_spec.rb +8 -22
  28. data/spec/unit/attached_files_spec.rb +6 -6
  29. data/spec/unit/base_cma_spec.rb +1 -1
  30. data/spec/unit/base_extra_spec.rb +2 -18
  31. data/spec/unit/base_spec.rb +1 -1
  32. data/spec/unit/callback_spec.rb +2 -2
  33. data/spec/unit/checksum_spec.rb +2 -2
  34. data/spec/unit/code_configurator_spec.rb +1 -1
  35. data/spec/unit/core_spec.rb +36 -0
  36. data/spec/unit/default_model_mapper_spec.rb +3 -3
  37. data/spec/unit/file_configurator_spec.rb +4 -4
  38. data/spec/unit/file_path_builder_spec.rb +1 -1
  39. data/spec/unit/file_spec.rb +1 -1
  40. data/spec/unit/files_hash_spec.rb +2 -2
  41. data/spec/unit/finder_methods_spec.rb +3 -3
  42. data/spec/unit/has_and_belongs_to_many_association_spec.rb +0 -2
  43. data/spec/unit/has_many_association_spec.rb +2 -2
  44. data/spec/unit/indexing_spec.rb +2 -2
  45. data/spec/unit/logger_spec.rb +1 -1
  46. data/spec/unit/orders/reflection_spec.rb +1 -1
  47. data/spec/unit/property_spec.rb +2 -2
  48. data/spec/unit/query_spec.rb +1 -1
  49. data/spec/unit/reflection_spec.rb +3 -3
  50. data/spec/unit/solr_config_options_spec.rb +1 -1
  51. data/spec/unit/solr_service_spec.rb +4 -10
  52. data/spec/unit/with_metadata/default_metadata_class_factory_spec.rb +1 -1
  53. data/spec/unit/with_metadata/metadata_node_spec.rb +1 -1
  54. metadata +10 -17
  55. data/spec/fixtures/damsObjectModel.xml +0 -38
  56. data/spec/fixtures/dublin_core_rdf_descMetadata.nt +0 -13
  57. data/spec/fixtures/mixed_rdf_descMetadata.nt +0 -7
  58. data/spec/fixtures/mods_articles/mods_article1.xml +0 -98
  59. data/spec/fixtures/solr_rdf_descMetadata.nt +0 -7
  60. data/spec/samples/oral_history_sample.xml +0 -38
  61. data/spec/samples/oral_history_xml.xml +0 -35
@@ -36,8 +36,8 @@ describe ActiveFedora::Versionable do
36
36
  allow(graph).to receive(:fedora_versions) { versions }
37
37
  end
38
38
 
39
- let(:version1) { double('version1', uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e711aa993d-e1d2-4a65-93ee-3a12fc9541ab', label: 'version1', created: '2015-04-02T19:54:45.962Z') }
40
- let(:version2) { double('version2', uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e790373a67-c9ee-447d-b740-4faa882b1a1f', label: 'version2', created: '2015-04-02T19:54:45.96Z') }
39
+ let(:version1) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e711aa993d-e1d2-4a65-93ee-3a12fc9541ab', label: 'version1', created: '2015-04-02T19:54:45.962Z') }
40
+ let(:version2) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e790373a67-c9ee-447d-b740-4faa882b1a1f', label: 'version2', created: '2015-04-02T19:54:45.96Z') }
41
41
  let(:versions) { [version1, version2] }
42
42
 
43
43
  subject(:graph) { ActiveFedora::VersionsGraph.new }
@@ -47,7 +47,7 @@ describe ActiveFedora::Versionable do
47
47
  end
48
48
 
49
49
  context 'with an unparseable created date' do
50
- let(:version2) { double('version2', uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e790373a67-c9ee-447d-b740-4faa882b1a1f', label: 'version2', created: '') }
50
+ let(:version2) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e790373a67-c9ee-447d-b740-4faa882b1a1f', label: 'version2', created: '') }
51
51
 
52
52
  it 'raises an exception' do
53
53
  expect { graph.first }.to raise_error(ActiveFedora::VersionLacksCreateDate)
@@ -60,7 +60,7 @@ describe ActiveFedora::Versionable do
60
60
  allow(version2).to receive(:created) { raise NoMethodError }
61
61
  end
62
62
 
63
- let(:version2) { double('version2', uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e790373a67-c9ee-447d-b740-4faa882b1a1f', label: 'version2') }
63
+ let(:version2) { instance_double(ActiveFedora::VersionsGraph::ResourceVersion, uri: 'http://localhost:8983/fedora/rest/test/84/61/63/98/84616398-f63a-4572-ba01-0689339e4fcb/fcr:versions/87a0a8c317f1e790373a67-c9ee-447d-b740-4faa882b1a1f', label: 'version2') }
64
64
 
65
65
  it 'raises an exception' do
66
66
  expect { graph.first }.to raise_error(ActiveFedora::VersionLacksCreateDate)
data/spec/spec_helper.rb CHANGED
@@ -44,10 +44,59 @@ RSpec.configure do |config|
44
44
  $stderr.puts e.message
45
45
  end
46
46
  end
47
- config.after(:each) do
48
- # cleanout_fedora
47
+
48
+ # rspec-expectations config goes here. You can use an alternate
49
+ # assertion/expectation library such as wrong or the stdlib/minitest
50
+ # assertions if you prefer.
51
+ config.expect_with :rspec do |expectations|
52
+ # This option will default to `true` in RSpec 4. It makes the `description`
53
+ # and `failure_message` of custom matchers include text for helper methods
54
+ # defined using `chain`, e.g.:
55
+ # be_bigger_than(2).and_smaller_than(4).description
56
+ # # => "be bigger than 2 and smaller than 4"
57
+ # ...rather than:
58
+ # # => "be bigger than 2"
59
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
49
60
  end
50
- config.order = :random if ENV['CI']
61
+
62
+ config.default_formatter = 'doc' if config.files_to_run.one?
63
+
64
+ config.shared_context_metadata_behavior = :apply_to_host_groups
65
+
66
+ # This allows you to limit a spec run to individual examples or groups
67
+ # you care about by tagging them with `:focus` metadata. When nothing
68
+ # is tagged with `:focus`, all examples get run. RSpec also provides
69
+ # aliases for `it`, `describe`, and `context` that include `:focus`
70
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
71
+ config.filter_run_when_matching :focus
72
+
73
+ config.example_status_persistence_file_path = 'spec/examples.txt'
74
+ # Many RSpec users commonly either run the entire suite or an individual
75
+ # file, and it's useful to allow more verbose output when running an
76
+ # individual spec file.
77
+ if config.files_to_run.one?
78
+ # Use the documentation formatter for detailed output,
79
+ # unless a formatter has already been configured
80
+ # (e.g. via a command-line flag).
81
+ config.default_formatter = 'doc'
82
+ end
83
+
84
+ # Print the 10 slowest examples and example groups at the
85
+ # end of the spec run, to help surface which specs are running
86
+ # particularly slow.
87
+ config.profile_examples = 10
88
+
89
+ # Run specs in random order to surface order dependencies. If you find an
90
+ # order dependency and want to debug it, you can fix the order by providing
91
+ # the seed, which is printed after each run.
92
+ # --seed 1234
93
+ config.order = :random
94
+
95
+ # Seed global randomization in this process using the `--seed` CLI option.
96
+ # Setting this allows you to use `--seed` to deterministically reproduce
97
+ # test failures related to randomization by passing the same `--seed` value
98
+ # as the one that triggered the failure.
99
+ Kernel.srand config.seed
51
100
  end
52
101
 
53
102
  def fixture(file)
@@ -85,7 +85,7 @@ describe ActiveFedora do
85
85
  end
86
86
 
87
87
  describe "within rails" do
88
- after(:each) do
88
+ after do
89
89
  unstub_rails
90
90
  end
91
91
 
@@ -3,60 +3,46 @@ require 'spec_helper'
3
3
  describe ActiveFedora::AssociationHash do
4
4
  subject(:association_hash) { described_class.new(model, reflections) }
5
5
 
6
- let(:model) { double(association: nil) }
7
- let(:reflections) { double(keys: [:foo]) }
6
+ let(:model) { instance_double(ActiveFedora::Base, association: nil) }
7
+ let(:reflections) { { foo: association } }
8
8
  let(:reader) { double("reader") }
9
9
  let(:writer) { double("writer") }
10
10
  let(:association) { double(reader: reader, writer: writer) }
11
11
 
12
+ before do
13
+ allow(model).to receive(:association).with(:foo).and_return(association)
14
+ end
15
+
12
16
  describe "key reader" do
13
17
  describe "when the association exists" do
14
- before do
15
- allow(association_hash).to receive(:association).with("foo") { association }
16
- end
17
18
  it "calls the association reader" do
18
19
  expect(association_hash["foo"]).to eq(reader)
19
20
  end
20
21
  end
21
22
  describe "when the association does not exist" do
22
- before do
23
- allow(association_hash).to receive(:association).with("foo") { nil }
24
- end
25
23
  it "returns nil" do
26
- expect(association_hash["foo"]).to be_nil
24
+ expect(association_hash["bar"]).to be_nil
27
25
  end
28
26
  end
29
27
  end
30
28
 
31
29
  describe "key setter" do
32
30
  let(:obj) { double }
33
- before do
34
- allow(association).to receive(:writer).with(obj) { writer }
35
- end
36
31
  describe "when the association exists" do
37
- before do
38
- allow(association_hash).to receive(:association).with("foo") { association }
39
- end
40
32
  it "calls the association writer" do
41
33
  expect(association).to receive(:writer).with(obj)
42
34
  association_hash["foo"] = obj
43
35
  end
44
36
  end
45
37
  describe "when the association does not exist" do
46
- before do
47
- allow(association_hash).to receive(:association).with("foo") { nil }
48
- end
49
38
  it "doesn't call the association writer" do
50
39
  expect(association).not_to receive(:writer).with(obj)
51
- association_hash["foo"] = obj
40
+ association_hash["bar"] = obj
52
41
  end
53
42
  end
54
43
  end
55
44
 
56
45
  describe "#association" do
57
- before do
58
- allow(model).to receive(:association).with(:foo) { association }
59
- end
60
46
  it "works with a string key" do
61
47
  expect(association_hash.association("foo")).to eq(association)
62
48
  end
@@ -99,8 +99,8 @@ describe ActiveFedora::AttachedFiles do
99
99
 
100
100
  describe "#serialize_attached_files" do
101
101
  it "touches each file" do
102
- m1 = double
103
- m2 = double
102
+ m1 = instance_double(ActiveFedora::File)
103
+ m2 = instance_double(ActiveFedora::File)
104
104
 
105
105
  expect(m1).to receive(:serialize!)
106
106
  expect(m2).to receive(:serialize!)
@@ -178,10 +178,10 @@ describe ActiveFedora::AttachedFiles do
178
178
 
179
179
  describe "#metadata_streams" do
180
180
  it "only is metadata datastreams" do
181
- ds1 = double(metadata?: true)
182
- ds2 = double(metadata?: true)
183
- ds3 = double(metadata?: true)
184
- file_ds = double(metadata?: false)
181
+ ds1 = instance_double(ActiveFedora::File, metadata?: true)
182
+ ds2 = instance_double(ActiveFedora::File, metadata?: true)
183
+ ds3 = instance_double(ActiveFedora::File, metadata?: true)
184
+ file_ds = instance_double(ActiveFedora::File, metadata?: false)
185
185
  allow(af_base).to receive(:attached_files).and_return(a: ds1, b: ds2, c: ds3, e: file_ds)
186
186
  expect(af_base.metadata_streams).to include(ds1, ds2, ds3)
187
187
  expect(af_base.metadata_streams).to_not include(file_ds)
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActiveFedora::Base do
4
- before(:each) do
4
+ before do
5
5
  @test_object = described_class.new
6
6
  end
7
7
 
@@ -4,11 +4,11 @@ describe ActiveFedora::Base do
4
4
  subject(:object) { described_class.new }
5
5
  describe ".update_index" do
6
6
  before do
7
- mock_conn = double("SolrConnection")
7
+ mock_conn = instance_double(RSolr::Client)
8
8
  expect(mock_conn).to receive(:add) do |_, opts|
9
9
  expect(opts).to eq(params: { softCommit: true })
10
10
  end
11
- mock_ss = double("SolrService")
11
+ mock_ss = instance_double(ActiveFedora::SolrService)
12
12
  allow(mock_ss).to receive(:conn).and_return(mock_conn)
13
13
  allow(ActiveFedora::SolrService).to receive(:instance).and_return(mock_ss)
14
14
  end
@@ -30,20 +30,4 @@ describe ActiveFedora::Base do
30
30
  object.delete
31
31
  end
32
32
  end
33
-
34
- describe "to_class_uri" do
35
- before :all do
36
- module SpecModel
37
- class CamelCased < ActiveFedora::Base
38
- end
39
- end
40
- end
41
-
42
- after :all do
43
- Object.send(:remove_const, :SpecModel)
44
- end
45
- subject { SpecModel::CamelCased.to_class_uri }
46
-
47
- it { should == 'SpecModel::CamelCased' }
48
- end
49
33
  end
@@ -274,7 +274,7 @@ describe ActiveFedora::Base do
274
274
 
275
275
  describe "#create" do
276
276
  it "builds a new record and save it" do
277
- obj = double
277
+ obj = instance_double(FooHistory)
278
278
  expect(obj).to receive(:save)
279
279
  expect(FooHistory).to receive(:new).and_return(obj)
280
280
  FooHistory.create(fubar: 'ta')
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActiveFedora::Base do
4
- before :each do
4
+ before do
5
5
  class CallbackStub < ActiveFedora::Base
6
6
  after_initialize :a_init
7
7
  before_save :b_save
@@ -19,7 +19,7 @@ describe ActiveFedora::Base do
19
19
  end
20
20
  end
21
21
  end
22
- after :each do
22
+ after do
23
23
  @cb.destroy if @cb && @cb.persisted? # this only is called if the test failed to run all the way through.
24
24
  Object.send(:remove_const, :CallbackStub)
25
25
  end
@@ -7,7 +7,7 @@ module ActiveFedora
7
7
  let(:uri) { ::RDF::URI("urn:sha1:bb3200c2ddaee4bd7b9a4dc1ad3e10ed886eaef1") }
8
8
 
9
9
  describe "when initialized with a file having a digest" do
10
- let(:file) { double(digest: [uri]) }
10
+ let(:file) { instance_double(ActiveFedora::File, digest: [uri]) }
11
11
 
12
12
  its(:uri) { is_expected.to eq(uri) }
13
13
  its(:value) { is_expected.to eq("bb3200c2ddaee4bd7b9a4dc1ad3e10ed886eaef1") }
@@ -15,7 +15,7 @@ module ActiveFedora
15
15
  end
16
16
 
17
17
  describe "when initialized with a file not having a digest" do
18
- let(:file) { double(digest: []) }
18
+ let(:file) { instance_double(ActiveFedora::File, digest: []) }
19
19
 
20
20
  its(:uri) { is_expected.to be_nil }
21
21
  its(:value) { is_expected.to be_nil }
@@ -18,7 +18,7 @@ describe ActiveFedora::FileConfigurator do
18
18
  }
19
19
  end
20
20
 
21
- before :each do
21
+ before do
22
22
  ActiveFedora.configurator = TestConfigurator.new
23
23
  end
24
24
 
@@ -169,4 +169,40 @@ describe ActiveFedora::Base do
169
169
  it { should eq '123456w' }
170
170
  end
171
171
  end
172
+
173
+ describe "to_class_uri" do
174
+ before do
175
+ module SpecModel
176
+ class CamelCased < ActiveFedora::Base
177
+ end
178
+ end
179
+ end
180
+
181
+ after do
182
+ Object.send(:remove_const, :SpecModel)
183
+ end
184
+ subject do
185
+ Deprecation.silence(ActiveFedora::Core::ClassMethods) do
186
+ SpecModel::CamelCased.to_class_uri
187
+ end
188
+ end
189
+
190
+ it { is_expected.to eq 'SpecModel::CamelCased' }
191
+ end
192
+
193
+ describe "to_rdf_representation" do
194
+ before do
195
+ module SpecModel
196
+ class CamelCased < ActiveFedora::Base
197
+ end
198
+ end
199
+ end
200
+
201
+ after do
202
+ Object.send(:remove_const, :SpecModel)
203
+ end
204
+ subject { SpecModel::CamelCased.to_rdf_representation }
205
+
206
+ it { is_expected.to eq 'SpecModel::CamelCased' }
207
+ end
172
208
  end
@@ -1,8 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActiveFedora::DefaultModelMapper do
4
- let(:classifier) { double }
5
- let(:classifier_instance) { double }
4
+ let(:classifier) { class_double(ActiveFedora::ModelClassifier) }
5
+ let(:classifier_instance) { instance_double(ActiveFedora::ModelClassifier) }
6
6
  let(:solr_field) { 'solr_field' }
7
7
  let(:predicate) { 'info:predicate' }
8
8
  subject(:mapper) { described_class.new classifier_class: classifier, solr_field: solr_field, predicate: predicate }
@@ -25,7 +25,7 @@ describe ActiveFedora::DefaultModelMapper do
25
25
  RDF::Graph.new << [:hello, predicate, 'xyz']
26
26
  end
27
27
 
28
- let(:resource) { double(graph: graph) }
28
+ let(:resource) { instance_double(ActiveFedora::LdpResource, graph: graph) }
29
29
 
30
30
  before do
31
31
  expect(classifier).to receive(:new).with(['xyz']).and_return(classifier_instance)
@@ -105,12 +105,12 @@ describe ActiveFedora::FileConfigurator do
105
105
  end
106
106
 
107
107
  context "no solr.yml in same directory as fedora.yml and fedora.yml does not contain solr url" do
108
- before :each do
108
+ before do
109
109
  allow(configurator).to receive(:config_options).and_return({})
110
110
  expect(configurator).to receive(:path).and_return("/path/to/fedora/config/fedora.yml")
111
111
  expect(File).to receive(:file?).with("/path/to/fedora/config/solr.yml").and_return(false)
112
112
  end
113
- after :each do
113
+ after do
114
114
  unstub_rails
115
115
  end
116
116
 
@@ -137,7 +137,7 @@ describe ActiveFedora::FileConfigurator do
137
137
  end
138
138
 
139
139
  describe "load_fedora_config" do
140
- before(:each) do
140
+ before do
141
141
  configurator.reset!
142
142
  end
143
143
  it "loads the file specified in fedora_config_path" do
@@ -169,7 +169,7 @@ describe ActiveFedora::FileConfigurator do
169
169
  end
170
170
 
171
171
  describe "load_solr_config" do
172
- before(:each) do
172
+ before do
173
173
  configurator.reset!
174
174
  end
175
175
  it "loads the file specified in solr_config_path" do
@@ -9,7 +9,7 @@ describe ActiveFedora::FilePathBuilder do
9
9
 
10
10
  context "when some datastreams exist" do
11
11
  before do
12
- allow(parent).to receive(:attached_files).and_return('FOO56' => double)
12
+ allow(parent).to receive(:attached_files).and_return('FOO56' => instance_double(ActiveFedora::File))
13
13
  end
14
14
 
15
15
  it { should eq 'FOO57' }
@@ -110,7 +110,7 @@ describe ActiveFedora::File do
110
110
  context 'when content has changed from what is currently persisted' do
111
111
  context 'and has been set to something that has a #size method (i.e. string or File)' do
112
112
  it 'returns the size of the dirty content' do
113
- dirty_content = double
113
+ dirty_content = instance_double(::File)
114
114
  allow(dirty_content).to receive(:size) { 8_675_309 }
115
115
  af_file.content = dirty_content
116
116
  expect(af_file.size).to eq dirty_content.size
@@ -10,8 +10,8 @@ describe ActiveFedora::FilesHash do
10
10
 
11
11
  after { Object.send(:remove_const, :FilesContainer) }
12
12
 
13
- let(:reflection) { double('reflection') }
14
- let(:association) { double('association', reader: object) }
13
+ let(:reflection) { instance_double(ActiveFedora::Reflection::MacroReflection) }
14
+ let(:association) { instance_double(ActiveFedora::Associations::SingularAssociation, reader: object) }
15
15
  let(:object) { double('object') }
16
16
  let(:container) { FilesContainer.new }
17
17
 
@@ -57,9 +57,9 @@ describe ActiveFedora::FinderMethods do
57
57
  end
58
58
 
59
59
  describe "#search_in_batches" do
60
- let(:docs) { double('docs', has_next?: false) }
60
+ let(:docs) { instance_double(RSolr::Response::PaginatedDocSet, has_next?: false) }
61
61
  let(:select_handler) { 'select' }
62
- let(:connection) { double('conn') }
62
+ let(:connection) { instance_double(RSolr::Client) }
63
63
  before do
64
64
  expect(finder).to receive(:create_query).with('age_t' => '21').and_return('dummy query')
65
65
  allow(ActiveFedora::SolrService.instance).to receive(:conn).and_return(connection)
@@ -84,7 +84,7 @@ describe ActiveFedora::FinderMethods do
84
84
 
85
85
  describe '#search_by_id' do
86
86
  context 'with a document in solr' do
87
- let(:doc) { double('Document') }
87
+ let(:doc) { instance_double(Hash) }
88
88
 
89
89
  before do
90
90
  expect(finder).to receive(:search_with_conditions).with({ id: 'x' }, hash_including(rows: 1)).and_return([doc])