#!/usr/bin/env ruby require File.join(File.dirname(__FILE__), "spec_helper") require 'spec' require 'irb' require 'delegate' require File.join(File.dirname(__FILE__), '..', 'lib', 'flyrb', 'interactive_editor') # Using SimpleDelegator allows us to replace the constants without triggering a # "constant redefined" warning. module StubPlatform ARCH = SimpleDelegator.new(:x86) OS = SimpleDelegator.new(:unix) IMPL = SimpleDelegator.new(:linux) end # Sneak a stub Platform class into InteractiveEditor so that we don't have to # override constants on the real Platform module # # P.S. This ugliness is why libraries should always prefer to expose methods # over constants. class InteractiveEditor Platform = StubPlatform end describe InteractiveEditor, "given no clues as to what editor to use" do before :each do ENV.delete("VISUAL") ENV.delete("EDITOR") Kernel.stub!(:test).and_return(false) File.stub!(:executable?).and_return(false) end it "should complain" do lambda do InteractiveEditor.sensible_editor end.should raise_error end end describe InteractiveEditor, "given a Mac OS X platform and no editor environment vars" do before :each do ENV.delete("VISUAL") ENV.delete("EDITOR") @old_impl = StubPlatform::IMPL.__getobj__ StubPlatform::IMPL.__setobj__(:macosx) end after :each do StubPlatform::IMPL.__setobj__(@old_impl) end it "should use the OS X 'open' command as the default editor" do InteractiveEditor.sensible_editor.should == "open" end end # xdg-open is a facility from the freedesktop.org, available on some recent free # desktop operating systems (like Ubuntu). It uses the desktop environments # filetype associations to determine what program to open a file in. describe InteractiveEditor, "given a Linux OS and no environment vars" do before :each do ENV.delete("VISUAL") ENV.delete("EDITOR") @old_impl = StubPlatform::IMPL.__getobj__ StubPlatform::OS.__setobj__(:linux) File.stub!(:executable?).and_return(true) end after :each do StubPlatform::IMPL.__setobj__(@old_impl) end it "should attempt to use 'xdg-open' command as the default editor" do File.should_receive(:executable?). with("/usr/bin/xdg-open"). and_return(true) InteractiveEditor.sensible_editor.should == "/usr/bin/xdg-open" end end # /usr/bin/sensible-editor is a Debian-ism AFAIK describe InteractiveEditor, "given the existence of /usr/bin/sensible-editor and no xdg-open" do it "should use /usr/bin/sensible-editor as the default editor" do File.should_receive(:executable?). with("/usr/bin/xdg-open"). and_return(false) File.should_receive(:executable?). with("/usr/bin/sensible-editor"). and_return(true) InteractiveEditor.sensible_editor.should == "/usr/bin/sensible-editor" end end describe InteractiveEditor, "given an EDITOR environment variable" do before :each do File.stub!(:executable?).and_return(true) ENV["EDITOR"] = "MY_EDITOR" end after :each do ENV.delete("EDITOR") end it "should use the EDITOR environment variable to determine a sensible editor" do InteractiveEditor.sensible_editor.should == "MY_EDITOR" end end describe InteractiveEditor, "given a VISUAL environment variable" do before :each do File.stub!(:executable?).and_return(true) ENV["EDITOR"] = "MY_EDITOR" ENV["VISUAL"] = "MY_VISUAL_EDITOR" end after :each do ENV.delete("EDITOR") ENV.delete("VISUAL") end it "should use the environment variable to determine a sensible editor" do InteractiveEditor.sensible_editor.should == "MY_VISUAL_EDITOR" end end describe InteractiveEditing, "(calling out to an external editor)" do before :each do @it = Object.new @it.extend(InteractiveEditing) @editor = stub("Editor", :edit_interactively => nil) @editor_path = stub("Editor Path") InteractiveEditor.stub!(:sensible_editor).and_return(@editor_path) InteractiveEditor.stub!(:new).and_return(@editor) end it "should use InteractiveEditor to determine default editor" do @it.edit_interactively IRB.conf[:interactive_editors][@editor_path].should equal(@editor) end end