require_relative "../spec_helper" describe "exception_page plugin" do def ep_app(&block) app(:exception_page) do |r| raise "foo" rescue block ? instance_exec($!, &block) : exception_page($!) end end def req(path = '/', headers={}) if path.is_a?(Hash) super(path.merge('rack.input'=>StringIO.new)) else super(path, headers.merge('rack.input'=>StringIO.new)) end end it "returns HTML page with exception information if text/html is accepted" do ep_app s, h, body = req('HTTP_ACCEPT'=>'text/html') s.must_equal 200 h['Content-Type'].must_equal 'text/html' body = body.join body.must_include "RuntimeError at /" body.must_include "<h1>RuntimeError at /</h1>" body.must_include "<h2>foo</h2>" body.must_include __FILE__ body.must_include "No GET data" body.must_include "No POST data" body.must_include "No cookie data" body.must_include "Rack ENV" body.must_include "HTTP_ACCEPT" body.must_include "text/html" body.must_include "table td.code" body.must_include "function toggle()" body.wont_include "\"/exception_page.css\"" body.wont_include "\"/exception_page.js\"" size = body.size ep_app{|e| exception_page(e, :context=>10)} body('HTTP_ACCEPT'=>'text/html').size.must_be :>, size ep_app{|e| exception_page(e, :assets=>true, :context=>0)} body = body('HTTP_ACCEPT'=>'text/html') body.wont_include "table td.code" body.wont_include "function toggle()" body.must_include "\"/exception_page.css\"" body.must_include "\"/exception_page.js\"" ep_app{|e| exception_page(e, :assets=>"/static", :context=>0)} body = body('HTTP_ACCEPT'=>'text/html') body.wont_include "table td.code" body.wont_include "function toggle()" body.must_include "\"/static/exception_page.css\"" body.must_include "\"/static/exception_page.js\"" ep_app{|e| exception_page(e, :css_file=>"/foo.css", :context=>0)} body = body('HTTP_ACCEPT'=>'text/html') body.wont_include "table td.code" body.must_include "function toggle()" body.must_include "\"/foo.css\"" ep_app{|e| exception_page(e, :js_file=>"/foo.js", :context=>0)} body = body('HTTP_ACCEPT'=>'text/html') body.must_include "table td.code" body.wont_include "function toggle()" body.must_include "\"/foo.js\"" ep_app{|e| exception_page(e, :assets=>false, :context=>0)} body = body('HTTP_ACCEPT'=>'text/html') body.wont_include "table td.code" body.wont_include "function toggle()" body.wont_include "\"/exception_page.css\"" body.wont_include "\"/exception_page.js\"" ep_app{|e| exception_page(e, :assets=>false, :css_file=>"/foo.css", :context=>0)} body = body('HTTP_ACCEPT'=>'text/html') body.wont_include "table td.code" body.wont_include "function toggle()" body.must_include "\"/foo.css\"" ep_app{|e| exception_page(e, :assets=>false, :js_file=>"/foo.js", :context=>0)} body = body('HTTP_ACCEPT'=>'text/html') body.wont_include "table td.code" body.wont_include "function toggle()" body.must_include "\"/foo.js\"" ep_app{|e| exception_page(e, :css_file=>false, :context=>0)} body = body('HTTP_ACCEPT'=>'text/html') body.wont_include "table td.code" body.must_include "function toggle()" body.wont_include "\"/exception_page.css\"" body.wont_include "\"/exception_page.js\"" ep_app{|e| exception_page(e, :js_file=>false, :context=>0)} body = body('HTTP_ACCEPT'=>'text/html') body.must_include "table td.code" body.wont_include "function toggle()" body.wont_include "\"/exception_page.css\"" body.wont_include "\"/exception_page.js\"" end it "returns plain text page with exception information if text/html is not accepted" do ep_app s, h, body = req s.must_equal 200 h['Content-Type'].must_equal 'text/plain' body = body.join first, *bt = body.split("\n") first.must_equal "RuntimeError: foo" bt.first.must_include __FILE__ end it "returns JSON with exception information if :json information is used" do ep_app{|e| exception_page(e, :json=>true)} @app.plugin :json s, h, body = req s.must_equal 200 h['Content-Type'].must_equal 'application/json' hash = JSON.parse(body.join) bt = hash["exception"].delete("backtrace") hash.must_equal("exception"=>{"class"=>"RuntimeError", "message"=>"foo"}) bt.must_be_kind_of Array bt.each{|line| line.must_be_kind_of String} end it "should handle backtrace lines in unexpected forms" do ep_app do |e| e.backtrace.first.upcase! e.backtrace[-1] = '' exception_page(e) end body = body('HTTP_ACCEPT'=>'text/html') body.must_include "RuntimeError: foo" body.must_include __FILE__ body.wont_include 'id="c0"' end it "should serve exception page assets" do app(:exception_page) do |r| r.exception_page_assets end s, h, b = req('/exception_page.css') s.must_equal 200 h['Content-Type'].must_equal 'text/css' b.join.must_equal Roda::RodaPlugins::ExceptionPage.css s, h, b = req('/exception_page.js') s.must_equal 200 h['Content-Type'].must_equal 'application/javascript' b.join.must_equal Roda::RodaPlugins::ExceptionPage.js end end