spec/mongo/collection_spec.rb in mongo-2.3.1 vs spec/mongo/collection_spec.rb in mongo-2.4.0.rc0

- old
+ new

@@ -2,21 +2,18 @@ describe Mongo::Collection do after do authorized_collection.delete_many - collection_with_validator.drop() end let(:collection_invalid_write_concern) do authorized_collection.client.with(write: { w: (WRITE_CONCERN[:w] + 1) })[authorized_collection.name] end + let(:collection_with_validator) do - authorized_client[:validating, - :validator => { :a => { '$exists' => true } }].tap do |c| - c.create - end + authorized_client[:validating] end describe '#==' do let(:database) do @@ -414,10 +411,111 @@ context 'when validators can be set', if: find_command_enabled? do it_behaves_like 'a validated collection command' end end end + + context 'when the collection has a write concern' do + + after do + database[:specs].drop + end + + let(:options) do + { + write: { w: WRITE_CONCERN[:w] + 1} + } + end + + let(:collection) do + described_class.new(database, :specs, options) + end + + context 'when the server supports write concern on the create command', if: replica_set? && collation_enabled? do + + it 'applies the write concern' do + expect{ + collection.create + }.to raise_exception(Mongo::Error::OperationFailure) + end + end + + context 'when the server does not support write concern on the create command', unless: collation_enabled? do + + it 'does not apply the write concern' do + expect(collection.create).to be_successful + end + end + end + + context 'when the collection has a collation' do + + shared_examples 'a collection command with a collation option' do + + let!(:response) do + collection.create + end + + let(:options) do + { :collation => { locale: 'fr' } } + end + + let(:collection_info) do + database.list_collections.find { |i| i['name'] == 'specs' } + end + + after do + collection.drop + end + + context 'when the server supports collations', if: collation_enabled? do + + it 'executes the command' do + expect(response).to be_successful + end + + it 'sets the collection with a collation' do + expect(collection_info['options']['collation']['locale']).to eq('fr') + end + + it 'creates the collection in the database' do + expect(database.collection_names).to include('specs') + end + end + + context 'when the server does not support collations', unless: collation_enabled? do + + it 'raises an error' do + expect { + response + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when instantiating a collection directly' do + + let(:collection) do + described_class.new(database, :specs, options) + end + + context 'when the server supports collation', if: collation_enabled? do + it_behaves_like 'a collection command with a collation option' + end + end + + context 'when instantiating a collection through the database' do + + let(:collection) do + authorized_client[:specs, options] + end + + context 'when the server supports collation', if: collation_enabled? do + it_behaves_like 'a collection command with a collation option' + end + end + end end end describe '#drop' do @@ -431,27 +529,63 @@ before do collection.create end - let!(:response) do - collection.drop - end + context 'when the collection does not have a write concern set' do - it 'executes the command' do - expect(response).to be_successful - end + let!(:response) do + collection.drop + end - it 'drops the collection from the database' do - expect(database.collection_names).to_not include('specs') + it 'executes the command' do + expect(response).to be_successful + end + + it 'drops the collection from the database' do + expect(database.collection_names).to_not include('specs') + end + + context 'when the collection does not exist' do + + it 'does not raise an error' do + expect(database['non-existent-coll'].drop).to be(false) + end + end end - context 'when the collection does not exist' do + context 'when the collection has a write concern' do - it 'does not raise an error' do - expect(database['non-existent-coll'].drop).to be(false) + let(:write_options) do + { + write: { w: WRITE_CONCERN[:w] + 1} + } end + + let(:collection_with_write_options) do + collection.with(write_options) + end + + after do + collection.drop + end + + context 'when the server supports write concern on the drop command', if: collation_enabled? do + + it 'applies the write concern' do + expect{ + collection_with_write_options.drop + }.to raise_exception(Mongo::Error::OperationFailure) + end + end + + context 'when the server does not support write concern on the drop command', unless: collation_enabled? do + + it 'does not apply the write concern' do + expect(collection_with_write_options.drop).to be_successful + end + end end end describe '#find' do @@ -494,14 +628,10 @@ before do authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }]) end - after do - authorized_collection.delete_many - end - let(:view) do authorized_collection.find end it 'iterates over the documents' do @@ -540,14 +670,10 @@ before do authorized_collection.insert_one({ field => value }) end - after do - authorized_collection.delete_many - end - it 'iterates over the documents' do view.each do |document| expect(document[field]).to eq(value) end end @@ -603,12 +729,10 @@ it 'returns a view with :cursor_type set' do expect(view.options[:cursor_type]).to eq(options[:cursor_type]) end end - #limit - context 'when provided :max_time_ms' do let(:options) do { max_time_ms: 500 } end @@ -685,20 +809,26 @@ it 'returns a view with :sort set' do expect(view.modifiers[:$orderby]).to eq(options[:sort]) end end + + context 'when provided :collation' do + + let(:options) do + { collation: { 'locale' => 'en_US' } } + end + + it 'returns a view with :collation set' do + expect(view.options[:collation]).to eq(options[:collation]) + end + end end end describe '#insert_many' do - after do - authorized_collection.delete_many - collection_with_validator.delete_many - end - let(:result) do authorized_collection.insert_many([{ name: 'test1' }, { name: 'test2' }]) end it 'inserts the documents into the collection' do @@ -779,10 +909,19 @@ end end context 'when collection has a validator', if: find_command_enabled? do + around(:each) do |spec| + authorized_client[:validating, + :validator => { :a => { '$exists' => true } }].tap do |c| + c.create + end + spec.run + collection_with_validator.drop + end + context 'when the document is valid' do let(:result) do collection_with_validator.insert_many([{ a: 1 }, { a: 2 }]) end @@ -822,15 +961,10 @@ end end describe '#insert_one' do - after do - authorized_collection.delete_many - collection_with_validator.delete_many - end - let(:result) do authorized_collection.insert_one({ name: 'testing' }) end it 'inserts the document into the collection', if: write_command_enabled? do @@ -903,10 +1037,19 @@ end end context 'when collection has a validator', if: find_command_enabled? do + around(:each) do |spec| + authorized_client[:validating, + :validator => { :a => { '$exists' => true } }].tap do |c| + c.create + end + spec.run + collection_with_validator.drop + end + context 'when the document is valid' do let(:result) do collection_with_validator.insert_one({ a: 1 }) end @@ -1004,10 +1147,45 @@ end it 'sets the options on the Aggregation object' do expect(authorized_collection.aggregate([], options).options).to eq(options) end + + context 'when collation is provided' do + + before do + authorized_collection.insert_many([ { name: 'bang' }, { name: 'bang' }]) + end + + let(:pipeline) do + [{ "$match" => { "name" => "BANG" } }] + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + let(:result) do + authorized_collection.aggregate(pipeline, options).collect { |doc| doc['name']} + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation' do + expect(result).to eq(['bang', 'bang']) + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end end end describe '#count' do @@ -1017,23 +1195,54 @@ before do authorized_collection.insert_many(documents) end - after do - authorized_collection.delete_many - end - it 'returns an integer count' do expect(authorized_collection.count).to eq(10) end context 'when options are provided' do it 'passes the options to the count' do expect(authorized_collection.count({}, limit: 5)).to eq(5) end + + context 'when a collation is specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.count(selector, options) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation to the count' do + expect(result).to eq(1) + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end end end describe '#distinct' do @@ -1043,14 +1252,10 @@ before do authorized_collection.insert_many(documents) end - after do - authorized_collection.delete_many - end - it 'returns the distinct values' do expect(authorized_collection.distinct(:field).sort).to eq([ 'test1', 'test2', 'test3' ]) end context 'when a selector is provided' do @@ -1064,10 +1269,58 @@ it 'passes the options to the distinct command' do expect(authorized_collection.distinct(:field, {}, max_time_ms: 100).sort).to eq([ 'test1', 'test2', 'test3' ]) end end + + context 'when a collation is specified' do + + let(:result) do + authorized_collection.distinct(:name, {}, options) + end + + before do + authorized_collection.insert_one(name: 'bang') + authorized_collection.insert_one(name: 'BANG') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation to the distinct' do + expect(result).to eq(['bang']) + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when a collation is not specified' do + + let(:result) do + authorized_collection.distinct(:name) + end + + before do + authorized_collection.insert_one(name: 'bang') + authorized_collection.insert_one(name: 'BANG') + end + + it 'does not apply the collation to the distinct' do + expect(result).to eq(['bang', 'BANG']) + end + end end describe '#delete_one' do context 'when a selector was provided' do @@ -1082,14 +1335,10 @@ { field: 'test1' }, { field: 'test1' } ]) end - after do - authorized_collection.delete_many - end - let(:response) do authorized_collection.delete_one(selector) end it 'deletes the first matching document in the collection' do @@ -1122,22 +1371,91 @@ expect { result }.to raise_exception(Mongo::Error::OperationFailure) end end + + context 'when a collation is provided' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.delete_one(selector, options) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation' do + expect(result.written_count).to eq(1) + expect(authorized_collection.find(name: 'bang').count).to eq(0) + end + + context 'when unacknowledged writes is used' do + + let(:collection_with_unacknowledged_write_concern) do + authorized_collection.with(write: { w: 0 }) + end + + let(:result) do + collection_with_unacknowledged_write_concern.delete_one(selector, options) + end + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when collation is not specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.delete_one(selector) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + it 'does not apply the collation' do + expect(result.written_count).to eq(0) + expect(authorized_collection.find(name: 'bang').count).to eq(1) + end + end end describe '#delete_many' do before do authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }]) end - after do - authorized_collection.delete_many - end - context 'when a selector was provided' do let(:selector) do { field: 'test1' } end @@ -1164,10 +1482,85 @@ expect { result }.to raise_exception(Mongo::Error::OperationFailure) end end + + context 'when a collation is specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.delete_many(selector, options) + end + + before do + authorized_collection.insert_one(name: 'bang') + authorized_collection.insert_one(name: 'bang') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation' do + expect(result.written_count).to eq(2) + expect(authorized_collection.find(name: 'bang').count).to eq(0) + end + + context 'when unacknowledged writes is used' do + + let(:collection_with_unacknowledged_write_concern) do + authorized_collection.with(write: { w: 0 }) + end + + let(:result) do + collection_with_unacknowledged_write_concern.delete_many(selector, options) + end + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when a collation is not specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.delete_many(selector) + end + + before do + authorized_collection.insert_one(name: 'bang') + authorized_collection.insert_one(name: 'bang') + end + + it 'does not apply the collation' do + expect(result.written_count).to eq(0) + expect(authorized_collection.find(name: 'bang').count).to eq(2) + end + end end describe '#parallel_scan', unless: sharded? do let(:documents) do @@ -1260,10 +1653,41 @@ expect { result }.to raise_exception(Mongo::Error::NoServerAvailable) end end + + context 'when a max time ms value is provided', if: (!sharded? && write_command_enabled?) do + + let(:result) do + authorized_collection.parallel_scan(2, options) + end + + context 'when the read concern is valid' do + + let(:options) do + { max_time_ms: 2 } + end + + it 'sends the max time ms value' do + expect { result }.to_not raise_error + end + end + + context 'when the max time ms is not valid' do + + let(:options) do + { max_time_ms: 0.1 } + end + + it 'raises an exception' do + expect { + result + }.to raise_error(Mongo::Error::OperationFailure) + end + end + end end describe '#replace_one' do let(:selector) do @@ -1274,14 +1698,10 @@ before do authorized_collection.insert_many([{ field: 'test1' }, { field: 'test1' }]) end - after do - authorized_collection.delete_many - end - let!(:response) do authorized_collection.replace_one(selector, { field: 'testing' }) end let(:updated) do @@ -1324,14 +1744,10 @@ let(:updated) do authorized_collection.find(field: 'test1').first end - after do - authorized_collection.delete_many - end - it 'reports that a document was written' do expect(response.written_count).to eq(1) end it 'inserts the document' do @@ -1371,18 +1787,23 @@ end end context 'when collection has a validator', if: find_command_enabled? do + around(:each) do |spec| + authorized_client[:validating, + :validator => { :a => { '$exists' => true } }].tap do |c| + c.create + end + spec.run + collection_with_validator.drop + end + before do collection_with_validator.insert_one({ a: 1 }) end - after do - collection_with_validator.delete_many - end - context 'when the document is valid' do let(:result) do collection_with_validator.replace_one({ a: 1 }, { a: 5 }) end @@ -1418,22 +1839,91 @@ expect(result3.written_count).to eq(1) end end end end + + context 'when a collation is specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.replace_one(selector, { name: 'doink' }, options) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation' do + expect(result.written_count).to eq(1) + expect(authorized_collection.find(name: 'doink').count).to eq(1) + end + + context 'when unacknowledged writes is used' do + + let(:collection_with_unacknowledged_write_concern) do + authorized_collection.with(write: { w: 0 }) + end + + let(:result) do + collection_with_unacknowledged_write_concern.replace_one(selector, { name: 'doink' }, options) + end + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when a collation is not specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.replace_one(selector, { name: 'doink' }) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + it 'does not apply the collation' do + expect(result.written_count).to eq(0) + expect(authorized_collection.find(name: 'bang').count).to eq(1) + end + end end describe '#update_many' do let(:selector) do { field: 'test' } end - after do - authorized_collection.delete_many - end - context 'when a selector was provided' do before do authorized_collection.insert_many([{ field: 'test' }, { field: 'test' }]) end @@ -1527,18 +2017,23 @@ end end context 'when collection has a validator', if: find_command_enabled? do + around(:each) do |spec| + authorized_client[:validating, + :validator => { :a => { '$exists' => true } }].tap do |c| + c.create + end + spec.run + collection_with_validator.drop + end + before do collection_with_validator.insert_many([{ a: 1 }, { a: 2 }]) end - after do - collection_with_validator.delete_many - end - context 'when the document is valid' do let(:result) do collection_with_validator.update_many( { :a => { '$gt' => 0 } }, '$inc' => { :a => 1 } ) @@ -1577,10 +2072,84 @@ expect(result3.written_count).to eq(2) end end end end + + context 'when a collation is specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.update_many(selector, { '$set' => { other: 'doink' } }, options) + end + + before do + authorized_collection.insert_one(name: 'bang') + authorized_collection.insert_one(name: 'baNG') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation' do + expect(result.written_count).to eq(2) + expect(authorized_collection.find(other: 'doink').count).to eq(2) + end + + context 'when unacknowledged writes is used' do + + let(:collection_with_unacknowledged_write_concern) do + authorized_collection.with(write: { w: 0 }) + end + + let(:result) do + collection_with_unacknowledged_write_concern.update_many(selector, { '$set' => { other: 'doink' } }, options) + end + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when collation is not specified' do + + let(:selector) do + {name: 'BANG'} + end + + let(:result) do + authorized_collection.update_many(selector, { '$set' => {other: 'doink'} }) + end + + before do + authorized_collection.insert_one(name: 'bang') + authorized_collection.insert_one(name: 'baNG') + end + + it 'does not apply the collation' do + expect(result.written_count).to eq(0) + end + end end describe '#update_one' do let(:selector) do @@ -1682,18 +2251,23 @@ end end context 'when collection has a validator', if: find_command_enabled? do + around(:each) do |spec| + authorized_client[:validating, + :validator => { :a => { '$exists' => true } }].tap do |c| + c.create + end + spec.run + collection_with_validator.drop + end + before do collection_with_validator.insert_one({ a: 1 }) end - after do - collection_with_validator.delete_many - end - context 'when the document is valid' do let(:result) do collection_with_validator.update_one( { :a => { '$gt' => 0 } }, '$inc' => { :a => 1 } ) @@ -1732,10 +2306,82 @@ expect(result3.written_count).to eq(1) end end end end + + context 'when there is a collation specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.update_one(selector, { '$set' => { other: 'doink' } }, options) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation' do + expect(result.written_count).to eq(1) + expect(authorized_collection.find(other: 'doink').count).to eq(1) + end + + context 'when unacknowledged writes is used' do + + let(:collection_with_unacknowledged_write_concern) do + authorized_collection.with(write: { w: 0 }) + end + + let(:result) do + collection_with_unacknowledged_write_concern.update_one(selector, { '$set' => { other: 'doink' } }, options) + end + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when a collation is not specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.update_one(selector, { '$set' => { other: 'doink' } }) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + it 'does not apply the collation' do + expect(result.written_count).to eq(0) + end + end end describe '#find_one_and_delete' do before do @@ -1853,10 +2499,65 @@ collection.find_one_and_delete(selector, write_concern: { w: 2 }) }.to raise_error(Mongo::Error::OperationFailure) end end + + context 'when collation is specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.find_one_and_delete(selector, options) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation' do + expect(result['name']).to eq('bang') + expect(authorized_collection.find(name: 'bang').count).to eq(0) + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when collation is not specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.find_one_and_delete(selector) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + it 'does not apply the collation' do + expect(result).to be_nil + end + end end describe '#find_one_and_update' do let(:selector) do @@ -2010,18 +2711,23 @@ end end context 'when collection has a validator', if: find_command_enabled? do + around(:each) do |spec| + authorized_client[:validating, + :validator => { :a => { '$exists' => true } }].tap do |c| + c.create + end + spec.run + collection_with_validator.drop + end + before do collection_with_validator.insert_one({ a: 1 }) end - after do - collection_with_validator.delete_many - end - context 'when the document is valid' do let(:result) do collection_with_validator.find_one_and_update( { a: 1 }, { '$inc' => { :a => 1 } }, :return_document => :after) @@ -2087,10 +2793,67 @@ { '$set' => { field: 'testing' }}, write_concern: { w: 2 }) }.to raise_error(Mongo::Error::OperationFailure) end end + + context 'when a collation is specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.find_one_and_update(selector, + { '$set' => { other: 'doink' } }, + options) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation' do + expect(result['name']).to eq('bang') + expect(authorized_collection.find({ name: 'bang' }, limit: -1).first['other']).to eq('doink') + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when there is no collation specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.find_one_and_update(selector, { '$set' => { other: 'doink' } }) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + it 'does not apply the collation' do + expect(result).to be_nil + end + end end describe '#find_one_and_replace' do before do @@ -2218,18 +2981,23 @@ end end context 'when collection has a validator', if: find_command_enabled? do + around(:each) do |spec| + authorized_client[:validating, + :validator => { :a => { '$exists' => true } }].tap do |c| + c.create + end + spec.run + collection_with_validator.drop + end + before do collection_with_validator.insert_one({ a: 1 }) end - after do - collection_with_validator.delete_many - end - context 'when the document is valid' do let(:result) do collection_with_validator.find_one_and_replace( { a: 1 }, { a: 5 }, :return_document => :after) @@ -2293,9 +3061,66 @@ expect { collection.find_one_and_replace(selector, { field: 'testing' }, write_concern: { w: 2 }) }.to raise_error(Mongo::Error::OperationFailure) + end + end + + context 'when collation is provided' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.find_one_and_replace(selector, + { name: 'doink' }, + options) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + let(:options) do + { collation: { locale: 'en_US', strength: 2 } } + end + + context 'when the server selected supports collations', if: collation_enabled? do + + it 'applies the collation' do + expect(result['name']).to eq('bang') + expect(authorized_collection.find(name: 'doink').count).to eq(1) + end + end + + context 'when the server selected does not support collations', unless: collation_enabled? do + + it 'raises an exception' do + expect { + result + }.to raise_exception(Mongo::Error::UnsupportedCollation) + end + end + end + + context 'when collation is not specified' do + + let(:selector) do + { name: 'BANG' } + end + + let(:result) do + authorized_collection.find_one_and_replace(selector, { name: 'doink' }) + end + + before do + authorized_collection.insert_one(name: 'bang') + end + + it 'does not apply the collation' do + expect(result).to be_nil end end end end