diff options
Diffstat (limited to 'test/irb/yamatanooroti/test_rendering.rb')
-rw-r--r-- | test/irb/yamatanooroti/test_rendering.rb | 401 |
1 files changed, 334 insertions, 67 deletions
diff --git a/test/irb/yamatanooroti/test_rendering.rb b/test/irb/yamatanooroti/test_rendering.rb index 1586dc6504..44e07a3a12 100644 --- a/test/irb/yamatanooroti/test_rendering.rb +++ b/test/irb/yamatanooroti/test_rendering.rb @@ -8,8 +8,12 @@ rescue LoadError, NameError return end -class IRB::TestRendering < Yamatanooroti::TestCase +class IRB::RenderingTest < Yamatanooroti::TestCase def setup + @original_term = ENV['TERM'] + @home_backup = ENV['HOME'] + @xdg_config_home_backup = ENV['XDG_CONFIG_HOME'] + ENV['TERM'] = "xterm-256color" @pwd = Dir.pwd suffix = '%010d' % Random.rand(0..65535) @tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_irb_#{$$}_#{suffix}") @@ -22,12 +26,16 @@ class IRB::TestRendering < Yamatanooroti::TestCase @irbrc_backup = ENV['IRBRC'] @irbrc_file = ENV['IRBRC'] = File.join(@tmpdir, 'temporaty_irbrc') File.unlink(@irbrc_file) if File.exist?(@irbrc_file) + ENV['HOME'] = File.join(@tmpdir, 'home') + ENV['XDG_CONFIG_HOME'] = File.join(@tmpdir, 'xdg_config_home') end def teardown FileUtils.rm_rf(@tmpdir) ENV['IRBRC'] = @irbrc_backup - ENV.delete('RELINE_TEST_PROMPT') if ENV['RELINE_TEST_PROMPT'] + ENV['TERM'] = @original_term + ENV['HOME'] = @home_backup + ENV['XDG_CONFIG_HOME'] = @xdg_config_home_backup end def test_launch @@ -41,9 +49,74 @@ class IRB::TestRendering < Yamatanooroti::TestCase close assert_screen(<<~EOC) start IRB - irb(main):001:0> 'Hello, World!' + irb(main):001> 'Hello, World!' => "Hello, World!" - irb(main):002:0> + irb(main):002> + EOC + end + + def test_configuration_file_is_skipped_with_dash_f + write_irbrc <<~'LINES' + puts '.irbrc file should be ignored when -f is used' + LINES + start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb -f}, startup_message: '') + write(<<~EOC) + 'Hello, World!' + EOC + close + assert_screen(<<~EOC) + irb(main):001> 'Hello, World!' + => "Hello, World!" + irb(main):002> + EOC + end + + def test_configuration_file_is_skipped_with_dash_f_for_nested_sessions + write_irbrc <<~'LINES' + puts '.irbrc file should be ignored when -f is used' + LINES + start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb -f}, startup_message: '') + write(<<~EOC) + 'Hello, World!' + binding.irb + exit! + EOC + close + assert_screen(<<~EOC) + irb(main):001> 'Hello, World!' + => "Hello, World!" + irb(main):002> binding.irb + irb(main):003> exit! + irb(main):001> + EOC + end + + def test_nomultiline + write_irbrc <<~'LINES' + puts 'start IRB' + LINES + start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb --nomultiline}, startup_message: 'start IRB') + write(<<~EOC) + if true + if false + a = "hello + world" + puts a + end + end + EOC + close + assert_screen(<<~EOC) + start IRB + irb(main):001> if true + irb(main):002* if false + irb(main):003* a = "hello + irb(main):004" world" + irb(main):005* puts a + irb(main):006* end + irb(main):007* end + => nil + irb(main):008> EOC end @@ -64,25 +137,27 @@ class IRB::TestRendering < Yamatanooroti::TestCase a .a .b + .itself EOC close assert_screen(<<~EOC) start IRB - irb(main):001:1* class A - irb(main):002:1* def inspect; '#<A>'; end - irb(main):003:1* def a; self; end - irb(main):004:1* def b; true; end - irb(main):005:0> end + irb(main):001* class A + irb(main):002* def inspect; '#<A>'; end + irb(main):003* def a; self; end + irb(main):004* def b; true; end + irb(main):005> end => :b - irb(main):006:0> - irb(main):007:0> a = A.new + irb(main):006> + irb(main):007> a = A.new => #<A> - irb(main):008:0> - irb(main):009:0> a - irb(main):010:0> .a - irb(main):011:0> .b + irb(main):008> + irb(main):009> a + irb(main):010> .a + irb(main):011> .b + irb(main):012> .itself => true - irb(main):012:0> + irb(main):013> EOC end @@ -108,7 +183,6 @@ class IRB::TestRendering < Yamatanooroti::TestCase (a) &.b() - class A def b; self; end; def c; true; end; end; a = A.new a @@ -117,44 +191,44 @@ class IRB::TestRendering < Yamatanooroti::TestCase .c (a) &.b() + .itself EOC close assert_screen(<<~EOC) start IRB - irb(main):001:1* class A - irb(main):002:1* def inspect; '#<A>'; end - irb(main):003:1* def b; self; end - irb(main):004:1* def c; true; end - irb(main):005:0> end + irb(main):001* class A + irb(main):002* def inspect; '#<A>'; end + irb(main):003* def b; self; end + irb(main):004* def c; true; end + irb(main):005> end => :c - irb(main):006:0> - irb(main):007:0> a = A.new + irb(main):006> + irb(main):007> a = A.new => #<A> - irb(main):008:0> - irb(main):009:0> a - irb(main):010:0> .b - irb(main):011:0> # aaa - irb(main):012:0> .c + irb(main):008> + irb(main):009> a + irb(main):010> .b + irb(main):011> # aaa + irb(main):012> .c => true - irb(main):013:0> - irb(main):014:0> (a) - irb(main):015:0> &.b() + irb(main):013> + irb(main):014> (a) + irb(main):015> &.b() => #<A> - irb(main):016:0> - irb(main):017:0> - irb(main):018:0> class A def b; self; end; def c; true; end; end; - => :c - irb(main):019:0> a = A.new + irb(main):016> + irb(main):017> class A def b; self; end; def c; true; end; end; + irb(main):018> a = A.new => #<A> - irb(main):020:0> a - irb(main):021:0> .b - irb(main):022:0> # aaa - irb(main):023:0> .c + irb(main):019> a + irb(main):020> .b + irb(main):021> # aaa + irb(main):022> .c => true - irb(main):024:0> (a) - irb(main):025:0> &.b() + irb(main):023> (a) + irb(main):024> &.b() + irb(main):025> .itself => #<A> - irb(main):026:0> + irb(main):026> EOC end @@ -169,41 +243,70 @@ class IRB::TestRendering < Yamatanooroti::TestCase close assert_screen(<<~EOC) start IRB - irb(main):001:0> :` + irb(main):001> :` => :` - irb(main):002:0> + irb(main):002> EOC end - def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_right - pend "Needs a dummy document to show doc" + def test_autocomplete_with_multiple_doc_namespaces write_irbrc <<~'LINES' + puts 'start IRB' + LINES + start_terminal(3, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("{}.__id_") + write("\C-i") + sleep 0.2 + close + screen = result.join("\n").sub(/\n*\z/, "\n") + assert_match(/start\ IRB\nirb\(main\):001> {}\.__id__\n }\.__id__(?:Press )?/, screen) + end + + def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_right + rdoc_dir = File.join(@tmpdir, 'rdoc') + system("bundle exec rdoc -r -o #{rdoc_dir}") + write_irbrc <<~LINES + IRB.conf[:EXTRA_DOC_DIRS] = ['#{rdoc_dir}'] IRB.conf[:PROMPT][:MY_PROMPT] = { :PROMPT_I => "%03n> ", - :PROMPT_N => "%03n> ", :PROMPT_S => "%03n> ", :PROMPT_C => "%03n> " } IRB.conf[:PROMPT_MODE] = :MY_PROMPT puts 'start IRB' LINES - start_terminal(4, 19, %W{ruby -I/home/aycabta/ruby/reline/lib -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') - write("Str\C-i") + start_terminal(4, 19, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("IR") + write("\C-i") + sleep 0.2 close - assert_screen(<<~EOC) - 001> String - StringPress A - StructString - of byte - EOC + + # This is because on macOS we display different shortcut for displaying the full doc + # 'O' is for 'Option' and 'A' is for 'Alt' + if RUBY_PLATFORM =~ /darwin/ + assert_screen(<<~EOC) + start IRB + 001> IRB + IRBPress Opti + IRB + EOC + else + assert_screen(<<~EOC) + start IRB + 001> IRB + IRBPress Alt+ + IRB + EOC + end end def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_left - pend "Needs a dummy document to show doc" - write_irbrc <<~'LINES' + rdoc_dir = File.join(@tmpdir, 'rdoc') + system("bundle exec rdoc -r -o #{rdoc_dir}") + write_irbrc <<~LINES + IRB.conf[:EXTRA_DOC_DIRS] = ['#{rdoc_dir}'] IRB.conf[:PROMPT][:MY_PROMPT] = { :PROMPT_I => "%03n> ", - :PROMPT_N => "%03n> ", :PROMPT_S => "%03n> ", :PROMPT_C => "%03n> " } @@ -211,13 +314,15 @@ class IRB::TestRendering < Yamatanooroti::TestCase puts 'start IRB' LINES start_terminal(4, 12, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') - write("Str\C-i") + write("IR") + write("\C-i") + sleep 0.2 close assert_screen(<<~EOC) - 001> String - PressString - StrinStruct - of by + start IRB + 001> IRB + PressIRB + IRB EOC end @@ -232,14 +337,176 @@ class IRB::TestRendering < Yamatanooroti::TestCase close assert_screen(<<~EOC) start IRB - irb(main):001:0> #{code} + irb(main):001> #{code} => [0, ... - irb(main):002:0> + irb(main):002> + EOC + end + + def test_ctrl_c_is_handled + write_irbrc <<~'LINES' + puts 'start IRB' + LINES + start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + # Assignment expression code that turns into non-assignment expression after evaluation + write("\C-c") + close + assert_screen(<<~EOC) + start IRB + irb(main):001> + ^C + irb(main):001> EOC end + def test_show_cmds_with_pager_can_quit_with_ctrl_c + write_irbrc <<~'LINES' + puts 'start IRB' + LINES + start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("help\n") + write("G") # move to the end of the screen + write("\C-c") # quit pager + write("'foo' + 'bar'\n") # eval something to make sure IRB resumes + close + + screen = result.join("\n").sub(/\n*\z/, "\n") + # IRB::Abort should be rescued + assert_not_match(/IRB::Abort/, screen) + # IRB should resume + assert_match(/foobar/, screen) + end + + def test_pager_page_content_pages_output_when_it_does_not_fit_in_the_screen_because_of_total_length + write_irbrc <<~'LINES' + puts 'start IRB' + require "irb/pager" + LINES + start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("IRB::Pager.page_content('a' * (80 * 8))\n") + write("'foo' + 'bar'\n") # eval something to make sure IRB resumes + close + + screen = result.join("\n").sub(/\n*\z/, "\n") + assert_match(/a{80}/, screen) + # because pager is invoked, foobar will not be evaluated + assert_not_match(/foobar/, screen) + end + + def test_pager_page_content_pages_output_when_it_does_not_fit_in_the_screen_because_of_screen_height + write_irbrc <<~'LINES' + puts 'start IRB' + require "irb/pager" + LINES + start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("IRB::Pager.page_content('a\n' * 8)\n") + write("'foo' + 'bar'\n") # eval something to make sure IRB resumes + close + + screen = result.join("\n").sub(/\n*\z/, "\n") + assert_match(/(a\n){8}/, screen) + # because pager is invoked, foobar will not be evaluated + assert_not_match(/foobar/, screen) + end + + def test_pager_page_content_doesnt_page_output_when_it_fits_in_the_screen + write_irbrc <<~'LINES' + puts 'start IRB' + require "irb/pager" + LINES + start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("IRB::Pager.page_content('a' * (80 * 7))\n") + write("'foo' + 'bar'\n") # eval something to make sure IRB resumes + close + + screen = result.join("\n").sub(/\n*\z/, "\n") + assert_match(/a{80}/, screen) + # because pager is not invoked, foobar will be evaluated + assert_match(/foobar/, screen) + end + + def test_long_evaluation_output_is_paged + write_irbrc <<~'LINES' + puts 'start IRB' + require "irb/pager" + LINES + start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("'a' * 80 * 11\n") + write("'foo' + 'bar'\n") # eval something to make sure IRB resumes + close + + screen = result.join("\n").sub(/\n*\z/, "\n") + assert_match(/(a{80}\n){8}/, screen) + # because pager is invoked, foobar will not be evaluated + assert_not_match(/foobar/, screen) + end + + def test_long_evaluation_output_is_preserved_after_paging + write_irbrc <<~'LINES' + puts 'start IRB' + require "irb/pager" + LINES + start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write("'a' * 80 * 11\n") + write("q") # quit pager + write("'foo' + 'bar'\n") # eval something to make sure IRB resumes + close + + screen = result.join("\n").sub(/\n*\z/, "\n") + # confirm pager has exited + assert_match(/foobar/, screen) + # confirm output is preserved + assert_match(/(a{80}\n){6}/, screen) + end + + def test_debug_integration_hints_debugger_commands + write_irbrc <<~'LINES' + IRB.conf[:USE_COLORIZE] = false + LINES + script = Tempfile.create(["debug", ".rb"]) + script.write <<~RUBY + puts 'start IRB' + binding.irb + RUBY + script.close + start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{script.to_path}}, startup_message: 'start IRB') + write("debug\n") + write("pp 1\n") + write("pp 1") + close + + screen = result.join("\n").sub(/\n*\z/, "\n") + # submitted input shouldn't contain hint + assert_include(screen, "irb:rdbg(main):002> pp 1\n") + # unsubmitted input should contain hint + assert_include(screen, "irb:rdbg(main):003> pp 1 # debug command\n") + ensure + File.unlink(script) if script + end + + def test_debug_integration_doesnt_hint_non_debugger_commands + write_irbrc <<~'LINES' + IRB.conf[:USE_COLORIZE] = false + LINES + script = Tempfile.create(["debug", ".rb"]) + script.write <<~RUBY + puts 'start IRB' + binding.irb + RUBY + script.close + start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{script.to_path}}, startup_message: 'start IRB') + write("debug\n") + write("foo") + close + + screen = result.join("\n").sub(/\n*\z/, "\n") + assert_include(screen, "irb:rdbg(main):002> foo\n") + ensure + File.unlink(script) if script + end + private def write_irbrc(content) |