Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions lib/profile_api_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def validate_school_students(token:, students:, school_id:)

students = Array(students)
endpoint = "/api/v1/schools/#{school_id}/students/preflight-student-upload"
response = connection(token).post(endpoint) do |request|
response = connection(token, connection_options_for_slow_requests).post(endpoint) do |request|
request.body = students.to_json
request.headers['Content-Type'] = 'application/json'
end
Expand All @@ -128,7 +128,7 @@ def create_school_students(token:, students:, school_id:, preflight: false)
students = Array(students)
endpoint = "/api/v1/schools/#{school_id}/students"
endpoint += '/preflight' if preflight
response = connection(token).post(endpoint) do |request|
response = connection(token, connection_options_for_slow_requests).post(endpoint) do |request|
request.body = students.to_json
request.headers['Content-Type'] = 'application/json'
end
Expand All @@ -146,7 +146,7 @@ def create_school_students_sso(token:, students:, school_id:)

students = Array(students)
endpoint = "/api/v1/schools/#{school_id}/students/sso"
response = connection(token).post(endpoint) do |request|
response = connection(token, connection_options_for_slow_requests).post(endpoint) do |request|
request.body = students.to_json
request.headers['Content-Type'] = 'application/json'
end
Expand Down Expand Up @@ -220,8 +220,8 @@ def update_school_email_domains(token:, school_id:, school_email_domains: [])

private

def connection(token)
HttpClient.new(ENV.fetch('IDENTITY_URL')) do |faraday|
def connection(token, options = {})
HttpClient.new(ENV.fetch('IDENTITY_URL'), options) do |faraday|
faraday.request :json
faraday.response :json
faraday.response :raise_error, allowed_statuses: [401]
Expand Down Expand Up @@ -263,5 +263,16 @@ def unauthorized!(response)
# The API is only available to verified non-student users that are over 13. Others get a 401.
raise UnauthorizedError, 'Profile API unauthorized' if response.status == 401
end

def connection_options_for_slow_requests
{
request: {
read_timeout: 50,
open_timeout: 5,
write_timeout: 5,
timeout: 50
}
}
end
end
end
44 changes: 44 additions & 0 deletions spec/lib/profile_api_client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,48 @@ def create_school_student
end
end

describe '.validate_school_students' do
subject(:validate_school_students_response) { validate_school_students }

let(:students) { [{ name: 'name', username: 'username', password: 'password' }] }
let(:school) { build(:school, id: SecureRandom.uuid) }
let(:validate_students_url) { "#{api_url}/api/v1/schools/#{school.id}/students/preflight-student-upload" }

before do
stub_request(:post, validate_students_url).to_return(status: 200, body: '{}', headers: { 'content-type' => 'application/json' })
end

it_behaves_like 'an authenticated JSON API request', :post, url: -> { validate_students_url }
it_behaves_like 'a request that handles standard HTTP errors', :post, url: -> { validate_students_url }
it_behaves_like 'a request that handles an unexpected response status', :post, url: -> { validate_students_url }, status: 201
it_behaves_like 'a request that allows longer for a response'

it 'sends the student details in the request body' do
validate_school_students_response
expect(WebMock).to have_requested(:post, validate_students_url).with(body: students.to_json)
end

it 'raises 422 exception with the validation errors if 422 status code is returned' do
response = { errors: [{ message: 'The password is well dodgy' }] }
stub_request(:post, validate_students_url)
.to_return(status: 422, body: response.to_json, headers: { 'content-type' => 'application/json' })

expect { validate_school_students }.to raise_error(ProfileApiClient::Student422Error) do |error|
expect(error.errors.first['message']).to eq('The password is well dodgy')
end
end

it 'returns nil if token is blank' do
expect(described_class.validate_school_students(token: '', students:, school_id: school.id)).to be_nil
end

private

def validate_school_students
described_class.validate_school_students(token:, students:, school_id: school.id)
end
end

describe '.create_school_students' do
subject(:create_school_students_response) { create_school_students }

Expand All @@ -245,6 +287,7 @@ def create_school_student
it_behaves_like 'an authenticated JSON API request', :post, url: -> { create_students_url }
it_behaves_like 'a request that handles standard HTTP errors', :post, url: -> { create_students_url }
it_behaves_like 'a request that handles an unexpected response status', :post, url: -> { create_students_url }, status: 202
it_behaves_like 'a request that allows longer for a response'

it 'raises 422 exception with the relevant message if 400 status code is returned' do
response = { errors: [{ message: 'The password is well dodgy' }] }
Expand Down Expand Up @@ -317,6 +360,7 @@ def create_school_students
it_behaves_like 'an authenticated JSON API request', :post, url: -> { create_students_sso_url }
it_behaves_like 'a request that handles standard HTTP errors', :post, url: -> { create_students_sso_url }
it_behaves_like 'a request that handles an unexpected response status', :post, url: -> { create_students_sso_url }, status: 202
it_behaves_like 'a request that allows longer for a response'

it 'raises 422 exception with the relevant message if 400 status code is returned' do
response = { errors: [{ message: 'The password is well dodgy' }] }
Expand Down
16 changes: 16 additions & 0 deletions spec/support/shared_examples/profile_api_client_examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,19 @@
expect { subject }.to raise_error(ProfileApiClient::UnexpectedResponse)
end
end

RSpec.shared_examples 'a request that allows longer for a response' do
let(:faraday_connections) { [] }

before do
connections = faraday_connections
allow(HttpClient).to receive(:new).and_wrap_original do |original_method, *args, &block|
original_method.call(*args, &block).tap { |connection| connections << connection }
end
end

it 'gives the profile api longer to respond than the default timeouts allow' do
subject
expect(faraday_connections.last.options).to have_attributes(open_timeout: 5, write_timeout: 5, read_timeout: 50, timeout: 50)
end
end
Loading