~cytrogen/masto-fe

4d9186a48c494bdd098f7a6273c3f0bf4dc5e19a — jsgoldstein 2 years ago 3a67984
Add search tests (#26703)

M .github/workflows/test-ruby.yml => .github/workflows/test-ruby.yml +113 -0
@@ 250,3 250,116 @@ jobs:
        with:
          name: e2e-screenshots
          path: tmp/screenshots/

  test-search:
    name: Testing search
    runs-on: ubuntu-latest

    needs:
      - build

    services:
      postgres:
        image: postgres:14-alpine
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_USER: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

      redis:
        image: redis:7-alpine
        options: >-
          --health-cmd "redis-cli ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 6379:6379

      elasticsearch:
        image: docker.elastic.co/elasticsearch/elasticsearch:7.17.9
        env:
          discovery.type: single-node
          xpack.security.enabled: false
        options: >-
          --health-cmd "curl http://localhost:9200/_cluster/health"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 10
        ports:
          - 9200:9200

    env:
      DB_HOST: localhost
      DB_USER: postgres
      DB_PASS: postgres
      DISABLE_SIMPLECOV: true
      RAILS_ENV: test
      BUNDLE_WITH: test
      ES_ENABLED: true
      ES_HOST: localhost
      ES_PORT: 9200

    strategy:
      fail-fast: false
      matrix:
        ruby-version:
          - '3.0'
          - '3.1'
          - '.ruby-version'

    steps:
      - uses: actions/checkout@v3

      - uses: actions/download-artifact@v3
        with:
          path: './public'
          name: ${{ github.sha }}

      - name: Update package index
        run: sudo apt-get update

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          cache: yarn
          node-version-file: '.nvmrc'

      - name: Install native Ruby dependencies
        run: sudo apt-get install -y libicu-dev libidn11-dev

      - name: Install additional system dependencies
        run: sudo apt-get install -y ffmpeg imagemagick

      - name: Set up bundler cache
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby-version}}
          bundler-cache: true

      - run: yarn --frozen-lockfile

      - name: Load database schema
        run: './bin/rails db:create db:schema:load db:seed'

      - run: bundle exec rake spec:search

      - name: Archive logs
        uses: actions/upload-artifact@v3
        if: failure()
        with:
          name: test-search-logs-${{ matrix.ruby-version }}
          path: log/

      - name: Archive test screenshots
        uses: actions/upload-artifact@v3
        if: failure()
        with:
          name: test-search-screenshots
          path: tmp/screenshots/

M Vagrantfile => Vagrantfile +2 -1
@@ 76,7 76,8 @@ path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["localhost"]
cluster.initial_master_nodes: ["node-1"]' > /etc/elasticsearch/elasticsearch.yml
cluster.initial_master_nodes: ["node-1"]
xpack.security.enabled: false' > /etc/elasticsearch/elasticsearch.yml

sudo systemctl restart elasticsearch


M lib/tasks/spec.rake => lib/tasks/spec.rake +10 -0
@@ 9,3 9,13 @@ if Rake::Task.task_defined?('spec:system')

  Rake::Task['spec:system'].enhance ['spec:enable_system_specs']
end

if Rake::Task.task_defined?('spec:search')
  namespace :spec do
    task :enable_search_specs do # rubocop:disable Rails/RakeEnvironment
      ENV['RUN_SEARCH_SPECS'] = 'true'
    end
  end

  Rake::Task['spec:search'].enhance ['spec:enable_search_specs']
end

M spec/rails_helper.rb => spec/rails_helper.rb +28 -1
@@ 4,11 4,17 @@ ENV['RAILS_ENV'] ||= 'test'

# This needs to be defined before Rails is initialized
RUN_SYSTEM_SPECS = ENV.fetch('RUN_SYSTEM_SPECS', false)
RUN_SEARCH_SPECS = ENV.fetch('RUN_SEARCH_SPECS', false)

if RUN_SYSTEM_SPECS
  STREAMING_PORT = ENV.fetch('TEST_STREAMING_PORT', '4020')
  ENV['STREAMING_API_BASE_URL'] = "http://localhost:#{STREAMING_PORT}"
end

if RUN_SEARCH_SPECS
  # Include any configuration or setups specific to search tests here
end

require File.expand_path('../config/environment', __dir__)

abort('The Rails environment is running in production mode!') if Rails.env.production?


@@ 30,6 36,7 @@ Sidekiq.logger = nil
# System tests config
DatabaseCleaner.strategy = [:deletion]
streaming_server_manager = StreamingServerManager.new
search_data_manager = SearchDataManager.new

Devise::Test::ControllerHelpers.module_eval do
  alias_method :original_sign_in, :sign_in


@@ 69,7 76,14 @@ end

RSpec.configure do |config|
  # This is set before running spec:system, see lib/tasks/tests.rake
  config.filter_run_excluding type: :system unless RUN_SYSTEM_SPECS
  config.filter_run_excluding type: lambda { |type|
    case type
    when :system
      !RUN_SYSTEM_SPECS
    when :search
      !RUN_SEARCH_SPECS
    end
  }
  config.fixture_path = Rails.root.join('spec', 'fixtures')
  config.use_transactional_fixtures = true
  config.order = 'random'


