summaryrefslogtreecommitdiff
path: root/spec/models/merge_request/diff_commit_user_spec.rb
blob: 08e073568f9a46a87180a9e4e3a6e5de6e70cdaf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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