Follow the Brass

spec/production_run_fault_spec.rb

92 lines · ruby

Project files
# frozen_string_literal: true

require "admission"
require "case_classifier"
require "classification"
require "final_inspection"
require "foreign_object"
require "press_recovery"
require "production_readiness_gate"
require "production_run"
require "progressive_press"
require "work_in_progress"

RSpec.describe ProductionRun, "when the press faults" do
  subject(:run) do
    described_class.new(
      classifier: classifier,
      gate: gate,
      line: line,
      final_inspection: final_inspection
    )
  end

  let(:classifier) { instance_double(CaseClassifier) }
  let(:gate) { instance_double(ProductionReadinessGate) }
  let(:press) { instance_double(ProgressivePress) }
  let(:recovery) { instance_double(PressRecovery) }
  let(:final_inspection) { instance_double(FinalInspection) }
  let(:line) { double("ProductionLine", press: press, recovery: recovery) }
  let(:ready_case) { double("ready case") }
  let(:wrong_context) { double("wrong-context case") }
  let(:foreign) { ForeignObject.new(description: "stripper clip") }
  let(:classification) do
    Classification.new(
      accepted: [ready_case], wrong_context: [wrong_context], foreign: [foreign]
    )
  end
  let(:fault) do
    PositionOutcome.new(
      station: "charge", status: :faulted, fault: :powder_hopper_empty
    )
  end
  let(:cycle_result) do
    CycleResult.new(advanced: false, outcomes: [fault], ejected: nil)
  end
  let(:station) { double("charge station", name: "charge") }
  let(:work) do
    WorkInProgress.new(cartridge_case: ready_case, facts: { primed: true })
  end
  let(:positions) { [PositionSnapshot.new(station: station, work: work)] }
  let(:recovery_plan) do
    [
      PositionAssessment.new(
        station: "charge", disposition: :resume, missing: []
      )
    ]
  end

  before do
    allow(classifier).to receive(:classify).and_return(classification)
    allow(gate).to receive(:assess).with(ready_case).and_return(
      Admission.new(reasons: [])
    )
    allow(press).to receive(:feed)
    allow(press).to receive(:cycle).and_return(cycle_result)
    allow(press).to receive(:positions).and_return(positions)
    allow(recovery).to receive(:assess).with(positions).and_return(recovery_plan)
  end

  it "returns the partial truth without asking final inspection to release it" do
    result = run.call([ready_case], provenance: {})

    expect(result).to have_attributes(
      halted?: true,
      faults: [fault],
      positions: positions,
      recovery_plan: recovery_plan,
      wrong_context: [wrong_context],
      foreign: [foreign],
      rejected: []
    )
  end

  it "commands one feed and one cycle before returning control" do
    expect(press).to receive(:feed).with(
      have_attributes(cartridge_case: ready_case)
    ).once
    expect(press).to receive(:cycle).once.and_return(cycle_result)

    run.call([ready_case], provenance: {})
  end
end

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