using Jiaowu.Api.Contracts; using Jiaowu.Api.Controllers; using Jiaowu.Api.Domain.Academic; using Jiaowu.Api.Domain.Identity; using Jiaowu.Api.Infrastructure.Auth; using Jiaowu.Api.Infrastructure.Persistence; using Microsoft.AspNetCore.Mvc; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; namespace Jiaowu.Api.Tests; public sealed class GradesPaginationTests { [Fact] public async Task GradeTasksAndStudentRecords_AreReturnedByPage() { await using var connection = new SqliteConnection("Data Source=:memory:"); await connection.OpenAsync(); await using var db = new AppDbContext( new DbContextOptionsBuilder() .UseSqlite(connection) .Options); await db.Database.EnsureCreatedAsync(); var college = new College { Code = "CS", Name = "计算机学院" }; var major = new Major { Code = "080901", Name = "计算机科学与技术", CollegeId = college.Id, DegreeType = "工学学士" }; var administrativeClass = new AdministrativeClass { Code = "CS2026-01", Name = "计科 2026-1 班", MajorId = major.Id, Grade = 2026 }; var course = new Course { Code = "CS101", Name = "程序设计基础", CollegeId = college.Id, Credits = 4, TotalHours = 64, LectureHours = 48, PracticeHours = 16, Nature = CourseNature.MajorRequired, AssessmentMethod = AssessmentMethod.Examination }; var term = new AcademicTerm { Code = "2026-1", Name = "2026—2027 学年第一学期", AcademicYear = "2026-2027", Season = TermSeason.Autumn, StartDate = new DateOnly(2026, 9, 1), EndDate = new DateOnly(2027, 1, 20) }; var tasks = Enumerable.Range(1, 11) .Select(number => new TeachingTask { TaskNumber = $"2026-1-CS101-{number:00}", Name = $"程序设计基础教学班 {number}", AcademicTermId = term.Id, CourseId = course.Id, Capacity = 60, Status = TeachingTaskStatus.Published }) .ToList(); var students = Enumerable.Range(1, 11) .Select(number => new Student { StudentNumber = $"202601{number:000}", Name = $"学生 {number}", AdministrativeClassId = administrativeClass.Id, EnrollmentYear = 2026, EnrollmentDate = new DateOnly(2026, 9, 1) }) .ToList(); var sheet = new GradeSheet { TeachingTaskId = tasks[0].Id, RegularWeight = 30, FinalWeight = 70, Records = students.Select(student => new GradeRecord { StudentId = student.Id }).ToList() }; db.AddRange(college, major, administrativeClass, course, term); db.AddRange(tasks); db.AddRange(students); db.Add(sheet); await db.SaveChangesAsync(); var controller = new GradesController(db, new AllScope()); var listResult = await controller.GetSheets( term.Id, null, null, 1, 10, CancellationToken.None); var listOk = Assert.IsType(listResult); var page = Assert.IsType>(listOk.Value); Assert.Equal(11, page.Total); Assert.Equal(10, page.Items.Count); var firstDetail = Assert.IsType(await controller.GetSheet( sheet.Id, 1, 10, null, CancellationToken.None)); var firstSheet = firstDetail.Value!.GetType().GetProperty("Sheet")! .GetValue(firstDetail.Value)!; Assert.Equal(11, ReadInt(firstSheet, "RecordTotal")); Assert.Equal(10, ReadItems(firstSheet, "Records").Count); var secondDetail = Assert.IsType(await controller.GetSheet( sheet.Id, 2, 10, null, CancellationToken.None)); var secondSheet = secondDetail.Value!.GetType().GetProperty("Sheet")! .GetValue(secondDetail.Value)!; Assert.Single(ReadItems(secondSheet, "Records")); } private static int ReadInt(object value, string property) => (int)value.GetType().GetProperty(property)!.GetValue(value)!; private static List ReadItems(object value, string property) => ((System.Collections.IEnumerable)value.GetType().GetProperty(property)! .GetValue(value)!).Cast().ToList(); private sealed class AllScope : ICurrentUserDataScope { public CurrentUserScope Current { get; } = new( Guid.NewGuid(), "测试管理员", null, DataScope.All, new HashSet([SystemRoles.SuperAdmin])); } }