Skip to content

Commit 86c56f1

Browse files
Return error_codes in SchoolEmailDomain response
1 parent 511affb commit 86c56f1

4 files changed

Lines changed: 26 additions & 19 deletions

File tree

app/controllers/api/school_email_domains_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def create
1515
if result.success?
1616
render json: { domain: result[:school_email_domain].domain }, status: :created
1717
else
18-
render json: { error: result[:error] }, status: :unprocessable_content
18+
render json: { error: result[:error], error_code: result[:error_code] }, status: :unprocessable_content
1919
end
2020
end
2121

lib/concepts/school_email_domain/operations/create.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,18 @@ def call(school:, domain:, token:)
1414
rescue ActiveRecord::RecordInvalid => e
1515
record = response[:school_email_domain] || e.record
1616
response[:error] = record.errors.full_messages.join(', ')
17+
response[:error_code] = domain_error_code(record)
1718
response
1819
rescue ActiveRecord::RecordNotUnique
1920
record = response[:school_email_domain]
2021
record.errors.add(:domain, :taken)
2122
response[:error] = record.errors.full_messages.join(', ')
23+
response[:error_code] = 'taken'
2224
response
2325
rescue StandardError => e
2426
Sentry.capture_exception(e) # Send unexpected/Profile errors to Sentry
2527
response[:error] = e.message
28+
response[:error_code] = 'profile_sync_failed'
2629
response
2730
end
2831

@@ -36,6 +39,10 @@ def update_profile(school, token)
3639
school_email_domains = school.school_email_domains.order(:created_at).pluck(:domain)
3740
ProfileApiClient.update_school_email_domains(token:, school_id: school.id, school_email_domains:)
3841
end
42+
43+
def domain_error_code(record)
44+
record.errors.details[:domain].first.fetch(:error).to_s
45+
end
3946
end
4047
end
4148
end

spec/concepts/school_email_domain/create_spec.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@
7878
expect(Sentry).not_to have_received(:capture_exception).with(kind_of(StandardError))
7979
end
8080

81-
it 'returns the error message in the operation response' do
81+
it 'returns the error code in the operation response' do
8282
response = described_class.call(school:, domain:, token:)
83-
expect(response[:error]).to include('')
83+
expect(response[:error_code]).to eq(expected_error_code)
8484
end
8585

8686
it 'does not attempt to update Profile' do
@@ -91,42 +91,42 @@
9191

9292
context 'when domain is blank' do
9393
let(:domain) { '' }
94-
let(:expected_error_message) { "Domain can't be blank" }
94+
let(:expected_error_code) { 'blank' }
9595

9696
it_behaves_like 'an invalid record'
9797
end
9898

9999
context 'when domain is not an FQDN' do
100100
let(:domain) { 'edu' }
101-
let(:expected_error_message) { 'Domain must be a fully qualified domain name' }
101+
let(:expected_error_code) { 'invalid_host' }
102102

103103
it_behaves_like 'an invalid record'
104104
end
105105

106106
context 'when domain has an invalid URI' do
107107
let(:domain) { 'exa mple.com' }
108-
let(:expected_error_message) { 'Domain must be a valid domain format' }
108+
let(:expected_error_code) { 'invalid_uri' }
109109

110110
it_behaves_like 'an invalid record'
111111
end
112112

113113
context 'when domain has an invalid public suffix' do
114114
let(:domain) { 'co.uk' }
115-
let(:expected_error_message) { 'Domain must be a registrable domain name' }
115+
let(:expected_error_code) { 'invalid_public_suffix' }
116116

117117
it_behaves_like 'an invalid record'
118118
end
119119

120120
context 'when domain is a duplicate' do
121121
before { create(:school_email_domain, school:, domain:) }
122122

123-
let(:expected_error_message) { 'Domain has already been taken' }
123+
let(:expected_error_code) { 'taken' }
124124

125125
it_behaves_like 'an invalid record'
126126
end
127127

128128
context 'when a concurrent request creates the same domain' do
129-
let(:expected_error_message) { 'Domain has already been taken' }
129+
let(:expected_error_code) { 'taken' }
130130
let(:school_email_domain) { SchoolEmailDomain.new(school:, domain:) }
131131

132132
before do
@@ -171,9 +171,9 @@
171171
expect(described_class.call(school:, domain:, token:)).to be_failure
172172
end
173173

174-
it 'returns the error message in the operation response' do
174+
it 'returns the error code in the operation response' do
175175
response = described_class.call(school:, domain:, token:)
176-
expect(response[:error]).to eq('Unexpected response from Profile API (status code 500)')
176+
expect(response[:error_code]).to eq('profile_sync_failed')
177177
end
178178
end
179179
end

spec/features/school_email_domain/creating_school_email_domains_spec.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@
4343
expect(response).to have_http_status(:unprocessable_content)
4444
end
4545

46-
it 'returns the error in the response body' do
46+
it 'returns the error code in the response body' do
4747
data = JSON.parse(response.body, symbolize_names: true)
48-
expect(data[:error]).to match(expected_error)
48+
expect(data[:error_code]).to eq(expected_error_code)
4949
end
5050
end
5151

@@ -117,7 +117,7 @@
117117
context 'when the domain cannot be processed' do
118118
context 'when the domain is blank' do
119119
let(:domain) { '' }
120-
let(:expected_error) { /Domain can't be blank/ }
120+
let(:expected_error_code) { 'blank' }
121121

122122
it_behaves_like 'an unprocessable school email domain creation response'
123123

@@ -130,7 +130,7 @@
130130

131131
context 'when the domain is not an FQDN' do
132132
let(:domain) { 'edu' }
133-
let(:expected_error) { /Domain must be a fully qualified domain name/ }
133+
let(:expected_error_code) { 'invalid_host' }
134134

135135
it_behaves_like 'an unprocessable school email domain creation response'
136136

@@ -143,7 +143,7 @@
143143

144144
context 'when the uri is invalid' do
145145
let(:domain) { 'exa mple.com' }
146-
let(:expected_error) { /Domain must be a valid domain format/ }
146+
let(:expected_error_code) { 'invalid_uri' }
147147

148148
it_behaves_like 'an unprocessable school email domain creation response'
149149

@@ -156,7 +156,7 @@
156156

157157
context 'when the public suffix is invalid' do
158158
let(:domain) { 'co.uk' }
159-
let(:expected_error) { /Domain must be a registrable domain name/ }
159+
let(:expected_error_code) { 'invalid_public_suffix' }
160160

161161
it_behaves_like 'an unprocessable school email domain creation response'
162162

@@ -168,7 +168,7 @@
168168
end
169169

170170
context 'when the domain is a duplicate' do
171-
let(:expected_error) { /Domain has already been taken/ }
171+
let(:expected_error_code) { 'taken' }
172172

173173
before do
174174
create(:school_email_domain, school:, domain:)
@@ -190,7 +190,7 @@
190190
instance_double(Faraday::Response, status: 500, headers: {}, body: '')
191191
)
192192
end
193-
let(:expected_error) { /Unexpected response from Profile API \(status code 500\)/ }
193+
let(:expected_error_code) { 'profile_sync_failed' }
194194

195195
before do
196196
allow(ProfileApiClient).to receive(:update_school_email_domains).and_raise(profile_error)

0 commit comments

Comments
 (0)