# frozen_string_literal: true require_relative '../../spec_helper' module Seahorse module Client describe Configuration do let(:config) { Configuration.new } describe '#add_option' do it 'defines a getter' do config.add_option(:name) expect(config.build!).to respond_to(:name) end it 'defaults the value to nil' do config.add_option(:name) expect(config.build!.name).to be(nil) end it 'accepts a default value' do config.add_option(:name, 'John Doe') expect(config.build!.name).to eq('John Doe') end it 'accepts blocks' do config.add_option(:name) { 'John Doe' } expect(config.build!.name).to eq('John Doe') end it 'accepts blocks with an arity of 1, yielding self' do config.add_option(:name) { 'John Doe' } config.add_option(:username) { |cfg| cfg.name.gsub(/\W+/, '').downcase } expect(config.build!.name).to eq('John Doe') expect(config.build!.username).to eq('johndoe') end it 'blocks can rely on other blocks' do config.add_option(:base) { 2 } config.add_option(:next) { |cfg| cfg.base * 2 } config.add_option(:last) { |cfg| cfg.next * 3 } cfg = config.build! expect(cfg.last).to eq(12) expect(cfg.next).to eq(4) expect(cfg.base).to eq(2) end it 'blocks work with supplied values' do config.add_option(:base) { 2 } config.add_option(:next) { |cfg| cfg.base * 2 } config.add_option(:last) { |cfg| cfg.next * 3 } cfg = config.build!(base: 1, next: 1) expect(cfg.base).to eq(1) expect(cfg.next).to eq(1) expect(cfg.last).to eq(3) end it 'replaces previous default values when called twice' do config.add_option(:name, 'abc') config.add_option(:name, 'xyz') expect(config.build!.name).to eq('xyz') end it 'returns self so it can be chained' do c = config.add_option(:name).add_option(:color) expect(c).to be(config) expect(c.build!.members).to eq([:color, :name]) end end describe '#build!' do it 'returns a Struct' do expect(config.add_option(:opt).build!).to be_kind_of(Struct) end it 'accepts a hash of options' do config.add_option(:size, 'default') config.add_option(:color, 'default') cfg = config.build!(size: 'large', color: 'red') expect(cfg.size).to eq('large') expect(cfg.color).to eq('red') end it 'raises an argument error for uknown options' do config.add_option(:known) expect { config.build!(unknown: 'option') }.to raise_error(ArgumentError, /invalid configuration option/) end it 'resolves nested dependent options' do config.add_option(:base, 1) config.add_option(:top) { |cfg| cfg.middle } config.add_option(:middle) { |cfg| cfg.base } expect(config.build!.top).to eq(1) end it 'does not resolve procs passed as args' do value = lambda {} config.add_option(:proc, value) expect(config.build!.proc).to be(value) end it 'resolves defaults in LIFO order until a non-nil value is found' do # default cost is 10 config.add_option(:cost) { 10 } # increase cost for red items config.add_option(:cost) { |cfg| cfg.color == 'red' ? 9001 : nil } config.add_option(:color) expect(config.build!(color: 'green').cost).to eq(10) expect(config.build!(color: 'red').cost).to eq(9001) # over 9000! end end end end end