test: cover OrmSerializationTest, greeting
This commit is contained in:
1 parent
c791df50e0
commit
25beb85254
2 files changed
+191
No files matched your search
@@ -0,0 +1,145 @@
|
||||
require 'minitest/autorun'
|
||||
require 'json'
|
||||
require 'prism'
|
||||
require 'tmpdir'
|
||||
|
||||
class OrmSerializationTest < Minitest::Test
|
||||
def setup
|
||||
@dir = Dir.mktmpdir('prism-serialization-store')
|
||||
@store = Prism::Orm::Store.new(File.join(@dir, 'test.pstore'))
|
||||
@store.create_table(:authors, %w[id name email password_digest created_at])
|
||||
@store.create_table(:articles, %w[id author_id title body])
|
||||
|
||||
author_class = Class.new(Prism::Orm::Model) do
|
||||
table_name :authors
|
||||
has_many :articles, class_name: 'Article', foreign_key: 'author_id'
|
||||
has_secure_password validations: false
|
||||
|
||||
def greeting
|
||||
"hi #{name}"
|
||||
end
|
||||
end
|
||||
article_class = Class.new(Prism::Orm::Model) do
|
||||
table_name :articles
|
||||
belongs_to :author, class_name: 'Author', foreign_key: 'author_id'
|
||||
end
|
||||
[author_class, article_class].each { |klass| klass.store = @store }
|
||||
Object.const_set(:Author, author_class)
|
||||
Object.const_set(:Article, article_class)
|
||||
end
|
||||
|
||||
def teardown
|
||||
FileUtils.remove_entry(@dir)
|
||||
%i[Author Article].each { |name| Object.send(:remove_const, name) if Object.const_defined?(name) }
|
||||
end
|
||||
|
||||
def test_serializable_hash_returns_all_attributes_by_default
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com')
|
||||
hash = author.serializable_hash
|
||||
assert_equal 'Ada', hash['name']
|
||||
assert_equal 'ada@example.com', hash['email']
|
||||
assert_equal author.id, hash['id']
|
||||
end
|
||||
|
||||
def test_only_filters_to_named_attributes
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com')
|
||||
hash = author.serializable_hash(only: :name)
|
||||
assert_equal({ 'name' => 'Ada' }, hash)
|
||||
end
|
||||
|
||||
def test_except_removes_named_attributes
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com')
|
||||
hash = author.serializable_hash(except: [:email, :created_at, :updated_at])
|
||||
assert_equal %w[id name], hash.keys.sort
|
||||
end
|
||||
|
||||
def test_methods_option_adds_computed_values
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com')
|
||||
hash = author.serializable_hash(only: :name, methods: :greeting)
|
||||
assert_equal 'hi Ada', hash['greeting']
|
||||
end
|
||||
|
||||
def test_password_digest_is_hidden_from_json_by_default
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com', password: 'sekret123')
|
||||
refute_nil author['password_digest']
|
||||
hash = author.serializable_hash
|
||||
refute hash.key?('password_digest'), 'password_digest must not leak through default serialization'
|
||||
end
|
||||
|
||||
def test_explicit_only_can_override_the_default_hide
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com', password: 'sekret123')
|
||||
hash = author.serializable_hash(only: %i[name password_digest])
|
||||
assert hash.key?('password_digest'), 'an explicit only: is a deliberate opt-in, it must win'
|
||||
end
|
||||
|
||||
def test_as_json_stringifies_time_columns
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com')
|
||||
assert_kind_of Time, author['created_at'], 'sanity check: raw attribute is a Time'
|
||||
json = author.as_json
|
||||
assert_kind_of String, json['created_at']
|
||||
assert_equal author['created_at'].iso8601, json['created_at']
|
||||
end
|
||||
|
||||
def test_to_json_round_trips_through_json_generate
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com')
|
||||
parsed = JSON.parse(author.to_json)
|
||||
assert_equal 'Ada', parsed['name']
|
||||
refute parsed.key?('password_digest')
|
||||
end
|
||||
|
||||
def test_json_generate_on_a_bare_record_uses_to_json
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com')
|
||||
parsed = JSON.parse(JSON.generate(author))
|
||||
assert_equal 'Ada', parsed['name']
|
||||
end
|
||||
|
||||
def test_include_serializes_a_belongs_to_association
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com')
|
||||
article = Article.create!(author_id: author.id, title: 'Hello', body: 'World')
|
||||
hash = article.serializable_hash(include: :author)
|
||||
assert_equal 'Ada', hash['author']['name']
|
||||
end
|
||||
|
||||
def test_include_serializes_a_has_many_collection
|
||||
author = Author.create!(name: 'Ada', email: 'ada@example.com')
|
||||
Article.create!(author_id: author.id, title: 'One', body: 'x')
|
||||
Article.create!(author_id: author.id, title: 'Two', body: 'y')
|
||||
hash = author.serializable_hash(only: :name, include: { articles: { only: :title } })
|
||||
titles = hash['articles'].map { |row| row['title'] }
|
||||
assert_equal %w[One Two], titles.sort
|
||||
end
|
||||
|
||||
def test_include_with_nil_belongs_to_yields_nil
|
||||
orphan = Article.create!(author_id: nil, title: 'Orphan', body: 'x')
|
||||
hash = orphan.serializable_hash(include: :author)
|
||||
assert_nil hash['author']
|
||||
end
|
||||
|
||||
def test_relation_as_json_serializes_each_record
|
||||
Author.create!(name: 'Ada', email: 'a@example.com')
|
||||
Author.create!(name: 'Bea', email: 'b@example.com')
|
||||
rows = Author.all.as_json(only: :name)
|
||||
assert_equal [{ 'name' => 'Ada' }, { 'name' => 'Bea' }], rows.sort_by { |row| row['name'] }
|
||||
end
|
||||
|
||||
def test_relation_to_json_produces_a_json_array_without_leaking_hidden_columns
|
||||
Author.create!(name: 'Ada', email: 'a@example.com', password: 'sekret123')
|
||||
parsed = JSON.parse(Author.all.to_json)
|
||||
assert_equal 1, parsed.size
|
||||
refute parsed.first.key?('password_digest')
|
||||
end
|
||||
|
||||
def test_hide_from_json_is_inherited_by_subclasses
|
||||
base_class = Class.new(Prism::Orm::Model) { table_name :authors }
|
||||
base_class.hide_from_json(:email)
|
||||
Object.const_set(:BaseAuthor, base_class)
|
||||
sub_class = Class.new(base_class) { table_name :authors }
|
||||
Object.const_set(:SubAuthor, sub_class)
|
||||
sub_class.store = @store
|
||||
|
||||
record = sub_class.create!(name: 'Ada', email: 'ada@example.com')
|
||||
refute record.serializable_hash.key?('email')
|
||||
ensure
|
||||
%i[BaseAuthor SubAuthor].each { |name| Object.send(:remove_const, name) if Object.const_defined?(name) }
|
||||
end
|
||||
end
|
||||
@@ -104,6 +104,52 @@ class OrmStoreTest < Minitest::Test
|
||||
assert_empty @store.applied_migrations
|
||||
end
|
||||
|
||||
def test_insert_emits_sql_prism_event
|
||||
@store.create_table(:users, %w[id name])
|
||||
events = []
|
||||
subscriber = Prism::Instrumentation.subscribe('sql.prism') { |event| events << event }
|
||||
begin
|
||||
@store.insert(:users, name: 'foksiu')
|
||||
ensure
|
||||
Prism::Instrumentation.unsubscribe(subscriber)
|
||||
end
|
||||
|
||||
assert_equal 1, events.size
|
||||
assert_equal 'INSERT', events.first.payload[:operation]
|
||||
assert_equal 'users', events.first.payload[:table]
|
||||
end
|
||||
|
||||
def test_find_and_all_and_count_emit_select_events
|
||||
@store.create_table(:users, %w[id name])
|
||||
id = @store.insert(:users, name: 'foksiu')
|
||||
events = []
|
||||
subscriber = Prism::Instrumentation.subscribe('sql.prism') { |event| events << event }
|
||||
begin
|
||||
@store.find(:users, id)
|
||||
@store.all(:users)
|
||||
@store.count(:users)
|
||||
ensure
|
||||
Prism::Instrumentation.unsubscribe(subscriber)
|
||||
end
|
||||
|
||||
assert_equal %w[SELECT SELECT], events.first(2).map { |e| e.payload[:operation] }
|
||||
assert_equal 'SELECT COUNT', events.last.payload[:operation]
|
||||
end
|
||||
|
||||
def test_update_missing_record_still_emits_event_with_exception
|
||||
@store.create_table(:users, %w[id name])
|
||||
events = []
|
||||
subscriber = Prism::Instrumentation.subscribe('sql.prism') { |event| events << event }
|
||||
begin
|
||||
assert_raises(Prism::Orm::Store::RecordNotFound) { @store.update(:users, 999, name: 'nope') }
|
||||
ensure
|
||||
Prism::Instrumentation.unsubscribe(subscriber)
|
||||
end
|
||||
|
||||
assert_equal 1, events.size
|
||||
assert_equal 'Prism::Orm::Store::RecordNotFound', events.first.payload[:exception].first
|
||||
end
|
||||
|
||||
def test_data_survives_reopening_the_store
|
||||
@store.create_table(:users, %w[id name])
|
||||
@store.insert(:users, name: 'persisted-foksiu')
|
||||
|
||||
Reference in new issue
Block a user