Friday, September 20, 2024 5:43:55 AM
> settings

Customize


Authenticate

> test.rb
# frozen_string_literal: true

module ESM
  class Test
    # Don't forget to add new entries to .reset!
    class << self
      DATA = YAML.load_file(File.expand_path("./spec/test_data.yml")).deep_symbolize_keys.freeze

      attr_reader :response
      attr_writer :messages
      attr_accessor :skip_cooldown, :territory_admin_uids

      def messages
        @messages ||= Messages.new
      end

      def data
        @data ||= lambda do
          data = DATA.deep_dup
          redis.set("test_data", data.to_json)

          data
        end.call
      end

      def community(*, type: @community_type)
        FactoryBot.create(type, :player_mode_disabled, *)
      end

      def second_community(*)
        FactoryBot.create(@second_community_type, :player_mode_disabled, *)
      end

      def user(*args, type: @user_type)
        args = [type] + args

        counter = 0
        loop do
          if counter > 10
            raise "Failed to create unique user. Decrease number of calls to ESM::Test.user or add more users to test_data.yml"
          end

          counter += 1

          user = FactoryBot.build(*args)
          existing_user_query = ESM::User.where(discord_id: user.discord_id).or(
            ESM::User.where(steam_uid: user.steam_uid)
          )

          next if existing_user_query.exists?

          user.save!
          return user
        end
      end

      def server(opts = {})
        FactoryBot.create(:server, community_id: opts[:for].id)
      end

      def channel(opts = {})
        ESM.bot.channel(opts[:in].channel_ids.sample)
      end

      def redis
        @redis ||= Redis.new(ESM::REDIS_OPTS)
      end

      def response=(value)
        @response = {
          message: {
            content: value
          }
        }.to_ostruct
      end

      def steam_uid
        data[:steam_uids].delete(data[:steam_uids].sample).to_s
      end

      def reset!
        @data = nil
        @response = nil
        @messages = nil
        @outbound_server_messages = nil
        @inbound_server_messages = nil
        @community = nil
        @second_community = nil

        @skip_cooldown = false
        @territory_admin_uids = []

        @communities = %i[primary_community secondary_community]
        @community_type = @communities.sample
        @user_type = (@community_type == :primary_community) ? :user : :secondary_user
        @second_community_type = @communities.find { |type| type != @community_type }

        # Clear the test list in Redis
        redis.del("test")
        redis.del("server_key")

        ESM.bot.delivery_overseer.queue.clear # Otherwise messages from other tests may leak between each other

        ESM.connection_server.pause
      end

      def wait_for_response(timeout: nil)
        timeout ||= 5

        # Offset the fact that we check every 0.25s
        timeout *= 4
        counter = 0

        while response.blank? && counter < timeout
          sleep(0.1)
          counter += 1
        end

        output = response
        @response = nil

        output
      end

      def reply_in(message, wait: 1)
        Thread.new do
          sleep(wait)
          self.response = message
        end
      end

      def wait_until(timeout: 30)
        # Offset the fact that we check every 0.25s
        timeout *= 4
        counter = 0

        while counter < timeout
          sleep(0.1)
          counter += 1

          # I don't have this in the conditional above because I want it to sleep at least once
          return if yield == true
        end

        raise StandardError, "Timeout!"
      end
    end
  end
end
All opinions represented herein are my own
- © 2024 itsthedevman
- build 340fbb8