1require_relative '../../spec_helper'
2require_relative 'fixtures/classes'
3
4# These specs only illustrate the basic autoload cases
5# and where toplevel autoload behaves differently from
6# Module#autoload. See those specs for more examples.
7
8autoload :KSAutoloadA, "autoload_a.rb"
9autoload :KSAutoloadB, fixture(__FILE__, "autoload_b.rb")
10autoload :KSAutoloadCallsRequire, "main_autoload_not_exist.rb"
11
12def check_autoload(const)
13  autoload? const
14end
15
16describe "Kernel#autoload" do
17  before :each do
18    @loaded_features = $".dup
19  end
20
21  after :each do
22    $".replace @loaded_features
23  end
24
25  it "is a private method" do
26    Kernel.should have_private_instance_method(:autoload)
27  end
28
29  it "registers a file to load the first time the named constant is accessed" do
30    Object.autoload?(:KSAutoloadA).should == "autoload_a.rb"
31  end
32
33  it "registers a file to load the first time the named constant is accessed" do
34    check_autoload(:KSAutoloadA).should == "autoload_a.rb"
35  end
36
37  it "sets the autoload constant in Object's constant table" do
38    Object.should have_constant(:KSAutoloadA)
39  end
40
41  it "loads the file when the constant is accessed" do
42    KSAutoloadB.loaded.should == :ksautoload_b
43  end
44
45  it "calls main.require(path) to load the file" do
46    main = TOPLEVEL_BINDING.eval("self")
47    main.should_receive(:require).with("main_autoload_not_exist.rb")
48    # The constant won't be defined since require is mocked to do nothing
49    -> { KSAutoloadCallsRequire }.should raise_error(NameError)
50  end
51
52  it "can autoload in instance_eval" do
53    Object.new.instance_eval do
54      autoload :KSAutoloadD, fixture(__FILE__, "autoload_d.rb")
55      KSAutoloadD.loaded.should == :ksautoload_d
56    end
57  end
58
59  describe "when Object is frozen" do
60    it "raises a FrozenError before defining the constant" do
61      ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "#{frozen_error_class} - nil"
62    end
63  end
64
65  describe "when called from included module's method" do
66    before :all do
67      @path = fixture(__FILE__, "autoload_from_included_module.rb")
68      KernelSpecs::AutoloadMethodIncluder.new.setup_autoload(@path)
69    end
70
71    it "setups the autoload on the included module" do
72      KernelSpecs::AutoloadMethod.autoload?(:AutoloadFromIncludedModule).should == @path
73    end
74
75    it "the autoload is reacheable from the class too" do
76      KernelSpecs::AutoloadMethodIncluder.autoload?(:AutoloadFromIncludedModule).should == @path
77    end
78
79    it "the autoload relative to the included module works" do
80      KernelSpecs::AutoloadMethod::AutoloadFromIncludedModule.loaded.should == :autoload_from_included_module
81    end
82  end
83end
84
85describe "Kernel#autoload?" do
86  it "is a private method" do
87    Kernel.should have_private_instance_method(:autoload?)
88  end
89
90  it "returns the name of the file that will be autoloaded" do
91    check_autoload(:KSAutoloadA).should == "autoload_a.rb"
92  end
93
94  it "returns nil if no file has been registered for a constant" do
95    check_autoload(:Manualload).should be_nil
96  end
97end
98
99Kernel.autoload :KSAutoloadBB, "no_autoload.rb"
100
101describe "Kernel.autoload" do
102  before :all do
103    @non_existent = fixture __FILE__, "no_autoload.rb"
104  end
105
106  before :each do
107    @loaded_features = $".dup
108
109    ScratchPad.clear
110  end
111
112  after :each do
113    $".replace @loaded_features
114  end
115
116  it "registers a file to load the first time the toplevel constant is accessed" do
117    Kernel.autoload :KSAutoloadAA, @non_existent
118    Kernel.autoload?(:KSAutoloadAA).should == @non_existent
119  end
120
121  it "sets the autoload constant in Object's constant table" do
122    Object.should have_constant(:KSAutoloadBB)
123  end
124
125  it "calls #to_path on non-String filenames" do
126    p = mock('path')
127    p.should_receive(:to_path).and_return @non_existent
128    Kernel.autoload :KSAutoloadAA, p
129  end
130
131  describe "when called from included module's method" do
132    before :all do
133      @path = fixture(__FILE__, "autoload_from_included_module2.rb")
134      KernelSpecs::AutoloadMethodIncluder2.new.setup_autoload(@path)
135    end
136
137    it "setups the autoload on the included module" do
138      KernelSpecs::AutoloadMethod2.autoload?(:AutoloadFromIncludedModule2).should == @path
139    end
140
141    it "the autoload is reacheable from the class too" do
142      KernelSpecs::AutoloadMethodIncluder2.autoload?(:AutoloadFromIncludedModule2).should == @path
143    end
144
145    it "the autoload relative to the included module works" do
146      KernelSpecs::AutoloadMethod2::AutoloadFromIncludedModule2.loaded.should == :autoload_from_included_module2
147    end
148  end
149end
150
151describe "Kernel.autoload?" do
152  it "returns the name of the file that will be autoloaded" do
153    Kernel.autoload :KSAutoload, "autoload.rb"
154    Kernel.autoload?(:KSAutoload).should == "autoload.rb"
155  end
156
157  it "returns nil if no file has been registered for a constant" do
158    Kernel.autoload?(:Manualload).should be_nil
159  end
160end
161