feat: add practice session workflow endpoints

This commit is contained in:
xiong
2026-07-26 15:25:33 +08:00
parent db319ef5a2
commit e505384ecf
7 changed files with 1090 additions and 1 deletions

View File

@@ -62,6 +62,114 @@ public sealed class LearningEndpointTests
Assert.Equal(1, wrong.GetProperty("wrongCount").GetInt32());
}
[Fact]
public async Task Practice_session_can_be_created_detailed_submitted_and_listed()
{
await using var factory = new ApiTestFactory();
var seed = await SeedLearningUserAsync(factory);
var collectionId = Guid.NewGuid();
var firstQuestionId = Guid.NewGuid();
var secondQuestionId = Guid.NewGuid();
await factory.SeedAsync(
new QuestionCollection
{
Id = collectionId,
TenantId = seed.TenantId,
Name = "基础练习",
Status = ContentStatus.Active
},
new Question
{
Id = firstQuestionId,
TenantId = seed.TenantId,
Type = "choice",
Status = QuestionStatus.Published
},
new Question
{
Id = secondQuestionId,
TenantId = seed.TenantId,
Type = "choice",
Status = QuestionStatus.Published
},
new QuestionCollectionItem
{
Id = Guid.NewGuid(),
TenantId = seed.TenantId,
CollectionId = collectionId,
QuestionId = firstQuestionId,
SortOrder = 1
},
new QuestionCollectionItem
{
Id = Guid.NewGuid(),
TenantId = seed.TenantId,
CollectionId = collectionId,
QuestionId = secondQuestionId,
SortOrder = 2
});
using var client = factory.CreateClient();
await LoginAsync(client, seed);
var createResponse = await client.PostAsJsonAsync(
"/api/learning/practice-sessions",
new CreatePracticeSessionDto
{
Mode = "chapter",
CollectionId = collectionId,
QuestionLimit = 2,
TotalScore = 100
});
var created = await ReadJsonAsync(createResponse);
var practiceSessionId = created.RootElement.GetProperty("id").GetGuid();
var detailResponse = await client.GetAsync($"/api/learning/practice-sessions/detail?practiceSessionId={practiceSessionId}");
var detail = await ReadJsonAsync(detailResponse);
await client.PostAsJsonAsync(
"/api/learning/answers",
new SubmitAnswerDto
{
QuestionId = firstQuestionId,
PracticeSessionId = practiceSessionId,
SelectedOptions = ["A"],
SelfJudgedCorrect = true
});
await client.PostAsJsonAsync(
"/api/learning/answers",
new SubmitAnswerDto
{
QuestionId = secondQuestionId,
PracticeSessionId = practiceSessionId,
SelectedOptions = ["B"],
SelfJudgedCorrect = false
});
var submitResponse = await client.PostAsJsonAsync(
"/api/learning/practice-sessions/submit",
new SubmitPracticeSessionDto { PracticeSessionId = practiceSessionId });
var report = await ReadJsonAsync(submitResponse);
var reportResponse = await client.GetAsync($"/api/learning/practice-sessions/report?practiceSessionId={practiceSessionId}");
var reportsResponse = await client.GetAsync("/api/learning/practice-reports");
var historyResponse = await client.GetAsync("/api/learning/practice-sessions/history?status=finished");
var reports = await ReadItemsAsync(reportsResponse);
var history = await ReadItemsAsync(historyResponse);
Assert.Equal(HttpStatusCode.OK, createResponse.StatusCode);
Assert.Equal(2, created.RootElement.GetProperty("questionCount").GetInt32());
Assert.Equal("active", created.RootElement.GetProperty("status").GetString());
Assert.Equal(HttpStatusCode.OK, detailResponse.StatusCode);
Assert.Equal(2, detail.RootElement.GetProperty("questions").GetArrayLength());
Assert.Equal(HttpStatusCode.OK, submitResponse.StatusCode);
Assert.Equal(2, report.RootElement.GetProperty("totalQuestions").GetInt32());
Assert.Equal(1, report.RootElement.GetProperty("correctCount").GetInt32());
Assert.Equal(1, report.RootElement.GetProperty("wrongCount").GetInt32());
Assert.Equal(50m, report.RootElement.GetProperty("score").GetDecimal());
Assert.Equal(HttpStatusCode.OK, reportResponse.StatusCode);
Assert.Single(reports);
var historyItem = Assert.Single(history);
Assert.Equal(practiceSessionId, historyItem.GetProperty("id").GetGuid());
Assert.Equal("finished", historyItem.GetProperty("status").GetString());
}
[Fact]
public async Task Favorite_question_can_be_added_listed_and_removed()
{