package agzam.vyatsu import agzam.vyatsu.data.remote.TeacherScheduleParser import agzam.vyatsu.domain.model.LessonType import java.time.LocalDate import java.time.LocalTime import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test class TeacherScheduleParserTest { private fun fixture(): String = checkNotNull(javaClass.getResourceAsStream("/prepod.html")) .readBytes().toString(Charsets.UTF_8) private fun fixture517(): String = checkNotNull(javaClass.getResourceAsStream("/prepod517.html")) .readBytes().toString(Charsets.UTF_8) private fun fixture974(): String = checkNotNull(javaClass.getResourceAsStream("/prepod974.html")) .readBytes().toString(Charsets.UTF_8) @Test fun teachersHeaderParsedInOrderAndDeduped() { val parsed = TeacherScheduleParser.parse(fixture()) assertEquals(listOf("Лелекова Е.В.", "Иванов И.И.", "Петрова А.С."), parsed.teachers) } @Test fun daysWithCorrectDates() { val parsed = TeacherScheduleParser.parse(fixture()) assertEquals(2, parsed.days.size) assertEquals(LocalDate.of(2026, 9, 14), parsed.days[0].date) assertEquals(LocalDate.of(2026, 9, 15), parsed.days[1].date) } @Test fun intervalTimesParsed() { val parsed = TeacherScheduleParser.parse(fixture()) val day0 = parsed.days[0] assertEquals(2, day0.intervals.size) assertEquals(LocalTime.of(8, 20), day0.intervals[0].start) assertEquals(LocalTime.of(9, 50), day0.intervals[0].end) assertEquals(LocalTime.of(10, 0), day0.intervals[1].start) assertEquals(LocalTime.of(11, 30), day0.intervals[1].end) } @Test fun multiGroupCellSplitsIntoPerGroupLessons() { val parsed = TeacherScheduleParser.parse(fixture()) val cell = parsed.days[0].intervals[0].lessons.filter { it.teacher == "Лелекова Е.В." } assertEquals(2, cell.size) val lesson0 = cell[0] val lesson1 = cell[1] assertEquals("Бб-1101-04-00", lesson0.group) assertNull(lesson0.subgroup) assertEquals("01 подгруппа", lesson1.subgroup) assertEquals("4-302", lesson0.room) assertEquals("Биоразнообразие", lesson0.subject) assertEquals(LessonType.LECTURE, lesson0.type) assertEquals("Лелекова Е.В.", lesson0.teacher) } @Test fun emptyCellContributesNoLesson() { val parsed = TeacherScheduleParser.parse(fixture()) val threeSlots = (0..6).map { slot -> parsed.days[0].intervals.firstOrNull { it.start.hour == 8 && it.start.minute == 20 } ?: return@map true } val petrovLessons = parsed.days[0].intervals[0].lessons.filter { it.teacher == "Петрова А.С." } assertEquals(0, petrovLessons.size) assertTrue(threeSlots.isEmpty() || threeSlots.size == 7) } @Test fun noRoomCellKeepsRawAndNullRoom() { val parsed = TeacherScheduleParser.parse(fixture()) val cell = parsed.days[0].intervals[1].lessons.filter { it.teacher == "Лелекова Е.В." } assertEquals(2, cell.size) assertNull(cell[0].room) assertTrue(cell[0].raw.contains("Бб-1101-04-00")) assertNull(cell[0].subject) } @Test fun exactTotalLessonCount() { val parsed = TeacherScheduleParser.parse(fixture()) val total = parsed.days.sumOf { day -> day.intervals.sumOf { it.lessons.size } } assertEquals(11, total) } private fun spacerColumnFixture(): String = """
| День | Интервал | Марков Р.В. | Мельцов В.Ю. | |
| четверг 08.10.26 | 08:20-09:50 | 2-206 Математика Практическое занятие УТб-2301-02-00 | 1-334 Организация параллельных вычислительных систем Лекция ИВТб-4301-05-00 | |
| 10:00-11:30 | 2-206 Математика Практическое занятие УТб-2301-02-00 | 1-334 Организация параллельных вычислительных систем Лекция ИВТб-4301-05-00 |