@@ -294,7 +294,7 @@ def initialize(message, original_exception = nil)
294294 let ( :request_env ) {
295295 Rack ::MockRequest . env_for ( "/__better_errors/#{ id } /variables" , input : StringIO . new ( JSON . dump ( request_body_data ) ) )
296296 }
297- let ( :request_body_data ) { { "index" : 0 } }
297+ let ( :request_body_data ) { { "index" => 0 } }
298298 let ( :json_body ) { JSON . parse ( body ) }
299299 let ( :id ) { 'abcdefg' }
300300
@@ -384,7 +384,131 @@ def initialize(message, original_exception = nil)
384384 end
385385
386386 context 'when the body csrfToken does not match the CSRF token cookie' do
387- let ( :request_body_data ) { { "index" : 0 , "csrfToken" : "csrfToken123" } }
387+ let ( :request_body_data ) { { "index" => 0 , "csrfToken" => "csrfToken123" } }
388+ before do
389+ request_env [ "HTTP_COOKIE" ] = "BetterErrors-CSRF-Token=csrfToken456"
390+ end
391+
392+ it 'returns a JSON error' do
393+ expect ( json_body ) . to match (
394+ 'error' => 'Invalid CSRF Token' ,
395+ 'explanation' => /session might have been cleared/ ,
396+ )
397+ end
398+ end
399+
400+ context 'when there is no CSRF token in the request' do
401+ it 'returns a JSON error' do
402+ expect ( json_body ) . to match (
403+ 'error' => 'Invalid CSRF Token' ,
404+ 'explanation' => /session might have been cleared/ ,
405+ )
406+ end
407+ end
408+ end
409+ end
410+ end
411+
412+ context "requesting eval for a specific frame" do
413+ let ( :env ) { { } }
414+ let ( :response_env ) {
415+ app . call ( request_env )
416+ }
417+ let ( :request_env ) {
418+ Rack ::MockRequest . env_for ( "/__better_errors/#{ id } /eval" , input : StringIO . new ( JSON . dump ( request_body_data ) ) )
419+ }
420+ let ( :request_body_data ) { { "index" => 0 , source : "do_a_thing" } }
421+ let ( :json_body ) { JSON . parse ( body ) }
422+ let ( :id ) { 'abcdefg' }
423+
424+ context 'when no errors have been recorded' do
425+ it 'returns a JSON error' do
426+ expect ( json_body ) . to match (
427+ 'error' => 'No exception information available' ,
428+ 'explanation' => /application has been restarted/ ,
429+ )
430+ end
431+
432+ context 'when Middleman is in use' do
433+ let! ( :middleman ) { class_double ( "Middleman" ) . as_stubbed_const }
434+ it 'returns a JSON error' do
435+ expect ( json_body [ 'explanation' ] )
436+ . to match ( /Middleman reloads all dependencies/ )
437+ end
438+ end
439+
440+ context 'when Shotgun is in use' do
441+ let! ( :shotgun ) { class_double ( "Shotgun" ) . as_stubbed_const }
442+
443+ it 'returns a JSON error' do
444+ expect ( json_body [ 'explanation' ] )
445+ . to match ( /The shotgun gem/ )
446+ end
447+
448+ context 'when Hanami is also in use' do
449+ let! ( :hanami ) { class_double ( "Hanami" ) . as_stubbed_const }
450+ it 'returns a JSON error' do
451+ expect ( json_body [ 'explanation' ] )
452+ . to match ( /--no-code-reloading/ )
453+ end
454+ end
455+ end
456+ end
457+
458+ context 'when an error has been recorded' do
459+ let ( :error_page ) { ErrorPage . new ( exception , env ) }
460+ before do
461+ app . instance_variable_set ( '@error_page' , error_page )
462+ end
463+
464+ context 'but it does not match the request' do
465+ it 'returns a JSON error' do
466+ expect ( json_body ) . to match (
467+ 'error' => 'Session expired' ,
468+ 'explanation' => /no longer available in memory/ ,
469+ )
470+ end
471+ end
472+
473+ context 'and its ID matches the requested ID' do
474+ let ( :id ) { error_page . id }
475+
476+ context 'when the body csrfToken matches the CSRF token cookie' do
477+ let ( :request_body_data ) { { "index" => 0 , "csrfToken" => "csrfToken123" } }
478+ before do
479+ request_env [ "HTTP_COOKIE" ] = "BetterErrors-CSRF-Token=csrfToken123"
480+ end
481+
482+ context 'when the Content-Type of the request is application/json' do
483+ before do
484+ request_env [ 'CONTENT_TYPE' ] = 'application/json'
485+ end
486+
487+ it 'returns JSON containing the eval result' do
488+ expect ( error_page ) . to receive ( :do_eval ) . and_return ( prompt : '#' , result : "much_stuff_here" )
489+ expect ( json_body ) . to match (
490+ 'prompt' => '#' ,
491+ 'result' => 'much_stuff_here' ,
492+ )
493+ end
494+ end
495+
496+ context 'when the Content-Type of the request is application/json' do
497+ before do
498+ request_env [ 'HTTP_CONTENT_TYPE' ] = 'application/json'
499+ end
500+
501+ it 'returns a JSON error' do
502+ expect ( json_body ) . to match (
503+ 'error' => 'Request not acceptable' ,
504+ 'explanation' => /did not match an acceptable content type/ ,
505+ )
506+ end
507+ end
508+ end
509+
510+ context 'when the body csrfToken does not match the CSRF token cookie' do
511+ let ( :request_body_data ) { { "index" => 0 , "csrfToken" => "csrfToken123" } }
388512 before do
389513 request_env [ "HTTP_COOKIE" ] = "BetterErrors-CSRF-Token=csrfToken456"
390514 end
@@ -408,5 +532,25 @@ def initialize(message, original_exception = nil)
408532 end
409533 end
410534 end
535+
536+ context "requesting an invalid internal method" do
537+ let ( :env ) { { } }
538+ let ( :response_env ) {
539+ app . call ( request_env )
540+ }
541+ let ( :request_env ) {
542+ Rack ::MockRequest . env_for ( "/__better_errors/#{ id } /invalid" , input : StringIO . new ( JSON . dump ( request_body_data ) ) )
543+ }
544+ let ( :request_body_data ) { { "index" => 0 } }
545+ let ( :json_body ) { JSON . parse ( body ) }
546+ let ( :id ) { 'abcdefg' }
547+
548+ it 'returns a JSON error' do
549+ expect ( json_body ) . to match (
550+ 'error' => 'Not found' ,
551+ 'explanation' => /recognized internal call/ ,
552+ )
553+ end
554+ end
411555 end
412556end
0 commit comments