summaryrefslogtreecommitdiff
path: root/spec/ruby/core/main/using_spec.rb
blob: ed18cdca391742ec08cb9da4002d53454c2685b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
require File.expand_path('../../../spec_helper', __FILE__)

ruby_version_is "2.0.0" do
  require File.expand_path('../fixtures/classes', __FILE__)
  require File.expand_path('../fixtures/string_refinement', __FILE__)

  describe "main.using" do
    it "requires one Module argument" do
      lambda do
        eval('using', TOPLEVEL_BINDING)
      end.should raise_error(ArgumentError)

      lambda do
        eval('using "foo"', TOPLEVEL_BINDING)
      end.should raise_error(TypeError)
    end

    it "uses refinements from the given module only in the target file" do
      load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__)
      MainSpecs::DATA[:in_module].should == 'foo'
      MainSpecs::DATA[:toplevel].should == 'foo'
      lambda do
        'hello'.foo
      end.should raise_error(NoMethodError)
    end

    it "uses refinements from the given module for method calls in the target file" do
      load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__)
      lambda do
        'hello'.foo
      end.should raise_error(NoMethodError)
      MainSpecs.call_foo('hello').should == 'foo'
    end

    it "uses refinements from the given module in the eval string" do
      cls = MainSpecs::DATA[:cls] = Class.new {def foo; 'foo'; end}
      MainSpecs::DATA[:mod] = Module.new do
        refine(cls) do
          def foo; 'bar'; end
        end
      end
      eval(<<-EOS, TOPLEVEL_BINDING).should == 'bar'
        using MainSpecs::DATA[:mod]
        MainSpecs::DATA[:cls].new.foo
      EOS
    end

    it "does not affect methods defined before it is called" do
      cls = Class.new {def foo; 'foo'; end}
      MainSpecs::DATA[:mod] = Module.new do
        refine(cls) do
          def foo; 'bar'; end
        end
      end
      x = MainSpecs::DATA[:x] = Object.new
      eval <<-EOS, TOPLEVEL_BINDING
        x = MainSpecs::DATA[:x]
        def x.before_using(obj)
          obj.foo
        end
        using MainSpecs::DATA[:mod]
        def x.after_using(obj)
          obj.foo
        end
      EOS

      obj = cls.new
      x.before_using(obj).should == 'foo'
      x.after_using(obj).should == 'bar'
    end

    it "propagates refinements added to existing modules after it is called" do
      cls = Class.new {def foo; 'foo'; end}
      mod = MainSpecs::DATA[:mod] = Module.new do
        refine(cls) do
          def foo; 'quux'; end
        end
      end
      x = MainSpecs::DATA[:x] = Object.new
      eval <<-EOS, TOPLEVEL_BINDING
        using MainSpecs::DATA[:mod]
        x = MainSpecs::DATA[:x]
        def x.call_foo(obj)
          obj.foo
        end
        def x.call_bar(obj)
          obj.bar
        end
      EOS

      obj = cls.new
      x.call_foo(obj).should == 'quux'

      mod.module_eval do
        refine(cls) do
          def bar; 'quux'; end
        end
      end

      x.call_bar(obj).should == 'quux'
    end

    it "does not propagate refinements of new modules added after it is called" do
      cls = Class.new {def foo; 'foo'; end}
      cls2 = Class.new {def bar; 'bar'; end}
      mod = MainSpecs::DATA[:mod] = Module.new do
        refine(cls) do
          def foo; 'quux'; end
        end
      end
      x = MainSpecs::DATA[:x] = Object.new
      eval <<-EOS, TOPLEVEL_BINDING
        using MainSpecs::DATA[:mod]
        x = MainSpecs::DATA[:x]
        def x.call_foo(obj)
          obj.foo
        end
        def x.call_bar(obj)
          obj.bar
        end
      EOS

      x.call_foo(cls.new).should == 'quux'

      mod.module_eval do
        refine(cls2) do
          def bar; 'quux'; end
        end
      end

      x.call_bar(cls2.new).should == 'bar'
    end
  end
end