diff --git a/spec/factories/history.rb b/spec/factories/history.rb new file mode 100644 index 000000000..0e91be58b --- /dev/null +++ b/spec/factories/history.rb @@ -0,0 +1,8 @@ +FactoryBot.define do + factory :history do + association :history_type, factory: :'history/type' + association :history_object, factory: :'history/object' + o_id { history_object.name.constantize.pluck(:id).sample } + created_by_id { 1 } + end +end diff --git a/spec/factories/history/object.rb b/spec/factories/history/object.rb new file mode 100644 index 000000000..64f56cc67 --- /dev/null +++ b/spec/factories/history/object.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :'history/object', aliases: %i[history_object] do + name { (ApplicationModel.descendants.select(&:any?).map(&:name) - History::Object.pluck(:name)).sample } + end +end diff --git a/spec/factories/history/type.rb b/spec/factories/history/type.rb new file mode 100644 index 000000000..92aadf8a9 --- /dev/null +++ b/spec/factories/history/type.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :'history/type', aliases: %i[history_type] do + name { Faker::Verb.past_participle } + end +end diff --git a/spec/factories/ticket/article.rb b/spec/factories/ticket/article.rb index e2cf23e70..35b4fc683 100644 --- a/spec/factories/ticket/article.rb +++ b/spec/factories/ticket/article.rb @@ -1,5 +1,5 @@ FactoryBot.define do - factory :ticket_article, class: Ticket::Article do + factory :'ticket/article', aliases: %i[ticket_article] do transient do type_name 'email' sender_name 'Customer' diff --git a/spec/factories/ticket/state.rb b/spec/factories/ticket/state.rb new file mode 100644 index 000000000..40841268f --- /dev/null +++ b/spec/factories/ticket/state.rb @@ -0,0 +1,8 @@ +FactoryBot.define do + factory :'ticket/state', aliases: %i[ticket_state] do + name { Faker::Verb.past_participle } + association :state_type, factory: :'ticket/state_type' + updated_by_id { 1 } + created_by_id { 1 } + end +end diff --git a/spec/factories/ticket/state_type.rb b/spec/factories/ticket/state_type.rb new file mode 100644 index 000000000..8903bd783 --- /dev/null +++ b/spec/factories/ticket/state_type.rb @@ -0,0 +1,7 @@ +FactoryBot.define do + factory :'ticket/state_type', aliases: %i[ticket_state_type] do + name { Faker::Verb.past_participle } + updated_by_id { 1 } + created_by_id { 1 } + end +end diff --git a/spec/models/application_model/checks_import_examples.rb b/spec/models/application_model/checks_import_examples.rb new file mode 100644 index 000000000..bb374a826 --- /dev/null +++ b/spec/models/application_model/checks_import_examples.rb @@ -0,0 +1,39 @@ +RSpec.shared_examples 'ApplicationModel::ChecksImport' do |importable: false| + subject(:new_instance) { build(described_class.name.underscore, id: unused_id) } + let(:unused_id) { described_class.pluck(:id).max * 2 } + + context 'when Setting.get("system_init_done") is true AND Setting.get("import_mode") is false' do + before { Setting.set('system_init_done', true) } + before { Setting.set('import_mode', false) } + + it 'prevents explicit setting of #id attribute' do + expect { new_instance.save }.to change { new_instance.id } + end + end + + context 'when Setting.get("system_init_done") is false' do + before { Setting.set('system_init_done', false) } + + it 'allows explicit setting of #id attribute' do + expect { new_instance.save }.not_to change { new_instance.id } + end + end + + context 'when Setting.get("import_mode") is true' do + before { Setting.set('import_mode', true) } + + shared_examples 'importable classes' do + it 'allows explicit setting of #id attribute' do + expect { new_instance.save }.not_to change { new_instance.id } + end + end + + shared_examples 'non-importable classes' do + it 'prevents explicit setting of #id attribute' do + expect { new_instance.save }.to change { new_instance.id } + end + end + + include_examples importable ? 'importable classes' : 'non-importable classes' + end +end diff --git a/spec/models/application_model_examples.rb b/spec/models/application_model_examples.rb new file mode 100644 index 000000000..bc4ffc0af --- /dev/null +++ b/spec/models/application_model_examples.rb @@ -0,0 +1,16 @@ +require 'models/application_model/checks_import_examples' + +RSpec.shared_examples 'ApplicationModel' do + include_examples 'ApplicationModel::ChecksImport', + importable: described_class.name.in?( + %w[Group + History + Role + Ticket + Ticket::Article + Ticket::Priority + Ticket::State + Ticket::StateType + User] + ) +end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb new file mode 100644 index 000000000..68778ad41 --- /dev/null +++ b/spec/models/group_spec.rb @@ -0,0 +1,6 @@ +require 'rails_helper' +require 'models/application_model_examples' + +RSpec.describe Group, type: :model do + include_examples 'ApplicationModel' +end diff --git a/spec/models/history_spec.rb b/spec/models/history_spec.rb new file mode 100644 index 000000000..324550e6b --- /dev/null +++ b/spec/models/history_spec.rb @@ -0,0 +1,6 @@ +require 'rails_helper' +require 'models/application_model_examples' + +RSpec.describe History, type: :model do + include_examples 'ApplicationModel' +end diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb index 492725e9c..eb7ebf29d 100644 --- a/spec/models/role_spec.rb +++ b/spec/models/role_spec.rb @@ -1,8 +1,11 @@ require 'rails_helper' +require 'models/application_model_examples' require 'models/concerns/has_groups_examples' RSpec.describe Role do + include_examples 'ApplicationModel' include_examples 'HasGroups', group_access_factory: :role + subject(:role) { create(:role) } describe 'Default state' do diff --git a/spec/models/ticket/article_spec.rb b/spec/models/ticket/article_spec.rb index 15254f0cf..fb1fa655a 100644 --- a/spec/models/ticket/article_spec.rb +++ b/spec/models/ticket/article_spec.rb @@ -1,6 +1,9 @@ require 'rails_helper' +require 'models/application_model_examples' + +RSpec.describe Ticket::Article, type: :model do + include_examples 'ApplicationModel' -RSpec.describe Ticket::Article do describe '.create' do it 'handles NULL byte in subject or body' do expect(create(:ticket_article, subject: "com test 1\u0000", body: "some\u0000message 123")) diff --git a/spec/models/ticket/priority_spec.rb b/spec/models/ticket/priority_spec.rb index d662ce4dc..677dcac02 100644 --- a/spec/models/ticket/priority_spec.rb +++ b/spec/models/ticket/priority_spec.rb @@ -1,6 +1,9 @@ require 'rails_helper' +require 'models/application_model_examples' RSpec.describe Ticket::Priority, type: :model do + include_examples 'ApplicationModel' + describe 'Default state' do describe 'of whole table:' do it 'has exactly one default record' do diff --git a/spec/models/ticket/state_spec.rb b/spec/models/ticket/state_spec.rb index 6e802e8ff..b618818b3 100644 --- a/spec/models/ticket/state_spec.rb +++ b/spec/models/ticket/state_spec.rb @@ -1,18 +1,21 @@ require 'rails_helper' +require 'models/application_model_examples' -RSpec.describe Ticket::State do - - context '.by_category' do +RSpec.describe Ticket::State, type: :model do + include_examples 'ApplicationModel' + describe '.by_category' do it 'looks up states by category' do - result = described_class.by_category(:open) - expect(result).to be_an(ActiveRecord::Relation) - expect(result).to_not be_empty - expect(result.first).to be_a(Ticket::State) + expect(described_class.by_category(:open)) + .to be_an(ActiveRecord::Relation) + .and include(instance_of(Ticket::State)) end - it 'raises RuntimeError for invalid category' do - expect { described_class.by_category(:invalidcategoryname) }.to raise_error(RuntimeError) + context 'with invalid category name' do + it 'raises RuntimeError' do + expect { described_class.by_category(:invalidcategoryname) } + .to raise_error(RuntimeError) + end end end end diff --git a/spec/models/ticket/state_type_spec.rb b/spec/models/ticket/state_type_spec.rb new file mode 100644 index 000000000..6130131fe --- /dev/null +++ b/spec/models/ticket/state_type_spec.rb @@ -0,0 +1,6 @@ +require 'rails_helper' +require 'models/application_model_examples' + +RSpec.describe Ticket::StateType, type: :model do + include_examples 'ApplicationModel' +end diff --git a/spec/models/ticket_spec.rb b/spec/models/ticket_spec.rb index 06f0beb2d..2d5899d04 100644 --- a/spec/models/ticket_spec.rb +++ b/spec/models/ticket_spec.rb @@ -1,7 +1,9 @@ require 'rails_helper' +require 'models/application_model_examples' require 'models/concerns/can_lookup_examples' -RSpec.describe Ticket do +RSpec.describe Ticket, type: :model do + include_examples 'ApplicationModel' include_examples 'CanLookup' describe '#merge_to' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index e82221753..3597a4ac5 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,10 +1,12 @@ require 'rails_helper' +require 'models/application_model_examples' require 'models/concerns/has_groups_examples' require 'models/concerns/has_roles_examples' require 'models/concerns/has_groups_permissions_examples' require 'models/concerns/can_lookup_examples' RSpec.describe User do + include_examples 'ApplicationModel' include_examples 'HasGroups', group_access_factory: :agent_user include_examples 'HasRoles', group_access_factory: :agent_user include_examples 'HasGroups and Permissions', group_access_no_permission_factory: :user