Follow the Brass

spec/reloading_lab_spec.rb

122 lines · ruby

Project files
# frozen_string_literal: true

require "caliber_specification"
require "cartridge_case"
require "case_classifier"
require "fact_station"
require "final_inspection"
require "foreign_object"
require "press_recovery"
require "production_line"
require "production_readiness_gate"
require "production_run"
require "progressive_press"
require_relative "support/fakes/fake_fault_once_station"

RSpec.describe "The reloading lab" do
  subject(:result) do
    run.call(
      [ready_case, unsized, nine_millimeter, stripper_clip],
      provenance: provenance
    )
  end

  let(:charge) do
    FakeFaultOnceStation.new(
      name: "charge", fact: :charged, fault: :powder_hopper_empty
    )
  end
  let(:stations) do
    [
      FactStation.new(name: "prime", fact: :primed),
      charge,
      FactStation.new(name: "seat", fact: :seated),
      FactStation.new(name: "crimp", fact: :crimped)
    ]
  end
  let(:press) { ProgressivePress.new(stations: stations) }
  let(:line) do
    ProductionLine.new(
      press: press, recovery: PressRecovery.new(stations: stations)
    )
  end
  let(:run) do
    ProductionRun.new(
      classifier: CaseClassifier.new(expected_caliber: "5.56"),
      gate: readiness_gate,
      line: line,
      final_inspection: FinalInspection.new(
        required_facts: %i[primed charged seated crimped]
      )
    )
  end
  let(:readiness_gate) do
    ProductionReadinessGate.new(
      caliber_specification: CaliberSpecification.new(
        caliber: "5.56", maximum_case_length: 1.760
      )
    )
  end
  let(:ready_case) { cartridge_case }
  let(:unsized) { cartridge_case(sized: false) }
  let(:nine_millimeter) { CartridgeCase.new(caliber: "9mm") }
  let(:stripper_clip) { ForeignObject.new(description: "stripper clip") }
  let(:provenance) do
    {
      load_specification: "556-2026-001 v1",
      brass_lot: "LC-2026-A",
      component_lots: {
        primer: "P-77", powder: "H-4895-23", bullet: "B-62gr-9"
      }
    }
  end

  it "stops at the first station fault instead of silently retrying" do
    result

    expect(charge.attempts).to eq(1)
  end

  it "returns a halted result with the fault and a derived recovery plan" do
    expect(result).to have_attributes(
      halted?: true,
      faults: contain_exactly(
        have_attributes(
          station: "charge", status: :faulted, fault: :powder_hopper_empty
        )
      ),
      recovery_plan: contain_exactly(
        have_attributes(station: "charge", disposition: :resume, missing: [])
      )
    )
  end

  it "preserves the in-progress material and its established facts" do
    expect(result).to have_attributes(
      positions: include(
        have_attributes(
          station: have_attributes(name: "charge"),
          work: have_attributes(facts: { primed: true })
        )
      )
    )
  end

  it "preserves every exit decided before the production fault" do
    expect(result.rejected.map { |kase, _admission| kase }).to eq([unsized])
    expect(result.rejected.first.last.reasons).to eq([:unsized])
    expect(result.wrong_context).to eq([nine_millimeter])
    expect(result.foreign).to eq([stripper_clip])
  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)