summaryrefslogtreecommitdiffstats
path: root/spec/unit/interface_spec.rb
blob: 4ff71ac3d127eed44fcd3957fed83dce5e03ef7b (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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
require 'spec_helper'
require 'puppet/face'
require 'puppet/interface'

describe Puppet::Interface do
  subject { Puppet::Interface }

  before :each do
    @faces = Puppet::Interface::FaceCollection.
      instance_variable_get("@faces").dup
    @dq = $".dup
    $".delete_if do |path| path =~ %r{/face/.*\.rb$} end
    Puppet::Interface::FaceCollection.instance_variable_get("@faces").clear
  end

  after :each do
    Puppet::Interface::FaceCollection.instance_variable_set("@faces", @faces)
    $".clear ; @dq.each do |item| $" << item end
  end

  describe "#[]" do
    it "should fail when no version is requested" do
      expect { subject[:huzzah] }.should raise_error ArgumentError
    end

    it "should raise an exception when the requested version is unavailable" do
      expect { subject[:huzzah, '17.0.0'] }.should raise_error, Puppet::Error
    end

    it "should raise an exception when the requested face doesn't exist" do
      expect { subject[:burrble_toot, :current] }.should raise_error, Puppet::Error
    end

    describe "version matching" do
      { '1'     => '1.1.1',
        '1.0'   => '1.0.1',
        '1.0.1' => '1.0.1',
        '1.1'   => '1.1.1',
        '1.1.1' => '1.1.1'
      }.each do |input, expect|
        it "should match #{input.inspect} to #{expect.inspect}" do
          face = subject[:version_matching, input]
          face.should be
          face.version.should == expect
        end
      end

      %w{1.0.2 1.2}.each do |input|
        it "should not match #{input.inspect} to any version" do
          expect { subject[:version_matching, input] }.
            to raise_error Puppet::Error, /Could not find version/
        end
      end
    end
  end

  describe "#define" do
    it "should register the face" do
      face  = subject.define(:face_test_register, '0.0.1')
      face.should == subject[:face_test_register, '0.0.1']
    end

    it "should load actions" do
      subject.any_instance.expects(:load_actions)
      subject.define(:face_test_load_actions, '0.0.1')
    end

    it "should require a version number" do
      expect { subject.define(:no_version) }.to raise_error ArgumentError
    end

    it "should support summary builder and accessor methods" do
      subject.new(:foo, '1.0.0').should respond_to(:summary).with(0).arguments
      subject.new(:foo, '1.0.0').should respond_to(:summary=).with(1).arguments
    end

    # Required documentation methods...
    { :summary     => "summary",
      :description => "This is the description of the stuff\n\nWhee",
      :examples    => "This is my example",
      :short_description => "This is my custom short description",
      :notes       => "These are my notes...",
      :author      => "This is my authorship data",
    }.each do |attr, value|
      it "should support #{attr} in the builder" do
        face = subject.new(:builder, '1.0.0') do
          self.send(attr, value)
        end
        face.send(attr).should == value
      end
    end
  end

  describe "#initialize" do
    it "should require a version number" do
      expect { subject.new(:no_version) }.to raise_error ArgumentError
    end

    it "should require a valid version number" do
      expect { subject.new(:bad_version, 'Rasins') }.
        should raise_error ArgumentError
    end

    it "should instance-eval any provided block", :'fails_on_ruby_1.9.2' => true do
      face = subject.new(:face_test_block, '0.0.1') do
        action(:something) do
          when_invoked { "foo" }
        end
      end

      face.something.should == "foo"
    end
  end

  it "should have a name" do
    subject.new(:me, '0.0.1').name.should == :me
  end

  it "should stringify with its own name" do
    subject.new(:me, '0.0.1').to_s.should =~ /\bme\b/
  end

  # Why?
  it "should create a class-level autoloader" do
    subject.autoloader.should be_instance_of(Puppet::Util::Autoload)
  end

  it "should try to require faces that are not known" do
    subject::FaceCollection.expects(:load_face).with(:foo, :current)
    subject::FaceCollection.expects(:load_face).with(:foo, '0.0.1')
    expect { subject[:foo, '0.0.1'] }.to raise_error Puppet::Error
  end

  it_should_behave_like "things that declare options" do
    def add_options_to(&block)
      subject.new(:with_options, '0.0.1', &block)
    end
  end

  describe "with face-level options", :'fails_on_ruby_1.9.2' => true do
    it "should not return any action-level options" do
      face = subject.new(:with_options, '0.0.1') do
        option "--foo"
        option "--bar"
        action :baz do
          when_invoked { true }
          option "--quux"
        end
      end
      face.options.should =~ [:foo, :bar]
    end

    it "should fail when a face option duplicates an action option" do
      expect {
        subject.new(:action_level_options, '0.0.1') do
          action :bar do
            when_invoked { true }
            option "--foo"
          end
          option "--foo"
        end
      }.should raise_error ArgumentError, /Option foo conflicts with existing option foo on/i
    end

    it "should work when two actions have the same option" do
      face = subject.new(:with_options, '0.0.1') do
        action :foo do when_invoked { true } ; option "--quux" end
        action :bar do when_invoked { true } ; option "--quux" end
      end

      face.get_action(:foo).options.should =~ [:quux]
      face.get_action(:bar).options.should =~ [:quux]
    end

    it "should only list options and not aliases" do
      face = subject.new(:face_options, '0.0.1') do
        option "--bar", "-b", "--foo-bar"
      end
      face.options.should =~ [:bar]
    end

  end

  describe "with inherited options" do
    let :parent do
      parent = Class.new(subject)
      parent.option("--inherited")
      parent.action(:parent_action) do when_invoked { true } end
      parent
    end

    let :face do
      face = parent.new(:example, '0.2.1')
      face.option("--local")
      face.action(:face_action) do when_invoked { true } end
      face
    end

    describe "#options", :'fails_on_ruby_1.9.2' => true do
      it "should list inherited options" do
        face.options.should =~ [:inherited, :local]
      end

      it "should see all options on face actions" do
        face.get_action(:face_action).options.should =~ [:inherited, :local]
      end

      it "should see all options on inherited actions accessed on the subclass" do
        face.get_action(:parent_action).options.should =~ [:inherited, :local]
      end

      it "should not see subclass actions on the parent class" do
        parent.options.should =~ [:inherited]
      end

      it "should not see subclass actions on actions accessed on the parent class" do
        parent.get_action(:parent_action).options.should =~ [:inherited]
      end
    end

    describe "#get_option", :'fails_on_ruby_1.9.2' => true do
      it "should return an inherited option object" do
        face.get_option(:inherited).should be_an_instance_of subject::Option
      end
    end
  end

  it_should_behave_like "documentation on faces" do
    subject do
      Puppet::Interface.new(:face_documentation, '0.0.1')
    end
  end
end