Save 36% for Black Friday! Learn more

Patrício

Joined

4,460 Experience
44 Lessons Completed
0 Questions Solved

Activity

Posted in Setup Searchkick with Minitest

Hi everyone,

Just followed the searchkick official's docs to setup the tests, so that I can test my search controller:

Let's assume I have the following model:

class User < ApplicationRecord
searchkick

    def search_data
      {
        first_name: first_name,
        last_name: last_name,
        email: email,
        emergency_contacts: build_emergency_contacts_data
      }
    end

    def build_emergency_contacts_data
      emergency_contacts.map do |contact|
        {
          id: contact.id,
          name: contact.name,
          email: contact.email,
        }
      end
    end

  has_many :emergency_contacts, dependent: :destroy
end

The following controller:

class UsersController < ApplicationController
  def search
    response = User.search(params[:query])

    render json: response, status: :ok
  end
end

With that, I wrote the following test:

require 'test_helper'

class UsersSearchTest < ActionDispatch::IntegrationTest
  def setup
    Searchkick.enable_callbacks
  end

  def teardown
    Searchkick.disable_callbacks
  end

  test 'search users' do
    create(:user, :reindex)
    create(:user, :reindex, first_name: 'Jane', email: 'jane.doe@example.com')
    create(:user, :reindex, last_name: 'Smith', email: 'john.smith@example.com')

    get '/users/search', params: { query: 'john' }

    assert_response :success
    assert_equal 2, response.parsed_body["query"].size
  end
end

this is my users factory:

FactoryBot.define do
  factory :user do
    first_name { "John" }
    last_name { "Doe" }
    email { "john@example.com" }

    trait :reindex do
      after(:create) do |user, _evaluator|
        user.reindex(refresh: true)
      end
    end

    trait :with_emergency_contacts do
      after(:create) do |user, _evaluator|
        create_list(:emergency_contact, 2, user: user)
      end
    end
  end
end

Running the previous test, I expect it to pass. But instead, I am getting the following error:

Error:
UsersSearchTest#test_search_users:
Searchkick::InvalidQueryError: Bad mapping - run User.reindex
    app/controllers/users_controller.rb:7:in `search'
    test/integration/users_search_test.rb:29:in `block in <class:UsersSearchTest>'

Why to I need to rerun User.reindex, when my factory already does it?

With that Error, I did the following change:

test 'search users' do
    create(:user, :reindex)
    create(:user, :reindex, first_name: 'Jane', email: 'jane.doe@example.com')
    create(:user, :reindex, last_name: 'Smith', email: 'john.smith@example.com')

    User.reindex

    get '/users/search', params: { query: 'john' }

    assert_response :success
    assert_equal 2, response.parsed_body["query"].size
  end

Now the tests passes, but calling User.reindex after create(:user, :reindex) feels redundant. Also, the test becomes very slow:

Running 1 tests in a single process (parallelization threshold is 50)
Run options: --seed 43504

Running:

.

Finished in 4.227345s, 0.2366 runs/s, 0.4731 assertions/s.
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips

What am I missing?