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
128
129
130
131
132
133
134
135
136
137
138
139
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Users::UpsertCreditCardValidationService, feature_category: :user_profile do
include CryptoHelpers
let_it_be(:user) { create(:user) }
let(:user_id) { user.id }
let(:network) { 'American Express' }
let(:holder_name) { 'John Smith' }
let(:last_digits) { '1111' }
let(:expiration_year) { Date.today.year + 10 }
let(:expiration_month) { 1 }
let(:expiration_date) { Date.new(expiration_year, expiration_month, -1) }
let(:credit_card_validated_at) { Time.utc(2020, 1, 1) }
let(:params) do
{
user_id: user_id,
credit_card_validated_at: credit_card_validated_at,
credit_card_expiration_year: expiration_year,
credit_card_expiration_month: expiration_month,
credit_card_holder_name: holder_name,
credit_card_type: network,
credit_card_mask_number: last_digits
}
end
describe '#execute' do
subject(:service) { described_class.new(params) }
context 'successfully set credit card validation record for the user' do
context 'when user does not have credit card validation record' do
it 'creates the credit card validation and returns a success', :aggregate_failures do
expect(user.credit_card_validated_at).to be nil
service_result = service.execute
expect(service_result.status).to eq(:success)
expect(service_result.message).to eq(_('Credit card validation record saved'))
user.reload
expect(user.credit_card_validation).to have_attributes(
credit_card_validated_at: credit_card_validated_at,
network_hash: sha256(network.downcase),
holder_name_hash: sha256(holder_name.downcase),
last_digits_hash: sha256(last_digits),
expiration_date_hash: sha256(expiration_date.to_s)
)
end
end
context 'when user has credit card validation record' do
let(:previous_credit_card_validated_at) { Time.utc(1999, 2, 2) }
before do
create(:credit_card_validation, user: user, credit_card_validated_at: previous_credit_card_validated_at)
end
it 'updates the credit card validation record and returns a success', :aggregate_failures do
expect(user.credit_card_validated_at).to eq(previous_credit_card_validated_at)
service_result = service.execute
expect(service_result.status).to eq(:success)
expect(service_result.message).to eq(_('Credit card validation record saved'))
user.reload
expect(user.credit_card_validated_at).to eq(credit_card_validated_at)
end
end
end
shared_examples 'returns an error without tracking the exception' do
it 'does not send an exception to Gitlab::ErrorTracking' do
expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
service.execute
end
it 'returns an error', :aggregate_failures do
service_result = service.execute
expect(service_result.status).to eq(:error)
expect(service_result.message).to eq(_('Error saving credit card validation record'))
end
end
shared_examples 'returns an error and tracks the exception' do
it 'sends an exception to Gitlab::ErrorTracking' do
expect(Gitlab::ErrorTracking).to receive(:track_exception)
service.execute
end
it 'returns an error', :aggregate_failures do
service_result = service.execute
expect(service_result.status).to eq(:error)
expect(service_result.message).to eq(_('Error saving credit card validation record'))
end
end
context 'when the user_id does not exist' do
let(:user_id) { non_existing_record_id }
it_behaves_like 'returns an error without tracking the exception'
end
context 'when the request is missing the credit_card_validated_at field' do
let(:params) { { user_id: user_id } }
it_behaves_like 'returns an error and tracks the exception'
end
context 'when the request is missing the user_id field' do
let(:params) { { credit_card_validated_at: credit_card_validated_at } }
it_behaves_like 'returns an error and tracks the exception'
end
context 'when there is an unexpected error' do
let(:exception) { StandardError.new }
before do
allow_next_instance_of(::Users::CreditCardValidation) do |instance|
allow(instance).to receive(:save).and_raise(exception)
end
end
it_behaves_like 'returns an error and tracks the exception'
end
end
end
|