discourse/spec/components/concern/has_custom_fields_spec.rb
Josh Soref 59097b207f
DEV: Correct typos and spelling mistakes (#12812)
Over the years we accrued many spelling mistakes in the code base. 

This PR attempts to fix spelling mistakes and typos in all areas of the code that are extremely safe to change 

- comments
- test descriptions
- other low risk areas
2021-05-21 11:43:47 +10:00

369 lines
12 KiB
Ruby

# frozen_string_literal: true
require "rails_helper"
describe HasCustomFields do
context "custom_fields" do
before do
DB.exec("create temporary table custom_fields_test_items(id SERIAL primary key)")
DB.exec("create temporary table custom_fields_test_item_custom_fields(id SERIAL primary key, custom_fields_test_item_id int, name varchar(256) not null, value text, created_at TIMESTAMP, updated_at TIMESTAMP)")
DB.exec(<<~SQL)
CREATE UNIQUE INDEX ON custom_fields_test_item_custom_fields (custom_fields_test_item_id)
WHERE NAME = 'rare'
SQL
class CustomFieldsTestItem < ActiveRecord::Base
include HasCustomFields
end
class CustomFieldsTestItemCustomField < ActiveRecord::Base
belongs_to :custom_fields_test_item
end
end
after do
DB.exec("drop table custom_fields_test_items")
DB.exec("drop table custom_fields_test_item_custom_fields")
# this weakref in the descendant tracker should clean up the two tests
# if this becomes an issue we can revisit (watch out for erratic tests)
Object.send(:remove_const, :CustomFieldsTestItem)
Object.send(:remove_const, :CustomFieldsTestItemCustomField)
end
it "allows simple modification of custom fields" do
test_item = CustomFieldsTestItem.new
expect(test_item.custom_fields["a"]).to eq(nil)
test_item.custom_fields["bob"] = "marley"
test_item.custom_fields["jack"] = "black"
test_item.save
test_item = CustomFieldsTestItem.find(test_item.id)
expect(test_item.custom_fields["bob"]).to eq("marley")
expect(test_item.custom_fields["jack"]).to eq("black")
test_item.custom_fields.delete("bob")
test_item.custom_fields["jack"] = "jill"
test_item.save
test_item = CustomFieldsTestItem.find(test_item.id)
expect(test_item.custom_fields).to eq("jack" => "jill")
end
it "casts integers to string without error" do
test_item = CustomFieldsTestItem.new
expect(test_item.custom_fields["a"]).to eq(nil)
test_item.custom_fields["a"] = 0
expect(test_item.custom_fields["a"]).to eq(0)
test_item.save
# should be casted right after saving
expect(test_item.custom_fields["a"]).to eq("0")
test_item = CustomFieldsTestItem.find(test_item.id)
expect(test_item.custom_fields["a"]).to eq("0")
end
it "reloads from the database" do
test_item = CustomFieldsTestItem.new
test_item.custom_fields["a"] = 0
expect(test_item.custom_fields["a"]).to eq(0)
test_item.save
# should be casted right after saving
expect(test_item.custom_fields["a"]).to eq("0")
DB.exec("UPDATE custom_fields_test_item_custom_fields SET value='1' WHERE custom_fields_test_item_id=? AND name='a'", test_item.id)
# still the same, did not load
expect(test_item.custom_fields["a"]).to eq("0")
# refresh loads from database
expect(test_item.reload.custom_fields["a"]).to eq("1")
expect(test_item.custom_fields["a"]).to eq("1")
end
it "actually saves on double save" do
test_item = CustomFieldsTestItem.new
test_item.custom_fields = { "a" => "b" }
test_item.save
test_item.custom_fields["c"] = "d"
test_item.save
db_item = CustomFieldsTestItem.find(test_item.id)
expect(db_item.custom_fields).to eq("a" => "b", "c" => "d")
end
it "handles arrays properly" do
CustomFieldsTestItem.register_custom_field_type "array", [:integer]
test_item = CustomFieldsTestItem.new
test_item.custom_fields = { "array" => ["1"] }
test_item.save
db_item = CustomFieldsTestItem.find(test_item.id)
expect(db_item.custom_fields).to eq("array" => [1])
test_item = CustomFieldsTestItem.new
test_item.custom_fields = { "a" => ["b", "c", "d"] }
test_item.save
db_item = CustomFieldsTestItem.find(test_item.id)
expect(db_item.custom_fields).to eq("a" => ["b", "c", "d"])
db_item.custom_fields.update('a' => ['c', 'd'])
db_item.save
expect(db_item.custom_fields).to eq("a" => ["c", "d"])
# It can be updated to the exact same value
db_item.custom_fields.update('a' => ['c'])
db_item.save
expect(db_item.custom_fields).to eq("a" => "c")
db_item.custom_fields.update('a' => ['c'])
db_item.save
expect(db_item.custom_fields).to eq("a" => "c")
db_item.custom_fields.delete('a')
expect(db_item.custom_fields).to eq({})
end
it "casts integers in arrays properly without error" do
test_item = CustomFieldsTestItem.new
test_item.custom_fields = { "a" => ["b", 10, "d"] }
test_item.save
expect(test_item.custom_fields).to eq("a" => ["b", "10", "d"])
db_item = CustomFieldsTestItem.find(test_item.id)
expect(db_item.custom_fields).to eq("a" => ["b", "10", "d"])
end
it "supports type coercion" do
test_item = CustomFieldsTestItem.new
CustomFieldsTestItem.register_custom_field_type("bool", :boolean)
CustomFieldsTestItem.register_custom_field_type("int", :integer)
CustomFieldsTestItem.register_custom_field_type("json", :json)
test_item.custom_fields = { "bool" => true, "int" => 1, "json" => { "foo" => "bar" } }
test_item.save
test_item.reload
expect(test_item.custom_fields).to eq("bool" => true, "int" => 1, "json" => { "foo" => "bar" })
before_ids = CustomFieldsTestItemCustomField.where(custom_fields_test_item_id: test_item.id).pluck(:id)
test_item.custom_fields["bool"] = false
test_item.save
after_ids = CustomFieldsTestItemCustomField.where(custom_fields_test_item_id: test_item.id).pluck(:id)
# we updated only 1 custom field, so there should be only 1 different id
expect((before_ids - after_ids).size).to eq(1)
end
it "doesn't allow simple modifications to interfere" do
test_item = CustomFieldsTestItem.new
expect(test_item.custom_fields["a"]).to eq(nil)
test_item.custom_fields["bob"] = "marley"
test_item.custom_fields["jack"] = "black"
test_item.save
test_item2 = CustomFieldsTestItem.new
expect(test_item2.custom_fields["x"]).to eq(nil)
test_item2.custom_fields["sixto"] = "rodriguez"
test_item2.custom_fields["de"] = "la playa"
test_item2.save
test_item = CustomFieldsTestItem.find(test_item.id)
test_item2 = CustomFieldsTestItem.find(test_item2.id)
expect(test_item.custom_fields).to eq("jack" => "black", "bob" => "marley")
expect(test_item2.custom_fields).to eq("sixto" => "rodriguez", "de" => "la playa")
end
it "supports arrays in json fields" do
field_type = "json_array"
CustomFieldsTestItem.register_custom_field_type(field_type, :json)
item = CustomFieldsTestItem.new
item.custom_fields = {
"json_array" => [{ a: "test" }, { b: "another" }]
}
item.save
item.reload
expect(item.custom_fields[field_type]).to eq(
[{ "a" => "test" }, { "b" => "another" }]
)
item.custom_fields["json_array"] = ['a', 'b']
item.save
item.reload
expect(item.custom_fields[field_type]).to eq(["a", "b"])
end
it "will not fail to load custom fields if json is corrupt" do
field_type = "bad_json"
CustomFieldsTestItem.register_custom_field_type(field_type, :json)
item = CustomFieldsTestItem.create!
CustomFieldsTestItemCustomField.create!(
custom_fields_test_item_id: item.id,
name: field_type,
value: "{test"
)
item = item.reload
expect(item.custom_fields[field_type]).to eq({})
end
it "supports bulk retrieval with a list of ids" do
item1 = CustomFieldsTestItem.new
item1.custom_fields = { "a" => ["b", "c", "d"], 'not_allowlisted' => 'secret' }
item1.save
item2 = CustomFieldsTestItem.new
item2.custom_fields = { "e" => 'hallo' }
item2.save
fields = CustomFieldsTestItem.custom_fields_for_ids([item1.id, item2.id], ['a', 'e'])
expect(fields).to be_present
expect(fields[item1.id]['a']).to match_array(['b', 'c', 'd'])
expect(fields[item1.id]['not_allowlisted']).to be_blank
expect(fields[item2.id]['e']).to eq('hallo')
end
it "handles interleaving saving properly" do
field_type = 'deep-nest-test'
CustomFieldsTestItem.register_custom_field_type(field_type, :json)
test_item = CustomFieldsTestItem.create!
test_item.custom_fields[field_type] ||= {}
test_item.custom_fields[field_type]['b'] ||= {}
test_item.custom_fields[field_type]['b']['c'] = 'd'
test_item.save_custom_fields(true)
db_item = CustomFieldsTestItem.find(test_item.id)
db_item.custom_fields[field_type]['b']['e'] = 'f'
test_item.custom_fields[field_type]['b']['e'] = 'f'
expected = { field_type => { 'b' => { 'c' => 'd', 'e' => 'f' } } }
db_item.save_custom_fields(true)
expect(db_item.reload.custom_fields).to eq(expected)
test_item.save_custom_fields(true)
expect(test_item.reload.custom_fields).to eq(expected)
end
describe "create_singular" do
it "creates new records" do
item = CustomFieldsTestItem.create!
item.create_singular('hello', 'world')
expect(item.reload.custom_fields['hello']).to eq('world')
end
it "upserts on a database constraint error" do
item0 = CustomFieldsTestItem.new
item0.custom_fields = { "rare" => "gem" }
item0.save
expect(item0.reload.custom_fields['rare']).to eq("gem")
item0.create_singular('rare', "diamond")
expect(item0.reload.custom_fields['rare']).to eq("diamond")
end
end
describe "upsert_custom_fields" do
it 'upserts records' do
test_item = CustomFieldsTestItem.create
test_item.upsert_custom_fields('hello' => 'world', 'abc' => 'def')
# In memory
expect(test_item.custom_fields['hello']).to eq('world')
expect(test_item.custom_fields['abc']).to eq('def')
# Persisted
test_item.reload
expect(test_item.custom_fields['hello']).to eq('world')
expect(test_item.custom_fields['abc']).to eq('def')
# In memory
test_item.upsert_custom_fields('abc' => 'ghi')
expect(test_item.custom_fields['hello']).to eq('world')
expect(test_item.custom_fields['abc']).to eq('ghi')
# Persisted
test_item.reload
expect(test_item.custom_fields['hello']).to eq('world')
expect(test_item.custom_fields['abc']).to eq('ghi')
end
it 'allows upsert to use keywords' do
test_item = CustomFieldsTestItem.create
test_item.upsert_custom_fields(hello: 'world', abc: 'def')
# In memory
expect(test_item.custom_fields['hello']).to eq('world')
expect(test_item.custom_fields['abc']).to eq('def')
# Persisted
test_item.reload
expect(test_item.custom_fields['hello']).to eq('world')
expect(test_item.custom_fields['abc']).to eq('def')
# In memory
test_item.upsert_custom_fields('abc' => 'ghi')
expect(test_item.custom_fields['hello']).to eq('world')
expect(test_item.custom_fields['abc']).to eq('ghi')
# Persisted
test_item.reload
expect(test_item.custom_fields['hello']).to eq('world')
expect(test_item.custom_fields['abc']).to eq('ghi')
end
it 'allows using string and symbol indices interchangeably' do
test_item = CustomFieldsTestItem.new
test_item.custom_fields["bob"] = "marley"
test_item.custom_fields["jack"] = "black"
# In memory
expect(test_item.custom_fields[:bob]).to eq('marley')
expect(test_item.custom_fields[:jack]).to eq('black')
# Persisted
test_item.save
test_item.reload
expect(test_item.custom_fields[:bob]).to eq('marley')
expect(test_item.custom_fields[:jack]).to eq('black')
# Update via string index again
test_item.custom_fields['bob'] = 'the builder'
expect(test_item.custom_fields[:bob]).to eq('the builder')
test_item.save
test_item.reload
expect(test_item.custom_fields[:bob]).to eq('the builder')
end
end
end
end