Skip to content

Commit c332139

Browse files
committed
1 parent fb98f93 commit c332139

File tree

4 files changed

+96
-8
lines changed

4 files changed

+96
-8
lines changed

lib/concepts/school_student/list.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ def call(school:, token:)
1616
private
1717

1818
def list_students(school, token)
19-
response = ProfileApiClient.list_school_students(token:, organisation_id: school.id)
19+
student_ids = Role.student.where(school:).map(&:user_id)
20+
response = ProfileApiClient.list_school_students(token:, school_id: school.id, student_ids:)
2021
user_ids = response.fetch(:ids)
2122

2223
User.from_userinfo(ids: user_ids)

lib/profile_api_client.rb

+10-6
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,19 @@ def remove_school_teacher(token:, teacher_id:, organisation_id:)
147147
#
148148
# The API should respond:
149149
# - 422 Unprocessable if the constraints are not met
150-
def list_school_students(token:, organisation_id:)
150+
def list_school_students(token:, school_id:, student_ids:)
151151
return [] if token.blank?
152152

153-
_ = organisation_id
153+
response = connection(token).post("/api/v1/schools/#{school_id}/students/list") do |request|
154+
request.body = student_ids
155+
end
154156

155-
# TODO: We should make Faraday raise a Ruby error for a non-2xx status
156-
# code so that SchoolOwner::Invite propagates the error in the response.
157-
response = { 'ids' => ['99999999-9999-9999-9999-999999999999'] }
158-
response.deep_symbolize_keys
157+
return [] if response.status == 404
158+
unless response.status == 200
159+
raise "Students cannot be listed in Profile API. HTTP response code: #{response.status}"
160+
end
161+
162+
response.body.map(&:deep_symbolize_keys)
159163
end
160164

161165
# The API should enforce these constraints:

spec/concepts/school_student/list_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
described_class.call(school:, token:)
2222

2323
# TODO: Replace with WebMock assertion once the profile API has been built.
24-
expect(ProfileApiClient).to have_received(:list_school_students).with(token:, organisation_id: school.id)
24+
expect(ProfileApiClient).to have_received(:list_school_students).with(token:, school_id: school.id, student_ids: [student.id])
2525
end
2626

2727
it 'returns the school students in the operation response' do

spec/lib/profile_api_client_spec.rb

+83
Original file line numberDiff line numberDiff line change
@@ -369,4 +369,87 @@ def create_school_student
369369
described_class.create_school_student(token:, username:, password:, name:, school_id: school.id)
370370
end
371371
end
372+
373+
describe '.list_school_student' do
374+
let(:school) { build(:school, id: SecureRandom.uuid) }
375+
let(:list_students_url) { "#{api_url}/api/v1/schools/#{school.id}/students/list" }
376+
let(:student_ids) { [SecureRandom.uuid] }
377+
378+
before do
379+
stub_request(:post, list_students_url).to_return(status: 200, body: '[]', headers: { 'content-type' => 'application/json' })
380+
end
381+
382+
it 'makes a request to the profile api host' do
383+
list_school_students
384+
expect(WebMock).to have_requested(:post, list_students_url)
385+
end
386+
387+
it 'includes token in the authorization request header' do
388+
list_school_students
389+
expect(WebMock).to have_requested(:post, list_students_url).with(headers: { authorization: "Bearer #{token}" })
390+
end
391+
392+
it 'includes the profile api key in the x-api-key request header' do
393+
list_school_students
394+
expect(WebMock).to have_requested(:post, list_students_url).with(headers: { 'x-api-key' => api_key })
395+
end
396+
397+
it 'sets content-type of request to json' do
398+
list_school_students
399+
expect(WebMock).to have_requested(:post, list_students_url).with(headers: { 'content-type' => 'application/json' })
400+
end
401+
402+
it 'sets accept header to json' do
403+
list_school_students
404+
expect(WebMock).to have_requested(:post, list_students_url).with(headers: { 'accept' => 'application/json' })
405+
end
406+
407+
it 'sets body to the student IDs' do
408+
list_school_students
409+
expect(WebMock).to have_requested(:post, list_students_url).with(body: student_ids)
410+
end
411+
412+
# rubocop:disable RSpec/ExampleLength
413+
it 'returns a hash representing the student(s) if successful' do
414+
response = [
415+
{
416+
id: '549e4674-6ffd-4ac6-9a97-b4d7e5c0e5c5',
417+
schoolId: '132383f1-702a-46a0-9eb2-a40dd4f212e3',
418+
name: 'student-name',
419+
username: 'student-username',
420+
createdAt: '2024-07-03T13:00:40.041Z',
421+
updatedAt: '2024-07-03T13:00:40.041Z',
422+
discardedAt: nil
423+
}
424+
]
425+
stub_request(:post, list_students_url)
426+
.to_return(status: 200, body: response.to_json)
427+
expect(list_school_students).to eq(response)
428+
end
429+
# rubocop:enable RSpec/ExampleLength
430+
431+
it "returns empty array if the API returns a 404 because one or more of the student IDs aren't found" do
432+
stub_request(:post, list_students_url)
433+
.to_return(status: 404, body: '')
434+
expect(list_school_students).to eq([])
435+
end
436+
437+
it 'raises exception if anything other than a 200 status code is returned' do
438+
stub_request(:post, list_students_url)
439+
.to_return(status: 500)
440+
441+
expect { list_school_students }.to raise_error(RuntimeError)
442+
end
443+
444+
it 'includes details of underlying response when exception is raised' do
445+
stub_request(:post, list_students_url)
446+
.to_return(status: 401)
447+
448+
expect { list_school_students }.to raise_error('Students cannot be listed in Profile API. HTTP response code: 401')
449+
end
450+
451+
def list_school_students
452+
described_class.list_school_students(token:, school_id: school.id, student_ids:)
453+
end
454+
end
372455
end

0 commit comments

Comments
 (0)