require "spec_helper" describe ActiveEnum::Base do describe ".store" do it 'should load the storage class instance using the storage setting' do expect(ActiveEnum::Base.send(:store)).to be_instance_of(ActiveEnum::Storage::MemoryStore) end end describe ".enum_classes" do it 'should return all enum classes defined use class definition' do ActiveEnum.enum_classes = [] class NewEnum < ActiveEnum::Base; end expect(ActiveEnum.enum_classes).to eq([NewEnum]) end it 'should return all enum classes defined using define block' do ActiveEnum.enum_classes = [] ActiveEnum.define do enum(:bulk_new_enum) { } end expect(ActiveEnum.enum_classes).to eq([BulkNewEnum]) end end describe ".values" do it 'should return an empty array when no values defined' do expect(define_enum.values).to eq([]) end it 'should return an array of arrays with all values defined as [id, name]' do enum = define_enum do value name: 'Name 1' value name: 'Name 2' end expect(enum.values).to eq([[1,'Name 1'], [2, 'Name 2']]) end end describe ".value" do it 'should allow me to define a value with an id and name' do enum = define_enum do value id: 1, name: 'Name' end expect(enum.values).to eq([[1,'Name']]) end it 'should allow me to define a value with a name only' do enum = define_enum do value name: 'Name' end expect(enum.values).to eq([[1,'Name']]) end it 'should allow me to define a value as hash with id as key and name as value' do enum = define_enum do value 1 => 'Name' end expect(enum.values).to eq([[1,'Name']]) end it 'should allow to define meta data value with extra key value pairs' do enum = define_enum do value id: 1, name: 'Name', description: 'extra' end expect(enum.values).to eq([[1,'Name',{description: 'extra'}]]) end it 'should increment value ids when defined without ids' do enum = define_enum do value name: 'Name 1' value name: 'Name 2' end expect(enum.values).to eq([[1,'Name 1'], [2, 'Name 2']]) end it 'should raise error if the id is a duplicate' do expect { define_enum do value id: 1, name: 'Name 1' value id: 1, name: 'Name 2' end }.to raise_error(ActiveEnum::DuplicateValue) end it 'should raise error if the name is a duplicate' do expect { define_enum do value id: 1, name: 'Name' value id: 2, name: 'Name' end }.to raise_error(ActiveEnum::DuplicateValue) end end describe ".meta" do it 'should return meta values hash for a given index value' do enum = define_enum do value id: 1, name: 'Name', description: 'extra' end expect(enum.meta(1)).to eq({description: 'extra'}) end it 'should return empty hash for index with no meta defined' do enum = define_enum do value id: 1, name: 'Name' end expect(enum.meta(1)).to eq({}) end context "with raise_on_not_found: false" do let(:enum) { define_enum do value id: 1, name: 'Name', description: 'extra' end } it "should raise ActiveEnum::NotFound for missing id" do expect { enum.meta(0, raise_on_not_found: true) }.to raise_error(ActiveEnum::NotFound) end it "should raise ActiveEnum::NotFound for missing name" do expect { enum.meta('Not a value', raise_on_not_found: true) }.to raise_error(ActiveEnum::NotFound) end end end context "sorting" do it 'should return values ascending by default' do enum = define_enum do value id: 2, name: 'Name 2' value id: 1, name: 'Name 1' end expect(enum.values).to eq([[1,'Name 1'], [2, 'Name 2']]) end it 'should return sorted values by id using order setting' do enum = define_enum do order :desc value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end expect(enum.values).to eq([[2, 'Name 2'], [1,'Name 1']]) end it 'should return sorted values by id using order setting' do enum = define_enum do order :natural value id: 3, name: 'Name 3' value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end expect(enum.values).to eq([[3,'Name 3'], [1,'Name 1'], [2, 'Name 2']]) end end describe ".ids" do it 'should return array of ids' do enum = define_enum do value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end expect(enum.ids).to eq([1,2]) end end describe ".names" do it 'should return array of names' do enum = define_enum do value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end expect(enum.names).to eq(['Name 1', 'Name 2']) end end context "element reference method" do let(:enum) { define_enum do value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end } it 'should return name when given an id' do expect(enum[1]).to eq('Name 1') end it 'should return id when given a name' do expect(enum['Name 1']).to eq(1) end it 'should return id when given a symbol of the name' do expect(enum[:Name_1]).to eq(1) expect(enum[:name_1]).to eq(1) end context "for missing value" do it "should return nil for missing id" do expect(enum['Not a value']).to eq nil end it "should return nil for missing name" do expect(enum[0]).to eq nil end context "with config raise_on_not_found" do with_config :raise_on_not_found, true it "should raise ActiveEnum::NotFound for missing id" do expect { enum['Not a value'] }.to raise_error(ActiveEnum::NotFound) end it "should raise ActiveEnum::NotFound for missing name" do expect { enum[0] }.to raise_error(ActiveEnum::NotFound) end end end end describe '.get' do with_config :raise_on_not_found, false let(:enum) { define_enum do value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end } context "with raise_on_not_found: false" do it "should raise ActiveEnum::NotFound for missing id" do expect { enum.get('Not a value', raise_on_not_found: true) }.to raise_error(ActiveEnum::NotFound) end it "should raise ActiveEnum::NotFound for missing name" do expect { enum.get(0, raise_on_not_found: true) }.to raise_error(ActiveEnum::NotFound) end end end describe ".include?" do let(:enum) { define_enum do value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end } it "should return true if value is a fixnum and matches an id" do expect(enum.include?(1)).to be_truthy end it "should return false if value is a fixnum and does not match an id" do expect(enum.include?(3)).to be_falsey end it "should return true if value is a string and matches a name" do expect(enum.include?('Name 1')).to be_truthy end it "should return false if value is a string and does not match a name" do expect(enum.include?('No match')).to be_falsey end end describe ".to_select" do it 'should return array for select helpers' do enum = define_enum do value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end expect(enum.to_select).to eq([['Name 1',1], ['Name 2',2]]) end it 'should return array sorted using order setting' do enum = define_enum do order :desc value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end expect(enum.to_select).to eq([['Name 2',2], ['Name 1',1]]) end end describe ".to_grouped_select" do it 'should return array for grouped select helpers grouped by meta key value' do enum = define_enum do value id: 1, name: 'Name 1', category: 'Foo' value id: 2, name: 'Name 2', category: 'Bar' end expect(enum.to_grouped_select(:category)).to eq([ [ 'Foo', [ ['Name 1',1] ] ], [ 'Bar', [ ['Name 2',2] ] ] ]) end it 'should group any value missing the group_by key by nil' do enum = define_enum do value id: 1, name: 'Name 1', category: 'Foo' value id: 2, name: 'Name 2' end expect(enum.to_grouped_select(:category)).to eq([ [ 'Foo', [ ['Name 1',1] ] ], [ nil, [ ['Name 2',2] ] ] ]) end it 'shoud transform group name with custom group transform proc' do enum = define_enum do value id: 1, name: 'Name 1', category: 'Foo' value id: 2, name: 'Name 2' end expect(enum.to_grouped_select(:category, group_transform: proc { |group| group.to_s.upcase })).to eq([ [ 'FOO', [ ['Name 1',1] ] ], [ '', [ ['Name 2',2] ] ] ]) end end describe ".to_h" do it 'should return hash of ids as keys and names as values' do enum = define_enum do value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end expect(enum.to_h).to eq({ 1 => 'Name 1', 2 => 'Name 2' }) end end describe ".length" do it 'should return number of values defined' do enum = define_enum do value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end expect(enum.length).to eq 2 end it 'should return 0 when no values defined' do enum = define_enum {} expect(enum.length).to eq 0 end it 'should be aliased as size' do enum = define_enum do value id: 1, name: 'Name 1' value id: 2, name: 'Name 2' end expect(enum.size).to eq enum.length end end def define_enum(&block) Class.new(ActiveEnum::Base, &block) end end