require "rails_helper" RSpec.describe Search::Base, type: :service do let(:document_id) { 123 } before do # Need to use an existing index name to ensure proper data cleanup stub_const("#{described_class}::INDEX_NAME", "tags_#{Rails.env}") stub_const("#{described_class}::INDEX_ALIAS", "tags_#{Rails.env}_alias") stub_const("#{described_class}::MAPPINGS", Search::Tag::MAPPINGS) Search::Tag.refresh_index clear_elasticsearch_data(Search::Tag) allow(described_class).to receive(:index_settings).and_return({}) end describe "::index" do it "indexes a document to elasticsearch" do expect { described_class.find_document(document_id) }.to raise_error(Search::Errors::Transport::NotFound) described_class.index(document_id, id: document_id) expect(described_class.find_document(document_id)).not_to be_nil end it "sets last_indexed_at field" do Timecop.freeze(Time.current) do described_class.index(document_id, id: document_id) last_indexed_at = described_class.find_document(document_id).dig("_source", "last_indexed_at") expect(Time.zone.parse(last_indexed_at).to_i).to eq(Time.current.to_i) end end end describe "::bulk_index" do it "indexes a set of data hashes to Elasticsearch" do id_list = [123, 456, 789] id_list.each do |document_id| expect { described_class.find_document(document_id) }.to raise_error(Search::Errors::Transport::NotFound) end data_hashes = id_list.map { |id| { id: id, name: "i_am_a_tag" } } described_class.bulk_index(data_hashes) id_list.each do |document_id| doc = described_class.find_document(document_id) expect(doc.dig("_source", "id")).to eql(document_id) end end it "sets last_indexed_at field" do Timecop.freeze(Time.current) do described_class.bulk_index([{ id: document_id, name: "i_am_a_tag" }]) last_indexed_at = described_class.find_document(document_id).dig("_source", "last_indexed_at") expect(Time.zone.parse(last_indexed_at).to_i).to eq(Time.current.to_i) end end end describe "::find_document" do it "fetches a document for a given ID from elasticsearch" do described_class.index(document_id, id: document_id) expect { described_class.find_document(document_id) }.not_to raise_error end end describe "::delete_document" do it "deletes a document for a given ID from elasticsearch" do described_class.index(document_id, id: document_id) expect { described_class.find_document(document_id) }.not_to raise_error described_class.delete_document(document_id) expect { described_class.find_document(document_id) }.to raise_error(Search::Errors::Transport::NotFound) end end describe "::create_index", elasticsearch_reset: true do it "creates an elasticsearch index with INDEX_NAME" do described_class.delete_index expect(Search::Client.indices.exists(index: described_class::INDEX_NAME)).to eq(false) described_class.create_index expect(Search::Client.indices.exists(index: described_class::INDEX_NAME)).to eq(true) end it "creates an elasticsearch index with name argument" do other_name = "random" expect(Search::Client.indices.exists(index: other_name)).to eq(false) described_class.create_index(index_name: other_name) expect(Search::Client.indices.exists(index: other_name)).to eq(true) # Have to cleanup index since it wont automatically be handled by our cluster class bc of the unexpected name described_class.delete_index(index_name: other_name) end end describe "::delete_index", elasticsearch_reset: true do it "deletes an elasticsearch index with INDEX_NAME" do expect(Search::Client.indices.exists(index: described_class::INDEX_NAME)).to eq(true) described_class.delete_index expect(Search::Client.indices.exists(index: described_class::INDEX_NAME)).to eq(false) end it "deletes an elasticsearch index with name argument" do other_name = "random" described_class.create_index(index_name: other_name) expect(Search::Client.indices.exists(index: other_name)).to eq(true) described_class.delete_index(index_name: other_name) expect(Search::Client.indices.exists(index: other_name)).to eq(false) end end describe "::add_alias" do it "adds alias INDEX_ALIAS to elasticsearch index with INDEX_NAME" do Search::Client.indices.delete_alias(index: described_class::INDEX_NAME, name: described_class::INDEX_ALIAS) expect(Search::Client.indices.exists(index: described_class::INDEX_ALIAS)).to eq(false) described_class.add_alias expect(Search::Client.indices.exists(index: described_class::INDEX_ALIAS)).to eq(true) end it "adds custom alias to elasticsearch index with INDEX_NAME" do other_alias = "random" expect(Search::Client.indices.exists(index: other_alias)).to eq(false) described_class.add_alias(index_name: described_class::INDEX_NAME, index_alias: other_alias) expect(Search::Client.indices.exists(index: other_alias)).to eq(true) end end describe "::update_mappings" do it "updates index mappings" do other_name = "index_name" allow(Search::Client.indices).to receive(:put_mapping) described_class.update_mappings(index_alias: other_name) expect(Search::Client.indices).to have_received(:put_mapping).with( index: other_name, body: described_class::MAPPINGS, ) end end end