summaryrefslogtreecommitdiff
path: root/spec/ruby/core/module/shared/set_visibility.rb
blob: a04b1a54a0f9d5bca87d63f8d0e58f9ec7060cdc (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# -*- encoding: us-ascii -*-

describe :set_visibility, shared: true do
  it "is a private method" do
    Module.should have_private_instance_method(@method, false)
  end

  describe "with argument" do
    it "does not clone method from the ancestor when setting to the same visibility in a child" do
      visibility = @method
      parent = Module.new {
        def test_method; end
        send(visibility, :test_method)
      }

      child = Module.new {
        include parent
        send(visibility, :test_method)
      }

      child.should_not send(:"have_#{visibility}_instance_method", :test_method, false)
    end
  end

  describe "without arguments" do
    it "sets visibility to following method definitions" do
      visibility = @method
      mod = Module.new {
        send visibility

        def test1() end
        def test2() end
      }

      mod.should send(:"have_#{@method}_instance_method", :test1, false)
      mod.should send(:"have_#{@method}_instance_method", :test2, false)
    end

    it "stops setting visibility if the body encounters other visibility setters without arguments" do
      visibility = @method
      new_visibility = nil
      mod = Module.new {
        send visibility
        new_visibility = [:protected, :private].find {|vis| vis != visibility }
        send new_visibility
        def test1() end
      }

      mod.should send(:"have_#{new_visibility}_instance_method", :test1, false)
    end

    it "continues setting visibility if the body encounters other visibility setters with arguments" do
      visibility = @method
      mod = Module.new {
        send visibility
        def test1() end
        send([:protected, :private].find {|vis| vis != visibility }, :test1)
        def test2() end
      }

      mod.should send(:"have_#{@method}_instance_method", :test2, false)
    end

    it "does not affect module_evaled method definitions when itself is outside the eval" do
      visibility = @method
      mod = Module.new {
        send visibility

        module_eval { def test1() end }
        module_eval " def test2() end "
      }

      mod.should have_public_instance_method(:test1, false)
      mod.should have_public_instance_method(:test2, false)
    end

    it "does not affect outside method definitions when itself is inside a module_eval" do
      visibility = @method
      mod = Module.new {
        module_eval { send visibility }

        def test1() end
      }

      mod.should have_public_instance_method(:test1, false)
    end

    it "affects normally if itself and method definitions are inside a module_eval" do
      visibility = @method
      mod = Module.new {
        module_eval {
          send visibility

          def test1() end
        }
      }

      mod.should send(:"have_#{@method}_instance_method", :test1, false)
    end

    it "does not affect method definitions when itself is inside an eval and method definitions are outside" do
      visibility = @method
      initialized_visibility = [:public, :protected, :private].find {|sym| sym != visibility }
      mod = Module.new {
        send initialized_visibility
        eval visibility.to_s

        def test1() end
      }

      mod.should send(:"have_#{initialized_visibility}_instance_method", :test1, false)
    end

    it "affects evaled method definitions when itself is outside the eval" do
      visibility = @method
      mod = Module.new {
        send visibility

        eval "def test1() end"
      }

      mod.should send(:"have_#{@method}_instance_method", :test1, false)
    end

    it "affects normally if itself and following method definitions are inside a eval" do
      visibility = @method
      mod = Module.new {
        eval <<-CODE
          #{visibility}

          def test1() end
        CODE
      }

      mod.should send(:"have_#{@method}_instance_method", :test1, false)
    end

    describe "within a closure" do
      it "sets the visibility outside the closure" do
        visibility = @method
        mod = Module.new {
          1.times {
            send visibility
          }
          def test1() end
        }

        mod.should send(:"have_#{@method}_instance_method", :test1, false)
      end
    end
  end
end