Add observer-related GraphQL fields
Add the associatedUser field to the enrollment type, and the ability to filter a course's enrollmentsConnection by specific enrollment types and observed user IDs. This allows us to return only enrollments for observers observing specific students. closes EVAL-2059 flag=none Test plan: - Have a course with at least two observer enrollments, and various other types of enrollments - Take note of the ID of one of the students being observed - In GraphiQL or your preferred testing platform, run a query like query MyQuery { course(id: <course ID>) { enrollmentsConnection(filter: { associatedUserIds: [<observed student ID>] types: [ObserverEnrollment] }) { nodes { _id type user { _id name } associatedUser { _id name } } } } } - Check that you only receive observer enrollments observing the user ID you specified - Check that the associatedUser field for observer enrollments contains the id/name of the observed user and is null for other enrollment types - Check that the "types" filter option does the right thing without specifying any associatedUserIds; e.g., test that asking for types: [StudentEnrollment, ObserverEnrollment] returns only student and observer enrollments Change-Id: Ic0be3f6006e84202e017750fe0d3adde9ade2fdc Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/276775 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Product-Review: Syed Hussain <shussain@instructure.com> Reviewed-by: Spencer Olson <solson@instructure.com> Reviewed-by: Kai Bjorkman <kbjorkman@instructure.com> QA-Review: Kai Bjorkman <kbjorkman@instructure.com>
This commit is contained in:
parent
221cbf2b96
commit
b0b0074d22
|
@ -163,15 +163,19 @@ module Types
|
|||
scope
|
||||
end
|
||||
|
||||
field :enrollments_connection, EnrollmentType.connection_type, null: true
|
||||
def enrollments_connection
|
||||
field :enrollments_connection, EnrollmentType.connection_type, null: true do
|
||||
argument :filter, EnrollmentFilterInputType, required: false
|
||||
end
|
||||
def enrollments_connection(filter: {})
|
||||
return nil unless course.grants_any_right?(
|
||||
current_user, session,
|
||||
:read_roster, :view_all_grades, :manage_grades
|
||||
)
|
||||
|
||||
course.apply_enrollment_visibility(course.all_enrollments,
|
||||
current_user).active
|
||||
scope = course.apply_enrollment_visibility(course.all_enrollments, current_user).active
|
||||
scope = scope.where(associated_user_id: filter[:associated_user_ids]) if filter[:associated_user_ids].present?
|
||||
scope = scope.where(type: filter[:types]) if filter[:types].present?
|
||||
scope
|
||||
end
|
||||
|
||||
field :grading_periods_connection, GradingPeriodType.connection_type, null: true
|
||||
|
|
|
@ -40,6 +40,16 @@ module Types
|
|||
value "StudentViewEnrollment"
|
||||
end
|
||||
|
||||
class EnrollmentFilterInputType < Types::BaseInputObject
|
||||
graphql_name "EnrollmentFilterInput"
|
||||
|
||||
argument :types, [EnrollmentTypeType], required: false, default_value: nil
|
||||
argument :associated_user_ids, [ID],
|
||||
prepare: GraphQLHelpers.relay_or_legacy_ids_prepare_func("User"),
|
||||
required: false,
|
||||
default_value: []
|
||||
end
|
||||
|
||||
class EnrollmentType < ApplicationObjectType
|
||||
graphql_name "Enrollment"
|
||||
|
||||
|
@ -57,6 +67,11 @@ module Types
|
|||
load_association(:user)
|
||||
end
|
||||
|
||||
field :associated_user, UserType, null: true
|
||||
def associated_user
|
||||
load_association(:associated_user)
|
||||
end
|
||||
|
||||
field :course, CourseType, null: true
|
||||
def course
|
||||
load_association(:course)
|
||||
|
|
|
@ -418,6 +418,39 @@ describe Types::CourseType do
|
|||
other_teacher.enrollments.first.id.to_s,
|
||||
]
|
||||
end
|
||||
|
||||
describe "filtering" do
|
||||
it "returns only enrollments of the specified types if included" do
|
||||
ta_enrollment = course.enroll_ta(User.create!, enrollment_state: :active)
|
||||
|
||||
expect(
|
||||
course_type.resolve(
|
||||
"enrollmentsConnection(filter: {types: [TeacherEnrollment, TaEnrollment]}) { nodes { _id } }",
|
||||
current_user: @teacher
|
||||
)
|
||||
).to match_array([
|
||||
@teacher.enrollments.first.id.to_s,
|
||||
other_teacher.enrollments.first.id.to_s,
|
||||
ta_enrollment.id.to_s
|
||||
])
|
||||
end
|
||||
|
||||
it "returns only enrollments with the specified associated_user_ids if included" do
|
||||
observer = User.create!
|
||||
observer_enrollment = observer_in_course(course: @course, user: observer)
|
||||
observer_enrollment.update!(associated_user: @student1)
|
||||
|
||||
other_observer_enrollment = observer_in_course(course: @course, user: observer)
|
||||
other_observer_enrollment.update!(associated_user: @student2)
|
||||
|
||||
expect(
|
||||
course_type.resolve(
|
||||
"enrollmentsConnection(filter: {associatedUserIds: [#{@student1.id}]}) { nodes { _id } }",
|
||||
current_user: @teacher
|
||||
)
|
||||
).to eq [observer_enrollment.id.to_s]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -118,4 +118,19 @@ describe Types::EnrollmentType do
|
|||
).to eq enrollment.course_section.id.to_s
|
||||
end
|
||||
end
|
||||
|
||||
describe "associated_user" do
|
||||
it "returns the associated user when one exists" do
|
||||
observer = User.create!
|
||||
observer_enrollment = observer_in_course(course: @course, user: observer)
|
||||
observer_enrollment.update!(associated_user: @student)
|
||||
|
||||
tester = GraphQLTypeTester.new(observer_enrollment, current_user: @observer)
|
||||
expect(tester.resolve("associatedUser { _id }")).to eq @student.id.to_s
|
||||
end
|
||||
|
||||
it "returns nil when no associated user exists" do
|
||||
expect(enrollment_type.resolve("associatedUser { _id }")).to be nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue