Skip to content

Commit de80577

Browse files
authored
Add comprehensive request specs for InspectionsController with enhanced coverage and error handling (#222)
1 parent 16aea71 commit de80577

File tree

1 file changed

+292
-0
lines changed

1 file changed

+292
-0
lines changed

spec/requests/inspections/inspections_spec.rb

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,19 @@ def mock_failing_update(error_messages = ["Update error"])
116116
end
117117
end
118118

119+
describe "assessments disabled" do
120+
before do
121+
allow(ENV).to receive(:[]).and_call_original
122+
allow(ENV).to receive(:[]).with("HAS_ASSESSMENTS").and_return("false")
123+
login_as(user)
124+
end
125+
126+
it "returns 404 when assessments are disabled" do
127+
get "/inspections"
128+
expect(response).to have_http_status(:not_found)
129+
end
130+
end
131+
119132
describe "when logged in" do
120133
before { login_as(user) }
121134

@@ -166,6 +179,22 @@ def mock_failing_update(error_messages = ["Update error"])
166179
# Verify that the Rails path helper generates the expected URL
167180
expect(inspection_path(inspection, format: :pdf)).to eq("/inspections/#{inspection.id}.pdf")
168181
end
182+
183+
context "JSON format" do
184+
it "returns inspection data as JSON using InspectionBlueprint" do
185+
# Don't mock - let InspectionBlueprint actually render
186+
get "/inspections/#{inspection.id}.json"
187+
188+
expect(response).to have_http_status(:success)
189+
expect(response.content_type).to include("application/json")
190+
191+
json = JSON.parse(response.body)
192+
# id is excluded from public API, check other fields
193+
expect(json["inspection_date"]).to be_present
194+
expect(json["complete"]).to be false
195+
expect(json["passed"]).to eq(inspection.passed)
196+
end
197+
end
169198
end
170199

171200
describe "POST /create" do
@@ -273,6 +302,29 @@ def mock_failing_update(error_messages = ["Update error"])
273302
expect(flash[:alert]).to match(/invalid.*unit/i)
274303
end
275304

305+
context "with image processing error" do
306+
before do
307+
# Simulate image processing error by stubbing process_image_params
308+
allow_any_instance_of(InspectionsController).to receive(:process_image_params) do |controller, params, *args|
309+
controller.instance_variable_set(:@image_processing_error, StandardError.new("Image processing failed"))
310+
params
311+
end
312+
end
313+
314+
it "handles image processing errors gracefully" do
315+
patch "/inspections/#{inspection.id}", params: {
316+
inspection: {
317+
risk_assessment: "Test assessment",
318+
photo_1: fixture_file_upload("spec/fixtures/files/test_image.jpg", "image/jpeg")
319+
}
320+
}
321+
322+
expect(response).to have_http_status(:unprocessable_content)
323+
expect(flash[:alert]).to eq("Image processing failed")
324+
expect(response).to render_template(:edit)
325+
end
326+
end
327+
276328
%w[json turbo_stream].each do |format|
277329
context "#{format} format" do
278330
let(:headers) do
@@ -361,12 +413,18 @@ def mock_failing_update(error_messages = ["Update error"])
361413

362414
inspection.reload
363415
expect(inspection.unit).to eq(unit1)
416+
417+
# Verify event logging
418+
event = Event.for_resource(inspection).last
419+
expect(event.action).to eq("unit_changed")
420+
expect(event.details).to include(unit1.name)
364421
end
365422

366423
it "handles invalid unit_id" do
367424
patch "/inspections/#{inspection.id}/update_unit", params: {unit_id: "invalid"}
368425
expect_redirect_with_alert(select_unit_inspection_path(inspection), /invalid.*unit/i)
369426
end
427+
370428
end
371429
end
372430

@@ -434,6 +492,240 @@ def mock_failing_update(error_messages = ["Update error"])
434492
expect(response).to have_http_status(:success)
435493
end
436494
end
495+
496+
describe "HEAD requests" do
497+
let(:inspection) { create(:inspection, user: user, unit: unit) }
498+
499+
it "returns 200 OK for HEAD request" do
500+
head "/inspections/#{inspection.id}"
501+
expect(response).to have_http_status(:ok)
502+
expect(response.body).to be_empty
503+
end
504+
end
505+
506+
describe "GET /log" do
507+
let(:inspection) { create(:inspection, user: user, unit: unit) }
508+
509+
before do
510+
# Create some events for the inspection
511+
Event.log(
512+
user: user,
513+
action: "created",
514+
resource: inspection,
515+
details: "Inspection created"
516+
)
517+
Event.log(
518+
user: user,
519+
action: "updated",
520+
resource: inspection,
521+
details: "Inspection updated"
522+
)
523+
end
524+
525+
it "displays inspection event log" do
526+
get "/inspections/#{inspection.id}/log"
527+
528+
expect(response).to have_http_status(:success)
529+
expect(assigns(:events)).to be_present
530+
expect(assigns(:events).count).to eq(2)
531+
expect(assigns(:title)).to include(inspection.id)
532+
end
533+
end
534+
535+
536+
describe "prefill functionality" do
537+
let(:previous_inspection) do
538+
create(:inspection, :completed,
539+
user: user,
540+
unit: unit,
541+
risk_assessment: "Previous risk")
542+
end
543+
544+
let(:new_inspection) do
545+
create(:inspection, user: user, unit: unit)
546+
end
547+
548+
before do
549+
# Set up previous inspection on unit
550+
allow_any_instance_of(Unit).to receive(:last_inspection).and_return(previous_inspection)
551+
end
552+
553+
describe "translate_field_name" do
554+
it "translates field names for prefill display" do
555+
get "/inspections/#{new_inspection.id}/edit", params: { tab: "inspection" }
556+
557+
expect(response).to have_http_status(:success)
558+
# The prefilled_fields will be set if there are fields to prefill
559+
expect(assigns(:prefilled_fields)).to be_an(Array)
560+
end
561+
562+
it "handles pass/fail field translation for assessments" do
563+
# Update previous inspection's assessment with data
564+
previous_inspection.user_height_assessment.update(
565+
containing_wall_height: 100,
566+
containing_wall_height_comment: "Test comment"
567+
)
568+
569+
get "/inspections/#{new_inspection.id}/edit", params: { tab: "user_height" }
570+
571+
expect(response).to have_http_status(:success)
572+
expect(assigns(:previous_inspection)).to eq(previous_inspection)
573+
# Prefilled fields would include the ground_clearance fields
574+
expect(assigns(:prefilled_fields)).to be_an(Array)
575+
end
576+
end
577+
578+
describe "get_prefill_objects for results tab" do
579+
it "handles results tab prefill correctly" do
580+
previous_inspection.update(
581+
passed: true,
582+
risk_assessment: "Test risk"
583+
)
584+
585+
get "/inspections/#{new_inspection.id}/edit", params: {tab: "results"}
586+
587+
expect(assigns(:previous_inspection)).to eq(previous_inspection)
588+
# Results tab should only prefill specific fields
589+
expect(response).to have_http_status(:success)
590+
end
591+
end
592+
end
593+
594+
describe "validate_tab_parameter" do
595+
let(:inspection) { create(:inspection, user: user, unit: unit) }
596+
597+
it "redirects with invalid tab parameter" do
598+
get "/inspections/#{inspection.id}/edit", params: {tab: "invalid_tab"}
599+
600+
expect(response).to redirect_to(edit_inspection_path(inspection))
601+
expect(flash[:alert]).to be_present
602+
end
603+
604+
it "allows valid tab parameter" do
605+
get "/inspections/#{inspection.id}/edit", params: {tab: "user_height"}
606+
607+
expect(response).to have_http_status(:success)
608+
end
609+
end
610+
611+
describe "log_inspection_event error handling" do
612+
it "handles logging errors gracefully" do
613+
# Mock Event.log to raise an error
614+
allow(Event).to receive(:log).and_raise(StandardError, "Database error")
615+
allow(Rails.logger).to receive(:error)
616+
617+
# This should not raise an error
618+
post "/inspections", params: {
619+
inspection: {unit_id: unit.id}
620+
}
621+
622+
expect(Rails.logger).to have_received(:error).with(/Failed to log inspection event/)
623+
# Request should still succeed
624+
expect(response).to have_http_status(:redirect)
625+
end
626+
627+
it "logs system events without specific inspection" do
628+
allow(Event).to receive(:log_system_event)
629+
630+
# CSV export logs a system event
631+
get "/inspections.csv"
632+
633+
expect(Event).to have_received(:log_system_event).with(
634+
hash_including(
635+
user: user,
636+
action: "exported",
637+
metadata: hash_including(resource_type: "Inspection")
638+
)
639+
)
640+
end
641+
end
642+
643+
describe "calculate_changes" do
644+
let(:inspection) { create(:inspection, user: user, unit: unit) }
645+
646+
it "tracks changes correctly in update" do
647+
# Store original values
648+
original_passed = inspection.passed
649+
original_risk = inspection.risk_assessment
650+
651+
patch "/inspections/#{inspection.id}", params: {
652+
inspection: {
653+
passed: !original_passed,
654+
risk_assessment: "New risk"
655+
}
656+
}
657+
658+
expect(response).to redirect_to(inspection_path(inspection))
659+
660+
# Check the event was logged with changed data
661+
event = Event.for_resource(inspection).last
662+
expect(event.action).to eq("updated")
663+
expect(event.changed_data).to be_present
664+
expect(event.changed_data["risk_assessment"]).to be_present
665+
expect(event.changed_data["risk_assessment"]["to"]).to eq("New risk")
666+
end
667+
668+
it "ignores unchanged values" do
669+
original_value = inspection.risk_assessment
670+
671+
patch "/inspections/#{inspection.id}", params: {
672+
inspection: {
673+
risk_assessment: "New risk",
674+
passed: inspection.passed # Same value
675+
}
676+
}
677+
678+
expect(response).to redirect_to(inspection_path(inspection))
679+
680+
# Check that only changed fields are in changed_data
681+
event = Event.for_resource(inspection).last
682+
expect(event.action).to eq("updated")
683+
expect(event.changed_data.keys).to include("risk_assessment")
684+
expect(event.changed_data.keys).not_to include("passed")
685+
end
686+
end
687+
688+
describe "validate_inspection_completability" do
689+
context "with invalid complete inspection" do
690+
let(:invalid_complete_inspection) do
691+
# Create an inspection marked as complete but with missing data
692+
inspection = create(:inspection, user: user, unit: unit)
693+
inspection.update_column(:complete_date, Time.current) # Bypass validations
694+
inspection
695+
end
696+
697+
before do
698+
allow_any_instance_of(Inspection).to receive(:can_mark_complete?).and_return(false)
699+
allow_any_instance_of(Inspection).to receive(:completion_errors).and_return(
700+
["Missing inspection date", "Unit not specified"]
701+
)
702+
end
703+
704+
context "in development/test environment" do
705+
before { allow(Rails.env).to receive(:local?).and_return(true) }
706+
707+
it "raises error for invalid completion state" do
708+
expect {
709+
get "/inspections/#{invalid_complete_inspection.id}"
710+
}.to raise_error(StandardError, /DATA INTEGRITY ERROR/)
711+
end
712+
end
713+
714+
context "in production environment" do
715+
before do
716+
allow(Rails.env).to receive(:local?).and_return(false)
717+
allow(Rails.logger).to receive(:error)
718+
end
719+
720+
it "logs error but continues" do
721+
get "/inspections/#{invalid_complete_inspection.id}"
722+
723+
expect(Rails.logger).to have_received(:error).with(/DATA INTEGRITY ERROR/)
724+
expect(response).to have_http_status(:success)
725+
end
726+
end
727+
end
728+
end
437729
end
438730

439731
describe "public routes (no authentication required)" do

0 commit comments

Comments
 (0)