diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index ff612ea2..638fce8b 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2016-01-12 08:44:10 -0500 using RuboCop version 0.34.2. +# on 2016-01-18 16:47:02 -0500 using RuboCop version 0.34.2. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -38,32 +38,32 @@ Lint/RescueException: Metrics/AbcSize: Max: 91 -# Offense count: 1 +# Offense count: 5 Metrics/BlockNesting: Max: 4 -# Offense count: 1 +# Offense count: 2 # Configuration parameters: CountComments. Metrics/ClassLength: - Max: 186 + Max: 177 -# Offense count: 9 +# Offense count: 11 Metrics/CyclomaticComplexity: - Max: 17 + Max: 19 -# Offense count: 498 +# Offense count: 522 # Configuration parameters: AllowURI, URISchemes. Metrics/LineLength: - Max: 197 + Max: 208 # Offense count: 32 # Configuration parameters: CountComments. Metrics/MethodLength: - Max: 39 + Max: 48 -# Offense count: 9 +# Offense count: 11 Metrics/PerceivedComplexity: - Max: 17 + Max: 20 # Offense count: 73 # Configuration parameters: Exclude. diff --git a/CHANGELOG.md b/CHANGELOG.md index cc98e4ca..3c8f9cad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### Changelog +* [#78](https://github.com/dblock/slack-gamebot/issues/78): Losers can record a loss or a resignation without a prior challenge - [@dblock](https://github.com/dblock). * [#77](https://github.com/dblock/slack-gamebot/issues/77): Opt-in now required to expose team data via the public API - [@dblock](https://github.com/dblock). * [#76](https://github.com/dblock/slack-gamebot/issues/76): Prevent multiple bots from responding to you suck - [@dblock](https://github.com/dblock). * [#75](https://github.com/dblock/slack-gamebot/issues/75): Nudge inactive teams every couple of weeks - [@dblock](https://github.com/dblock). diff --git a/README.md b/README.md index 5bed5f29..fabcc4af 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ gamebot register Welcome back Victor Barna! I've updated your registration. ``` -#### gamebot challenge , ... [with , ...] +#### gamebot challenge ... [with ...] Creates a new challenge between you and an opponent. @@ -92,7 +92,7 @@ gamebot accept Wang Hoe and Zhang Jike accepted Victor Barna and Deng Yaping's challenge. ``` -#### gamebot lost [score, ...] +#### gamebot lost [to [with ]] [score ...] Record your loss. @@ -128,7 +128,24 @@ gamebot lost 15:21 21:17 18:21 Match scores have been updated! Wang Hoe defeated Victor Barna with the scores of 15:21 21:17 18:21. ``` -#### gamebot draw [score, ...] +You can record a loss without a challenge. + +``` +gamebot lost to @WangHoe + +Match has been recorded! Wang Hoe defeated Victor Barna. +``` + +You can also record scores and record lost matches with multiple players. + +``` +gamebot lost to @WangHoe @ZhangJike with @DengYaping 5:21 + +Match has been recorded! Wang Hoe and Zhang Jike defeated Victor Barna and Deng Yaping with the score of 21:5. +``` + + +#### gamebot draw [score ...] Draws a challenge, records a tie. All other players will also have to draw to record a match. @@ -142,7 +159,7 @@ gamebot draw 2:2 Match has been recorded. Victor Barna tied with Zhang Jike with a score of 2:2. ``` -#### gamebot resigned +#### gamebot resigned [to [with ]] Records your resignation, which is a special kind of `lost` without a score. @@ -154,6 +171,14 @@ Match has been recorded! Victor Barna resigned against Wang Hoe. ![](screenshots/resigned.gif) +You can resign without a prior challenge. + +``` +gamebot resigned to WangHoe + +Match has been recorded! Victor Barna resigned against Wang Hoe. +``` + #### gamebot decline Decline a challenge. diff --git a/slack-gamebot/commands/lost.rb b/slack-gamebot/commands/lost.rb index c46b9e00..9b1b322e 100644 --- a/slack-gamebot/commands/lost.rb +++ b/slack-gamebot/commands/lost.rb @@ -3,9 +3,43 @@ module Commands class Lost < SlackRubyBot::Commands::Base def self.call(client, data, match) challenger = ::User.find_create_or_update_by_slack_id!(client, data.user) + expression = match['expression'] if match.names.include?('expression') + arguments = expression.split.reject(&:blank?) if expression + + scores = nil + opponents = [] + teammates = [challenger] + multi_player = expression && expression.include?(' with ') + + current = :scores + while arguments && arguments.any? + argument = arguments.shift + case argument + when 'to' then + current = :opponents + when 'with' then + current = :teammates + else + if current == :opponents + opponents << ::User.find_by_slack_mention!(client.team, argument) + current = :scores unless multi_player + elsif current == :teammates + teammates << ::User.find_by_slack_mention!(client.team, argument) + current = :scores if opponents.count == teammates.count + else + scores ||= [] + scores << Score.check(argument) + end + end + end + challenge = ::Challenge.find_by_user(client.team, data.channel, challenger, [ChallengeState::PROPOSED, ChallengeState::ACCEPTED]) - scores = Score.parse(match['expression']) if match.names.include?('expression') - if challenge + + if opponents.any? && (challenge.nil? || (challenge.challengers != opponents && challenge.challenged != opponents)) + match = ::Match.lose!(team: client.team, winners: opponents, losers: teammates, scores: scores) + client.say(channel: data.channel, text: "Match has been recorded! #{match}.", gif: 'loser') + logger.info "LOST TO: #{client.team} - #{match}" + elsif challenge challenge.lose!(challenger, scores) client.say(channel: data.channel, text: "Match has been recorded! #{challenge.match}.", gif: 'loser') logger.info "LOST: #{client.team} - #{challenge}" diff --git a/slack-gamebot/commands/resigned.rb b/slack-gamebot/commands/resigned.rb index 9968dd19..5bc456d5 100644 --- a/slack-gamebot/commands/resigned.rb +++ b/slack-gamebot/commands/resigned.rb @@ -3,11 +3,48 @@ module Commands class Resigned < SlackRubyBot::Commands::Base def self.call(client, data, match) challenger = ::User.find_create_or_update_by_slack_id!(client, data.user) + expression = match['expression'] if match.names.include?('expression') + arguments = expression.split.reject(&:blank?) if expression + + scores = nil + opponents = [] + teammates = [challenger] + multi_player = expression && expression.include?(' with ') + + current = :scores + while arguments && arguments.any? + argument = arguments.shift + case argument + when 'to' then + current = :opponents + when 'with' then + current = :teammates + else + if current == :opponents + opponents << ::User.find_by_slack_mention!(client.team, argument) + current = :scores unless multi_player + elsif current == :teammates + teammates << ::User.find_by_slack_mention!(client.team, argument) + current = :scores if opponents.count == teammates.count + else + scores ||= [] + scores << argument + end + end + end + challenge = ::Challenge.find_by_user(client.team, data.channel, challenger, [ChallengeState::PROPOSED, ChallengeState::ACCEPTED]) - scores = Score.parse(match['expression']) if match.names.include?('expression') - if challenge - challenge.resign!(challenger, scores) - client.say(channel: data.channel, text: "Match has been recorded! #{challenge.match}.", gif: 'coward') + + if scores && scores.any? + client.say(channel: data.channel, text: 'Cannot score when resigning.', gif: 'idiot') + logger.info "RESIGNED: #{client.team} - #{data.user}, cannot score." + elsif opponents.any? && (challenge.nil? || (challenge.challengers != opponents && challenge.challenged != opponents)) + match = ::Match.resign!(team: client.team, winners: opponents, losers: teammates) + client.say(channel: data.channel, text: "Match has been recorded! #{match}.", gif: 'loser') + logger.info "RESIGNED TO: #{client.team} - #{match}" + elsif challenge + challenge.resign!(challenger) + client.say(channel: data.channel, text: "Match has been recorded! #{challenge.match}.", gif: 'loser') logger.info "RESIGNED: #{client.team} - #{challenge}" else client.say(channel: data.channel, text: 'No challenge to resign!') diff --git a/slack-gamebot/models/challenge.rb b/slack-gamebot/models/challenge.rb index 1dff6479..ea5a9365 100644 --- a/slack-gamebot/models/challenge.rb +++ b/slack-gamebot/models/challenge.rb @@ -101,10 +101,7 @@ def lose!(loser, scores = nil) else fail SlackGamebot::Error, "Only #{(challenged + challengers).map(&:user_name).or} can lose this challenge." end - Match.create!(team: team, challenge: self, winners: winners, losers: losers, scores: scores) - winners.inc(wins: 1) - losers.inc(losses: 1) - User.rank!(team) + Match.lose!(team: team, challenge: self, winners: winners, losers: losers, scores: scores) update_attributes!(state: ChallengeState::PLAYED) end @@ -122,10 +119,7 @@ def resign!(loser, scores = nil) else fail SlackGamebot::Error, "Only #{(challenged + challengers).map(&:user_name).or} can lose this challenge." end - Match.create!(team: team, challenge: self, winners: winners, losers: losers, scores: scores, resigned: true) - winners.inc(wins: 1) - losers.inc(losses: 1) - User.rank!(team) + Match.resign!(team: team, challenge: self, winners: winners, losers: losers, scores: scores) update_attributes!(state: ChallengeState::PLAYED) end @@ -146,10 +140,7 @@ def draw!(player, scores = nil) losers = challenged winners = challengers end - Match.create!(team: team, challenge: self, winners: winners, losers: losers, tied: true, scores: scores) - challenged.inc(ties: 1) - challengers.inc(ties: 1) - User.rank!(team) + Match.draw!(team: team, challenge: self, winners: winners, losers: losers, scores: scores) update_attributes!(state: ChallengeState::PLAYED) end diff --git a/slack-gamebot/models/match.rb b/slack-gamebot/models/match.rb index 81d46d50..89d90655 100644 --- a/slack-gamebot/models/match.rb +++ b/slack-gamebot/models/match.rb @@ -35,6 +35,29 @@ def to_s end end + def self.lose!(attrs) + match = Match.create!(attrs) + match.winners.inc(wins: 1) + match.losers.inc(losses: 1) + User.rank!(match.team) + match + end + + def self.resign!(attrs) + match = Match.create!(attrs.merge(resigned: true)) + match.winners.inc(wins: 1) + match.losers.inc(losses: 1) + User.rank!(match.team) + match + end + + def self.draw!(attrs) + match = Match.create!(attrs.merge(tied: true)) + match.winners.inc(ties: 1) + match.losers.inc(ties: 1) + User.rank!(match.team) + end + private def validate_teams diff --git a/slack-gamebot/models/score.rb b/slack-gamebot/models/score.rb index 56b51dee..b7088666 100644 --- a/slack-gamebot/models/score.rb +++ b/slack-gamebot/models/score.rb @@ -26,28 +26,31 @@ def self.parse(expression) return unless expression scores = [] expression.split.reject(&:blank?).each do |pair| - pair_n = if pair.include?(':') - pair.split(':') if pair.include?(':') - elsif pair.include?('-') - pair.split('-') - elsif pair.include?(',') - pair.split(',') - end - fail SlackGamebot::Error, "Invalid score: #{pair}." unless pair_n && pair_n.length == 2 - pair_n = pair_n.map do |points| - begin - points = Integer(points) - fail SlackGamebot::Error, 'points must be greater or equal to zero' if points < 0 - points - rescue StandardError => e - raise SlackGamebot::Error, "Invalid score: #{pair}, #{e}." - end - end - scores << pair_n + scores << check(pair) end scores end + def self.check(pair) + pair_n = if pair.include?(':') + pair.split(':') if pair.include?(':') + elsif pair.include?('-') + pair.split('-') + elsif pair.include?(',') + pair.split(',') + end + fail SlackGamebot::Error, "Invalid score: #{pair}." unless pair_n && pair_n.length == 2 + pair_n.map do |points| + begin + points = Integer(points) + fail SlackGamebot::Error, 'points must be greater or equal to zero' if points < 0 + points + rescue StandardError => e + raise SlackGamebot::Error, "Invalid score: #{pair}, #{e}." + end + end + end + def self.scores_to_string(scores) [ scores.count > 1 ? 'the scores of' : 'the score of', diff --git a/spec/slack-gamebot/commands/challenge_spec.rb b/spec/slack-gamebot/commands/challenge_spec.rb index 0b42538e..d3ee00d3 100644 --- a/spec/slack-gamebot/commands/challenge_spec.rb +++ b/spec/slack-gamebot/commands/challenge_spec.rb @@ -24,6 +24,20 @@ ) end.to change(Challenge, :count).by(1) end + it 'creates a doubles challenge by user name' do + opponent2 = Fabricate(:user, team: team) + teammate = Fabricate(:user, team: team) + expect do + expect(message: "#{SlackRubyBot.config.user} challenge #{opponent.user_name} #{opponent2.user_name} with #{teammate.user_name}", user: user.user_id, channel: 'pongbot').to respond_with_slack_message( + "#{user.user_name} and #{teammate.user_name} challenged #{opponent.user_name} and #{opponent2.user_name} to a match!" + ) + end.to change(Challenge, :count).by(1) + challenge = Challenge.last + expect(challenge.channel).to eq 'pongbot' + expect(challenge.created_by).to eq user + expect(challenge.challengers).to eq [teammate, user] + expect(challenge.challenged).to eq [opponent2, opponent] + end it 'creates a singles challenge by user name case-insensitive' do expect do expect(message: "#{SlackRubyBot.config.user} challenge #{opponent.user_name.capitalize}", user: user.user_id, channel: 'pongbot').to respond_with_slack_message( diff --git a/spec/slack-gamebot/commands/lost_spec.rb b/spec/slack-gamebot/commands/lost_spec.rb index 62bd7bed..bcf9ecc3 100644 --- a/spec/slack-gamebot/commands/lost_spec.rb +++ b/spec/slack-gamebot/commands/lost_spec.rb @@ -3,75 +3,159 @@ describe SlackGamebot::Commands::Lost, vcr: { cassette_name: 'user_info' } do let!(:team) { Fabricate(:team) } let(:app) { SlackGamebot::Server.new(team: team) } - let(:challenged) { Fabricate(:user, user_name: 'username') } - let!(:challenge) { Fabricate(:challenge, challenged: [challenged]) } - before do - challenge.accept!(challenged) + context 'with an existing challenge' do + let(:challenged) { Fabricate(:user, user_name: 'username') } + let!(:challenge) { Fabricate(:challenge, challenged: [challenged]) } + before do + challenge.accept!(challenged) + end + it 'lost' do + expect(message: "#{SlackRubyBot.config.user} lost", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + "Match has been recorded! #{challenge.challengers.map(&:user_name).and} defeated #{challenge.challenged.map(&:user_name).and}." + ) + challenge.reload + expect(challenge.state).to eq ChallengeState::PLAYED + expect(challenge.match.winners).to eq challenge.challengers + expect(challenge.match.losers).to eq challenge.challenged + end + it 'updates existing challenge when lost to' do + expect(message: "#{SlackRubyBot.config.user} lost to #{challenge.challengers.first.user_name}", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + "Match has been recorded! #{challenge.challengers.map(&:user_name).and} defeated #{challenge.challenged.map(&:user_name).and}." + ) + challenge.reload + expect(challenge.state).to eq ChallengeState::PLAYED + expect(challenge.match.winners).to eq challenge.challengers + expect(challenge.match.losers).to eq challenge.challenged + end + it 'lost with score' do + expect(message: "#{SlackRubyBot.config.user} lost 15:21", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + "Match has been recorded! #{challenge.challengers.map(&:user_name).and} defeated #{challenge.challenged.map(&:user_name).and} with the score of 15:21." + ) + challenge.reload + expect(challenge.match.scores).to eq [[15, 21]] + expect(challenge.match.resigned?).to be false + end + it 'lost with invalid score' do + expect(message: "#{SlackRubyBot.config.user} lost 21:15", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + 'Loser scores must come first.' + ) + end + it 'lost with scores' do + expect(message: "#{SlackRubyBot.config.user} lost 21:15 14:21 5:11", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + "Match has been recorded! #{challenge.challengers.map(&:user_name).and} defeated #{challenge.challenged.map(&:user_name).and} with the scores of 21:15 14:21 5:11." + ) + challenge.reload + expect(challenge.match.scores).to eq [[21, 15], [14, 21], [5, 11]] + end + it 'lost with a crushing score' do + expect(message: "#{SlackRubyBot.config.user} lost 5:21", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + "Match has been recorded! #{challenge.challengers.map(&:user_name).and} crushed #{challenge.challenged.map(&:user_name).and} with the score of 5:21." + ) + end + it 'lost in a close game' do + expect(message: "#{SlackRubyBot.config.user} lost 19:21", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + "Match has been recorded! #{challenge.challengers.map(&:user_name).and} narrowly defeated #{challenge.challenged.map(&:user_name).and} with the score of 19:21." + ) + end + it 'lost amending scores' do + challenge.lose!(challenged) + expect(message: "#{SlackRubyBot.config.user} lost 21:15 14:21 5:11", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + "Match scores have been updated! #{challenge.challengers.map(&:user_name).and} defeated #{challenge.challenged.map(&:user_name).and} with the scores of 21:15 14:21 5:11." + ) + challenge.reload + expect(challenge.match.scores).to eq [[21, 15], [14, 21], [5, 11]] + end + it 'does not update a previously lost match' do + challenge.lose!(challenged, [[11, 21]]) + challenge2 = Fabricate(:challenge, challenged: [challenged]) + challenge2.accept!(challenged) + expect(message: "#{SlackRubyBot.config.user} lost", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + "Match has been recorded! #{challenge2.challengers.map(&:user_name).and} defeated #{challenge2.challenged.map(&:user_name).and}." + ) + challenge.reload + expect(challenge.match.scores).to eq [[11, 21]] + challenge2.reload + expect(challenge2.state).to eq ChallengeState::PLAYED + expect(challenge2.match.scores).to be nil + end + it 'does not update a previously won match' do + challenge.lose!(challenge.challengers.first, [[11, 21]]) + expect(message: "#{SlackRubyBot.config.user} lost", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + 'No challenge to lose!' + ) + end end - it 'lost' do - expect(message: "#{SlackRubyBot.config.user} lost", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - "Match has been recorded! #{challenge.challengers.map(&:user_name).and} defeated #{challenge.challenged.map(&:user_name).and}." - ) - challenge.reload - expect(challenge.state).to eq ChallengeState::PLAYED - expect(challenge.match.winners).to eq challenge.challengers - expect(challenge.match.losers).to eq challenge.challenged - end - it 'lost with score' do - expect(message: "#{SlackRubyBot.config.user} lost 15:21", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - "Match has been recorded! #{challenge.challengers.map(&:user_name).and} defeated #{challenge.challenged.map(&:user_name).and} with the score of 15:21." - ) - challenge.reload - expect(challenge.match.scores).to eq [[15, 21]] - expect(challenge.match.resigned?).to be false - end - it 'lost with invalid score' do - expect(message: "#{SlackRubyBot.config.user} lost 21:15", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - 'Loser scores must come first.' - ) - end - it 'lost with scores' do - expect(message: "#{SlackRubyBot.config.user} lost 21:15 14:21 5:11", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - "Match has been recorded! #{challenge.challengers.map(&:user_name).and} defeated #{challenge.challenged.map(&:user_name).and} with the scores of 21:15 14:21 5:11." - ) - challenge.reload - expect(challenge.match.scores).to eq [[21, 15], [14, 21], [5, 11]] - end - it 'lost with a crushing score' do - expect(message: "#{SlackRubyBot.config.user} lost 5:21", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - "Match has been recorded! #{challenge.challengers.map(&:user_name).and} crushed #{challenge.challenged.map(&:user_name).and} with the score of 5:21." - ) - end - it 'lost in a close game' do - expect(message: "#{SlackRubyBot.config.user} lost 19:21", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - "Match has been recorded! #{challenge.challengers.map(&:user_name).and} narrowly defeated #{challenge.challenged.map(&:user_name).and} with the score of 19:21." - ) - end - it 'lost amending scores' do - challenge.lose!(challenged) - expect(message: "#{SlackRubyBot.config.user} lost 21:15 14:21 5:11", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - "Match scores have been updated! #{challenge.challengers.map(&:user_name).and} defeated #{challenge.challenged.map(&:user_name).and} with the scores of 21:15 14:21 5:11." - ) - challenge.reload - expect(challenge.match.scores).to eq [[21, 15], [14, 21], [5, 11]] - end - it 'does not update a previously lost match' do - challenge.lose!(challenged, [[11, 21]]) - challenge2 = Fabricate(:challenge, challenged: [challenged]) - challenge2.accept!(challenged) - expect(message: "#{SlackRubyBot.config.user} lost", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - "Match has been recorded! #{challenge2.challengers.map(&:user_name).and} defeated #{challenge2.challenged.map(&:user_name).and}." - ) - challenge.reload - expect(challenge.match.scores).to eq [[11, 21]] - challenge2.reload - expect(challenge2.state).to eq ChallengeState::PLAYED - expect(challenge2.match.scores).to be nil - end - it 'does not update a previously won match' do - challenge.lose!(challenge.challengers.first, [[11, 21]]) - expect(message: "#{SlackRubyBot.config.user} lost", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - 'No challenge to lose!' - ) + context 'lost to' do + let(:loser) { Fabricate(:user, user_name: 'username') } + let(:winner) { Fabricate(:user) } + it 'a player' do + expect do + expect do + expect(message: "#{SlackRubyBot.config.user} lost to #{winner.user_name}", user: loser.user_id, channel: 'channel').to respond_with_slack_message( + "Match has been recorded! #{winner.user_name} defeated #{loser.user_name}." + ) + end.to_not change(Challenge, :count) + end.to change(Match, :count).by(1) + match = Match.asc(:_id).last + expect(match.winners).to eq [winner] + expect(match.losers).to eq [loser] + end + it 'two players' do + winner2 = Fabricate(:user, team: team) + loser2 = Fabricate(:user, team: team) + expect do + expect do + expect(message: "#{SlackRubyBot.config.user} lost to #{winner.user_name} #{winner2.user_name} with #{loser2.user_name}", user: loser.user_id, channel: 'pongbot').to respond_with_slack_message( + "Match has been recorded! #{winner.user_name} and #{winner2.user_name} defeated #{loser.user_name} and #{loser2.user_name}." + ) + end.to_not change(Challenge, :count) + end.to change(Match, :count).by(1) + match = Match.asc(:_id).last + expect(match.winners).to eq [winner2, winner] + expect(match.losers).to eq [loser2, loser] + end + it 'two players with scores' do + winner2 = Fabricate(:user, team: team) + loser2 = Fabricate(:user, team: team) + expect do + expect do + expect(message: "#{SlackRubyBot.config.user} lost to #{winner.user_name} #{winner2.user_name} with #{loser2.user_name} 15:21", user: loser.user_id, channel: 'pongbot').to respond_with_slack_message( + "Match has been recorded! #{winner.user_name} and #{winner2.user_name} defeated #{loser.user_name} and #{loser2.user_name} with the score of 15:21." + ) + end.to_not change(Challenge, :count) + end.to change(Match, :count).by(1) + match = Match.asc(:_id).last + expect(match.winners).to eq [winner2, winner] + expect(match.losers).to eq [loser2, loser] + expect(match.scores).to eq [[15, 21]] + end + it 'with score' do + expect do + expect do + expect(message: "#{SlackRubyBot.config.user} lost to #{winner.user_name} 15:21", user: loser.user_id, channel: 'channel').to respond_with_slack_message( + "Match has been recorded! #{winner.user_name} defeated #{loser.user_name} with the score of 15:21." + ) + end.to_not change(Challenge, :count) + end.to change(Match, :count).by(1) + match = Match.asc(:_id).last + expect(match.winners).to eq [winner] + expect(match.losers).to eq [loser] + expect(match.scores).to eq [[15, 21]] + expect(match.resigned?).to be false + end + it 'with scores' do + expect do + expect do + expect(message: "#{SlackRubyBot.config.user} lost to #{winner.user_name} 21:15 14:21 5:11", user: loser.user_id, channel: 'channel').to respond_with_slack_message( + "Match has been recorded! #{winner.user_name} defeated #{loser.user_name} with the scores of 21:15 14:21 5:11." + ) + end.to_not change(Challenge, :count) + end.to change(Match, :count).by(1) + match = Match.asc(:_id).last + expect(match.winners).to eq [winner] + expect(match.losers).to eq [loser] + expect(match.scores).to eq [[21, 15], [14, 21], [5, 11]] + expect(match.resigned?).to be false + end end end diff --git a/spec/slack-gamebot/commands/resigned_spec.rb b/spec/slack-gamebot/commands/resigned_spec.rb index 41f49fd2..c52414e8 100644 --- a/spec/slack-gamebot/commands/resigned_spec.rb +++ b/spec/slack-gamebot/commands/resigned_spec.rb @@ -3,24 +3,58 @@ describe SlackGamebot::Commands::Resigned, vcr: { cassette_name: 'user_info' } do let!(:team) { Fabricate(:team) } let(:app) { SlackGamebot::Server.new(team: team) } - let(:challenged) { Fabricate(:user, user_name: 'username') } - let!(:challenge) { Fabricate(:challenge, challenged: [challenged]) } - before do - challenge.accept!(challenged) + context 'with a challenge' do + let(:challenged) { Fabricate(:user, user_name: 'username') } + let!(:challenge) { Fabricate(:challenge, challenged: [challenged]) } + before do + challenge.accept!(challenged) + end + it 'resigned' do + expect(message: "#{SlackRubyBot.config.user} resigned", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + "Match has been recorded! #{challenge.challenged.map(&:user_name).and} resigned against #{challenge.challengers.map(&:user_name).and}." + ) + challenge.reload + expect(challenge.state).to eq ChallengeState::PLAYED + expect(challenge.match.winners).to eq challenge.challengers + expect(challenge.match.losers).to eq challenge.challenged + expect(challenge.match.resigned?).to be true + end + it 'resigned with score' do + expect(message: "#{SlackRubyBot.config.user} resigned 15:21", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( + 'Cannot score when resigning.' + ) + end end - it 'resigned' do - expect(message: "#{SlackRubyBot.config.user} resigned", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - "Match has been recorded! #{challenge.challenged.map(&:user_name).and} resigned against #{challenge.challengers.map(&:user_name).and}." - ) - challenge.reload - expect(challenge.state).to eq ChallengeState::PLAYED - expect(challenge.match.winners).to eq challenge.challengers - expect(challenge.match.losers).to eq challenge.challenged - expect(challenge.match.resigned?).to be true - end - it 'resigned with score' do - expect(message: "#{SlackRubyBot.config.user} resigned 15:21", user: challenged.user_id, channel: challenge.channel).to respond_with_slack_message( - 'Cannot score when resigning.' - ) + context 'resigned to' do + let(:loser) { Fabricate(:user, user_name: 'username') } + let(:winner) { Fabricate(:user) } + it 'a player' do + expect do + expect do + expect(message: "#{SlackRubyBot.config.user} resigned to #{winner.user_name}", user: loser.user_id, channel: 'channel').to respond_with_slack_message( + "Match has been recorded! #{loser.user_name} resigned against #{winner.user_name}." + ) + end.to_not change(Challenge, :count) + end.to change(Match, :count).by(1) + match = Match.asc(:_id).last + expect(match.winners).to eq [winner] + expect(match.losers).to eq [loser] + expect(match.resigned?).to be true + end + it 'two players' do + winner2 = Fabricate(:user, team: team) + loser2 = Fabricate(:user, team: team) + expect do + expect do + expect(message: "#{SlackRubyBot.config.user} resigned to #{winner.user_name} #{winner2.user_name} with #{loser2.user_name}", user: loser.user_id, channel: 'pongbot').to respond_with_slack_message( + "Match has been recorded! #{loser.user_name} and #{loser2.user_name} resigned against #{winner.user_name} and #{winner2.user_name}." + ) + end.to_not change(Challenge, :count) + end.to change(Match, :count).by(1) + match = Match.asc(:_id).last + expect(match.winners).to eq [winner2, winner] + expect(match.losers).to eq [loser2, loser] + expect(match.resigned?).to be true + end end end