From 21c3b31c97077f5f32e0a423c7639eb65db35167 Mon Sep 17 00:00:00 2001 From: Mantas Masalskis Date: Tue, 24 Sep 2019 15:04:42 +0200 Subject: [PATCH] Maintenance: Added test coverage for public Knowledge Base search. --- .gitlab-ci.yml | 11 ++++-- lib/search_index_backend.rb | 38 +++++++++++++++++++ lib/tasks/search_index_es.rake | 6 +++ spec/factories/knowledge_base/answer.rb | 4 ++ spec/factories/knowledge_base/category.rb | 4 ++ spec/support/capybara/kb_matchers.rb | 20 ++++++++++ spec/support/searchindex_backend.rb | 20 +++++++++- .../editor_search_spec.rb | 30 +++++++++++++++ .../guest_search_spec.rb | 30 +++++++++++++++ test/support/searchindex_helper.rb | 19 +++++++++- 10 files changed, 175 insertions(+), 7 deletions(-) create mode 100644 spec/support/capybara/kb_matchers.rb create mode 100644 spec/system/knowledge_base_public/editor_search_spec.rb create mode 100644 spec/system/knowledge_base_public/guest_search_spec.rb diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index db58de1ec..29c6e9f32 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -215,18 +215,21 @@ test:integration:clearbit: ### Elasticsearch +.script_integration_es_variables: &script_integration_es_variables + ES_INDEX_RAND: "true" + ES_URL: "http://elasticsearch:9200" + .script_integration_es_template: &script_integration_es_definition <<: *base_env stage: test variables: + <<: *script_integration_es_variables RAILS_ENV: "test" - ES_INDEX_RAND: "true" - ES_URL: "http://elasticsearch:9200" script: - bundle exec rake zammad:db:unseeded - bundle exec rails test test/integration/elasticsearch_active_test.rb - bundle exec rails test test/integration/elasticsearch_test.rb - - bundle exec rspec --tag searchindex + - bundle exec rspec --tag searchindex --tag ~type:system - bundle exec rails test test/integration/report_test.rb test:integration:es:5.6: @@ -375,12 +378,14 @@ browser:build: .variables_capybara_chrome_template: &variables_capybara_chrome_definition <<: *test_capybara_definition variables: + <<: *script_integration_es_variables RAILS_ENV: "test" BROWSER: "chrome" .variables_capybara_ff_template: &variables_capybara_ff_definition <<: *test_capybara_definition variables: + <<: *script_integration_es_variables RAILS_ENV: "test" BROWSER: "firefox" diff --git a/lib/search_index_backend.rb b/lib/search_index_backend.rb index cbb346678..26ea8100e 100644 --- a/lib/search_index_backend.rb +++ b/lib/search_index_backend.rb @@ -868,4 +868,42 @@ return true if backend is configured data end +=begin + +refreshes all indexes to make previous request data visible in future requests + + SearchIndexBackend.refresh + +=end + + def self.refresh + return if !enabled? + + url = "#{Setting.get('es_url')}/_all/_refresh" + + Rails.logger.info "# curl -X POST \"#{url}\" " + + response = UserAgent.post( + url, + {}, + { + open_timeout: 8, + read_timeout: 60, + open_socket_tries: 3, + user: Setting.get('es_user'), + password: Setting.get('es_password'), + } + ) + + Rails.logger.info "# #{response.code}" + + return true if response.success? + + raise humanized_error( + verb: 'POST', + url: url, + response: response, + ) + end + end diff --git a/lib/tasks/search_index_es.rake b/lib/tasks/search_index_es.rake index 9ca640cf0..13298a63c 100644 --- a/lib/tasks/search_index_es.rake +++ b/lib/tasks/search_index_es.rake @@ -147,6 +147,12 @@ namespace :searchindex do end + task :refresh, [:opts] => :environment do |_t, _args| + print 'refresh all indexes...' + + SearchIndexBackend.refresh + end + task :rebuild, [:opts] => :environment do |_t, _args| Rake::Task['searchindex:drop'].execute Rake::Task['searchindex:create'].execute diff --git a/spec/factories/knowledge_base/answer.rb b/spec/factories/knowledge_base/answer.rb index e1574859b..55d4d3f57 100644 --- a/spec/factories/knowledge_base/answer.rb +++ b/spec/factories/knowledge_base/answer.rb @@ -1,5 +1,9 @@ FactoryBot.define do factory 'knowledge_base/answer', aliases: %i[knowledge_base_answer] do + transient do + add_translation { true } + end + category { create(:knowledge_base_category) } before(:create) do |answer| diff --git a/spec/factories/knowledge_base/category.rb b/spec/factories/knowledge_base/category.rb index 3b4e16a4c..aee0ff0e4 100644 --- a/spec/factories/knowledge_base/category.rb +++ b/spec/factories/knowledge_base/category.rb @@ -1,5 +1,9 @@ FactoryBot.define do factory 'knowledge_base/category', aliases: %i[knowledge_base_category] do + transient do + add_translation { true } + end + knowledge_base { parent&.knowledge_base || create(:knowledge_base) } category_icon { 'f04b' } diff --git a/spec/support/capybara/kb_matchers.rb b/spec/support/capybara/kb_matchers.rb new file mode 100644 index 000000000..5e0730109 --- /dev/null +++ b/spec/support/capybara/kb_matchers.rb @@ -0,0 +1,20 @@ +RSpec::Matchers.define :allow_to_search_for do |expected| + match do |actual| + search_string = expected.translation.title + + actual.find('.js-search-input').fill_in with: search_string + actual.find('.search-results').has_text? search_string + end + + description do + "allows to search for \"#{expected.translation.title}\"" + end + + failure_message do + "could not search for \"#{expected.translation.title}\"" + end + + failure_message do + "\"#{expected.translation.title}\" showed up in search results" + end +end diff --git a/spec/support/searchindex_backend.rb b/spec/support/searchindex_backend.rb index 52890b84d..da6c1570b 100644 --- a/spec/support/searchindex_backend.rb +++ b/spec/support/searchindex_backend.rb @@ -16,7 +16,17 @@ module SearchindexBackendHelper end end - def configure_elasticsearch(required: false) +=begin + +prepares elasticsearch + +@param required [Boolean] raises error if ES is not configured. Recommended to avoid mysterious errors in CI. +@param rebuild [Boolean] rebuilds indexes and sleeps for 1 second after given yield block is executed + +@yield given block run after ES is setup, but before index rebuilding + +=end + def configure_elasticsearch(required: false, rebuild: false) if ENV['ES_URL'].blank? return if !required @@ -33,7 +43,7 @@ module SearchindexBackendHelper if ENV['ES_INDEX_RAND'].present? rand_id = ENV.fetch('CI_JOB_ID', "r#{rand(999)}") test_method_name = self.class.description.gsub(/[^\w]/, '_') - ENV['ES_INDEX'] = "es_index_#{test_method_name}_#{rand_id}_#{rand(999_999_999)}" + ENV['ES_INDEX'] = "es_index_#{test_method_name.downcase}_#{rand_id}_#{rand(999_999_999)}" end if ENV['ES_INDEX'].blank? raise "ERROR: Need ES_INDEX - hint ES_INDEX='estest.local_zammad'" @@ -45,16 +55,22 @@ module SearchindexBackendHelper Setting.set('es_attachment_max_size_in_mb', 1) yield if block_given? + + return if !rebuild + + rebuild_searchindex end def rebuild_searchindex Rake::Task.clear Zammad::Application.load_tasks Rake::Task['searchindex:rebuild'].execute + Rake::Task['searchindex:refresh'].execute end end +# configure_elasticsearch has to be executed manually!!! RSpec.configure do |config| config.include SearchindexBackendHelper, searchindex: true end diff --git a/spec/system/knowledge_base_public/editor_search_spec.rb b/spec/system/knowledge_base_public/editor_search_spec.rb new file mode 100644 index 000000000..7b01dd6cd --- /dev/null +++ b/spec/system/knowledge_base_public/editor_search_spec.rb @@ -0,0 +1,30 @@ +require 'rails_helper' + +RSpec.describe 'Public Knowledge Base for guest search', type: :system, authenticated: true, searchindex: true do + include_context 'basic Knowledge Base' + + before do + configure_elasticsearch(required: true, rebuild: true) do + published_answer && answer && internal_answer + end + + visit help_no_locale_path + end + + it 'shows no results notification for gibberish search' do + find('.js-search-input').fill_in with: 'Asdasdasdasdasd' + expect(page).to have_text 'No results were found' + end + + it 'list published article' do + expect(page).to allow_to_search_for published_answer + end + + it 'list draft article' do + expect(page).to allow_to_search_for answer + end + + it 'list internal article' do + expect(page).to allow_to_search_for internal_answer + end +end diff --git a/spec/system/knowledge_base_public/guest_search_spec.rb b/spec/system/knowledge_base_public/guest_search_spec.rb new file mode 100644 index 000000000..e7abc247a --- /dev/null +++ b/spec/system/knowledge_base_public/guest_search_spec.rb @@ -0,0 +1,30 @@ +require 'rails_helper' + +RSpec.describe 'Public Knowledge Base for guest search', type: :system, authenticated: false, searchindex: true do + include_context 'basic Knowledge Base' + + before do + configure_elasticsearch(required: true, rebuild: true) do + published_answer && answer && internal_answer + end + + visit help_no_locale_path + end + + it 'shows no results notification for gibberish search' do + find('.js-search-input').fill_in with: 'Asdasdasdasdasd' + expect(page).to have_text 'No results were found' + end + + it 'list published article' do + expect(page).to allow_to_search_for published_answer + end + + it 'not list draft article' do + expect(page).not_to allow_to_search_for answer + end + + it 'not list internal article' do + expect(page).not_to allow_to_search_for internal_answer + end +end diff --git a/test/support/searchindex_helper.rb b/test/support/searchindex_helper.rb index e754da78c..57afe0750 100644 --- a/test/support/searchindex_helper.rb +++ b/test/support/searchindex_helper.rb @@ -13,7 +13,17 @@ module SearchindexHelper end end - def configure_elasticsearch(required: false) +=begin + +prepares elasticsearch + +@param required [Boolean] raises error if ES is not configured. Recommended to avoid mysterious errors in CI. +@param rebuild [Boolean] rebuilds indexes and sleeps for 1 second after given yield block is executed + +@yield given block run after ES is setup, but before index rebuilding + +=end + def configure_elasticsearch(required: false, rebuild: false) if ENV['ES_URL'].blank? return if !required @@ -30,7 +40,7 @@ module SearchindexHelper if ENV['ES_INDEX_RAND'].present? rand_id = ENV.fetch('CI_JOB_ID', "r#{rand(999)}") test_method_name = method_name.gsub(/[^\w]/, '_') - ENV['ES_INDEX'] = "es_index_#{test_method_name}_#{rand_id}_#{rand(999_999_999)}" + ENV['ES_INDEX'] = "es_index_#{test_method_name.downcase}_#{rand_id}_#{rand(999_999_999)}" end if ENV['ES_INDEX'].blank? raise "ERROR: Need ES_INDEX - hint ES_INDEX='estest.local_zammad'" @@ -42,12 +52,17 @@ module SearchindexHelper Setting.set('es_attachment_max_size_in_mb', 1) yield if block_given? + + return if !rebuild + + rebuild_searchindex end def rebuild_searchindex Rake::Task.clear Zammad::Application.load_tasks Rake::Task['searchindex:rebuild'].execute + Rake::Task['searchindex:refresh'].execute end end