Add graphical duodenal ulcer interview
This commit is contained in:
@@ -91,6 +91,18 @@ public sealed class CcsCaseTests
|
||||
Assert.True(request!.Cases.Single().ScoringCriteria.Count >= 12);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DuodenalUlcerInterviewArtifactMatchesTheCaseSchema()
|
||||
{
|
||||
var path = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../../../content/ccs/duodenal-ulcer-office-001.json"));
|
||||
var request = JsonSerializer.Deserialize<CcsImportRequest>(File.ReadAllText(path), new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
|
||||
Assert.NotNull(request);
|
||||
Assert.Empty(CcsCaseValidator.ValidateImport(request!, new HashSet<string>()));
|
||||
Assert.Equal(CcsExperienceModes.GraphicalInterview, request.Cases.Single().ExperienceMode);
|
||||
Assert.Equal(4, request.Cases.Single().InitialInterview.Topics.Count(value => value.Required));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PublishedCaseRequiresReferencesAndKnownOrders()
|
||||
{
|
||||
@@ -210,6 +222,58 @@ public sealed class CcsCaseTests
|
||||
Assert.Same(definition.InitialInterview, CcsStore.EffectiveInterview(definition));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TopicInterviewBranchesAndUnlocksFinishAfterRequiredTopics()
|
||||
{
|
||||
var definition = ValidImport().Cases[0];
|
||||
definition.InitialInterview = TopicInterview();
|
||||
var attempt = new CcsAttempt { InterviewNodeId = "opening", OpeningCompleted = false };
|
||||
|
||||
Assert.Equal(["chief_concern"], CcsStore.CurrentInterviewNode(attempt, definition)!.Choices.Select(value => value.Id));
|
||||
Assert.Throws<ArgumentException>(() => CcsStore.ApplyDialogueChoice(attempt, definition, "required_history", DateTime.UtcNow));
|
||||
CcsStore.ApplyDialogueChoice(attempt, definition, "chief_concern", DateTime.UtcNow);
|
||||
Assert.Equal(["required_history", "optional_history"],
|
||||
CcsStore.CurrentInterviewNode(attempt, definition)!.Choices.Select(value => value.Id));
|
||||
Assert.Throws<ArgumentException>(() => CcsStore.ApplyDialogueChoice(attempt, definition, "finish_interview", DateTime.UtcNow));
|
||||
|
||||
CcsStore.ApplyDialogueChoice(attempt, definition, "required_history", DateTime.UtcNow);
|
||||
var finishable = CcsStore.CurrentInterviewNode(attempt, definition)!;
|
||||
Assert.Contains(finishable.Choices, value => value.Id == "finish_interview");
|
||||
Assert.DoesNotContain(finishable.Choices, value => value.Id == "chief_concern");
|
||||
Assert.Throws<ArgumentException>(() => CcsStore.ApplyDialogueChoice(attempt, definition, "chief_concern", DateTime.UtcNow));
|
||||
CcsStore.ApplyDialogueChoice(attempt, definition, "finish_interview", DateTime.UtcNow);
|
||||
Assert.True(attempt.OpeningCompleted);
|
||||
Assert.True(CcsStore.CurrentInterviewNode(attempt, definition)!.IsTerminal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TopicInterviewRejectsPrerequisiteCycles()
|
||||
{
|
||||
var request = ValidImport();
|
||||
request.Cases[0].InitialInterview = TopicInterview();
|
||||
request.Cases[0].InitialInterview.Topics[0].PrerequisiteTopicIds = ["required_history"];
|
||||
|
||||
var errors = CcsCaseValidator.ValidateImport(request, new HashSet<string>());
|
||||
|
||||
Assert.Contains(errors, value => value.Contains("prerequisites cannot contain cycles", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CaseContentComparisonIgnoresRevisionMetadata()
|
||||
{
|
||||
var first = ValidImport().Cases[0];
|
||||
var second = ValidImport().Cases[0];
|
||||
first.Id = "507f1f77bcf86cd799439011";
|
||||
first.Version = 4;
|
||||
first.IsCurrent = false;
|
||||
first.CreatedUtc = DateTime.UtcNow.AddDays(-2);
|
||||
second.InitialChart.SimulatedStartUtc = first.InitialChart.SimulatedStartUtc;
|
||||
|
||||
Assert.Equal(CcsStore.CaseContentDocument(first), CcsStore.CaseContentDocument(second));
|
||||
second.Title = "Changed title";
|
||||
Assert.NotEqual(CcsStore.CaseContentDocument(first), CcsStore.CaseContentDocument(second));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CcsExpectedScoreUsesSeparateUserAndCaseElo()
|
||||
{
|
||||
@@ -286,4 +350,23 @@ public sealed class CcsCaseTests
|
||||
new() { Id = "done", PatientText = "Thank you.", IsTerminal = true }
|
||||
]
|
||||
};
|
||||
|
||||
private static CcsInitialInterview TopicInterview() => new()
|
||||
{
|
||||
OpeningPatientText = "Good morning.", ClosingPatientText = "Thank you.", FinishChoiceText = "Finish",
|
||||
Topics =
|
||||
[
|
||||
new() { Id = "chief_concern", ClinicianText = "What brings you in?", PatientText = "I feel tired." },
|
||||
new()
|
||||
{
|
||||
Id = "required_history", ClinicianText = "Tell me more.", PatientText = "It started recently.", Required = true,
|
||||
PrerequisiteTopicIds = ["chief_concern"]
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = "optional_history", ClinicianText = "Anything else?", PatientText = "No.",
|
||||
PrerequisiteTopicIds = ["chief_concern"]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user