Follow the Brass

spec/production_readiness_gate_spec.rb

95 lines · ruby

Project files
# frozen_string_literal: true

require "caliber_specification"
require "cartridge_case"
require "production_readiness_gate"

RSpec.describe ProductionReadinessGate do
  subject(:gate) { described_class.new(caliber_specification: specification) }

  let(:specification) do
    CaliberSpecification.new(caliber: "5.56", maximum_case_length: 1.760)
  end

  it "admits a case when all six readiness facts hold" do
    admission = gate.assess(cartridge_case)

    expect(admission).to be_admitted
    expect(admission.reasons).to be_empty
  end

  {
    clean: [false, :dirty],
    primer_pocket_clear: [false, :primer_pocket_obstructed],
    primer_pocket_prepared: [false, :primer_pocket_unprepared],
    length: [1.761, :over_maximum_length],
    defects: [["split neck"], :defects_present]
  }.each do |fact, (value, reason)|
    it "rejects a case when #{fact} fails" do
      admission = gate.assess(cartridge_case(fact => value))

      expect(admission).to be_rejected
      expect(admission.reasons).to eq([reason])
    end
  end

  it "rejects an unsized case even when every other fact holds" do
    admission = gate.assess(cartridge_case(sized: false))

    expect(admission).to be_rejected
    expect(admission.reasons).to eq([:unsized])
  end

  it "reports every failed fact in one admission result" do
    admission = gate.assess(cartridge_case(clean: false, sized: false))

    expect(admission.reasons).to contain_exactly(:dirty, :unsized)
  end

  it "rejects a case whose readiness facts were never established" do
    admission = gate.assess(CartridgeCase.new(caliber: "5.56"))

    expect(admission).to be_rejected
    expect(admission.reasons).to contain_exactly(
      :dirty, :primer_pocket_obstructed, :primer_pocket_unprepared,
      :unsized, :over_maximum_length, :defects_present
    )
  end

  it "rejects a case whose caliber does not match the specification" do
    admission = gate.assess(cartridge_case(caliber: "9mm"))

    expect(admission).to be_rejected
    expect(admission.reasons).to eq([:wrong_caliber])
  end

  it "consults the injected specification rather than a built-in limit" do
    tighter = CaliberSpecification.new(caliber: "5.56", maximum_case_length: 1.750)
    tighter_gate = described_class.new(caliber_specification: tighter)

    admission = tighter_gate.assess(cartridge_case(length: 1.755))

    expect(admission).to be_rejected
    expect(admission.reasons).to eq([:over_maximum_length])
  end

  it "returns frozen reasons without freezing the caller's collections" do
    defects = ["split neck"]

    admission = gate.assess(cartridge_case(defects: defects))

    expect(admission.reasons).to be_frozen
    expect(defects).not_to be_frozen
  end

  def cartridge_case(overrides = {})
    CartridgeCase.new(**readiness_facts.merge(overrides))
  end

  def readiness_facts
    {
      caliber: "5.56", clean: true, primer_pocket_clear: true,
      primer_pocket_prepared: true, sized: true, length: 1.750, defects: []
    }
  end
end

Read along in the manual: The Reloading Lab · Download the project (zip)