require 'rails_helper'

describe Api::TestCaseResultController, type: :controller do

  describe 'GET show' do

    let(:test_case_result) { FactoryGirl.create(:test_case_result) }

    it 'gracefully errors if the supplied test case does not exist' do
      get :show, id: 3838
      expect(response).to have_http_status 404
    end

    it 'gracefully errors if no id is supplied' do
      get :show, id: ''
      expect(response).to have_http_status 404
    end

    it 'returns the data if a valid id is supplied' do
      get :show, id: test_case_result.id
      expect(response).to have_http_status 200
      body = JSON.parse(response.body)
      expect(body.dig('id')).to eq(test_case_result.id)
      expect(body.dig('result')).to eq(test_case_result.result)
      expect(body.dig('exception_class')).to eq(test_case_result.exception_class)
    end
  end

  describe 'POST create' do
    let(:build) { FactoryGirl.create(:smoca_build) }
    let(:test_case) { FactoryGirl.create(:test_case) }

    it 'attaches result to existing test case' do
      expect(TestCaseResult.count).to eq(0)
      expect(build.test_case_results.count).to eq(0)

      post :create, id: build.id, name: test_case.name, result: 'success'
      body = JSON.parse(response.body)

      expect(TestCaseResult.count).to eq(1)
      expect(build.test_case_results.count).to eq(1)

      expect(response).to have_http_status(200)
      expect(body['id']).to eq(TestCaseResult.first.id)
      expect(build.test_case_results.first[:test_case_id]).to eq(test_case.id)
      expect(build.test_case_results.first[:result]).to eq('success')
    end

    it 'fails gracefully if no test case name was given' do
      post :create, id: build.id, result: 'failure'
      body = JSON.parse(response.body)

      expect(response).to have_http_status(400)
      expect(body).to have_key('error')
      expect(body['error']).to eq('Unable to create test case result. Must provide "name" of test case')
    end

    it 'fails gracefully if no result was given' do
      post :create, id: build.id, name: test_case.name
      body = JSON.parse(response.body)

      expect(response).to have_http_status(400)
      expect(body).to have_key('error')
      expect(body['error']).to eq('Unable to create test case result.')

      expect(body).to have_key('error_messages')
      expect(body['error_messages']).to have_key('result')
      expect(body['error_messages']['result']).to include("can't be blank")
    end

    it 'fails gracefully if build was not found' do
      fake_build_id = 99999
      expect(TestCaseResult.count).to eq(0)
      post :create, id: fake_build_id, name: test_case.name
      body = JSON.parse(response.body)

      expect(TestCaseResult.count).to eq(0)
      expect(response).to have_http_status(404)
      expect(body['error']).to eq("Unable to find build with id #{fake_build_id}")
    end

    it 'creates a test case and attaches if none exist' do
      test_case_name = 'My new test case'

      expect(TestCase.count).to eq(0)
      post :create, id: build.id, name: test_case_name, result: 'success'
      body = JSON.parse(response.body)

      expect(TestCase.count).to eq(1) # Count Increases

      # Test Case Exists
      test_case = TestCase.find_by(name: test_case_name)
      expect(test_case).not_to be_nil

      expect(body['test_case_id']).to eq(test_case.id) # Proper Test Case ID is returned
    end

    it 'can attach exception class and exception message' do
      exception_class   = 'Capybara::ElementNotFound'
      exception_message = 'Unable to find css class .my-test'

      expect(TestCaseResult.count).to eq(0)
      post :create, id: build.id, name: test_case.name, result: 'failure', exception_class: exception_class,
           exception_message: exception_message
      expect(response).to have_http_status 200
      expect(TestCaseResult.count).to eq(1)

      result = TestCaseResult.first
      expect(result[:exception_class]).to eq(exception_class)
      expect(result[:exception_message]).to eq(exception_message)
    end

    describe 'backtrace' do
      backtrace = "./spec/test_spec.rb:6:in `block (2 levels) in <top (required)>'"\
        "\\n./core/base/spec_helper.rb:127:in `block (2 levels) in <top (required)>'"

      it 'gracefully fails if backtrace is too long' do
        post :create, id: build.id, name: test_case.name, result: 'failure',
                      backtrace: (backtrace * 66000)
        expect(response).to have_http_status(400)
        body = JSON.parse(response.body)
        error = body.dig('error')
        error_messages = body.dig('error_messages')

        expect(error).to eq('Unable to create test case result.')
        expect(error_messages).to have_key('backtrace')
        expect(error_messages['backtrace']).to include('is too long (maximum is 65535 characters)')
      end
    end
  end
end
