Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minitest assertions and indexing controls. #396

Merged
merged 7 commits into from
Aug 6, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
test SearchIndexReceiver
  • Loading branch information
Robert L. Carpenter committed Jun 27, 2016
commit 63ebd54ebe66fc431cfe26ab6d41462b857e449b
2 changes: 1 addition & 1 deletion lib/chewy/minitest/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Helpers
# @return (SearchIndexReceiver) for optional further assertions on the nature of the index changes.
def assert_indexes index, strategy: :atomic, bypass_actual_index: true, &test_actions
type = Chewy.derive_type index
receiver = SearchIndexReceiver.new filter: index
receiver = SearchIndexReceiver.new

bulk_method = type.method :bulk
# Manually mocking #bulk because we need to properly capture `self`
Expand Down
36 changes: 14 additions & 22 deletions lib/chewy/minitest/search_index_receiver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,15 @@
# method on a Chewy::Type class. (See SearchTestHelper)
#
# The class will capture the data from the *param on the Chewy::Type#bulk method and
# aggregate the data for test analysis. Optionally, a (Chewy::Type) filter parameter
# can be provided which will cause undesired indexes and deletes to be discarded.
# aggregate the data for test analysis.
class SearchIndexReceiver
# @param (Chewy::Type) filter
# @see SearchIndexCatcher for an explanation of the filter.
def initialize filter: nil
def initialize
@mutations = {}
@filter = filter
end

# @param bulk_params the bulk_params that should be sent to the Chewy::Type#bulk method.
# @param (Chewy::Type) type the Index::Type executing this query.
def catch bulk_params, type
return if filter? type
Array.wrap(bulk_params).map {|y| y[:body] }.flatten.each do |update|
if body = update[:delete]
mutation_for(type).deletes << body[:_id]
Expand All @@ -32,10 +27,10 @@ def catch bulk_params, type
def indexes_for index = nil
if index
mutation_for(index).indexes
elsif @filter
mutation_for(@filter).indexes
else
@mutations.transform_values {|v| v.indexes}
Hash[
@mutations.map { |a,b| [a, b.indexes] }
]
end
end
alias_method :indexes, :indexes_for
Expand All @@ -45,26 +40,28 @@ def indexes_for index = nil
def deletes_for index = nil
if index
mutation_for(index).deletes
elsif @filter
mutation_for(@filter).deletes
else
@mutations.transform_values {|v| v.deletes}
Hash[
@mutations.map { |a,b| [a, b.deletes] }
]
end
end
alias_method :deletes, :deletes_for

# Check to see if a given object has been indexed.
# @param (#id) obj the object to look for.
# @param Chewy::Type what type the object should be indexed as.
# @return bool if the object was indexed.
def indexed? obj
indexes.map {|i| i[:_id]}.compact.include? obj.id
def indexed? obj, type
indexes_for(type).map {|i| i[:_id]}.include? obj.id
end

# Check to see if a given object has been deleted.
# @param (#id) obj the object to look for.
# @param Chewy::Type what type the object should have been deleted from.
# @return bool if the object was deleted.
def deleted? obj
deletes.map {|i| i[:_id]}.compact.include? obj.id
def deleted? obj, type
deletes_for(type).include? obj.id
end

# @return a list of Chewy::Type indexes changed.
Expand All @@ -80,10 +77,5 @@ def mutation_for type
@mutations[type] ||= OpenStruct.new(indexes: [], deletes: [])
end

def filter? type
return false unless @filter
return ! type == @filter
end

end

7 changes: 3 additions & 4 deletions spec/chewy/minitest/helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ def assert_includes haystack, needle, comment
expect(
receiver.indexes_for(DummiesIndex::Dummy)
.map {|index| index[:_id]}
.sort
).to eq([41,42])
).to match_array([41,42])
end

