From b38057c665d31e08ae9ba0962581ea0ebceaa657 Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Tue, 12 Mar 2024 20:36:13 +0800 Subject: [PATCH 01/15] feat: Implement test for filter by assessment title --- test/cadet/assessments/assessments_test.exs | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index 3575768ff..72e40d53c 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1700,6 +1700,33 @@ defmodule Cadet.AssessmentsTest do end end + """ + mix test ./test/cadet/assessments/assessments_test.exs + TODO: + assessment: title + submission: status, notFullyGraded + course_reg: group, groupName + user: name, username + assessment_config: type, isManuallyGraded + """ + describe "get submission function" do + setup do + Cadet.Test.Seeds.assessments() + + end + + test "filter by assessment title", %{course_regs: %{avenger1_cr: avenger}, assessments: assessments} do + + assessment = assessments["mission"][:assessment] + title = assessment.title + {_, res} = Assessments.submissions_by_grader_for_index(avenger, %{"title" => title}) + assessments_from_res = res[:data][:assessments] + Enum.each(assessments_from_res, fn a -> + assert a.title == title + end) + end + end + defp get_answer_relative_scores(answers) do answers |> Enum.map(fn ans -> ans.relative_score end) end From 9e2c748e36a636cab60eb324740844a91e59a8eb Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Wed, 13 Mar 2024 08:54:18 +0800 Subject: [PATCH 02/15] feat: Implement random submission status in test seed --- test/support/seeds.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/support/seeds.ex b/test/support/seeds.ex index e88ec7f21..189697ac1 100644 --- a/test/support/seeds.ex +++ b/test/support/seeds.ex @@ -177,10 +177,11 @@ defmodule Cadet.Test.Seeds do }) end) + submissions_status = Enum.random(Cadet.Assessments.SubmissionStatus.__enums__) submissions = students |> Enum.take(2) - |> Enum.map(&insert(:submission, %{assessment: assessment, student: &1})) + |> Enum.map(&insert(:submission, %{assessment: assessment, student: &1, status: submissions_status})) # Programming Answers programming_answers = From c87261eeae7babe66995e2ce5506c1e630e356b6 Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Wed, 13 Mar 2024 09:06:40 +0800 Subject: [PATCH 03/15] feat: Implement test for filter by submission status --- test/cadet/assessments/assessments_test.exs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index 72e40d53c..a0ab2ec93 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1703,8 +1703,8 @@ defmodule Cadet.AssessmentsTest do """ mix test ./test/cadet/assessments/assessments_test.exs TODO: - assessment: title - submission: status, notFullyGraded + assessment: title(D) + submission: status(D), notFullyGraded course_reg: group, groupName user: name, username assessment_config: type, isManuallyGraded @@ -1725,6 +1725,16 @@ defmodule Cadet.AssessmentsTest do assert a.title == title end) end + + test "filer by submission status", %{course_regs: %{avenger1_cr: avenger}, assessments: assessments} do + submission = Enum.random(assessments["mission"][:submissions]) + submission_status = submission.status + {_, res} = Assessments.submissions_by_grader_for_index(avenger, %{"status" => submission_status}) + submissions_from_res = res[:data][:submissions] + Enum.each(submissions_from_res, fn s -> + assert s.status == submission_status + end) + end end defp get_answer_relative_scores(answers) do From 8b0ad564368ce0b9470e33d647156c82ada4700e Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:08:51 +0800 Subject: [PATCH 04/15] feat: Implement random graded status in test seed --- test/support/seeds.ex | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/support/seeds.ex b/test/support/seeds.ex index 189697ac1..0a4f9f4f9 100644 --- a/test/support/seeds.ex +++ b/test/support/seeds.ex @@ -113,7 +113,7 @@ defmodule Cadet.Test.Seeds do |> Enum.reduce( %{}, fn config, acc -> - Map.put(acc, config.type, insert_assessments(config, students, course1)) + Map.put(acc, config.type, insert_assessments(config, students, course1, avenger1_cr)) end ) @@ -139,7 +139,7 @@ defmodule Cadet.Test.Seeds do end end - defp insert_assessments(assessment_config, students, course) do + defp insert_assessments(assessment_config, students, course, avenger) do assessment = insert(:assessment, %{course: course, config: assessment_config, is_published: true}) @@ -183,6 +183,8 @@ defmodule Cadet.Test.Seeds do |> Enum.take(2) |> Enum.map(&insert(:submission, %{assessment: assessment, student: &1, status: submissions_status})) + is_graded = Enum.random([true, false]) + grader = if is_graded, do: avenger, else: nil # Programming Answers programming_answers = Enum.map(submissions, fn submission -> @@ -191,7 +193,8 @@ defmodule Cadet.Test.Seeds do xp: 800, question: question, submission: submission, - answer: build(:programming_answer) + answer: build(:programming_answer), + grader: grader }) end) end) @@ -203,7 +206,8 @@ defmodule Cadet.Test.Seeds do xp: 500, question: question, submission: submission, - answer: build(:mcq_answer) + answer: build(:mcq_answer), + grader: grader }) end) end) @@ -215,7 +219,8 @@ defmodule Cadet.Test.Seeds do xp: 100, question: question, submission: submission, - answer: build(:voting_answer) + answer: build(:voting_answer), + grader: grader }) end) end) From ab6d254cbef610bc32b1d78913e7265f49583185 Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:10:27 +0800 Subject: [PATCH 05/15] feat: Implement test for filter by notFullyGraded --- test/cadet/assessments/assessments_test.exs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index a0ab2ec93..d9e7f5ace 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1704,7 +1704,7 @@ defmodule Cadet.AssessmentsTest do mix test ./test/cadet/assessments/assessments_test.exs TODO: assessment: title(D) - submission: status(D), notFullyGraded + submission: status(D), notFullyGraded (D) course_reg: group, groupName user: name, username assessment_config: type, isManuallyGraded @@ -1735,6 +1735,14 @@ defmodule Cadet.AssessmentsTest do assert s.status == submission_status end) end + + test "filter by submission grading status", %{course_regs: %{avenger1_cr: avenger}, assessments: assessments} do + {_, res} = Assessments.submissions_by_grader_for_index(avenger, %{"notFullyGraded" => "true"}) + submissions_from_res = res[:data][:submissions] + Enum.each(submissions_from_res, fn s -> + assert s.question_count > s.graded_count + end) + end end defp get_answer_relative_scores(answers) do From e951a55db6a2300a63b0cb53a9dcb4f48909a8e3 Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Thu, 14 Mar 2024 21:48:33 +0800 Subject: [PATCH 06/15] feat: Improve test seed and make tests pure --- test/cadet/assessments/assessments_test.exs | 106 ++++++++++++++++++-- test/support/seeds.ex | 97 ++++++++++++++++-- 2 files changed, 181 insertions(+), 22 deletions(-) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index d9e7f5ace..360835eb4 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1711,34 +1711,118 @@ defmodule Cadet.AssessmentsTest do """ describe "get submission function" do setup do - Cadet.Test.Seeds.assessments() + seed = Cadet.Test.Seeds.assessments() - end + total_submissions = + Integer.to_string( + Enum.reduce(seed[:assessments], 0, fn {_, %{submissions: submissions}}, acc -> + length(submissions) + acc + end) + ) - test "filter by assessment title", %{course_regs: %{avenger1_cr: avenger}, assessments: assessments} do + Map.put(seed, :total_submissions, total_submissions) + end + test "filter by assessment title", %{ + course_regs: %{avenger1_cr: avenger}, + assessments: assessments, + total_submissions: total_submissions + } do assessment = assessments["mission"][:assessment] title = assessment.title - {_, res} = Assessments.submissions_by_grader_for_index(avenger, %{"title" => title}) + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "title" => title, + "pageSize" => total_submissions + }) + assessments_from_res = res[:data][:assessments] + Enum.each(assessments_from_res, fn a -> assert a.title == title end) end - test "filer by submission status", %{course_regs: %{avenger1_cr: avenger}, assessments: assessments} do - submission = Enum.random(assessments["mission"][:submissions]) - submission_status = submission.status - {_, res} = Assessments.submissions_by_grader_for_index(avenger, %{"status" => submission_status}) + test "filter by submission status :attempting", %{ + course_regs: %{avenger1_cr: avenger}, + assessments: assessments, + total_submissions: total_submissions + } do + expected_length = + Enum.reduce(assessments, 0, fn {_, %{submissions: submissions}}, acc -> + Enum.count(submissions, fn s -> s.status == :attempting end) + acc + end) + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "status" => "attempting", + "pageSize" => total_submissions + }) + submissions_from_res = res[:data][:submissions] + assert length(submissions_from_res) == expected_length + Enum.each(submissions_from_res, fn s -> - assert s.status == submission_status + assert s.status == :attempting end) end - test "filter by submission grading status", %{course_regs: %{avenger1_cr: avenger}, assessments: assessments} do - {_, res} = Assessments.submissions_by_grader_for_index(avenger, %{"notFullyGraded" => "true"}) + test "filter by submission status :attempted", %{ + course_regs: %{avenger1_cr: avenger}, + assessments: assessments + } do + {_, res} = Assessments.submissions_by_grader_for_index(avenger, %{"status" => "attempted"}) submissions_from_res = res[:data][:submissions] + + Enum.each(submissions_from_res, fn s -> + assert s.status == :attempted + end) + end + + test "filter by submission status :submitted", %{ + course_regs: %{avenger1_cr: avenger}, + assessments: assessments, + total_submissions: total_submissions + } do + expected_length = + Enum.reduce(assessments, 0, fn {_, %{submissions: submissions}}, acc -> + Enum.count(submissions, fn s -> s.status == :submitted end) + acc + end) + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "status" => "submitted", + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.status == :submitted + end) + end + + test "filter by submission not fully graded", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + # All but one is fully graded + expected_length = length(Map.keys(assessments)) * (length(students) - 1) + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "notFullyGraded" => "true", + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + Enum.each(submissions_from_res, fn s -> assert s.question_count > s.graded_count end) diff --git a/test/support/seeds.ex b/test/support/seeds.ex index 0a4f9f4f9..cee5d4d52 100644 --- a/test/support/seeds.ex +++ b/test/support/seeds.ex @@ -48,16 +48,30 @@ defmodule Cadet.Test.Seeds do email: "avenger1@gmail.com" }) + avenger2 = + insert(:user, %{ + name: "avenger2", + latest_viewed_course: course1, + email: "avenger2@gmail.com" + }) + admin1 = insert(:user, %{name: "admin", latest_viewed_course: course1}) studenta1admin2 = insert(:user, %{name: "student a", latest_viewed_course: course1}) studentb1 = insert(:user, %{latest_viewed_course: course1}) studentc1 = insert(:user, %{latest_viewed_course: course1}) + student_attempted = insert(:user, %{latest_viewed_course: course1}) + student_submitted = insert(:user, %{latest_viewed_course: course1}) + student_graded = insert(:user, %{latest_viewed_course: course1}) + student_different_group = insert(:user, %{latest_viewed_course: course1}) + student_group2 = insert(:user, %{latest_viewed_course: course1}) # CourseRegistration and Group avenger1_cr = insert(:course_registration, %{user: avenger1, course: course1, role: :staff}) + avenger2_cr = insert(:course_registration, %{user: avenger2, course: course1, role: :staff}) admin1_cr = insert(:course_registration, %{user: admin1, course: course1, role: :admin}) group = insert(:group, %{leader: avenger1_cr}) + group2 = insert(:group, %{leader: avenger2_cr}) student1a_cr = insert(:course_registration, %{ @@ -83,7 +97,58 @@ defmodule Cadet.Test.Seeds do group: group }) - students = [student1a_cr, student1b_cr, student1c_cr] + student_attempted_cr = + insert(:course_registration, %{ + user: student_attempted, + course: course1, + role: :student, + group: group + }) + + student_submitted_cr = + insert(:course_registration, %{ + user: student_submitted, + course: course1, + role: :student, + group: group + }) + + student_graded_cr = + insert(:course_registration, %{ + user: student_graded, + course: course1, + role: :student, + group: group + }) + + student_different_group_cr = + insert(:course_registration, %{ + user: student_different_group, + course: course1, + role: :student, + group: group2 + }) + + students = [ + student1a_cr, + student1b_cr, + student1c_cr, + student_attempted_cr, + student_submitted_cr, + student_graded_cr, + student_different_group_cr + ] + + # {student_cr, submission_status, is_graded, avenger} + students_with_assessment_info = [ + {student1a_cr, :attempting, false, avenger1_cr}, + {student1b_cr, :attempting, false, avenger1_cr}, + {student1c_cr, :attempting, false, avenger1_cr}, + {student_attempted_cr, :attempted, false, avenger1_cr}, + {student_submitted_cr, :submitted, false, avenger1_cr}, + {student_graded_cr, :submitted, true, avenger1_cr}, + {student_different_group_cr, :attempting, false, avenger2_cr} + ] _admin2cr = insert(:course_registration, %{user: studenta1admin2, course: course2, role: :admin}) @@ -113,7 +178,11 @@ defmodule Cadet.Test.Seeds do |> Enum.reduce( %{}, fn config, acc -> - Map.put(acc, config.type, insert_assessments(config, students, course1, avenger1_cr)) + Map.put( + acc, + config.type, + insert_assessments(config, students_with_assessment_info, course1, avenger1_cr) + ) end ) @@ -177,17 +246,23 @@ defmodule Cadet.Test.Seeds do }) end) - submissions_status = Enum.random(Cadet.Assessments.SubmissionStatus.__enums__) - submissions = + submissions_with_grader = students - |> Enum.take(2) - |> Enum.map(&insert(:submission, %{assessment: assessment, student: &1, status: submissions_status})) + |> Enum.map(fn {student, submission_status, is_graded, avenger} -> + grader = if is_graded, do: avenger, else: nil + + {grader, + insert(:submission, %{ + assessment: assessment, + student: student, + status: submission_status + })} + end) - is_graded = Enum.random([true, false]) - grader = if is_graded, do: avenger, else: nil + submissions = Enum.map(submissions_with_grader, fn {_, submission} -> submission end) # Programming Answers programming_answers = - Enum.map(submissions, fn submission -> + Enum.map(submissions_with_grader, fn {grader, submission} -> Enum.map(programming_questions, fn question -> insert(:answer, %{ xp: 800, @@ -200,7 +275,7 @@ defmodule Cadet.Test.Seeds do end) mcq_answers = - Enum.map(submissions, fn submission -> + Enum.map(submissions_with_grader, fn {grader, submission} -> Enum.map(mcq_questions, fn question -> insert(:answer, %{ xp: 500, @@ -213,7 +288,7 @@ defmodule Cadet.Test.Seeds do end) voting_answers = - Enum.map(submissions, fn submission -> + Enum.map(submissions_with_grader, fn {grader, submission} -> Enum.map(voting_questions, fn question -> insert(:answer, %{ xp: 100, From 06753a2ff620ec203116bbb84f5f45e4f48cbade Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Fri, 15 Mar 2024 21:29:34 +0800 Subject: [PATCH 07/15] feat: Update seed to include second group and avenger --- test/support/seeds.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/support/seeds.ex b/test/support/seeds.ex index cee5d4d52..545a25c2c 100644 --- a/test/support/seeds.ex +++ b/test/support/seeds.ex @@ -193,7 +193,9 @@ defmodule Cadet.Test.Seeds do }, course_regs: %{ avenger1_cr: avenger1_cr, + avenger2_cr: avenger2_cr, group: group, + group2: group2, students: students, admin1_cr: admin1_cr }, From e75dc5e87eaa7339bb43e7ef6e8cb62b1de38248 Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Fri, 15 Mar 2024 21:30:21 +0800 Subject: [PATCH 08/15] feat: Implement tests for filtering by group --- test/cadet/assessments/assessments_test.exs | 48 +++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index 360835eb4..0e5de6700 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1827,6 +1827,54 @@ defmodule Cadet.AssessmentsTest do assert s.question_count > s.graded_count end) end + + test "filter by group avenger", %{ + course_regs: %{avenger1_cr: avenger, group: group, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + # All but one is in the same group + expected_length = length(Map.keys(assessments)) * (length(students) - 1) + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "group" => "true", + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + student = Enum.find(students, fn student -> student.id == s.student_id end) + assert student.group.id == group.id + end) + end + + test "filter by group avenger2", %{ + course_regs: %{avenger2_cr: avenger2, group2: group2, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + # One in the same group + expected_length = length(Map.keys(assessments)) * 1 + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger2, %{ + "group" => "true", + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + student = Enum.find(students, fn student -> student.id == s.student_id end) + assert student.group.id == group2.id + end) + end end defp get_answer_relative_scores(answers) do From 3278ed8d9dde57904762b802ff7f9b13955d0737 Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Fri, 15 Mar 2024 22:02:35 +0800 Subject: [PATCH 09/15] feat: Implement tests for filter by group name --- test/cadet/assessments/assessments_test.exs | 54 +++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index 0e5de6700..ed4a745fc 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1708,7 +1708,11 @@ defmodule Cadet.AssessmentsTest do course_reg: group, groupName user: name, username assessment_config: type, isManuallyGraded + + checks: + mix test ./test/cadet/assessments/assessments_test.exs ./test/cadet/email_test.exs ./test/cadet/jobs/notification_worker/notification_worker_test.exs ./test/cadet_web/controllers/assessments_controller_test.exs ./test/cadet_web/admin_controllers/admin_assessments_controller_test.exs """ + describe "get submission function" do setup do seed = Cadet.Test.Seeds.assessments() @@ -1875,6 +1879,56 @@ defmodule Cadet.AssessmentsTest do assert student.group.id == group2.id end) end + + # Chose avenger2 to ensure that the group name is not the same as the avenger's group + test "filter by group name group", %{ + course_regs: %{avenger2_cr: avenger2, group: group, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + # All but one is in group + expected_length = length(Map.keys(assessments)) * (length(students) - 1) + group_name = group.name + {_, res} = + Assessments.submissions_by_grader_for_index(avenger2, %{ + "groupName" => group_name, + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + student = Enum.find(students, fn student -> student.id == s.student_id end) + assert student.group.id == group.id + end) + end + + # Chose avenger to ensure that the group name is not the same as the avenger's group + test "filter by group name group2", %{ + course_regs: %{avenger1_cr: avenger, group2: group2, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + # One in the group + expected_length = length(Map.keys(assessments)) * 1 + group_name = group2.name + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "groupName" => group_name, + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + student = Enum.find(students, fn student -> student.id == s.student_id end) + assert student.group.id == group2.id + end) + end end defp get_answer_relative_scores(answers) do From 991081bf2ec6da85a1fb9af1d58448f3126bfd3f Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Fri, 15 Mar 2024 22:15:59 +0800 Subject: [PATCH 10/15] feat: Implement tests for filter by student name --- test/cadet/assessments/assessments_test.exs | 81 ++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index ed4a745fc..a1f80a7d4 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1705,8 +1705,8 @@ defmodule Cadet.AssessmentsTest do TODO: assessment: title(D) submission: status(D), notFullyGraded (D) - course_reg: group, groupName - user: name, username + course_reg: group (D), groupName (D) + user: name (D), username assessment_config: type, isManuallyGraded checks: @@ -1889,6 +1889,7 @@ defmodule Cadet.AssessmentsTest do # All but one is in group expected_length = length(Map.keys(assessments)) * (length(students) - 1) group_name = group.name + {_, res} = Assessments.submissions_by_grader_for_index(avenger2, %{ "groupName" => group_name, @@ -1914,6 +1915,7 @@ defmodule Cadet.AssessmentsTest do # One in the group expected_length = length(Map.keys(assessments)) * 1 group_name = group2.name + {_, res} = Assessments.submissions_by_grader_for_index(avenger, %{ "groupName" => group_name, @@ -1929,6 +1931,81 @@ defmodule Cadet.AssessmentsTest do assert student.group.id == group2.id end) end + + test "filter by student name", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + expected_length = length(Map.keys(assessments)) * 1 + + student = Enum.at(students, 0) + student_name = student.user.name + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "name" => student_name, + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.student_id == student.id + end) + end + + test "filter by student name 2", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + expected_length = length(Map.keys(assessments)) * 1 + + student = Enum.at(students, 1) + student_name = student.user.name + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "name" => student_name, + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.student_id == student.id + end) + end + + test "filter by student name 3", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + expected_length = length(Map.keys(assessments)) * 1 + + student = Enum.at(students, 2) + student_name = student.user.name + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "name" => student_name, + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.student_id == student.id + end) + end end defp get_answer_relative_scores(answers) do From 05f805e1badbdd4519e77686eac089fc50fca33e Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Fri, 15 Mar 2024 22:18:53 +0800 Subject: [PATCH 11/15] feat: Implement tests for filter by student username --- test/cadet/assessments/assessments_test.exs | 77 ++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index a1f80a7d4..6cdb19fd0 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1706,7 +1706,7 @@ defmodule Cadet.AssessmentsTest do assessment: title(D) submission: status(D), notFullyGraded (D) course_reg: group (D), groupName (D) - user: name (D), username + user: name (D), username (D) assessment_config: type, isManuallyGraded checks: @@ -2006,6 +2006,81 @@ defmodule Cadet.AssessmentsTest do assert s.student_id == student.id end) end + + test "filter by student username 1", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + expected_length = length(Map.keys(assessments)) * 1 + + student = Enum.at(students, 0) + student_username = student.user.username + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "username" => student_username, + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.student_id == student.id + end) + end + + test "filter by student username 2", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + expected_length = length(Map.keys(assessments)) * 1 + + student = Enum.at(students, 1) + student_username = student.user.username + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "username" => student_username, + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.student_id == student.id + end) + end + + test "filter by student username 3", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + total_submissions: total_submissions + } do + expected_length = length(Map.keys(assessments)) * 1 + + student = Enum.at(students, 2) + student_username = student.user.username + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "username" => student_username, + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.student_id == student.id + end) + end end defp get_answer_relative_scores(answers) do From 5e0e7694464505409d6d31d3fc60c513bc461e3e Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Sat, 16 Mar 2024 18:51:21 +0800 Subject: [PATCH 12/15] feat: Implement tests for filter by manually graded config --- test/cadet/assessments/assessments_test.exs | 163 ++++++++++++++++++-- 1 file changed, 150 insertions(+), 13 deletions(-) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index 6cdb19fd0..80d6728be 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1700,19 +1700,7 @@ defmodule Cadet.AssessmentsTest do end end - """ - mix test ./test/cadet/assessments/assessments_test.exs - TODO: - assessment: title(D) - submission: status(D), notFullyGraded (D) - course_reg: group (D), groupName (D) - user: name (D), username (D) - assessment_config: type, isManuallyGraded - - checks: - mix test ./test/cadet/assessments/assessments_test.exs ./test/cadet/email_test.exs ./test/cadet/jobs/notification_worker/notification_worker_test.exs ./test/cadet_web/controllers/assessments_controller_test.exs ./test/cadet_web/admin_controllers/admin_assessments_controller_test.exs - """ - + # Tests assume each config has only 1 assessment describe "get submission function" do setup do seed = Cadet.Test.Seeds.assessments() @@ -2081,6 +2069,155 @@ defmodule Cadet.AssessmentsTest do assert s.student_id == student.id end) end + + test "filter by assessment config 1", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + assessment_configs: assessment_configs, + total_submissions: total_submissions + } do + expected_length = 1 * length(students) + + assessment_config = Enum.at(assessment_configs, 0) + assessment_type = assessment_config.type + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "type" => assessment_type, + "pageSize" => total_submissions + }) + + assessments_from_res = res[:data][:assessments] + submissions_from_res = res[:data][:submissions] + assert length(assessments_from_res) == 1 + assessment = Enum.at(assessments_from_res, 0) + assessment_id = assessment.id + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.assessment_id == assessment_id + end) + end + + test "filter by assessment config 2", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + assessment_configs: assessment_configs, + total_submissions: total_submissions + } do + expected_length = 1 * length(students) + + assessment_config = Enum.at(assessment_configs, 1) + assessment_type = assessment_config.type + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "type" => assessment_type, + "pageSize" => total_submissions + }) + + assessments_from_res = res[:data][:assessments] + submissions_from_res = res[:data][:submissions] + assert length(assessments_from_res) == 1 + assessment = Enum.at(assessments_from_res, 0) + assessment_id = assessment.id + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.assessment_id == assessment_id + end) + end + + test "filter by assessment config 3", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + assessment_configs: assessment_configs, + total_submissions: total_submissions + } do + expected_length = 1 * length(students) + + assessment_config = Enum.at(assessment_configs, 2) + assessment_type = assessment_config.type + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "type" => assessment_type, + "pageSize" => total_submissions + }) + + assessments_from_res = res[:data][:assessments] + submissions_from_res = res[:data][:submissions] + assert length(assessments_from_res) == 1 + assessment = Enum.at(assessments_from_res, 0) + assessment_id = assessment.id + assert length(submissions_from_res) == expected_length + + Enum.each(submissions_from_res, fn s -> + assert s.assessment_id == assessment_id + end) + end + + test "filter by assessment config manually graded", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + assessment_configs: assessment_configs, + total_submissions: total_submissions + } do + expected_length = + Enum.reduce(assessment_configs, 0, fn config, acc -> + if config.is_manually_graded, do: acc + 1, else: acc + end) * length(students) + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "isManuallyGraded" => "true", + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + assessments_from_res = res[:data][:assessments] + + assert length(submissions_from_res) == expected_length + + assessment_configs_from_res = Enum.map(assessments_from_res, fn a -> a.config end) + Enum.each(assessment_configs_from_res, fn config -> assert config.is_manually_graded end) + + # We know all assessments_from_res have correct config from previous check + Enum.each(submissions_from_res, fn s -> + assert Enum.find(assessments_from_res, fn a -> a.id == s.assessment_id end) != nil + end) + end + + test "filter by assessment config not manually graded", %{ + course_regs: %{avenger1_cr: avenger, students: students}, + assessments: assessments, + assessment_configs: assessment_configs, + total_submissions: total_submissions + } do + expected_length = + Enum.reduce(assessment_configs, 0, fn config, acc -> + if !config.is_manually_graded, do: acc + 1, else: acc + end) * length(students) + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "isManuallyGraded" => "false", + "pageSize" => total_submissions + }) + + submissions_from_res = res[:data][:submissions] + assessments_from_res = res[:data][:assessments] + + assert length(submissions_from_res) == expected_length + + assessment_configs_from_res = Enum.map(assessments_from_res, fn a -> a.config end) + Enum.each(assessment_configs_from_res, fn config -> assert !config.is_manually_graded end) + + # We know all assessments_from_res have correct config from previous check + Enum.each(submissions_from_res, fn s -> + assert Enum.find(assessments_from_res, fn a -> a.id == s.assessment_id end) != nil + end) + end end defp get_answer_relative_scores(answers) do From c8936118f27fc3586b14bf3087d5f3ebd4fcc2df Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Sat, 16 Mar 2024 19:00:44 +0800 Subject: [PATCH 13/15] refactor: Remove whitespace and move asserts to the bottom --- test/cadet/assessments/assessments_test.exs | 40 ++++++++++++--------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index 80d6728be..f50ddde41 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1753,6 +1753,7 @@ defmodule Cadet.AssessmentsTest do }) submissions_from_res = res[:data][:submissions] + assert length(submissions_from_res) == expected_length Enum.each(submissions_from_res, fn s -> @@ -1762,11 +1763,24 @@ defmodule Cadet.AssessmentsTest do test "filter by submission status :attempted", %{ course_regs: %{avenger1_cr: avenger}, - assessments: assessments + assessments: assessments, + total_submissions: total_submissions } do - {_, res} = Assessments.submissions_by_grader_for_index(avenger, %{"status" => "attempted"}) + expected_length = + Enum.reduce(assessments, 0, fn {_, %{submissions: submissions}}, acc -> + Enum.count(submissions, fn s -> s.status == :attempted end) + acc + end) + + {_, res} = + Assessments.submissions_by_grader_for_index(avenger, %{ + "status" => "attempted", + "pageSize" => total_submissions + }) + submissions_from_res = res[:data][:submissions] + assert length(submissions_from_res) == expected_length + Enum.each(submissions_from_res, fn s -> assert s.status == :attempted end) @@ -1926,7 +1940,6 @@ defmodule Cadet.AssessmentsTest do total_submissions: total_submissions } do expected_length = length(Map.keys(assessments)) * 1 - student = Enum.at(students, 0) student_name = student.user.name @@ -1951,7 +1964,6 @@ defmodule Cadet.AssessmentsTest do total_submissions: total_submissions } do expected_length = length(Map.keys(assessments)) * 1 - student = Enum.at(students, 1) student_name = student.user.name @@ -1976,7 +1988,6 @@ defmodule Cadet.AssessmentsTest do total_submissions: total_submissions } do expected_length = length(Map.keys(assessments)) * 1 - student = Enum.at(students, 2) student_name = student.user.name @@ -2001,7 +2012,6 @@ defmodule Cadet.AssessmentsTest do total_submissions: total_submissions } do expected_length = length(Map.keys(assessments)) * 1 - student = Enum.at(students, 0) student_username = student.user.username @@ -2026,7 +2036,6 @@ defmodule Cadet.AssessmentsTest do total_submissions: total_submissions } do expected_length = length(Map.keys(assessments)) * 1 - student = Enum.at(students, 1) student_username = student.user.username @@ -2051,7 +2060,6 @@ defmodule Cadet.AssessmentsTest do total_submissions: total_submissions } do expected_length = length(Map.keys(assessments)) * 1 - student = Enum.at(students, 2) student_username = student.user.username @@ -2077,7 +2085,6 @@ defmodule Cadet.AssessmentsTest do total_submissions: total_submissions } do expected_length = 1 * length(students) - assessment_config = Enum.at(assessment_configs, 0) assessment_type = assessment_config.type @@ -2089,9 +2096,10 @@ defmodule Cadet.AssessmentsTest do assessments_from_res = res[:data][:assessments] submissions_from_res = res[:data][:submissions] - assert length(assessments_from_res) == 1 assessment = Enum.at(assessments_from_res, 0) assessment_id = assessment.id + + assert length(assessments_from_res) == 1 assert length(submissions_from_res) == expected_length Enum.each(submissions_from_res, fn s -> @@ -2118,9 +2126,10 @@ defmodule Cadet.AssessmentsTest do assessments_from_res = res[:data][:assessments] submissions_from_res = res[:data][:submissions] - assert length(assessments_from_res) == 1 assessment = Enum.at(assessments_from_res, 0) assessment_id = assessment.id + + assert length(assessments_from_res) == 1 assert length(submissions_from_res) == expected_length Enum.each(submissions_from_res, fn s -> @@ -2147,9 +2156,10 @@ defmodule Cadet.AssessmentsTest do assessments_from_res = res[:data][:assessments] submissions_from_res = res[:data][:submissions] - assert length(assessments_from_res) == 1 assessment = Enum.at(assessments_from_res, 0) assessment_id = assessment.id + + assert length(assessments_from_res) == 1 assert length(submissions_from_res) == expected_length Enum.each(submissions_from_res, fn s -> @@ -2176,10 +2186,9 @@ defmodule Cadet.AssessmentsTest do submissions_from_res = res[:data][:submissions] assessments_from_res = res[:data][:assessments] + assessment_configs_from_res = Enum.map(assessments_from_res, fn a -> a.config end) assert length(submissions_from_res) == expected_length - - assessment_configs_from_res = Enum.map(assessments_from_res, fn a -> a.config end) Enum.each(assessment_configs_from_res, fn config -> assert config.is_manually_graded end) # We know all assessments_from_res have correct config from previous check @@ -2207,10 +2216,9 @@ defmodule Cadet.AssessmentsTest do submissions_from_res = res[:data][:submissions] assessments_from_res = res[:data][:assessments] + assessment_configs_from_res = Enum.map(assessments_from_res, fn a -> a.config end) assert length(submissions_from_res) == expected_length - - assessment_configs_from_res = Enum.map(assessments_from_res, fn a -> a.config end) Enum.each(assessment_configs_from_res, fn config -> assert !config.is_manually_graded end) # We know all assessments_from_res have correct config from previous check From cd76dbea4565a997b53b5967cc0cb47b331e2710 Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Sat, 16 Mar 2024 19:06:25 +0800 Subject: [PATCH 14/15] chore: Remove unused variables in test seed --- test/support/seeds.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/support/seeds.ex b/test/support/seeds.ex index 545a25c2c..ce9f55205 100644 --- a/test/support/seeds.ex +++ b/test/support/seeds.ex @@ -65,7 +65,7 @@ defmodule Cadet.Test.Seeds do student_submitted = insert(:user, %{latest_viewed_course: course1}) student_graded = insert(:user, %{latest_viewed_course: course1}) student_different_group = insert(:user, %{latest_viewed_course: course1}) - student_group2 = insert(:user, %{latest_viewed_course: course1}) + # CourseRegistration and Group avenger1_cr = insert(:course_registration, %{user: avenger1, course: course1, role: :staff}) avenger2_cr = insert(:course_registration, %{user: avenger2, course: course1, role: :staff}) @@ -181,7 +181,7 @@ defmodule Cadet.Test.Seeds do Map.put( acc, config.type, - insert_assessments(config, students_with_assessment_info, course1, avenger1_cr) + insert_assessments(config, students_with_assessment_info, course1) ) end ) @@ -210,7 +210,7 @@ defmodule Cadet.Test.Seeds do end end - defp insert_assessments(assessment_config, students, course, avenger) do + defp insert_assessments(assessment_config, students, course) do assessment = insert(:assessment, %{course: course, config: assessment_config, is_published: true}) From fd3dd30d114226c3d2c38065246ad72c943b53b9 Mon Sep 17 00:00:00 2001 From: GabrielCWT <77312579+GabrielCWT@users.noreply.github.com> Date: Sat, 16 Mar 2024 19:11:49 +0800 Subject: [PATCH 15/15] refactor: Remove unnecessary code --- test/cadet/assessments/assessments_test.exs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/cadet/assessments/assessments_test.exs b/test/cadet/assessments/assessments_test.exs index f50ddde41..7894ed5de 100644 --- a/test/cadet/assessments/assessments_test.exs +++ b/test/cadet/assessments/assessments_test.exs @@ -1864,7 +1864,7 @@ defmodule Cadet.AssessmentsTest do total_submissions: total_submissions } do # One in the same group - expected_length = length(Map.keys(assessments)) * 1 + expected_length = length(Map.keys(assessments)) {_, res} = Assessments.submissions_by_grader_for_index(avenger2, %{ @@ -1915,7 +1915,7 @@ defmodule Cadet.AssessmentsTest do total_submissions: total_submissions } do # One in the group - expected_length = length(Map.keys(assessments)) * 1 + expected_length = length(Map.keys(assessments)) group_name = group2.name {_, res} = @@ -1939,7 +1939,7 @@ defmodule Cadet.AssessmentsTest do assessments: assessments, total_submissions: total_submissions } do - expected_length = length(Map.keys(assessments)) * 1 + expected_length = length(Map.keys(assessments)) student = Enum.at(students, 0) student_name = student.user.name @@ -1963,7 +1963,7 @@ defmodule Cadet.AssessmentsTest do assessments: assessments, total_submissions: total_submissions } do - expected_length = length(Map.keys(assessments)) * 1 + expected_length = length(Map.keys(assessments)) student = Enum.at(students, 1) student_name = student.user.name @@ -1987,7 +1987,7 @@ defmodule Cadet.AssessmentsTest do assessments: assessments, total_submissions: total_submissions } do - expected_length = length(Map.keys(assessments)) * 1 + expected_length = length(Map.keys(assessments)) student = Enum.at(students, 2) student_name = student.user.name @@ -2011,7 +2011,7 @@ defmodule Cadet.AssessmentsTest do assessments: assessments, total_submissions: total_submissions } do - expected_length = length(Map.keys(assessments)) * 1 + expected_length = length(Map.keys(assessments)) student = Enum.at(students, 0) student_username = student.user.username @@ -2035,7 +2035,7 @@ defmodule Cadet.AssessmentsTest do assessments: assessments, total_submissions: total_submissions } do - expected_length = length(Map.keys(assessments)) * 1 + expected_length = length(Map.keys(assessments)) student = Enum.at(students, 1) student_username = student.user.username @@ -2059,7 +2059,7 @@ defmodule Cadet.AssessmentsTest do assessments: assessments, total_submissions: total_submissions } do - expected_length = length(Map.keys(assessments)) * 1 + expected_length = length(Map.keys(assessments)) student = Enum.at(students, 2) student_username = student.user.username @@ -2205,7 +2205,7 @@ defmodule Cadet.AssessmentsTest do } do expected_length = Enum.reduce(assessment_configs, 0, fn config, acc -> - if !config.is_manually_graded, do: acc + 1, else: acc + if config.is_manually_graded, do: acc, else: acc + 1 end) * length(students) {_, res} =