using TrainingPlanner.Application; namespace TrainingPlanner.Tests; public class ExerciseImportTests { private readonly ExerciseImportOptions options = new() { MaxRows = 1000, MaxClipboardCharacters = 100000 }; [Fact] public void ClipboardPreservesEmptyCellsAndExcelQuotedValues() { var rows = new ClipboardTableParser(options).Parse("\"Жим \"\"узкий\"\"\nсидя\"\thttps://example.com/video\r\nТяга\t\r\n\t\r\n"); Assert.Equal(2, rows.Count); Assert.Equal("Жим \"узкий\"\nсидя", rows[0][0]); Assert.Equal("https://example.com/video", rows[0][1]); Assert.Equal("", rows[1][1]); } [Fact] public void ClipboardHandlesLargePasteAndAllLineEndings() { var parser = new ClipboardTableParser(options); Assert.Equal(500, parser.Parse(string.Join('\n', Enumerable.Repeat("Упражнение\thttps://example.com", 500))).Count); Assert.Equal(3, parser.Parse("А\rБ\nВ\r\n").Count); Assert.Empty(parser.Parse("\r\n\t\r\n")); } [Fact] public void ClipboardRejectsUnclosedQuotesAndConfiguredLimits() { var parser = new ClipboardTableParser(new ExerciseImportOptions { MaxRows = 1, MaxClipboardCharacters = 20 }); Assert.Throws(() => parser.Parse("\"Открытая ячейка")); Assert.Throws(() => parser.Parse("А\nБ")); Assert.Throws(() => parser.Parse(new string('a', 21))); } [Fact] public void ValidationSkipsBlankRowsAndAllowsMissingVideo() { var rows = new ExerciseImportValidator(options).Validate([ new(), new() { Name = " Тяга ", VideoUrl = " " }, new() { Name = "Жим", VideoUrl = " https://example.com " }]); Assert.Equal(2, rows.Count); Assert.Equal("Тяга", rows[0].Name); Assert.Equal("", rows[0].VideoUrl); Assert.Equal("https://example.com", rows[1].VideoUrl); } [Fact] public void ValidationReportsOriginalRowAndRejectsUnsafeLinks() { var validator = new ExerciseImportValidator(options); var error = Assert.Throws(() => validator.Validate([ new(), new() { Name = "Жим", VideoUrl = "javascript:alert(1)" }])); Assert.Contains("Строка 2", error.Message); Assert.Throws(() => validator.Validate([new() { VideoUrl = "https://example.com" }])); Assert.Throws(() => validator.Validate([new()])); } }