specify 'Real index is bypassed when asserting' do
Expand All @@ -75,15 +74,15 @@ def assert_includes haystack, needle, comment
specify 'pushes onto the chewy strategy stack' do
Chewy.strategy :bypass do
run_indexing do
expect(Chewy.strategy).to be(:atomic)
expect(Chewy.strategy.current.name).to be(:atomic)
end
end
end

specify 'allows tester to specify the strategy' do
Chewy.strategy :atomic do
run_indexing strategy: :bypass do
expect(Chewy.strategy).to be(:bypass)
expect(Chewy.strategy.current.name).to be(:bypass)
end
end
end
Expand Down
121 changes: 121 additions & 0 deletions spec/chewy/minitest/search_index_receiver_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
require 'spec_helper'
require 'chewy/minitest'

describe :search_index_receiver do
def search_request item_count = 2, verb: :index
items = item_count.times.map do |i|
{
verb => {_id: i + 1, data: {}}
}
end

[
{
body: items
}
]
end

def parse_request request
request.map {|r| r[:_id]}
end

let(:receiver) do
SearchIndexReceiver.new
end

before do
stub_index(:dummies) do
define_type :fizz do
root value: ->(o){{}}
end

define_type :buzz do
root value: ->(o){{}}
end
end
end

context 'catch' do
specify 'archives more than one type' do
receiver.catch search_request(2), DummiesIndex::Fizz
receiver.catch search_request(3), DummiesIndex::Buzz
expect(receiver.indexes.keys).to match_array([DummiesIndex::Fizz, DummiesIndex::Buzz])
end
end

context 'indexes_for' do
before do
receiver.catch search_request(2), DummiesIndex::Fizz
receiver.catch search_request(3), DummiesIndex::Buzz
end

specify 'returns indexes for a specific type' do
expect(parse_request receiver.indexes_for(DummiesIndex::Fizz)).to match_array([1,2])
end

specify 'returns only indexes for all types' do
index_responses = receiver.indexes
expect(index_responses.keys).to match_array([DummiesIndex::Fizz, DummiesIndex::Buzz])
expect(parse_request index_responses.values.flatten).to match_array([1, 2, 1, 2, 3])
end
end

context 'deletes_for' do
before do
receiver.catch search_request(2, verb: :delete), DummiesIndex::Fizz
receiver.catch search_request(3, verb: :delete), DummiesIndex::Buzz
end

specify 'returns deletes for a specific type' do
expect(receiver.deletes_for(DummiesIndex::Buzz)).to match_array([1,2,3])
end

specify 'returns only deletes for all types' do
deletes = receiver.deletes
expect(deletes.keys).to match_array([DummiesIndex::Fizz, DummiesIndex::Buzz])
expect(deletes.values.flatten).to match_array([1, 2, 1, 2, 3])
end
end

context 'indexed?' do
before do
receiver.catch search_request(1), DummiesIndex::Fizz
end

specify 'validates that an object was indexed' do
dummy = OpenStruct.new(id: 1)
expect(receiver.indexed? dummy, DummiesIndex::Fizz).to be(true)
end

specify 'doesn\'t validate than unindexed objects were indexed' do
dummy = OpenStruct.new(id: 2)
expect(receiver.indexed? dummy, DummiesIndex::Fizz).to be(false)
end
end

context 'deleted?' do
before do
receiver.catch search_request(1, verb: :delete), DummiesIndex::Fizz
end

specify 'validates than an object was deleted' do
dummy = OpenStruct.new(id: 1)
expect(receiver.deleted? dummy, DummiesIndex::Fizz).to be(true)
end

specify 'doesn\'t validate than undeleted objects were deleted' do
dummy = OpenStruct.new(id: 2)
expect(receiver.deleted? dummy, DummiesIndex::Fizz).to be(false)
end
end

context 'updated_indexes' do
specify 'provides a list of indices updated' do
receiver.catch search_request(2, verb: :delete), DummiesIndex::Fizz
receiver.catch search_request(3, verb: :delete), DummiesIndex::Buzz
expect(receiver.updated_indexes).to match_array([DummiesIndex::Fizz, DummiesIndex::Buzz])
end
end

end