notices_controller_spec.rb 4.37 KB
require 'spec_helper'

describe NoticesController do
  it_requires_authentication :for => { :locate => :get }

  let(:notice) { Fabricate(:notice) }
  let(:xml) { Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read }
  let(:app) { Fabricate(:app) }
  let(:error_report) { mock(:valid? => true, :generate_notice! => true, :notice => notice) }

  context 'notices API' do
    before do
      ErrorReport.should_receive(:new).with(xml).and_return(error_report)
    end

    context "with xml pass in raw_port" do
      before do
        request.should_receive(:raw_post).and_return(xml)
        post :create, :format => :xml
      end

      it "generates a notice from raw xml [POST]" do
        response.should be_success
        # Same RegExp from Airbrake::Sender#send_to_airbrake (https://github.com/airbrake/airbrake/blob/master/lib/airbrake/sender.rb#L53)
        # Inspired by https://github.com/airbrake/airbrake/blob/master/test/sender_test.rb
        response.body.should match(%r{<id[^>]*>#{notice.id}</id>})
        response.body.should match(%r{<url[^>]*>(.+)#{locate_path(notice.id)}</url>})
      end

      it "should transform xml <va> tags to hashes correctly" do
        pending # TODO, need to be test on ErrorReport model
        # XML: <var key="SCRIPT_NAME"/>
        notice.env_vars.should have_key('SCRIPT_NAME')
        notice.env_vars['SCRIPT_NAME'].should be_nil # blank ends up nil

        # XML representation:
        # <var key="rack.session.options">
        #   <var key="secure">false</var>
        #   <var key="httponly">true</var>
        #   <var key="path">/</var>
        #   <var key="expire_after"/>
        #   <var key="domain"/>
        #   <var key="id"/>
        # </var>
        expected = {
          'secure'        => 'false',
          'httponly'      => 'true',
          'path'          => '/',
          'expire_after'  => nil,
          'domain'        => nil,
          'id'            => nil
        }
        notice.env_vars.should have_key('rack_session_options')
        notice.env_vars['rack_session_options'].should eql(expected)
      end
    end

    it "generates a notice from xml in a data param [POST]" do
      post :create, :data => xml, :format => :xml
      response.should be_success
      # Same RegExp from Airbrake::Sender#send_to_airbrake (https://github.com/airbrake/airbrake/blob/master/lib/airbrake/sender.rb#L53)
      # Inspired by https://github.com/airbrake/airbrake/blob/master/test/sender_test.rb
      response.body.should match(%r{<id[^>]*>#{notice.id}</id>})
      response.body.should match(%r{<url[^>]*>(.+)#{locate_path(notice.id)}</url>})
    end

    it "generates a notice from xml [GET]" do
      get :create, :data => xml, :format => :xml
      response.should be_success
      response.body.should match(%r{<id[^>]*>#{notice.id}</id>})
      response.body.should match(%r{<url[^>]*>(.+)#{locate_path(notice.id)}</url>})
    end
    context "with an invalid API_KEY" do
      let(:error_report) { mock(:valid? => false) }
      it 'return 422' do
        post :create, :format => :xml, :data => xml
        expect(response.status).to eq 422
      end
    end

    # Not relevant here, Nee to be test on App.report_error! test
    it "sends a notification email", :pending => true do
      App.should_receive(:report_error!).with(xml).and_return(notice)
      request.should_receive(:raw_post).and_return(xml)
      post :create, :format => :xml
      response.should be_success
      response.body.should match(%r{<id[^>]*>#{notice.id}</id>})
      response.body.should match(%r{<url[^>]*>(.+)#{locate_path(notice.id)}</url>})
      email = ActionMailer::Base.deliveries.last
      email.to.should include(app.watchers.first.email)
      email.subject.should include(notice.message.truncate(50))
      email.subject.should include("[#{app.name}]")
      email.subject.should include("[#{notice.environment_name}]")
    end
  end

  describe "GET /locate/:id" do
    context 'when logged in as an admin' do
      before(:each) do
        @user = Fabricate(:admin)
        sign_in @user
      end

      it "should locate notice and redirect to problem" do
        problem = Fabricate(:problem, :app => app, :environment => "production")
        notice = Fabricate(:notice, :err => Fabricate(:err, :problem => problem))
        get :locate, :id => notice.id
        response.should redirect_to(app_problem_path(problem.app, problem))
      end
    end
  end

end