forked from xiongyuxing/tiku-backend.net
feat: add student engagement endpoints
This commit is contained in:
@@ -7,6 +7,7 @@ using Tiku.Domain.Catalog;
|
||||
using Tiku.Domain.Common;
|
||||
using Tiku.Domain.Identity;
|
||||
using Tiku.Domain.Learning;
|
||||
using Tiku.Domain.Operations;
|
||||
using Tiku.Domain.Tenancy;
|
||||
using Tiku.Infrastructure.Auth;
|
||||
using Tiku.Infrastructure.Persistence;
|
||||
@@ -107,6 +108,83 @@ public sealed class ProfileEndpointTests
|
||||
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Student_can_manage_notifications_badges_and_feedbacks()
|
||||
{
|
||||
await using var factory = new ApiTestFactory();
|
||||
var seed = await SeedStudentAsync(factory);
|
||||
var notificationId = Guid.NewGuid();
|
||||
var badgeId = Guid.NewGuid();
|
||||
await factory.SeedAsync(
|
||||
new StudentProfile
|
||||
{
|
||||
TenantId = seed.TenantId,
|
||||
UserId = seed.UserId
|
||||
},
|
||||
new UserNotification
|
||||
{
|
||||
Id = notificationId,
|
||||
TenantId = seed.TenantId,
|
||||
UserId = seed.UserId,
|
||||
NotificationType = "system",
|
||||
Title = "欢迎",
|
||||
Message = "欢迎回来",
|
||||
Status = NotificationStatus.Unread
|
||||
},
|
||||
new Badge
|
||||
{
|
||||
Id = badgeId,
|
||||
TenantId = seed.TenantId,
|
||||
Name = "首练",
|
||||
Category = "learning",
|
||||
IsActive = true
|
||||
},
|
||||
new UserBadge
|
||||
{
|
||||
TenantId = seed.TenantId,
|
||||
UserId = seed.UserId,
|
||||
BadgeId = badgeId,
|
||||
GrantedAt = DateTimeOffset.UtcNow
|
||||
});
|
||||
using var client = factory.CreateClient();
|
||||
await LoginAsync(client, seed);
|
||||
|
||||
var notificationsResponse = await client.GetAsync("/api/profile/notifications");
|
||||
var notificationsJson = await ReadJsonAsync(notificationsResponse);
|
||||
var statusResponse = await client.PostAsJsonAsync(
|
||||
"/api/profile/notifications/status",
|
||||
new NotificationStatusDto { NotificationIds = [notificationId], Status = "read" });
|
||||
var badgesResponse = await client.GetAsync("/api/profile/badges?includeLocked=true");
|
||||
var badgesJson = await ReadJsonAsync(badgesResponse);
|
||||
var feedbackResponse = await client.PostAsJsonAsync(
|
||||
"/api/profile/feedbacks",
|
||||
new SubmitFeedbackDto
|
||||
{
|
||||
Type = "suggestion",
|
||||
Title = "建议",
|
||||
Description = "希望增加练习提醒",
|
||||
Priority = "normal"
|
||||
});
|
||||
var feedbackJson = await ReadJsonAsync(feedbackResponse);
|
||||
var feedbacksResponse = await client.GetAsync("/api/profile/feedbacks?type=suggestion");
|
||||
var feedbacksJson = await ReadJsonAsync(feedbacksResponse);
|
||||
|
||||
Assert.Equal(HttpStatusCode.OK, notificationsResponse.StatusCode);
|
||||
Assert.Equal("unread", notificationsJson.RootElement.GetProperty("items").EnumerateArray().Single().GetProperty("status").GetString());
|
||||
Assert.Equal(HttpStatusCode.OK, statusResponse.StatusCode);
|
||||
Assert.Equal(HttpStatusCode.OK, badgesResponse.StatusCode);
|
||||
Assert.True(badgesJson.RootElement.GetProperty("items").EnumerateArray().Single().GetProperty("isUnlocked").GetBoolean());
|
||||
Assert.Equal(HttpStatusCode.OK, feedbackResponse.StatusCode);
|
||||
Assert.Equal("suggestion", feedbackJson.RootElement.GetProperty("type").GetString());
|
||||
Assert.Equal(HttpStatusCode.OK, feedbacksResponse.StatusCode);
|
||||
Assert.Single(feedbacksJson.RootElement.EnumerateArray());
|
||||
|
||||
using var scope = factory.Services.CreateScope();
|
||||
var dbContext = scope.ServiceProvider.GetRequiredService<TikuDbContext>();
|
||||
Assert.Equal(NotificationStatus.Read, dbContext.UserNotifications.Single(item => item.Id == notificationId).Status);
|
||||
Assert.Single(dbContext.ReportStatusEvents);
|
||||
}
|
||||
|
||||
private static async Task<(Guid TenantId, Guid UserId, string Phone)> SeedStudentAsync(ApiTestFactory factory)
|
||||
{
|
||||
var tenantId = Guid.NewGuid();
|
||||
|
||||
Reference in New Issue
Block a user