ReminderDto: разделить на ApprovalOverdueReminderDto и ProbationEndingReminderDto
Абстрактный базовый класс + два sealed-наследника вместо одного DTO с опциональными полями под обе категории — так специфичные для каждого вида напоминания поля не путаются с полями другого вида. Полиморфная сериализация System.Text.Json ([JsonPolymorphic]/[JsonDerivedType]) нужна, иначе список IReadOnlyList<ReminderDto> сериализовался бы только по общим полям базового класса.
This commit is contained in:
+9
-10
@@ -138,7 +138,7 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
|
||||
var result = await service.GetOverdueAsync(Now, CancellationToken.None);
|
||||
|
||||
result.IsSuccess.ShouldBeTrue();
|
||||
var reminder = result.Value.ShouldHaveSingleItem();
|
||||
var reminder = result.Value.ShouldHaveSingleItem().ShouldBeOfType<ApprovalOverdueReminderDto>();
|
||||
reminder.Email.ShouldBe("approver@tnsu.kz");
|
||||
reminder.HoursOverdue.ShouldBe(24);
|
||||
reminder.RequestId.ShouldBe(1);
|
||||
@@ -173,7 +173,7 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
|
||||
|
||||
var result = await service.GetOverdueAsync(Now, CancellationToken.None);
|
||||
|
||||
result.Value.ShouldHaveSingleItem().HoursOverdue.ShouldBe(2);
|
||||
result.Value.ShouldHaveSingleItem().ShouldBeOfType<ApprovalOverdueReminderDto>().HoursOverdue.ShouldBe(2);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Активная строка без даты (Date пуста) — пропускается, а не падает")]
|
||||
@@ -199,7 +199,7 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
|
||||
|
||||
var result = await service.GetOverdueAsync(Now, CancellationToken.None);
|
||||
|
||||
result.Value.ShouldHaveSingleItem().HoursOverdue.ShouldBe(5);
|
||||
result.Value.ShouldHaveSingleItem().ShouldBeOfType<ApprovalOverdueReminderDto>().HoursOverdue.ShouldBe(5);
|
||||
}
|
||||
|
||||
// SharePoint отдаёт Number-колонки ДРОБНЫМИ («1.0», а не «1»), и на этом
|
||||
@@ -219,7 +219,7 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
|
||||
|
||||
var result = await service.GetOverdueAsync(Now, CancellationToken.None);
|
||||
|
||||
result.Value.ShouldHaveSingleItem().HoursOverdue.ShouldBe(5);
|
||||
result.Value.ShouldHaveSingleItem().ShouldBeOfType<ApprovalOverdueReminderDto>().HoursOverdue.ShouldBe(5);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Флаг опроса причины наследуется от типа заявки, если в строке не задан")]
|
||||
@@ -231,7 +231,7 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
|
||||
|
||||
var result = await service.GetOverdueAsync(Now, CancellationToken.None);
|
||||
|
||||
result.Value.ShouldHaveSingleItem().AskOverdueReason.ShouldBeTrue();
|
||||
result.Value.ShouldHaveSingleItem().ShouldBeOfType<ApprovalOverdueReminderDto>().AskOverdueReason.ShouldBeTrue();
|
||||
}
|
||||
|
||||
// Портал — одностраничный и живёт в корне сайта; вид ссылки подтверждён
|
||||
@@ -276,7 +276,7 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
|
||||
|
||||
var result = await service.GetOverdueAsync(Now, CancellationToken.None);
|
||||
|
||||
result.Value.ShouldHaveSingleItem().Email.ShouldBe("approver@tnsu.kz");
|
||||
result.Value.ShouldHaveSingleItem().ShouldBeOfType<ApprovalOverdueReminderDto>().Email.ShouldBe("approver@tnsu.kz");
|
||||
}
|
||||
|
||||
private static object HireDataRow(
|
||||
@@ -355,11 +355,10 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
|
||||
var result = await service.GetProbationEndingAsync(Now, CancellationToken.None);
|
||||
|
||||
result.IsSuccess.ShouldBeTrue();
|
||||
var reminder = result.Value.ShouldHaveSingleItem();
|
||||
var reminder = result.Value.ShouldHaveSingleItem().ShouldBeOfType<ProbationEndingReminderDto>();
|
||||
reminder.Category.ShouldBe(ReminderCategory.ProbationEnding);
|
||||
reminder.ManagerEmail.ShouldBe("manager@tnsu.kz");
|
||||
reminder.CandidateEmail.ShouldBe("candidate@tnsu.kz");
|
||||
reminder.Email.ShouldBe("manager@tnsu.kz");
|
||||
reminder.CandidateName.ShouldBe("Иванов Иван Иванович");
|
||||
reminder.DaysUntilProbationEnds.ShouldBe(3);
|
||||
}
|
||||
@@ -407,7 +406,7 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
|
||||
var service = BuildProbationService(pageUrl, listUrl, rows, portalClient);
|
||||
var result = await service.GetProbationEndingAsync(Now, CancellationToken.None);
|
||||
|
||||
result.Value.ShouldHaveSingleItem().CandidateEmail.ShouldBe("romanov@tnsu.kz");
|
||||
result.Value.ShouldHaveSingleItem().ShouldBeOfType<ProbationEndingReminderDto>().CandidateEmail.ShouldBe("romanov@tnsu.kz");
|
||||
}
|
||||
|
||||
// ФИО в заявке набирают руками — лишние пробелы и другой регистр не должны
|
||||
@@ -423,7 +422,7 @@ public sealed class ReminderServiceTests : IClassFixture<PostgresDatabaseFixture
|
||||
var service = BuildProbationService(pageUrl, listUrl, rows, portalClient);
|
||||
var result = await service.GetProbationEndingAsync(Now, CancellationToken.None);
|
||||
|
||||
result.Value.ShouldHaveSingleItem().CandidateEmail.ShouldBe("volkov@tnsu.kz");
|
||||
result.Value.ShouldHaveSingleItem().ShouldBeOfType<ProbationEndingReminderDto>().CandidateEmail.ShouldBe("volkov@tnsu.kz");
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Кандидат не найден в /Employee/FullBase — напоминания нет")]
|
||||
|
||||
Reference in New Issue
Block a user