using System.Text.Json; using Jiaowu.Api.Controllers; using Jiaowu.Api.Domain.Academic; using Jiaowu.Api.Domain.Identity; using Jiaowu.Api.Infrastructure.Persistence; using Jiaowu.Api.Infrastructure.Timetables; using Microsoft.AspNetCore.Mvc; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; namespace Jiaowu.Api.Tests; public sealed class VenueDisplaysControllerTests { [Fact] public async Task Classroom_IncludesApprovedReservationForToday() { await using var connection = new SqliteConnection("Data Source=:memory:"); await connection.OpenAsync(); var db = new AppDbContext(new DbContextOptionsBuilder() .UseSqlite(connection) .Options); await db.Database.EnsureCreatedAsync(); var today = DateOnly.FromDateTime(DateTime.Now); var campus = new Campus { Code = "MAIN", Name = "主校区" }; var building = new Building { Code = "A", Name = "明德楼", CampusId = campus.Id }; var classroom = new Classroom { Code = "A101", Name = "A101", BuildingId = building.Id, Capacity = 60 }; var college = new College { Code = "CS", Name = "计算机学院" }; var applicant = new ApplicationUser { Id = Guid.NewGuid(), UserName = "applicant", NormalizedUserName = "APPLICANT", DisplayName = "张老师", CollegeId = college.Id }; var term = new AcademicTerm { Code = "CURRENT", Name = "当前学期", AcademicYear = "2026-2027", Season = TermSeason.Autumn, StartDate = today.AddDays(-7), EndDate = today.AddDays(120), IsCurrent = true }; db.AddRange(campus, building, classroom, college, applicant, term); db.ClassroomReservations.Add(new ClassroomReservation { ApplicantUserId = applicant.Id, ApplicantName = applicant.DisplayName, ApplicantCollegeId = college.Id, AcademicTermId = term.Id, ClassroomId = classroom.Id, ReservationDate = today, StartPeriod = 3, PeriodCount = 2, AttendeeCount = 30, Purpose = "学院学术讲座", ContactPhone = "13800000000", Status = ClassroomReservationStatus.Approved }); db.VenueDisplayAnnouncements.Add(new VenueDisplayAnnouncement { Title = "消防演练提醒", Content = "今日 16:00 开展消防演练,请听从现场指引。", Scope = VenueDisplayAnnouncementScope.Building, TargetId = building.Id, IsPublished = true, IsUrgent = true }); await db.SaveChangesAsync(); var controller = new VenueDisplaysController( db, new TimetableDataService(db), new ClassroomReservationAvailabilityService(db)); var result = await controller.Classroom(classroom.Id, CancellationToken.None); var response = Assert.IsType(result).Value; using var document = JsonDocument.Parse(JsonSerializer.Serialize(response)); var entry = Assert.Single(document.RootElement.GetProperty("Entries").EnumerateArray()); Assert.Equal("教室借用", entry.GetProperty("CourseName").GetString()); Assert.Equal("学院学术讲座", entry.GetProperty("ClassNames")[0].GetString()); Assert.Equal("张老师", entry.GetProperty("TeacherNames")[0].GetString()); Assert.True(entry.GetProperty("IsReservation").GetBoolean()); var announcement = Assert.Single(document.RootElement.GetProperty("Announcements").EnumerateArray()); Assert.Equal("消防演练提醒", announcement.GetProperty("Title").GetString()); Assert.True(announcement.GetProperty("IsUrgent").GetBoolean()); var occupied = await new ClassroomReservationAvailabilityService(db) .GetOccupiedClassroomIdsByPeriodAsync(term, today, [2, 3, 4, 5], CancellationToken.None); Assert.DoesNotContain(classroom.Id, occupied[2]); Assert.Contains(classroom.Id, occupied[3]); Assert.Contains(classroom.Id, occupied[4]); Assert.DoesNotContain(classroom.Id, occupied[5]); } }