spec/lib/gdk/command/doctor_spec.rb (189 lines of code) (raw):
# frozen_string_literal: true
require 'stringio'
RSpec.describe GDK::Command::Doctor, :hide_output do
# rubocop:todo RSpec/VerifiedDoubles
let(:successful_diagnostic) do
double(GDK::Diagnostic, unexpected_error: nil, success?: true, correctable?: false, correct!: nil, message: nil)
end
let(:failing_diagnostic) do
double(GDK::Diagnostic, unexpected_error: nil, success?: false, correctable?: false, correct!: nil, message: 'check failed')
end
let(:correctable_diagnostic) do
double(GDK::Diagnostic, title: 'Correctable Diagnostic', unexpected_error: nil, success?: false, correctable?: true, correct!: nil, message: 'check failed')
end
let(:uncorrectable_diagnostic) do
double(GDK::Diagnostic, title: 'Uncorrectable Diagnostic', unexpected_error: nil, success?: false, correctable?: false, correct!: nil, message: 'check failed')
end
let(:shellout) { double(GDK::Shellout, run: nil) }
# rubocop:enable RSpec/VerifiedDoubles
let(:diagnostics) { [] }
let(:args) { [] }
let(:warning_message) do
<<~WARNING
================================================================================
Please note these warning only exist for debugging purposes and can
help you when you encounter issues with GDK.
If your GDK is working fine, you can safely ignore them. Thanks!
================================================================================
WARNING
end
subject { described_class.new(diagnostics: diagnostics) }
before do
allow(Runit).to receive(:start).with('postgresql', quiet: true).and_return(true)
gdk_root_stub = double('GDK_ROOT') # rubocop:todo RSpec/VerifiedDoubles
procfile_stub = double('Procfile', exist?: true) # rubocop:todo RSpec/VerifiedDoubles
allow(GDK).to receive(:root).and_return(gdk_root_stub)
allow(gdk_root_stub).to receive(:join).with('Procfile').and_return(procfile_stub)
allow_any_instance_of(GDK::Postgresql).to receive(:ready?).and_return(true)
end
it 'does not start necessary services' do
expect(Runit).not_to receive(:start).with('postgresql', quiet: true)
expect(subject.run).to be(true)
end
context 'when postgresql is not ready' do
before do
allow_any_instance_of(GDK::Postgresql)
.to receive(:ready?).with(try_times: 1, quiet: true).and_return(false)
end
it 'starts necessary services' do
expect(Runit).to receive(:start).with('postgresql', quiet: true)
expect_any_instance_of(GDK::Postgresql).to receive(:ready?)
.with(try_times: 20, interval: 0.5).and_return(true)
expect(subject.run).to be(true)
end
it 'fails if services cannot be started' do
expect(Runit).to receive(:start).with('postgresql', quiet: true)
expect_any_instance_of(GDK::Postgresql).to receive(:ready?)
.with(try_times: 20, interval: 0.5).and_return(false)
expect(subject.run).to be(false)
end
end
context 'with passing diagnostics' do
let(:diagnostics) { [successful_diagnostic, successful_diagnostic] }
it 'runs all diagnosis' do
expect(successful_diagnostic).to receive(:success?).twice
expect(subject.run).to be(true)
end
it 'does not check if successful diagnostics are correctable' do
expect(successful_diagnostic).not_to receive(:correctable?)
expect(subject.run).to be(true)
end
it 'prints GDK is ready.' do
expect(GDK::Output).to receive(:success).with('Your GDK is healthy.')
expect(subject.run).to be(true)
end
end
context 'with failing diagnostics' do
let(:diagnostics) { [failing_diagnostic, failing_diagnostic] }
it 'runs all diagnosis' do
expect(failing_diagnostic).to receive(:success?).twice
expect(subject.run).to be(false)
end
it 'checks if failed diagnostics are correctable' do
expect(failing_diagnostic).to receive(:correctable?).twice
expect(subject.run).to be(false)
end
it 'does not attempt to correct failed diagnostics' do
expect(failing_diagnostic).not_to receive(:correct!)
expect(subject.run).to be(false)
end
it 'prints a warning' do
expect(GDK::Output).to receive(:puts).with("\n").ordered
expect(GDK::Output).to receive(:warn).with('Your GDK may need attention.').ordered
expect(GDK::Output).to receive(:puts).with('check failed').ordered.twice
expect(subject.run).to be(false)
end
end
context 'with partial failing diagnostics' do
let(:diagnostics) { [failing_diagnostic, successful_diagnostic, failing_diagnostic] }
it 'runs all diagnosis' do
expect(failing_diagnostic).to receive(:success?).twice
expect(successful_diagnostic).to receive(:success?).once
expect(subject.run).to be(false)
end
it 'checks if failed diagnostics are correctable' do
expect(failing_diagnostic).to receive(:correctable?).twice
expect(subject.run).to be(false)
end
it 'does not attempt to correct failed diagnostics' do
expect(failing_diagnostic).not_to receive(:correct!)
expect(subject.run).to be(false)
end
it 'does not check if successful diagnostics are correctable' do
expect(successful_diagnostic).not_to receive(:correctable?)
expect(subject.run).to be(false)
end
it 'prints a message from failed diagnostics' do
expect(failing_diagnostic).to receive(:message).twice
expect(GDK::Output).to receive(:puts).with("\n").ordered
expect(GDK::Output).to receive(:warn).with('Your GDK may need attention.').ordered
expect(GDK::Output).to receive(:puts).with('check failed').ordered.twice
expect(subject.run).to be(false)
end
it 'does not print a message from successful diagnostics' do
expect(successful_diagnostic).not_to receive(:message)
expect(subject.run).to be(false)
end
end
context 'with diagnostic that raises an unexpected error' do
let(:diagnostics) { [successful_diagnostic, failing_diagnostic] }
it 'prints a message from failed diagnostics' do
expect(failing_diagnostic).to receive(:success?).and_raise(StandardError, 'some error occurred')
expect(GDK::Output).to receive(:puts).with("\n").ordered
expect(GDK::Output).to receive(:warn).with('Your GDK may need attention.').ordered
expect(GDK::Output).to receive(:puts).with('check failed').ordered.once
expect(failing_diagnostic).to receive(:unexpected_error=).with(an_instance_of(StandardError))
expect(subject.run).to be(2)
end
it 'returns code 2' do
expect(failing_diagnostic).to receive(:success?).and_raise(StandardError, 'some error occurred')
expect(failing_diagnostic).to receive(:unexpected_error=).with(an_instance_of(StandardError))
expect(subject.run).to be(2)
end
end
context "when passing '--correct' flag" do
let(:args) { ['--correct'] }
context 'with correctable diagnostics' do
let(:diagnostics) { [correctable_diagnostic, correctable_diagnostic] }
it 'runs all diagnosis' do
expect(correctable_diagnostic).to receive(:success?).twice
expect(subject.run(args)).to be(false)
end
it 'prints a message from failed diagnostics' do
expect(correctable_diagnostic).to receive(:message).twice
expect(GDK::Output).to receive(:puts).with("check failed").twice
expect(subject.run(args)).to be(false)
end
it 'corrects the diagnostics' do
expect(GDK::Output).to receive(:print).with("Performing correction for 'Correctable Diagnostic' ")
expect(correctable_diagnostic).to receive(:correct!).twice
expect(subject.run(args)).to be(false)
end
context 'that raise an error' do
before do
allow(correctable_diagnostic).to receive(:correct!).and_raise(StandardError, 'error during correction')
end
it 'prints an error message' do
expect(GDK::Output).to receive(:error).with('error during correction', StandardError)
expect(subject.run(args)).to be(2)
end
it('returns code 2') do
expect(subject.run(args)).to be(2)
end
end
end
context 'with uncorrectable diagnostics' do
let(:diagnostics) { [uncorrectable_diagnostic, uncorrectable_diagnostic] }
it 'runs all diagnosis' do
expect(uncorrectable_diagnostic).to receive(:success?).twice
expect(uncorrectable_diagnostic).to receive(:correctable?).twice
expect(subject.run(args)).to be(false)
end
it 'does not attempt to correct the diagnostics' do
expect(uncorrectable_diagnostic).not_to receive(:correct!)
expect(subject.run(args)).to be(false)
end
it 'warns of no problems to autocorrect' do
expect(GDK::Output).to receive(:warn).with('No problems to autocorrect.')
expect(subject.run(args)).to be(false)
end
end
end
end