module Domain.Tests.ValidationTests open System open Xunit open Domain let private newQuestion (qType: QuestionType) : Question = { Id = QuestionId(Guid.NewGuid()) TopicId = TopicId(Guid.NewGuid()) Text = "Sample?" Points = 1.0 Type = qType } [] let ``single choice: correct option must be among the listed options`` () = let optA = { Id = OptionId(Guid.NewGuid()); Text = "A" } let optB = { Id = OptionId(Guid.NewGuid()); Text = "B" } let foreignId = OptionId(Guid.NewGuid()) let question = newQuestion (SingleChoice([ optA; optB ], foreignId)) match QuestionValidation.validate question with | Error errors -> Assert.Contains("Correct option must be one of the provided options", errors) | Ok _ -> Assert.Fail "expected validation error" [] let ``multiple choice: correct set must be subset of options`` () = let optA = { Id = OptionId(Guid.NewGuid()); Text = "A" } let optB = { Id = OptionId(Guid.NewGuid()); Text = "B" } let foreignId = OptionId(Guid.NewGuid()) let question = newQuestion (MultipleChoice([ optA; optB ], Set.ofList [ optA.Id; foreignId ])) match QuestionValidation.validate question with | Error errors -> Assert.Contains("Correct options must be a subset of the provided options", errors) | Ok _ -> Assert.Fail "expected validation error" [] let ``numeric: negative tolerance is invalid`` () = let question = newQuestion (Numeric(1.0, -0.5)) match QuestionValidation.validate question with | Error errors -> Assert.Contains("Tolerance must not be negative", errors) | Ok _ -> Assert.Fail "expected validation error" [] let ``valid question passes validation`` () = let optA = { Id = OptionId(Guid.NewGuid()); Text = "A" } let optB = { Id = OptionId(Guid.NewGuid()); Text = "B" } let question = newQuestion (SingleChoice([ optA; optB ], optA.Id)) match QuestionValidation.validate question with | Ok _ -> () | Error errors -> Assert.Fail(String.concat "; " errors) [] let ``quiz: must contain at least one question`` () = let quiz: Quiz = { Id = QuizId(Guid.NewGuid()) OwnerId = UserId(Guid.NewGuid()) Title = "Empty quiz" Description = "" TimeLimit = None MaxAttempts = None GradingMethod = HighestAttempt ShuffleQuestions = false ShuffleAnswers = false OpenFrom = None OpenTo = None PassingScore = None QuestionSources = [] AssignedStudentIds = Set.empty } match QuizValidation.validate quiz with | Error errors -> Assert.Contains("Quiz must contain at least one question", errors) | Ok _ -> Assert.Fail "expected validation error" [] let ``quiz: OpenFrom must precede OpenTo`` () = let now = DateTimeOffset.UtcNow let quiz: Quiz = { Id = QuizId(Guid.NewGuid()) OwnerId = UserId(Guid.NewGuid()) Title = "Backwards window" Description = "" TimeLimit = None MaxAttempts = None GradingMethod = HighestAttempt ShuffleQuestions = false ShuffleAnswers = false OpenFrom = Some(now.AddDays 1.0) OpenTo = Some now PassingScore = None QuestionSources = [ FixedQuestion { QuestionId = QuestionId(Guid.NewGuid()); Points = 1.0; Order = 0 } ] AssignedStudentIds = Set.empty } match QuizValidation.validate quiz with | Error errors -> Assert.Contains("OpenFrom must be before OpenTo", errors) | Ok _ -> Assert.Fail "expected validation error"