add Match model
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Match, type: :model do
|
||||
let(:player1) { User.create!(nickname: "player_one", password: "secret123") }
|
||||
let(:player2) { User.create!(nickname: "player_two", password: "secret123") }
|
||||
|
||||
let(:valid_attributes) do
|
||||
{
|
||||
player1: player1,
|
||||
player2: player2,
|
||||
status: :ongoing,
|
||||
game_server: "ws://game-server:8080/ws",
|
||||
started_at: Time.current,
|
||||
player1_rating_before: 100,
|
||||
player2_rating_before: 100,
|
||||
player1_rating_change: 0,
|
||||
player2_rating_change: 0
|
||||
}
|
||||
end
|
||||
|
||||
it "is valid with valid attributes" do
|
||||
expect(Match.new(valid_attributes)).to be_valid
|
||||
end
|
||||
|
||||
it "generates a uuid automatically" do
|
||||
match = Match.create!(valid_attributes)
|
||||
expect(match.uuid).to match(/\A[0-9a-f-]{36}\z/)
|
||||
end
|
||||
|
||||
it "belongs to two players" do
|
||||
match = Match.create!(valid_attributes)
|
||||
expect(match.player1).to eq(player1)
|
||||
expect(match.player2).to eq(player2)
|
||||
end
|
||||
|
||||
it "does not allow the same player on both sides" do
|
||||
match = Match.new(valid_attributes.merge(player2: player1))
|
||||
expect(match).not_to be_valid
|
||||
expect(match.errors[:player2]).to be_present
|
||||
end
|
||||
|
||||
it "requires a game_server" do
|
||||
expect(Match.new(valid_attributes.merge(game_server: nil))).not_to be_valid
|
||||
end
|
||||
|
||||
it "requires started_at" do
|
||||
expect(Match.new(valid_attributes.merge(started_at: nil))).not_to be_valid
|
||||
end
|
||||
|
||||
it "allows finished_at and duration_seconds to be nil" do
|
||||
expect(Match.new(valid_attributes)).to be_valid
|
||||
end
|
||||
|
||||
it "rejects negative duration_seconds" do
|
||||
match = Match.new(valid_attributes.merge(duration_seconds: -1))
|
||||
expect(match).not_to be_valid
|
||||
end
|
||||
|
||||
it "rejects nil rating changes" do
|
||||
match = Match.new(valid_attributes.merge(player1_rating_change: nil))
|
||||
expect(match).not_to be_valid
|
||||
end
|
||||
|
||||
it "allows zero rating changes" do
|
||||
match = Match.new(valid_attributes.merge(player1_rating_change: 0, player2_rating_change: 0))
|
||||
expect(match).to be_valid
|
||||
end
|
||||
|
||||
describe "statuses" do
|
||||
it "defines all statuses" do
|
||||
expect(Match.statuses.keys).to contain_exactly(
|
||||
"ongoing", "player1_won", "player2_won", "draw", "abandoned"
|
||||
)
|
||||
end
|
||||
|
||||
it "defaults to ongoing" do
|
||||
match = Match.create!(valid_attributes)
|
||||
expect(match.status).to eq("ongoing")
|
||||
end
|
||||
|
||||
it "supports transitions to final statuses" do
|
||||
match = Match.create!(valid_attributes)
|
||||
match.player1_won!
|
||||
expect(match.reload.status).to eq("player1_won")
|
||||
end
|
||||
end
|
||||
|
||||
describe ".finished" do
|
||||
it "returns only matches with finished_at set" do
|
||||
finished = Match.create!(valid_attributes.merge(finished_at: Time.current))
|
||||
Match.create!(valid_attributes)
|
||||
expect(Match.finished).to contain_exactly(finished)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".for_user" do
|
||||
it "returns matches where the user is either player" do
|
||||
other = User.create!(nickname: "player_three", password: "secret123")
|
||||
m1 = Match.create!(valid_attributes)
|
||||
m2 = Match.create!(valid_attributes.merge(player1: player2, player2: player1))
|
||||
Match.create!(valid_attributes.merge(player1: player2, player2: other))
|
||||
|
||||
expect(Match.for_user(player1)).to contain_exactly(m1, m2)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -97,4 +97,33 @@ RSpec.describe User, type: :model do
|
||||
expect(user.update(nickname: "new_nickname")).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe "#finished_matches" do
|
||||
let(:user) { User.create!(valid_attributes) }
|
||||
let(:opponent) { User.create!(nickname: "opponent", password: "secret123") }
|
||||
let(:outsider) { User.create!(nickname: "outsider", password: "secret123") }
|
||||
|
||||
def build_match(attrs)
|
||||
Match.create!({
|
||||
player1: user,
|
||||
player2: opponent,
|
||||
status: :ongoing,
|
||||
game_server: "ws://game-server:8080/ws",
|
||||
started_at: Time.current,
|
||||
player1_rating_before: 100,
|
||||
player2_rating_before: 100,
|
||||
player1_rating_change: 0,
|
||||
player2_rating_change: 0
|
||||
}.merge(attrs))
|
||||
end
|
||||
|
||||
it "returns only finished matches of the user ordered by finished_at desc" do
|
||||
older = build_match(status: :player1_won, finished_at: 2.days.ago)
|
||||
newer = build_match(player1: opponent, player2: user, status: :player2_won, finished_at: 1.day.ago)
|
||||
build_match(status: :ongoing, finished_at: nil)
|
||||
build_match(player1: opponent, player2: outsider, status: :player1_won, finished_at: Time.current)
|
||||
|
||||
expect(user.finished_matches.to_a).to eq([ newer, older ])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user