@@ 113,10 127,17 @@ RSpec.configure do |config|
      Webpacker.compile
      streaming_server_manager.start(port: STREAMING_PORT)
    end

    if RUN_SEARCH_SPECS
      Chewy.strategy(:urgent)
      search_data_manager.prepare_test_data
    end
  end

  config.after :suite do
    streaming_server_manager.stop

    search_data_manager.cleanup_test_data if RUN_SEARCH_SPECS
  end

  config.around :each, type: :system do |example|


@@ 137,6 158,12 @@ RSpec.configure do |config|
    self.use_transactional_tests = true
  end

  config.around :each, type: :search do |example|
    search_data_manager.populate_indexes
    example.run
    search_data_manager.remove_indexes
  end

  config.before(:each) do |example|
    unless example.metadata[:paperclip_processing]
      allow_any_instance_of(Paperclip::Attachment).to receive(:post_process).and_return(true) # rubocop:disable RSpec/AnyInstance

A spec/search/models/concerns/account_search_spec.rb => spec/search/models/concerns/account_search_spec.rb +51 -0
@@ 0,0 1,51 @@
# frozen_string_literal: true

require 'rails_helper'

describe AccountSearch do
  describe 'a non-discoverable account becoming discoverable' do
    let(:account) { Account.find_by(username: 'search_test_account_1') }

    context 'when picking a non-discoverable account' do
      it 'its bio is not in the AccountsIndex' do
        results = AccountsIndex.filter(term: { username: account.username })
        expect(results.count).to eq(1)
        expect(results.first.text).to be_nil
      end
    end

    context 'when the non-discoverable account becomes discoverable' do
      it 'its bio is added to the AccountsIndex' do
        account.discoverable = true
        account.save!

        results = AccountsIndex.filter(term: { username: account.username })
        expect(results.count).to eq(1)
        expect(results.first.text).to eq(account.note)
      end
    end
  end

  describe 'a discoverable account becoming non-discoverable' do
    let(:account) { Account.find_by(username: 'search_test_account_0') }

    context 'when picking an discoverable account' do
      it 'has its bio in the AccountsIndex' do
        results = AccountsIndex.filter(term: { username: account.username })
        expect(results.count).to eq(1)
        expect(results.first.text).to eq(account.note)
      end
    end

    context 'when the discoverable account becomes non-discoverable' do
      it 'its bio is removed from the AccountsIndex' do
        account.discoverable = false
        account.save!

        results = AccountsIndex.filter(term: { username: account.username })
        expect(results.count).to eq(1)
        expect(results.first.text).to be_nil
      end
    end
  end
end

A spec/search/models/concerns/account_statuses_search_spec.rb => spec/search/models/concerns/account_statuses_search_spec.rb +53 -0
@@ 0,0 1,53 @@
# frozen_string_literal: true

require 'rails_helper'

describe AccountStatusesSearch do
  describe 'a non-indexable account becoming indexable' do
    let(:account) { Account.find_by(username: 'search_test_account_1') }

    context 'when picking a non-indexable account' do
      it 'has no statuses in the PublicStatusesIndex' do
        expect(PublicStatusesIndex.filter(term: { account_id: account.id }).count).to eq(0)
      end

      it 'has statuses in the StatusesIndex' do
        expect(StatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.count)
      end
    end

    context 'when the non-indexable account becomes indexable' do
      it 'adds the public statuses to the PublicStatusesIndex' do
        account.indexable = true
        account.save!

        expect(PublicStatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.where(visibility: :public).count)
        expect(StatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.count)
      end
    end
  end

  describe 'an indexable account becoming non-indexable' do
    let(:account) { Account.find_by(username: 'search_test_account_0') }

    context 'when picking an indexable account' do
      it 'has statuses in the PublicStatusesIndex' do
        expect(PublicStatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.where(visibility: :public).count)
      end

      it 'has statuses in the StatusesIndex' do
        expect(StatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.count)
      end
    end

    context 'when the indexable account becomes non-indexable' do
      it 'removes the statuses from the PublicStatusesIndex' do
        account.indexable = false
        account.save!

        expect(PublicStatusesIndex.filter(term: { account_id: account.id }).count).to eq(0)
        expect(StatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.count)
      end
    end
  end
end

M spec/spec_helper.rb => spec/spec_helper.rb +42 -0
@@ 129,3 129,45 @@ class StreamingServerManager
    @running_thread.join
  end
end

class SearchDataManager
  def prepare_test_data
    4.times do |i|
      username = "search_test_account_#{i}"
      account = Fabricate.create(:account, username: username, indexable: i.even?, discoverable: i.even?, note: "Lover of #{i}.")
      2.times do |j|
        Fabricate.create(:status, account: account, text: "#{username}'s #{j} post", visibility: j.even? ? :public : :private)
      end
    end

    3.times do |i|
      Fabricate.create(:tag, name: "search_test_tag_#{i}")
    end
  end

  def indexes
    [
      AccountsIndex,
      PublicStatusesIndex,
      StatusesIndex,
      TagsIndex,
    ]
  end

  def populate_indexes
    indexes.each do |index_class|
      index_class.purge!
      index_class.import!
    end
  end

  def remove_indexes
    indexes.each(&:delete!)
  end

  def cleanup_test_data
    Status.destroy_all
    Account.destroy_all
    Tag.destroy_all
  end
end