discourse/plugins/poll/spec/lib/ranked_choice_spec.rb

111 lines
4.0 KiB
Ruby

# frozen_string_literal: true
RSpec.describe DiscoursePoll::RankedChoice do
let(:options_1) { [{ id: "Alice", html: "Alice" }, { id: "Bob", html: "Bob" }] }
let(:options_2) do
[{ id: "Alice", html: "Alice" }, { id: "Bob", html: "Bob" }, { id: "Charlie", html: "Charlie" }]
end
let(:options_3) do
[
{ id: "Alice", html: "Alice" },
{ id: "Bob", html: "Bob" },
{ id: "Charlie", html: "Charlie" },
{ id: "Dave", html: "Dave" },
]
end
let(:options_4) do
[
{ id: "Belle-lettres", html: "Belle-lettres" },
{ id: "Comedy", html: "Comedy" },
{ id: "Fantasy", html: "Fantasy" },
{ id: "Historical", html: "Historical" },
{ id: "Mystery", html: "Mystery" },
{ id: "Non-fiction", html: "Non-fiction" },
{ id: "Sci-fi", html: "Sci-fi" },
{ id: "Thriller", html: "Thriller" },
]
end
it "correctly finds the winner with a simple majority" do
votes = [%w[Alice Bob], %w[Bob Alice], %w[Alice Bob], %w[Bob Alice], %w[Alice Bob]]
expect(described_class.run(votes, options_1)[:winning_candidate]).to eq(
{ digest: "Alice", html: "Alice" },
)
end
it "correctly finds the winner after one elimination" do
votes = [
%w[Alice Bob Charlie],
%w[Bob Charlie Alice],
%w[Charlie Alice Bob],
%w[Charlie Alice Bob],
%w[Bob Charlie Alice],
]
expect(described_class.run(votes, options_2)[:winning_candidate]).to eq(
{ digest: "Bob", html: "Bob" },
)
end
it "handles a tie" do
votes = [
%w[Alice Bob Charlie Dave],
%w[Bob Charlie Dave Alice],
%w[Charlie Dave Alice Bob],
%w[Dave Alice Bob Charlie],
%w[Bob Dave Charlie Alice],
%w[Dave Charlie Bob Alice],
]
expect(described_class.run(votes, options_3)[:tied_candidates]).to eq(
[{ digest: "Bob", html: "Bob" }, { digest: "Dave", html: "Dave" }],
)
end
it "handles multiple rounds of elimination and tracks round activity" do
votes = [
%w[Alice Bob Charlie Dave],
%w[Bob Charlie Dave Alice],
%w[Charlie Dave Alice Bob],
%w[Dave Alice Bob Charlie],
%w[Bob Dave Charlie Alice],
%w[Dave Charlie Bob Alice],
]
expect(described_class.run(votes, options_3)[:round_activity].length).to eq(2)
end
it "handles a tie after an elimination" do
votes = [%w[Dave Alice], %w[Bob Dave]]
expect(described_class.run(votes, options_3)[:tied_candidates]).to eq(
[{ digest: "Dave", html: "Dave" }, { digest: "Bob", html: "Bob" }],
)
end
it "handles a complex multi-round tie" do
votes = [
%w[Belle-lettres Thriller Non-fiction Sci-fi Mystery Comedy Historical Fantasy],
%w[Mystery Fantasy Belle-lettres Sci-fi Non-fiction Historical Thriller Comedy],
%w[Mystery Thriller Belle-lettres Sci-fi Comedy Non-fiction Fantasy Historical],
%w[Mystery Sci-fi Fantasy Thriller Non-fiction Belle-lettres Historical Comedy],
%w[Mystery Thriller Non-fiction Sci-fi Comedy Historical Belle-lettres Fantasy],
%w[Fantasy Non-fiction Mystery Sci-fi Thriller Historical Belle-lettres Comedy],
%w[Fantasy Mystery Historical Thriller Sci-fi Non-fiction Comedy Belle-lettres],
%w[Thriller Mystery Fantasy Non-fiction Sci-fi Historical Comedy Belle-lettres],
%w[Mystery Fantasy Historical Thriller Non-fiction Comedy Sci-fi Belle-lettres],
%w[Fantasy Sci-fi Thriller Mystery Non-fiction Comedy Historical Belle-lettres],
%w[Fantasy Sci-fi Historical Non-fiction Comedy],
%w[Fantasy Sci-fi Mystery Comedy Thriller Non-fiction Historical],
%w[Fantasy Mystery Historical Non-fiction Sci-fi Comedy],
%w[Fantasy Sci-fi Mystery Comedy Thriller Historical Non-fiction],
%w[Comedy Historical Fantasy Sci-fi Mystery],
%w[Sci-fi Thriller Mystery Non-fiction Comedy Fantasy],
]
outcome = described_class.run(votes, options_4)
expect(outcome[:tied_candidates]).to eq(
[{ digest: "Mystery", html: "Mystery" }, { digest: "Fantasy", html: "Fantasy" }],
)
expect(outcome[:round_activity].length).to eq(3)
end
end