Files
prism/test/test_orm_enum.rb

180 lines
5.8 KiB
Ruby

require 'minitest/autorun'
require 'prism'
require 'tmpdir'
class OrmEnumTest < Minitest::Test
def setup
@dir = Dir.mktmpdir('prism-enum-store')
@store = Prism::Orm::Store.new(File.join(@dir, 'test.pstore'))
@store.create_table(:posts, %w[id title status role])
post_class = Class.new(Prism::Orm::Model) do
table_name :posts
enum :status, { draft: 0, published: 1, archived: 2 }
enum role: { author: 0, editor: 1 }, prefix: true
end
post_class.store = @store
Object.const_set(:EnumPost, post_class)
end
def teardown
FileUtils.remove_entry(@dir)
Object.send(:remove_const, :EnumPost) if Object.const_defined?(:EnumPost)
end
def test_reader_translates_raw_value_to_label
post = EnumPost.create!(title: 'a', status: :published)
assert_equal 'published', post.status
assert_equal 1, post['status']
end
def test_writer_accepts_symbol_string_or_raw_value
post = EnumPost.new(title: 'a')
post.status = :draft
assert_equal 0, post['status']
post.status = 'published'
assert_equal 1, post['status']
post.status = 2
assert_equal 'archived', post.status
end
def test_invalid_value_raises_argument_error_immediately
post = EnumPost.new(title: 'a')
assert_raises(ArgumentError) { post.status = :deleted }
end
def test_nil_clears_the_attribute
post = EnumPost.new(title: 'a', status: :draft)
post.status = nil
assert_nil post.status
assert_nil post['status']
end
def test_predicate_methods
post = EnumPost.new(title: 'a', status: :draft)
assert post.draft?
refute post.published?
post.status = :published
assert post.published?
refute post.draft?
end
def test_bang_method_sets_and_persists
post = EnumPost.create!(title: 'a', status: :draft)
post.published!
assert_equal 'published', post.status
assert_equal 'published', EnumPost.find(post.id).status
end
def test_class_scope_matches_generated_predicate
EnumPost.create!(title: 'draft one', status: :draft)
EnumPost.create!(title: 'published one', status: :published)
EnumPost.create!(title: 'published two', status: :published)
assert_equal 2, EnumPost.published.count
assert_equal ['published one', 'published two'], EnumPost.published.order(:title).map(&:title)
end
def test_mapping_accessor
assert_equal({ 'draft' => 0, 'published' => 1, 'archived' => 2 }, EnumPost.statuses)
end
def test_prefixed_enum_method_names
post = EnumPost.new(title: 'a', role: :editor)
assert post.role_editor?
refute post.role_author?
assert EnumPost.respond_to?(:role_editor)
end
def test_duplicate_raw_values_are_rejected_at_declaration
assert_raises(ArgumentError) do
Class.new(Prism::Orm::Model) do
table_name :posts
enum :status, { draft: 0, published: 0 }
end
end
end
def test_serializable_hash_shows_the_label_not_the_raw_value
post = EnumPost.create!(title: 'a', status: :published, role: :editor)
json = post.as_json
assert_equal 'published', json['status']
assert_equal 'editor', json['role']
end
def test_where_translates_symbol_label_to_raw_value
draft = EnumPost.create!(title: 'a', status: :draft)
EnumPost.create!(title: 'b', status: :published)
assert_equal [draft], EnumPost.where(status: :draft).to_a
end
def test_where_translates_string_label_to_raw_value
EnumPost.create!(title: 'a', status: :draft)
published = EnumPost.create!(title: 'b', status: :published)
assert_equal [published], EnumPost.where(status: 'published').to_a
end
def test_where_still_accepts_the_raw_stored_value_directly
draft = EnumPost.create!(title: 'a', status: :draft)
EnumPost.create!(title: 'b', status: :published)
assert_equal [draft], EnumPost.where(status: 0).to_a
end
def test_where_translates_an_array_of_labels_for_in_style_matching
draft = EnumPost.create!(title: 'a', status: :draft)
published = EnumPost.create!(title: 'b', status: :published)
EnumPost.create!(title: 'c', status: :archived)
result = EnumPost.where(status: [:draft, 'published']).order(:title).to_a
assert_equal [draft, published], result
end
def test_where_translates_labels_inside_an_operator_hash
EnumPost.create!(title: 'a', status: :draft)
published = EnumPost.create!(title: 'b', status: :published)
archived = EnumPost.create!(title: 'c', status: :archived)
result = EnumPost.where(status: { not_in: [:draft] }).order(:title).to_a
assert_equal [published, archived], result
gt_result = EnumPost.where(status: { gt: :draft }).order(:title).to_a
assert_equal [published, archived], gt_result
end
def test_not_translates_enum_labels
draft = EnumPost.create!(title: 'a', status: :draft)
EnumPost.create!(title: 'b', status: :published)
assert_equal [draft], EnumPost.not(status: :published).to_a
end
def test_find_by_translates_enum_labels
published = EnumPost.create!(title: 'a', status: :published)
assert_equal published, EnumPost.find_by(status: :published)
assert_nil EnumPost.find_by(status: :archived)
end
def test_where_with_unknown_enum_label_raises_argument_error
assert_raises(ArgumentError) { EnumPost.where(status: :deleted).to_a }
end
def test_where_on_non_enum_column_is_unaffected
post = EnumPost.create!(title: 'unique-title', status: :draft)
assert_equal [post], EnumPost.where(title: 'unique-title').to_a
end
def test_subclass_inherits_enum_definitions
subclass = Class.new(EnumPost)
subclass.store = @store
subclass.table_name(:posts)
Object.const_set(:EnumSubPost, subclass)
post = EnumSubPost.new(title: 'a', status: :archived)
assert_equal 'archived', post.status
assert post.archived?
ensure
Object.send(:remove_const, :EnumSubPost) if Object.const_defined?(:EnumSubPost)
end
end