<commit_before>require 'simplecov'
SimpleCov.start { add_filter '/spec/' }

require 'cinch/test'
require 'cinch/plugins/rebellion_g54'

def get_replies_text(m)
  get_replies(m).map(&:text)
end

class MessageReceiver
  attr_accessor :messages

  def initialize
    @messages = []
  end

  def devoice(_)
  end
  def moderated=(_)
  end

  def send(m)
    @messages << m
  end
end

RSpec.describe Cinch::Plugins::RebellionG54 do
  include Cinch::Test

  let(:chan) { MessageReceiver.new }
  let(:channel1) { '#test' }
  let(:player1) { 'test1' }
  let(:player2) { 'test2' }
  let(:user1) { MessageReceiver.new }
  let(:user2) { MessageReceiver.new }
  let(:players) { {
    player1 => user1,
    player2 => user2,
  }}

  let(:opts) {{
    :channels => [channel1],
    :settings => '/dev/null',
    :allowed_idle => 300,
  }}
  let(:bot) {
    b = make_bot(described_class, opts) { |c|
      self.loggers.first.level = :warn
    }
    # No, c.nick = 'testbot' doesn't work because... isupport?
    allow(b).to receive(:nick).and_return('testbot')
    b
  }
  let(:plugin) { bot.plugins.first }

  def msg(text, nick: player1)
    make_message(bot, text, nick: nick, channel: channel1)
  end

  # Doh this sucks.
  # It's because when joining a game, bot checks that you're in that channel
  # I can't even stub out :Channel because it's on the parent, apparently?
  # So I'll just have to do whatever game_bot does.
  def force_join(message)
    games = plugin.instance_variable_get(:@games)
    game = games[message.channel]
    game.add_player(message.user)
    user_games = plugin.instance_variable_get(:@user_games)
    user_games[message.user] = game
  end

  it 'makes a test bot' do
    expect(bot).to be_a(Cinch::Bot)
  end

  context 'in a game' do
    before :each do
      force_join(msg('!join'))
      force_join(msg('!join', nick: player2))
      allow(plugin).to receive(:Channel).with(channel1).and_return(chan)
      games = plugin.instance_variable_get(:@games)
      game = games[channel1]
      game.each_player.each { |p| allow(p.user).to receive(:send) { |x| players[p.user.name].messages << x } }
      get_replies(msg('!start'))
    end

    it 'says hi' do
      puts "HI"
    end
  end

  describe 'get_roles' do
    it '!roles shows roles' do
      replies = get_replies_text(msg('!roles'))
      expect(replies).to_not be_empty
      expect(replies.first).to include('5 roles')
    end
  end

  describe 'random_roles' do<commit_msg>spec: Add gameplay/game end specs<commit_after>require 'simplecov'
SimpleCov.start { add_filter '/spec/' }

require 'cinch/test'
require 'cinch/plugins/rebellion_g54'

def get_replies_text(m)
  get_replies(m).map(&:text)
end

class MessageReceiver
  attr_accessor :messages

  def initialize
    @messages = []
  end

  def devoice(_)
  end
  def moderated=(_)
  end

  def send(m)
    @messages << m
  end
end

RSpec.describe Cinch::Plugins::RebellionG54 do
  include Cinch::Test

  let(:chan) { MessageReceiver.new }
  let(:channel1) { '#test' }
  let(:player1) { 'test1' }
  let(:player2) { 'test2' }
  let(:user1) { MessageReceiver.new }
  let(:user2) { MessageReceiver.new }
  let(:players) { {
    player1 => user1,
    player2 => user2,
  }}

  let(:opts) {{
    :channels => [channel1],
    :settings => '/dev/null',
    :allowed_idle => 300,
  }}
  let(:bot) {
    b = make_bot(described_class, opts) { |c|
      self.loggers.first.level = :warn
    }
    # No, c.nick = 'testbot' doesn't work because... isupport?
    allow(b).to receive(:nick).and_return('testbot')
    b
  }
  let(:plugin) { bot.plugins.first }

  def msg(text, nick: player1)
    make_message(bot, text, nick: nick, channel: channel1)
  end

  # Doh this sucks.
  # It's because when joining a game, bot checks that you're in that channel
  # I can't even stub out :Channel because it's on the parent, apparently?
  # So I'll just have to do whatever game_bot does.
  def force_join(message)
    games = plugin.instance_variable_get(:@games)
    game = games[message.channel]
    game.add_player(message.user)
    user_games = plugin.instance_variable_get(:@user_games)
    user_games[message.user] = game
  end

  it 'makes a test bot' do
    expect(bot).to be_a(Cinch::Bot)
  end

  context 'in a game' do
    before :each do
      force_join(msg('!join'))
      force_join(msg('!join', nick: player2))
      allow(plugin).to receive(:Channel).with(channel1).and_return(chan)
      games = plugin.instance_variable_get(:@games)
      game = games[channel1]
      game.each_player.each { |p| allow(p.user).to receive(:send) { |x| players[p.user.name].messages << x } }
      get_replies(msg('!start'))
    end

    # This is fragile but I can't do much better?
    let(:player_order) {
      get_replies_text(msg('!who')).map { |text|
        text.gsub(8203.chr('UTF-8'), '')
      }.find { |text|
        # Doing this to filter out the "not a valid choice" that we might get.
        text.include?(player1) && text.include?(player2)
      }.split
    }
    # Here, p1 and p2 mean original player order, not related to player1/player2
    let(:p1) { player_order.first }
    let(:p2) { player_order.last }

    it 'has a sane player order' do
      expect([p1, p2]).to match_array([player1, player2])
    end

    context 'playing the game' do
      before(:each) do
        3.times do
          get_replies(msg('!banker', nick: p1))
          get_replies(msg('!pass', nick: p2))
          get_replies(msg('!income', nick: p2))
        end
        get_replies(msg("!coup #{p2}", nick: p1))
        get_replies(msg("!lose1", nick: p2))
        # p1 at 4 coins, p2 at 5 coins
        get_replies(msg("!income", nick: p2))
        get_replies(msg('!banker', nick: p1))
        get_replies(msg('!pass', nick: p2))
        get_replies(msg('!income', nick: p2))
        # p1 can win by using coup next turn
      end

      it 'can end the game' do
        chan.messages.clear
        # We don't get replies to this; they're just sent to the channel
        get_replies(msg("!coup #{p2}", nick: p1))
        expect(chan.messages).to be_any { |x| x.include?('winner') }
      end

      context 'after game has ended' do
        before(:each) { get_replies(msg("!coup #{p2}", nick: p1)) }

        # OKAY, fine, these aren't actually joining the game,
        # but it checks the important part that I want to check:
        # the bot doesn't think the users are still in a game
        # If the bot did think that, it would reject with a different message

        it 'lets the winner join the next game' do
          replies = get_replies_text(msg('!join', nick: p1))
          expect(replies.first).to be =~ /need to be in .* to join/
        end

        it 'lets the loser join the next game' do
          replies = get_replies_text(msg('!join', nick: p2))
          expect(replies.first).to be =~ /need to be in .* to join/
        end
      end
    end
  end

  describe 'get_roles' do
    it '!roles shows roles' do
      replies = get_replies_text(msg('!roles'))
      expect(replies).to_not be_empty
      expect(replies.first).to include('5 roles')
    end
  end

  describe 'random_roles' do
{'fraction_non_alphanumeric': 0.1336883408071749, 'fraction_numerical': 0.012612107623318386, 'mean_word_length': 2.9387417218543046, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1652731', 'n_tokens_mistral': 2534, 'n_tokens_neox': 2483, 'n_words': 649}