diff options
Diffstat (limited to 'spec/unit/property_spec.rb')
-rw-r--r-- | spec/unit/property_spec.rb | 802 |
1 files changed, 802 insertions, 0 deletions
diff --git a/spec/unit/property_spec.rb b/spec/unit/property_spec.rb new file mode 100644 index 0000000000..ce0552c564 --- /dev/null +++ b/spec/unit/property_spec.rb @@ -0,0 +1,802 @@ +require 'support/shared/integration/integration_helper' + +describe "Chef::Resource.property" do + include IntegrationSupport + + module Namer + @i = 0 + def self.next_resource_name + "chef_resource_property_spec_#{@i += 1}" + end + def self.reset_index + @current_index = 0 + end + def self.current_index + @current_index + end + def self.next_index + @current_index += 1 + end + end + + def lazy(&block) + Chef::DelayedEvaluator.new(&block) + end + + before do + Namer.reset_index + end + + def self.new_resource_name + Namer.next_resource_name + end + + let(:resource_class) do + new_resource_name = self.class.new_resource_name + Class.new(Chef::Resource) do + resource_name new_resource_name + def next_index + Namer.next_index + end + end + end + + let(:resource) do + resource_class.new("blah") + end + + def self.english_join(values) + return '<nothing>' if values.size == 0 + return values[0].inspect if values.size == 1 + "#{values[0..-2].map { |v| v.inspect }.join(", ")} and #{values[-1].inspect}" + end + + def self.with_property(*properties, &block) + tags_index = properties.find_index { |p| !p.is_a?(String)} + if tags_index + properties, tags = properties[0..tags_index-1], properties[tags_index..-1] + else + tags = [] + end + properties = properties.map { |property| "property #{property}" } + context "With properties #{english_join(properties)}", *tags do + before do + properties.each do |property_str| + resource_class.class_eval(property_str, __FILE__, __LINE__) + end + end + instance_eval(&block) + end + end + + # Basic properties + with_property ':bare_property' do + it "can be set" do + expect(resource.bare_property 10).to eq 10 + expect(resource.bare_property).to eq 10 + end + # it "emits a deprecation warning and does a get, if set to nil" do + it "emits a deprecation warning and does a get, if set to nil" do + expect(resource.bare_property 10).to eq 10 + # expect { resource.bare_property nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError + # Chef::Config[:treat_deprecation_warnings_as_errors] = false + expect(resource.bare_property nil).to eq 10 + expect(resource.bare_property).to eq 10 + end + it "can be updated" do + expect(resource.bare_property 10).to eq 10 + expect(resource.bare_property 20).to eq 20 + expect(resource.bare_property).to eq 20 + end + it "can be set with =" do + expect(resource.bare_property 10).to eq 10 + expect(resource.bare_property).to eq 10 + end + # it "can be set to nil with =" do + # expect(resource.bare_property 10).to eq 10 + # expect(resource.bare_property = nil).to be_nil + # expect(resource.bare_property).to be_nil + # end + it "can be updated with =" do + expect(resource.bare_property 10).to eq 10 + expect(resource.bare_property = 20).to eq 20 + expect(resource.bare_property).to eq 20 + end + end + + with_property ":x, Integer" do + context "and subclass" do + let(:subresource_class) do + new_resource_name = self.class.new_resource_name + Class.new(resource_class) do + resource_name new_resource_name + end + end + let(:subresource) do + subresource_class.new('blah') + end + + it "x is inherited" do + expect(subresource.x 10).to eq 10 + expect(subresource.x).to eq 10 + expect(subresource.x = 20).to eq 20 + expect(subresource.x).to eq 20 + # expect(subresource_class.properties[:x]).not_to be_nil + end + + it "x's validation is inherited" do + expect { subresource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed + end + + context "with property :y on the subclass" do + before do + subresource_class.class_eval do + property :y + end + end + + it "x is still there" do + expect(subresource.x 10).to eq 10 + expect(subresource.x).to eq 10 + expect(subresource.x = 20).to eq 20 + expect(subresource.x).to eq 20 + # expect(subresource_class.properties[:x]).not_to be_nil + end + it "y is there" do + expect(subresource.y 10).to eq 10 + expect(subresource.y).to eq 10 + expect(subresource.y = 20).to eq 20 + expect(subresource.y).to eq 20 + # expect(subresource_class.properties[:y]).not_to be_nil + end + it "y is not on the superclass" do + expect { resource_class.y 10 }.to raise_error + # expect(resource_class.properties[:y]).to be_nil + end + end + + context "with property :x on the subclass" do + before do + subresource_class.class_eval do + property :x + end + end + + it "x is still there" do + expect(subresource.x 10).to eq 10 + expect(subresource.x).to eq 10 + expect(subresource.x = 20).to eq 20 + expect(subresource.x).to eq 20 + # expect(subresource_class.properties[:x]).not_to be_nil + # expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x] + end + + it "x's validation is overwritten" do + expect(subresource.x 'ohno').to eq 'ohno' + expect(subresource.x).to eq 'ohno' + end + + it "the superclass's validation for x is still there" do + expect { resource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed + end + end + + context "with property :x, String on the subclass" do + before do + subresource_class.class_eval do + property :x, String + end + end + + it "x is still there" do + expect(subresource.x "10").to eq "10" + expect(subresource.x).to eq "10" + expect(subresource.x = "20").to eq "20" + expect(subresource.x).to eq "20" + # expect(subresource_class.properties[:x]).not_to be_nil + # expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x] + end + + it "x's validation is overwritten" do + expect { subresource.x 10 }.to raise_error Chef::Exceptions::ValidationFailed + expect(subresource.x 'ohno').to eq 'ohno' + expect(subresource.x).to eq 'ohno' + end + + it "the superclass's validation for x is still there" do + expect { resource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed + expect(resource.x 10).to eq 10 + expect(resource.x).to eq 10 + end + end + end + end + + context "Chef::Resource::PropertyType#property_is_set?" do + it "when a resource is newly created, property_is_set?(:name) is true" do + expect(resource.property_is_set?(:name)).to be_truthy + end + + # it "when referencing an undefined property, property_is_set?(:x) raises an error" do + # expect { resource.property_is_set?(:x) }.to raise_error(ArgumentError) + # end + + with_property ':x' do + it "when the resource is newly created, property_is_set?(:x) is false" do + expect(resource.property_is_set?(:x)).to be_falsey + end + it "when x is set, property_is_set?(:x) is true" do + resource.x 10 + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is set with =, property_is_set?(:x) is true" do + resource.x = 10 + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is set to a lazy value, property_is_set?(:x) is true" do + resource.x lazy { 10 } + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is retrieved, property_is_set?(:x) is false" do + resource.x + expect(resource.property_is_set?(:x)).to be_falsey + end + end + + with_property ':x, default: 10' do + it "when the resource is newly created, property_is_set?(:x) is false" do + expect(resource.property_is_set?(:x)).to be_falsey + end + it "when x is set, property_is_set?(:x) is true" do + resource.x 10 + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is set with =, property_is_set?(:x) is true" do + resource.x = 10 + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is set to a lazy value, property_is_set?(:x) is true" do + resource.x lazy { 10 } + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is retrieved, property_is_set?(:x) is true" do + resource.x + expect(resource.property_is_set?(:x)).to be_truthy + end + end + + with_property ':x, default: nil' do + it "when the resource is newly created, property_is_set?(:x) is false" do + expect(resource.property_is_set?(:x)).to be_falsey + end + it "when x is set, property_is_set?(:x) is true" do + resource.x 10 + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is set with =, property_is_set?(:x) is true" do + resource.x = 10 + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is set to a lazy value, property_is_set?(:x) is true" do + resource.x lazy { 10 } + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is retrieved, property_is_set?(:x) is true" do + resource.x + expect(resource.property_is_set?(:x)).to be_truthy + end + end + + with_property ':x, default: lazy { 10 }' do + it "when the resource is newly created, property_is_set?(:x) is false" do + expect(resource.property_is_set?(:x)).to be_falsey + end + it "when x is set, property_is_set?(:x) is true" do + resource.x 10 + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is set with =, property_is_set?(:x) is true" do + resource.x = 10 + expect(resource.property_is_set?(:x)).to be_truthy + end + it "when x is retrieved, property_is_set?(:x) is true" do + resource.x + expect(resource.property_is_set?(:x)).to be_truthy + end + end + end + + context "Chef::Resource::PropertyType#default" do + with_property ':x, default: 10' do + it "when x is set, it returns its value" do + expect(resource.x 20).to eq 20 + expect(resource.property_is_set?(:x)).to be_truthy + expect(resource.x).to eq 20 + end + it "when x is not set, it returns 10" do + expect(resource.x).to eq 10 + end + it "when x is not set, it is not included in state" do + expect(resource.state).to eq({}) + end + it "when x is set to nil, it returns nil" do + resource.instance_eval { @x = nil } + expect(resource.x).to be_nil + end + + context "With a subclass" do + let(:subresource_class) do + new_resource_name = self.class.new_resource_name + Class.new(resource_class) do + resource_name new_resource_name + end + end + let(:subresource) { subresource_class.new('blah') } + it "The default is inherited" do + expect(subresource.x).to eq 10 + end + end + end + + with_property ':x, default: 10, identity: true' do + it "when x is not set, it is not included in identity" do + expect(resource.state).to eq({}) + end + end + + with_property ':x, default: nil' do + it "when x is not set, it returns nil" do + expect(resource.x).to be_nil + end + end + + with_property ':x' do + it "when x is not set, it returns nil" do + expect(resource.x).to be_nil + end + end + + context "hash default" do + with_property ':x, default: {}' do + it "when x is not set, it returns {}" do + expect(resource.x).to eq({}) + end + it "The same exact value is returned multiple times in a row" do + value = resource.x + expect(value).to eq({}) + expect(resource.x.object_id).to eq(value.object_id) + end + it "Multiple instances of x receive the exact same value" do + expect(resource.x.object_id).to eq(resource_class.new('blah2').x.object_id) + end + it "The default value is frozen" do + expect(resource.x).to be_frozen + end + it "The default value cannot be written to" do + expect { resource.x[:a] = 1 }.to raise_error RuntimeError, /frozen/ + end + end + + with_property ':x, default: lazy { {} }' do + it "when x is not set, it returns {}" do + expect(resource.x).to eq({}) + end + # it "The value is different each time it is called" do + # value = resource.x + # expect(value).to eq({}) + # expect(resource.x.object_id).not_to eq(value.object_id) + # end + it "Multiple instances of x receive different values" do + expect(resource.x.object_id).not_to eq(resource_class.new('blah2').x.object_id) + end + end + end + + context "with a class with 'blah' as both class and instance methods" do + before do + resource_class.class_eval do + def self.blah + 'class' + end + def blah + "#{name}#{next_index}" + end + end + end + + with_property ':x, default: lazy { blah }' do + it "x is run in context of the instance" do + expect(resource.x).to eq "blah1" + end + it "x is run in the context of each instance it is run in" do + expect(resource.x).to eq "blah1" + expect(resource_class.new('another').x).to eq "another2" + # expect(resource.x).to eq "blah3" + end + end + + with_property ':x, default: lazy { |x| "#{blah}#{x.blah}" }' do + it "x is run in context of the class (where it was defined) and passed the instance" do + expect(resource.x).to eq "classblah1" + end + it "x is passed the value of each instance it is run in" do + expect(resource.x).to eq "classblah1" + expect(resource_class.new('another').x).to eq "classanother2" + # expect(resource.x).to eq "classblah3" + end + end + end + + context "validation of defaults" do + with_property ':x, String, default: 10' do + it "when the resource is created, no error is raised" do + resource + end + it "when x is set, no error is raised" do + expect(resource.x 'hi').to eq 'hi' + expect(resource.x).to eq 'hi' + end + it "when x is retrieved, no validation error is raised" do + expect(resource.x).to eq 10 + end + # it "when x is retrieved, a validation error is raised" do + # expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed + # end + end + + with_property ":x, String, default: lazy { Namer.next_index }" do + it "when the resource is created, no error is raised" do + resource + end + it "when x is set, no error is raised" do + expect(resource.x 'hi').to eq 'hi' + expect(resource.x).to eq 'hi' + end + it "when x is retrieved, no validation error is raised" do + expect(resource.x).to eq 1 + expect(Namer.current_index).to eq 1 + end + # it "when x is retrieved, a validation error is raised" do + # expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed + # expect(Namer.current_index).to eq 1 + # end + end + + with_property ":x, default: lazy { Namer.next_index }, is: proc { |v| Namer.next_index; true }" do + it "validation is not run at all on the default value" do + expect(resource.x).to eq 1 + expect(Namer.current_index).to eq 1 + end + # it "validation is only run the first time" do + # expect(resource.x).to eq 1 + # expect(Namer.current_index).to eq 2 + # expect(resource.x).to eq 1 + # expect(Namer.current_index).to eq 2 + # end + end + end + + context "coercion of defaults" do + with_property ':x, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do + it "when the resource is created, the proc is not yet run" do + resource + expect(Namer.current_index).to eq 0 + end + it "when x is set, coercion is run" do + expect(resource.x 'hi').to eq 'hi1' + expect(resource.x).to eq 'hi1' + expect(Namer.current_index).to eq 1 + end + it "when x is retrieved, coercion is run, no more than once" do + expect(resource.x).to eq '101' + expect(resource.x).to eq '101' + expect(Namer.current_index).to eq 1 + end + end + + with_property ':x, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do + it "when the resource is created, the proc is not yet run" do + resource + expect(Namer.current_index).to eq 0 + end + it "when x is set, coercion is run" do + expect(resource.x 'hi').to eq 'hi1' + expect(resource.x).to eq 'hi1' + expect(Namer.current_index).to eq 1 + end + end + + with_property ':x, proc { |v| Namer.next_index; true }, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do + it "coercion is only run the first time x is retrieved, and validation is not run" do + expect(Namer.current_index).to eq 0 + expect(resource.x).to eq '101' + expect(Namer.current_index).to eq 1 + expect(resource.x).to eq '101' + expect(Namer.current_index).to eq 1 + end + end + + context "validation and coercion of defaults" do + with_property ':x, String, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do + it "when x is retrieved, it is coerced before validating and passes" do + expect(resource.x).to eq '101' + end + end + with_property ':x, Integer, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do + it "when x is retrieved, it is coerced and not validated" do + expect(resource.x).to eq '101' + end + # it "when x is retrieved, it is coerced before validating and fails" do + # expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed + # end + end + with_property ':x, String, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do + it "when x is retrieved, it is coerced before validating and passes" do + expect(resource.x).to eq '101' + end + end + with_property ':x, Integer, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do + it "when x is retrieved, it is coerced and not validated" do + expect(resource.x).to eq '101' + end + # it "when x is retrieved, it is coerced before validating and fails" do + # expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed + # end + end + with_property ':x, proc { |v| Namer.next_index; true }, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do + it "coercion is only run the first time x is retrieved, and validation is not run" do + expect(Namer.current_index).to eq 0 + expect(resource.x).to eq '101' + expect(Namer.current_index).to eq 1 + expect(resource.x).to eq '101' + expect(Namer.current_index).to eq 1 + end + end + end + end + end + + context "Chef::Resource#lazy" do + with_property ':x' do + it "setting x to a lazy value does not run it immediately" do + resource.x lazy { Namer.next_index } + expect(Namer.current_index).to eq 0 + end + it "you can set x to a lazy value in the instance" do + resource.instance_eval do + x lazy { Namer.next_index } + end + expect(resource.x).to eq 1 + expect(Namer.current_index).to eq 1 + end + it "retrieving a lazy value pops it open" do + resource.x lazy { Namer.next_index } + expect(resource.x).to eq 1 + expect(Namer.current_index).to eq 1 + end + it "retrieving a lazy value twice evaluates it twice" do + resource.x lazy { Namer.next_index } + expect(resource.x).to eq 1 + expect(resource.x).to eq 2 + expect(Namer.current_index).to eq 2 + end + it "setting the same lazy value on two different instances runs it on each instancee" do + resource2 = resource_class.new("blah2") + l = lazy { Namer.next_index } + resource.x l + resource2.x l + expect(resource2.x).to eq 1 + expect(resource.x).to eq 2 + expect(resource2.x).to eq 3 + end + + context "when the class has a class and instance method named blah" do + before do + resource_class.class_eval do + def self.blah + "class" + end + def blah + "#{name}#{Namer.next_index}" + end + end + end + def blah + "example" + end + # it "retrieving lazy { blah } gets the instance variable" do + # resource.x lazy { blah } + # expect(resource.x).to eq "blah1" + # end + # it "retrieving lazy { blah } from two different instances gets two different instance variables" do + # resource2 = resource_class.new("another") + # l = lazy { blah } + # resource2.x l + # resource.x l + # expect(resource2.x).to eq "another1" + # expect(resource.x).to eq "blah2" + # expect(resource2.x).to eq "another3" + # end + it 'retrieving lazy { |x| "#{blah}#{x.blah}" } gets the example and instance variables' do + resource.x lazy { |x| "#{blah}#{x.blah}" } + expect(resource.x).to eq "exampleblah1" + end + it 'retrieving lazy { |x| "#{blah}#{x.blah}" } from two different instances gets two different instance variables' do + resource2 = resource_class.new("another") + l = lazy { |x| "#{blah}#{x.blah}" } + resource2.x l + resource.x l + expect(resource2.x).to eq "exampleanother1" + expect(resource.x).to eq "exampleblah2" + expect(resource2.x).to eq "exampleanother3" + end + end + end + + with_property ':x, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do + it "lazy values are not coerced on set" do + resource.x lazy { Namer.next_index } + expect(Namer.current_index).to eq 0 + end + it "lazy values are coerced on get" do + resource.x lazy { Namer.next_index } + expect(resource.x).to eq "12" + expect(Namer.current_index).to eq 2 + end + it "lazy values are coerced on each access" do + resource.x lazy { Namer.next_index } + expect(resource.x).to eq "12" + expect(Namer.current_index).to eq 2 + expect(resource.x).to eq "34" + expect(Namer.current_index).to eq 4 + end + end + + with_property ':x, String' do + it "lazy values are not validated on set" do + resource.x lazy { Namer.next_index } + expect(Namer.current_index).to eq 0 + end + it "lazy values are validated on get" do + resource.x lazy { Namer.next_index } + expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed + expect(Namer.current_index).to eq 1 + end + end + + with_property ':x, is: proc { |v| Namer.next_index; true }' do + it "lazy values are validated on each access" do + resource.x lazy { Namer.next_index } + expect(resource.x).to eq 1 + expect(Namer.current_index).to eq 2 + expect(resource.x).to eq 3 + expect(Namer.current_index).to eq 4 + end + end + + with_property ':x, Integer, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do + it "lazy values are not validated or coerced on set" do + resource.x lazy { Namer.next_index } + expect(Namer.current_index).to eq 0 + end + it "lazy values are coerced before being validated, which fails" do + resource.x lazy { Namer.next_index } + expect(Namer.current_index).to eq 0 + expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed + expect(Namer.current_index).to eq 2 + end + end + + with_property ':x, coerce: proc { |v| "#{v}#{Namer.next_index}" }, is: proc { |v| Namer.next_index; true }' do + it "lazy values are coerced and validated exactly once" do + resource.x lazy { Namer.next_index } + expect(resource.x).to eq "12" + expect(Namer.current_index).to eq 3 + expect(resource.x).to eq "45" + expect(Namer.current_index).to eq 6 + end + end + + with_property ':x, String, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do + it "lazy values are coerced before being validated, which succeeds" do + resource.x lazy { Namer.next_index } + expect(resource.x).to eq "12" + expect(Namer.current_index).to eq 2 + end + end + end + + context "Chef::Resource::PropertyType#coerce" do + with_property ':x, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do + it "coercion runs on set" do + expect(resource.x 10).to eq "101" + expect(Namer.current_index).to eq 1 + end + it "coercion sets the value (and coercion does not run on get)" do + expect(resource.x 10).to eq "101" + expect(resource.x).to eq "101" + expect(Namer.current_index).to eq 1 + end + it "coercion runs each time set happens" do + expect(resource.x 10).to eq "101" + expect(Namer.current_index).to eq 1 + expect(resource.x 10).to eq "102" + expect(Namer.current_index).to eq 2 + end + end + with_property ':x, coerce: proc { |x| Namer.next_index; raise "hi" if x == 10; x }, is: proc { |x| Namer.next_index; x != 10 }' do + it "failed coercion fails to set the value" do + resource.x 20 + expect(resource.x).to eq 20 + expect(Namer.current_index).to eq 2 + expect { resource.x 10 }.to raise_error 'hi' + expect(resource.x).to eq 20 + expect(Namer.current_index).to eq 3 + end + it "validation does not run if coercion fails" do + expect { resource.x 10 }.to raise_error 'hi' + expect(Namer.current_index).to eq 1 + end + end + end + + context "Chef::Resource::PropertyType validation" do + with_property ':x, is: proc { |v| Namer.next_index; v.is_a?(Integer) }' do + it "validation runs on set" do + expect(resource.x 10).to eq 10 + expect(Namer.current_index).to eq 1 + end + it "validation sets the value (and validation does not run on get)" do + expect(resource.x 10).to eq 10 + expect(resource.x).to eq 10 + expect(Namer.current_index).to eq 1 + end + it "validation runs each time set happens" do + expect(resource.x 10).to eq 10 + expect(Namer.current_index).to eq 1 + expect(resource.x 10).to eq 10 + expect(Namer.current_index).to eq 2 + end + it "failed validation fails to set the value" do + expect(resource.x 10).to eq 10 + expect(Namer.current_index).to eq 1 + expect { resource.x 'blah' }.to raise_error Chef::Exceptions::ValidationFailed + expect(resource.x).to eq 10 + expect(Namer.current_index).to eq 2 + end + end + end + + [ 'name_attribute', 'name_property' ].each do |name| + context "Chef::Resource::PropertyType##{name}" do + with_property ":x, #{name}: true" do + it "defaults x to resource.name" do + expect(resource.x).to eq 'blah' + end + it "does not pick up resource.name if set" do + expect(resource.x 10).to eq 10 + expect(resource.x).to eq 10 + end + it "binds to the latest resource.name when run" do + resource.name 'foo' + expect(resource.x).to eq 'foo' + end + it "caches resource.name" do + expect(resource.x).to eq 'blah' + resource.name 'foo' + expect(resource.x).to eq 'blah' + end + end + with_property ":x, default: 10, #{name}: true" do + it "chooses default over #{name}" do + expect(resource.x).to eq 10 + end + end + with_property ":x, #{name}: true, default: 10" do + it "chooses default over #{name}" do + expect(resource.x).to eq 10 + end + end + end + end +end |