Update validation rules in ImportManualInboxCommand and ManualInboxDialog to allow season numbers starting from zero, reflecting the inclusion of special episodes and pilots. Adjust input constraints in the frontend to enhance user experience and ensure consistency with backend validation.
build / backend (push) Successful in 1m48s
build / frontend (push) Successful in 51s
tests / backend-tests (push) Successful in 2m2s

This commit is contained in:
Leonid Pershin
2026-07-26 15:53:09 +03:00
parent 7af6242003
commit 6bca42754c
3 changed files with 54 additions and 3 deletions
@@ -37,11 +37,12 @@ public sealed class ImportManualInboxCommandValidator
RuleFor(x => x.Items.Count).LessThanOrEqualTo(500); RuleFor(x => x.Items.Count).LessThanOrEqualTo(500);
RuleFor(x => x.ShowId).NotEmpty(); RuleFor(x => x.ShowId).NotEmpty();
// Ноль — законный номер: пилот часто идёт как E00, а спецвыпуски живут в нулевом сезоне.
RuleForEach(x => x.Items) RuleForEach(x => x.Items)
.Must(i => i.Season is null or (> 0 and <= 99)) .Must(i => i.Season is null or (>= 0 and <= 99))
.WithMessage("Сезон вне допустимого диапазона."); .WithMessage("Сезон вне допустимого диапазона.");
RuleForEach(x => x.Items) RuleForEach(x => x.Items)
.Must(i => i.Episode is null or (> 0 and <= 999)) .Must(i => i.Episode is null or (>= 0 and <= 999))
.WithMessage("Номер серии вне допустимого диапазона."); .WithMessage("Номер серии вне допустимого диапазона.");
} }
} }
@@ -0,0 +1,49 @@
using TeleWave.Application.Media.ManualInbox;
using Xunit;
namespace TeleWave.Application.Tests.Media;
public class ImportManualInboxValidatorTests
{
private static ImportManualInboxCommand Command(int? season, int? episode) =>
new([new ManualImportItem("Шоу/файл.mkv", season, episode)], Guid.NewGuid());
[Theory]
[InlineData(1, 0)] // пилот идёт как E00 — это норма, а не ошибка ввода
[InlineData(0, 1)] // спецвыпуски живут в нулевом сезоне
[InlineData(1, 1)]
[InlineData(99, 999)]
[InlineData(null, null)] // номера не заданы — сервер разберёт имя сам
public void AllowsRealWorldNumbers(int? season, int? episode)
{
Assert.True(new ImportManualInboxCommandValidator().Validate(Command(season, episode)).IsValid);
}
[Theory]
[InlineData(-1, 1)]
[InlineData(100, 1)]
[InlineData(1, -1)]
[InlineData(1, 1000)]
public void RejectsOutOfRange(int? season, int? episode)
{
Assert.False(new ImportManualInboxCommandValidator().Validate(Command(season, episode)).IsValid);
}
[Fact]
public void RejectsEmptyBatchAndMissingShow()
{
var validator = new ImportManualInboxCommandValidator();
Assert.False(validator.Validate(new ImportManualInboxCommand([], Guid.NewGuid())).IsValid);
Assert.False(
validator
.Validate(
new ImportManualInboxCommand(
[new ManualImportItem("файл.mkv", 1, 1)],
Guid.Empty
)
)
.IsValid
);
}
}
@@ -184,9 +184,10 @@ export function ManualInboxDialog({ onClose }: { onClose: () => void }) {
</div> </div>
<div className="flex flex-col gap-1.5"> <div className="flex flex-col gap-1.5">
<Label>{t('admin.media.toShowSeason')}</Label> <Label>{t('admin.media.toShowSeason')}</Label>
{/* Ноль — законный сезон: в нём живут спецвыпуски и пилоты. */}
<Input <Input
type="number" type="number"
min={1} min={0}
placeholder={t('admin.media.toShowAuto')} placeholder={t('admin.media.toShowAuto')}
value={seasonStr} value={seasonStr}
onChange={(e) => setSeasonStr(e.target.value)} onChange={(e) => setSeasonStr(e.target.value)}