diff options
Diffstat (limited to 'spec/models/merge_request/diff_commit_user_spec.rb')
-rw-r--r-- | spec/models/merge_request/diff_commit_user_spec.rb | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/spec/models/merge_request/diff_commit_user_spec.rb b/spec/models/merge_request/diff_commit_user_spec.rb new file mode 100644 index 00000000000..08e073568f9 --- /dev/null +++ b/spec/models/merge_request/diff_commit_user_spec.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe MergeRequest::DiffCommitUser do + describe 'validations' do + it 'requires that names are less than 512 characters long' do + expect(described_class.new(name: 'a' * 1000)).not_to be_valid + end + + it 'requires that Emails are less than 512 characters long' do + expect(described_class.new(email: 'a' * 1000)).not_to be_valid + end + + it 'requires either a name or Email' do + expect(described_class.new).not_to be_valid + end + + it 'allows setting of just a name' do + expect(described_class.new(name: 'Alice')).to be_valid + end + + it 'allows setting of just an Email' do + expect(described_class.new(email: 'alice@example.com')).to be_valid + end + + it 'allows setting of both a name and Email' do + expect(described_class.new(name: 'Alice', email: 'alice@example.com')) + .to be_valid + end + end + + describe '.prepare' do + it 'trims a value to at most 512 characters' do + expect(described_class.prepare('€' * 1_000)).to eq('€' * 512) + end + + it 'returns nil if the value is an empty string' do + expect(described_class.prepare('')).to be_nil + end + end + + describe '.find_or_create' do + it 'creates a new row if none exist' do + alice = described_class.find_or_create('Alice', 'alice@example.com') + + expect(alice.name).to eq('Alice') + expect(alice.email).to eq('alice@example.com') + end + + it 'returns an existing row if one exists' do + user1 = create(:merge_request_diff_commit_user) + user2 = described_class.find_or_create(user1.name, user1.email) + + expect(user1).to eq(user2) + end + + it 'handles concurrent inserts' do + user = create(:merge_request_diff_commit_user) + + expect(described_class) + .to receive(:find_or_create_by!) + .ordered + .with(name: user.name, email: user.email) + .and_raise(ActiveRecord::RecordNotUnique) + + expect(described_class) + .to receive(:find_or_create_by!) + .ordered + .with(name: user.name, email: user.email) + .and_return(user) + + expect(described_class.find_or_create(user.name, user.email)).to eq(user) + end + end + + describe '.bulk_find_or_create' do + it 'bulk creates missing rows and reuses existing rows' do + bob = create( + :merge_request_diff_commit_user, + name: 'Bob', + email: 'bob@example.com' + ) + + users = described_class.bulk_find_or_create( + [%w[Alice alice@example.com], %w[Bob bob@example.com]] + ) + alice = described_class.find_by(name: 'Alice') + + expect(users[%w[Alice alice@example.com]]).to eq(alice) + expect(users[%w[Bob bob@example.com]]).to eq(bob) + end + + it 'does not insert any data when all users exist' do + bob = create( + :merge_request_diff_commit_user, + name: 'Bob', + email: 'bob@example.com' + ) + + users = described_class.bulk_find_or_create([%w[Bob bob@example.com]]) + + expect(described_class).not_to receive(:insert_all) + expect(users[%w[Bob bob@example.com]]).to eq(bob) + end + + it 'handles concurrently inserted rows' do + bob = create( + :merge_request_diff_commit_user, + name: 'Bob', + email: 'bob@example.com' + ) + + input = [%w[Bob bob@example.com]] + + expect(described_class) + .to receive(:bulk_find) + .twice + .with(input) + .and_return([], [bob]) + + users = described_class.bulk_find_or_create(input) + + expect(users[%w[Bob bob@example.com]]).to eq(bob) + end + end +end |