# frozen_string_literal: true RSpec.describe GameOfLife::Cell do subject(:living_cell) { described_class.new(x: nil, y: nil, alive: true) } subject(:dead_cell) { described_class.new(x: nil, y: nil, alive: false) } describe "#to_s" do context "when alive" do it "returns LIVE_CELL representation" do stub_const("LIVE_CELL", "X") expect(living_cell.to_s).to eq "X" end end context "when dead" do it "returns DEAD_CELL representation" do stub_const("DEAD_CELL", ".") expect(dead_cell.to_s).to eq "." end end end describe "#evolve!" do it "calls #living_neighbors with param: neighbors" do neighbors = [1, 2, 3, 4, 5] expect(living_cell).to receive(:living_neighbors).with(neighbors) living_cell.evolve!(neighbors) end context "when dead" do it "stays dead" do expect(dead_cell).to receive(:living_neighbors).with([]).and_return 0 next_generation = dead_cell.evolve!([]) expect(next_generation.object_id).to eq dead_cell.object_id expect(next_generation.dead?).to be_truthy end it "becomes alive when having 3 living neighbors" do expect(dead_cell).to receive(:living_neighbors).with([]).and_return 3 next_generation = dead_cell.evolve!([]) expect(next_generation.object_id).not_to eq dead_cell.object_id expect(next_generation.alive?).to be_truthy end end context "when alive" do it "survives when having 2 neighbors" do expect(living_cell).to receive(:living_neighbors).with([]).and_return 2 next_generation = living_cell.evolve!([]) expect(next_generation.object_id).to eq living_cell.object_id expect(next_generation.alive?).to be_truthy end it "survives when having 3 neighbors" do expect(living_cell).to receive(:living_neighbors).with([]).and_return 3 next_generation = living_cell.evolve!([]) expect(next_generation.object_id).to eq living_cell.object_id expect(next_generation.alive?).to be_truthy end it "dies when having less than 2 neighbors" do expect(living_cell).to receive(:living_neighbors).with([]).and_return 1 next_generation = living_cell.evolve!([]) expect(next_generation.object_id).not_to eq living_cell.object_id expect(next_generation.dead?).to be_truthy end it "dies when having more than 3 neighbors" do expect(living_cell).to receive(:living_neighbors).with([]).and_return 4 next_generation = living_cell.evolve!([]) expect(next_generation).not_to eq living_cell expect(next_generation.dead?).to be_truthy end end end describe "#alive?" do it { expect(living_cell.alive?).to be_truthy } it { expect(dead_cell.alive?).to be_falsy } end describe "#dead?" do it { expect(living_cell.dead?).to be_falsy } it { expect(dead_cell.dead?).to be_truthy } end describe "#living_neighbors" do subject(:cell) { [living_cell, dead_cell].sample } let(:living_neighbors) { (0...rand(100)).map { described_class.new(x: nil, y: nil, alive: true) } } let(:dead_neighbors) { (0...rand(100)).map { described_class.new(x: nil, y: nil, alive: false) } } let(:neighbors) { (living_neighbors + dead_neighbors).shuffle } it "returns the count of living neighbors cells" do expect(cell.send(:living_neighbors, neighbors)).to eq living_neighbors.size end end describe "#repopulate!" do # evaluate subject to avoid multiple calls on first evaluation in the test subject!(:cell) { [dead_cell, living_cell].sample } it "returns living cell" do expect(described_class).to receive(:new).with(hash_including(alive: true)) cell.send(:repopulate!) end end describe "#survive!" do subject(:cell) { [dead_cell, living_cell].sample } it "returns self" do expect(cell.send(:survive!).object_id).to eq cell.object_id end end describe "#die!" do context "when dead" do subject(:cell) { dead_cell } it "returns self" do expect(cell.send(:die!).object_id).to eq cell.object_id end end context "when alive" do # evaluate subject to avoid multiple calls on first evaluation in the test subject!(:cell) { living_cell } it "returns new dead cell" do expect(described_class).to receive(:new).with(hash_including(alive: false)) cell.send(:die!) end end end end