require 'spec_helper' require 'tempfile' class Settings extend Chamber end describe Chamber do before do Settings.clear! end describe '.source' do context 'when an invalid option is specified' do let(:options) do { foo: 'bar' } end it 'raises ChamberInvalidOptionError' do expect { Settings.source('filename', options) }.to raise_error(Chamber::ChamberInvalidOptionError) end end context 'when no options are specified' do it 'does not raise an error' do expect { Settings.source('filename') }.not_to raise_error end end context 'when valid options are specified' do context 'and options only contains :namespace' do let(:options) do { namespace: 'bar' } end it 'does not raise an error' do expect { Settings.source('filename', options) }.not_to raise_error end end context 'and options only contains :override_from_environment' do let(:options) do { override_from_environment: 'bar' } end it 'does not raise an error' do expect { Settings.source('filename', options) }.not_to raise_error end end context 'and options contains both :namespace and :override_from_environment' do let(:options) do { namespace: 'bar', override_from_environment: 'bar' } end it 'does not raise an error' do expect { Settings.source('filename', options) }.not_to raise_error end end end end describe '.load!' do context 'when a non-existent file is specified' do let(:file) { Tempfile.new('test') } let!(:filename) { file.path } before do file.close file.unlink expect(File.exists?(filename)).to be_false Settings.source filename end it 'does not raise an error' do expect { Settings.load! }.not_to raise_error end it 'leaves the instance empty' do Settings.load! expect(Settings.instance).to be_empty end end context 'when an existing file is specified' do let(:file) { Tempfile.new('test') } let(:filename) { file.path } let(:content) do <<-CONTENT secret: environment: CHAMBER_TEST development: foo: bar dev test: foo: bar test CONTENT end before do file.write(content) file.close end after do file.unlink end context 'and no options are specified' do before { Settings.source(filename) } let(:expected) do { 'secret' => { 'environment' => 'CHAMBER_TEST' }, 'development' => { 'foo' => 'bar dev' }, 'test' => { 'foo' => 'bar test' } } end it 'loads all settings' do Settings.load! expect(Settings.instance.to_hash).to eq expected end end context 'and the :namespace option is specified' do before { Settings.source(filename, namespace: namespace) } context 'and it is valid' do let(:namespace) { 'development' } let(:expected) do { 'foo' => 'bar dev' } end it 'loads settings for the specified namespace' do Settings.load! expect(Settings.instance.to_hash).to eq expected end end context 'and it is not valid' do let(:namespace) { 'staging' } it 'raises a KeyError' do expect { Settings.load! }.to raise_error(KeyError) end end end context 'and the :override_from_environment option is specified' do before { Settings.source(filename, override_from_environment: true) } context 'and the environment variable is present' do before { ENV['CHAMBER_TEST'] = 'value' } it 'overrides the settings from the environment' do Settings.load! expect(Settings.instance.secret).to eq 'value' end end context 'and the environment variable is not present' do before { ENV.delete('CHAMBER_TEST') } it 'sets the value to nil' do Settings.load! expect(Settings.instance.secret).to be_nil end end end end end describe '.reload!' do context 'when a filename is changed after it is sourced and loaded' do let(:file) { Tempfile.new('test') } let!(:filename) { file.path } let(:content) do <<-CONTENT initial: value CONTENT end let(:modified) do <<-MODIFIED modified: changed MODIFIED end before do file.write(content) file.close Settings.source(filename) Settings.load! end after do file.unlink end it 'reloads the settings' do File.open(filename, 'w') { |writer| writer.write(modified) } expect { Settings.reload! }.to change { Settings.instance.to_hash }.from({ 'initial' => 'value' }).to({ 'modified' => 'changed' }) end end end describe '.instance' do it 'is a Hashie::Mash' do expect(Settings.instance).to be_a(Hashie::Mash) end end describe '.env' do it 'is aliased to :instance' do expect(Settings.method(:env)).to eq Settings.method(:instance) end end end