# frozen_string_literal: true require 'spec_helper' RSpec.describe DeclarativeEnum do let(:enum_module) do Module.new do extend DeclarativeEnum key :my_enum name 'MyEnumName' description "Enum description" define do foo value: 0, description: 'description of foo' bar value: 1, description: 'description of bar' end end end let(:original_definition) do { foo: { description: 'description of foo', value: 0 }, bar: { description: 'description of bar', value: 1 } } end describe '.key' do subject(:key) { enum_module.key(new_key) } context 'when the argument is set' do let(:new_key) { :new_enum_key } it 'changes the key' do expect { key }.to change { enum_module.key }.from(:my_enum).to(:new_enum_key) end end context 'when the argument is `nil`' do let(:new_key) { nil } it { is_expected.to eq(:my_enum) } end end describe '.name' do subject(:name) { enum_module.name(new_name) } context 'when the argument is set' do let(:new_name) { 'NewMyEnumName' } it 'changes the name' do expect { name }.to change { enum_module.name }.from('MyEnumName').to('NewMyEnumName') end end context 'when the argument is `nil`' do let(:new_name) { nil } it { is_expected.to eq('MyEnumName') } end end describe '.description' do subject(:description) { enum_module.description(new_description) } context 'when the argument is set' do let(:new_description) { 'New enum description' } it 'changes the description' do expect { description }.to change { enum_module.description }.from('Enum description').to('New enum description') end end context 'when the argument is `nil`' do let(:new_description) { nil } it { is_expected.to eq('Enum description') } end end describe '.define' do subject(:define) { enum_module.define(&block) } context 'when there is a block given' do context 'when the given block tries to register the same key' do let(:block) do proc do foo value: 2, description: 'description of foo' end end it 'raises a `KeyCollisionError`' do expect { define }.to raise_error(DeclarativeEnum::Builder::KeyCollisionError) end end context 'when the given block does not try to register the same key' do let(:expected_new_definition) { original_definition.merge(zoo: { description: 'description of zoo', value: 0 }) } let(:block) do proc do zoo value: 0, description: 'description of zoo' end end it 'appends the new definition' do expect { define }.to change { enum_module.definition }.from(original_definition).to(expected_new_definition) end end end context 'when there is no block given' do let(:block) { nil } it 'raises a LocalJumpError' do expect { define }.to raise_error(LocalJumpError) end end end describe '.definition' do subject { enum_module.definition } it { is_expected.to eq(original_definition) } end describe 'extending the enum module' do let(:extended_definition) { original_definition.merge(zoo: { value: 2, description: 'description of zoo' }) } let(:new_enum_module) do Module.new do extend DeclarativeEnum define do zoo value: 2, description: 'description of zoo' end end end subject(:prepend_new_enum_module) { enum_module.prepend(new_enum_module) } it 'extends the values of the base enum module' do expect { prepend_new_enum_module }.to change { enum_module.definition }.from(original_definition) .to(extended_definition) end end end