spec/configliere/config_file_spec.rb in configliere-0.4.10 vs spec/configliere/config_file_spec.rb in configliere-0.4.11

- old
+ new

@@ -1,171 +1,192 @@ -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'spec_helper' describe Configliere::ConfigFile do - before do - @config = Configliere::Param.new :my_param => 'default_val', :also_a_param => true - FileUtils.stub! :mkdir_p - end + let(:default_params) { { my_param: 'default_val', also_a_param: true } } + + subject{ Configliere::Param.new default_params } - it 'is used by default' do - @config.should respond_to(:read) + it 'is included by default' do + subject.class.included_modules.should include(described_class) end - describe 'loading a yaml config file' do - before do - @fake_file = "---\nmy_param: val_from_file" - end + context '#read' do + let(:file_params) { { my_param: 'val_from_file' } } + let(:file_string) { file_params.to_yaml } + let(:file_path) { '/absolute/path.yaml' } + + before{ File.stub(:open).and_return(file_string) } - describe 'successfully' do - it 'with an absolute pathname uses it directly' do - File.should_receive(:open).with(%r{/fake/path.yaml}).and_return(@fake_file) - @config.read '/fake/path.yaml' - end - it 'with a simple filename, references it to the default config dir' do - File.should_receive(:open).with(File.join(Configliere::DEFAULT_CONFIG_DIR, 'file.yaml')).and_return(@fake_file) - @config.read 'file.yaml' - end - it 'returns the config object for chaining' do - File.should_receive(:open).with(File.join(Configliere::DEFAULT_CONFIG_DIR, 'file.yaml')).and_return(@fake_file) - @config.defaults :also_a_param => true - @config.read('file.yaml').should == { :my_param => 'val_from_file', :also_a_param => true } - end - after do - @config[:my_param].should == 'val_from_file' - end + it 'returns the config object for chaining' do + subject.read(file_path).should == subject end - it 'no longer provides a default config file' do - lambda{ @config.read(:my_settings) }.should raise_error(Configliere::DeprecatedError) - defined?(Configliere::DEFAULT_CONFIG_FILE).should_not be_true + context 'a yaml file' do + let(:file_path) { '/absolute/path.yaml' } + + it 'reads successfully' do + subject.should_receive(:read_yaml).with(file_string, {}) + subject.read file_path + end + + it 'merges the data' do + subject.read(file_path).should == default_params.merge(file_params) + end end - it 'warns but does not fail if the file is missing' do - @config = Configliere::Param.new - File.stub(:open).and_raise(Errno::ENOENT) - @config.should_receive(:warn).with("Loading empty configliere settings file #{Configliere::DEFAULT_CONFIG_DIR}/nonexistent_file.yaml") - @config.read('nonexistent_file.yaml').should == {} - end - end + context 'a json file' do + let(:file_path) { '/absolute/path.json' } + let(:file_string) { file_params.to_json } + + it 'reads successfully' do + subject.should_receive(:read_json).with(file_string, {}) + subject.read file_path + end - describe 'loading a json config file' do - before do - require 'json' - @fake_file = '{"my_param":"val_from_file"}' + it 'merges the data' do + subject.read(file_path).should == default_params.merge(file_params) + end end + + context 'given a symbol' do + let(:file_path) { :my_settings } - describe 'successfully' do - it 'with an absolute pathname uses it directly' do - File.should_receive(:open).with(%r{/fake/path.json}).and_return(@fake_file) - @config.read '/fake/path.json' + it 'no longer provides a default config file' do + expect{ subject.read(file_path) }.to raise_error(Configliere::DeprecatedError) + defined?(Configliere::DEFAULT_CONFIG_FILE).should_not be_true end - it 'with a simple filename, references it to the default config dir' do - File.should_receive(:open).with(File.join(Configliere::DEFAULT_CONFIG_DIR, 'file.json')).and_return(@fake_file) - @config.read 'file.json' + end + + context 'given a nonexistent file' do + let(:file_path) { 'nonexistent.conf' } + + it 'warns but does not fail if the file is missing' do + File.stub(:open).and_raise(Errno::ENOENT) + subject.should_receive(:warn).with("Loading empty configliere settings file #{subject.default_conf_dir}/#{file_path}") + subject.read(file_path).should == subject end - it 'returns the config object for chaining' do - File.should_receive(:open).with(File.join(Configliere::DEFAULT_CONFIG_DIR, 'file.json')).and_return(@fake_file) - @config.defaults :also_a_param => true - @config.read('file.json').should == { :my_param => 'val_from_file', :also_a_param => true } - end - after do - @config[:my_param].should == 'val_from_file' - end end - it 'no longer provides a default config file' do - lambda{ @config.read(:my_settings) }.should raise_error(Configliere::DeprecatedError) - defined?(Configliere::DEFAULT_CONFIG_FILE).should_not be_true + context 'given an absolute path' do + let(:file_path) { '/absolute/path.yaml' } + + it 'uses it directly' do + File.should_receive(:open).with(file_path).and_return(file_string) + subject.read file_path + end end - - it 'warns but does not fail if the file is missing' do - @config = Configliere::Param.new - File.stub(:open).and_raise(Errno::ENOENT) - @config.should_receive(:warn).with("Loading empty configliere settings file #{Configliere::DEFAULT_CONFIG_DIR}/nonexistent_file.json") - @config.read('nonexistent_file.json').should == {} + + context 'given a simple filename' do + let(:file_path) { 'simple_path.yaml' } + + it 'references it to the default config dir' do + File.should_receive(:open).with(File.join(subject.default_conf_dir, file_path)).and_return(file_string) + subject.read file_path + end end - end + + context 'with options' do + let(:file_params) { { development: { reload: true }, production: { reload: false } } } - describe '#read_yaml' do - before do - @config.merge! :reload => :whatever - @simple_yaml = { :my_param => 'override_val', 'also_a_param' => true, 'strkey' => 'val', :falsekey => false, :nilkey => nil }.to_yaml - @yaml_with_subenvs = { :development => { :reload => true }, :production => { :reload => false }}.to_yaml - end + before{ subject.merge!(reload: 'whatever') } - it 'loads yaml' do - @config.read_yaml(@simple_yaml) - @config.should == { :reload => :whatever, :my_param => 'override_val', :also_a_param => true, :strkey => 'val', :falsekey => false, :nilkey => nil } - @config.should_not == { :reload => :whatever, :my_param => 'override_val', 'also_a_param' => true, 'strkey' => 'val', :falsekey => false, :nilkey => nil } - end + context ':env key' do + context 'valid :env' do + let(:opts) { { env: :development } } + + it 'slices out a subhash given by :env' do + subject.read(file_path, opts) + subject.should == default_params.merge(reload: true) + end + end - describe 'with an environment scope' do - it 'slices out a subhash given by :env' do - @config.read_yaml(@yaml_with_subenvs, :env => :development) - @config.should == { :reload => true, :my_param => 'default_val', :also_a_param => true } + context 'invalid :env' do + let(:opts) { { env: :not_there } } + + it 'has no effect if the key given by :env option is absent' do + subject.read(file_path, opts) + subject.should == default_params.merge(reload: 'whatever') + end + end end + + context 'no :env key' do + let(:opts) { Hash.new } + + it 'does no slicing without the :env option' do + subject.read(file_path, opts) + subject.should == default_params.merge(reload: 'whatever').merge(file_params) + end + end + end + end - it 'slices out a different subhash with a different :env' do - @config.read_yaml(@yaml_with_subenvs, :env => :production) - @config.should == { :reload => false, :my_param => 'default_val', :also_a_param => true } - end + context '#save!' do + let(:fake_file) { StringIO.new('', 'w') } - it 'does no slicing without the :env option' do - @config.read_yaml(@yaml_with_subenvs) - @config.should == { :development => { :reload => true }, :production => { :reload => false }, :reload => :whatever, :my_param => 'default_val', :also_a_param => true } + context 'given an absolute pathname' do + let(:file_path) { '/absolute/path.yaml' } + + it 'saves the filename as given' do + File.should_receive(:open).with(file_path, 'w').and_yield(fake_file) + fake_file.should_receive(:<<).with(default_params.to_yaml) + subject.save! file_path end + end + + context 'given a simple pathname' do + let(:file_path) { 'simple_path.yaml' } - it 'has no effect if the key given by :env option is absent' do - @config.read_yaml(@yaml_with_subenvs, :env => :foobar) - @config.should == { :reload => :whatever, :my_param => 'default_val', :also_a_param => true } + it 'saves the filename in the default config dir' do + File.should_receive(:open).with(File.join(subject.default_conf_dir, file_path), 'w').and_yield(fake_file) + fake_file.should_receive(:<<).with(default_params.to_yaml) + subject.save! file_path end - - it 'lets you use a string if the loading hash has a string' do - yaml_with_string_subenv = { 'john_woo' => { :reload => :sideways }}.to_yaml - @config.read_yaml(yaml_with_string_subenv, :env => 'john_woo') - @config.should == { :reload => :sideways, :my_param => 'default_val', :also_a_param => true } + + it 'ensures the directory exists' do + File.should_receive(:open).with(File.join(subject.default_conf_dir, file_path), 'w').and_yield(fake_file) + FileUtils.should_receive(:mkdir_p).with(subject.default_conf_dir.to_s) + subject.save! file_path end end end - - describe 'saves to a config file' do - it 'with an absolute pathname, as given' do - fake_file = StringIO.new('', 'w') - File.should_receive(:open).with(%r{/fake/path.yaml}, 'w').and_yield(fake_file) - fake_file.should_receive(:<<).with({ :my_param => 'default_val', :also_a_param => true }.to_yaml) - @config.save! '/fake/path.yaml' + + context '#resolve!' do + around do |example| + Configliere::ParamParent.class_eval{ def resolve!() parent_method ; end } + example.run + Configliere::ParamParent.class_eval{ def resolve!() self ; end } end - - it 'with a simple pathname, in the default config dir' do - fake_file = StringIO.new('', 'w') - File.should_receive(:open).with(Configliere::DEFAULT_CONFIG_DIR + '/file.yaml', 'w').and_yield(fake_file) - fake_file.should_receive(:<<).with({ :my_param => 'default_val', :also_a_param => true }.to_yaml) - @config.save! 'file.yaml' - end - - it 'and ensures the directory exists' do - fake_file = StringIO.new('', 'w') - File.stub!(:open).with(%r{/fake/path.yaml}, 'w').and_yield(fake_file) - FileUtils.should_receive(:mkdir_p).with(%r{/fake}) - @config.save! '/fake/path.yaml' - end - end - - describe '#resolve!' do + it 'calls super and returns self' do - Configliere::ParamParent.class_eval do def resolve!() dummy ; end ; end - @config.should_receive(:dummy) - @config.resolve!.should equal(@config) - Configliere::ParamParent.class_eval do def resolve!() self ; end ; end + subject.should_receive(:parent_method) + subject.resolve!.should equal(subject) end end - + describe '#validate!' do + around do |example| + Configliere::ParamParent.class_eval{ def validate!() parent_method ; end } + example.run + Configliere::ParamParent.class_eval{ def validate!() self ; end } + end + it 'calls super and returns self' do - Configliere::ParamParent.class_eval do def validate!() dummy ; end ; end - @config.should_receive(:dummy) - @config.validate!.should equal(@config) - Configliere::ParamParent.class_eval do def validate!() self ; end ; end + subject.should_receive(:parent_method) + subject.validate!.should equal(subject) end end + context '#load_configuration_in_order!' do + let(:scope) { 'test' } + + before{ subject.stub(:determine_conf_location).and_return('conf_dir') } + + it 'resolves configuration in order' do + subject.should_receive(:determine_conf_location).with(:machine, scope).ordered + subject.should_receive(:determine_conf_location).with(:user, scope).ordered + subject.should_receive(:determine_conf_location).with(:app, scope).ordered + subject.should_receive(:resolve!).ordered + subject.load_configuration_in_order!(scope) + end + end end