Files
serega404 99d25adbb1
Backend CI / build-and-test (push) Failing after 13m11s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Failing after 10m12s
Frontend CI / build-and-check (push) Failing after 16m9s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Failing after 14m6s
🚀 Create and publish a Docker image / Build & publish backend image (push) Failing after 14m58s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Failing after 14m58s
feat: перелопатил синхронизацию преподавателей
2026-05-24 21:06:03 +03:00

146 lines
5.1 KiB
C#

using Microsoft.EntityFrameworkCore;
using NSubstitute;
using UniVerse.Application.DTOs.Reviews;
using UniVerse.Application.DTOs.Common;
using UniVerse.Application.Interfaces;
using UniVerse.Domain.Entities;
using UniVerse.Domain.Enums;
using UniVerse.Domain.Exceptions;
using UniVerse.Infrastructure.Data;
using UniVerse.Infrastructure.Services;
using Xunit;
namespace UniVerse.Api.Tests.Reviews;
public class ReviewServiceTests
{
[Fact]
public async Task CreateAsync_EnqueuesReviewAnalysis()
{
await using var db = CreateDbContext();
var queue = Substitute.For<IReviewAnalysisQueue>();
var service = CreateService(db, queue);
await SeedLectureAsync(db);
var result = await service.CreateAsync(1, new CreateReviewRequest(1, ReviewRating.Like, "Great lecture"));
await queue.Received(1).EnqueueAsync(result.Id, Arg.Any<CancellationToken>());
}
[Fact]
public async Task UpdateAsync_ResetsAnalysisAndEnqueuesReview()
{
await using var db = CreateDbContext();
var queue = Substitute.For<IReviewAnalysisQueue>();
var service = CreateService(db, queue);
await SeedAnalyzedReviewAsync(db);
await service.UpdateAsync(1, 1, new UpdateReviewRequest(ReviewRating.Neutral, "Updated text"));
var review = await db.Reviews.SingleAsync(r => r.Id == 1);
Assert.Equal(ReviewLlmStatus.Pending, review.LlmStatus);
Assert.Null(review.Sentiment);
Assert.Null(review.QualityScore);
Assert.Null(review.IsInformative);
Assert.Null(review.LlmTags);
Assert.Null(review.LlmRawOutput);
await queue.Received(1).EnqueueAsync(1, Arg.Any<CancellationToken>());
}
[Fact]
public async Task ReanalyzeAsync_ResetsAnalysisAndEnqueuesReview()
{
await using var db = CreateDbContext();
var queue = Substitute.For<IReviewAnalysisQueue>();
var service = CreateService(db, queue);
await SeedAnalyzedReviewAsync(db);
await service.ReanalyzeAsync(1);
var review = await db.Reviews.SingleAsync(r => r.Id == 1);
Assert.Equal(ReviewLlmStatus.Pending, review.LlmStatus);
Assert.Null(review.Sentiment);
Assert.Null(review.QualityScore);
Assert.Null(review.IsInformative);
Assert.Null(review.LlmTags);
Assert.Null(review.LlmRawOutput);
await queue.Received(1).EnqueueAsync(1, Arg.Any<CancellationToken>());
}
[Fact]
public async Task GetByLectureAsync_TeacherCannotReadAnotherTeachersReviews()
{
await using var db = CreateDbContext();
var service = CreateService(db, Substitute.For<IReviewAnalysisQueue>());
await SeedAnalyzedReviewAsync(db, teacherId: 2);
await Assert.ThrowsAsync<ForbiddenException>(() =>
service.GetByLectureAsync(1, new PaginationRequest(), currentUserId: 1));
}
[Fact]
public async Task GetByLectureAsync_AdminCanReadAnyLectureReviews()
{
await using var db = CreateDbContext();
var service = CreateService(db, Substitute.For<IReviewAnalysisQueue>());
await SeedAnalyzedReviewAsync(db, teacherId: 2);
var result = await service.GetByLectureAsync(1, new PaginationRequest(), currentUserId: 1, isAdmin: true);
Assert.Single(result.Items);
}
private static ReviewService CreateService(AppDbContext db, IReviewAnalysisQueue queue)
{
var gamification = Substitute.For<IGamificationService>();
gamification.CheckAndAwardAchievementsAsync(Arg.Any<int>()).Returns(Task.CompletedTask);
return new ReviewService(db, gamification, queue);
}
private static async Task SeedLectureAsync(AppDbContext db, int? teacherId = null)
{
db.Users.Add(new User { Id = 1, Email = "student@test.local", DisplayName = "Student" });
db.Courses.Add(new Course { Id = 1, Name = "Course" });
db.Lectures.Add(new Lecture
{
Id = 1,
CourseId = 1,
TeacherId = teacherId,
Title = "Lecture",
StartsAt = DateTime.UtcNow.AddDays(-1),
EndsAt = DateTime.UtcNow.AddDays(-1).AddHours(2),
IsOpen = true,
MaxEnrollments = 30
});
await db.SaveChangesAsync();
}
private static async Task SeedAnalyzedReviewAsync(AppDbContext db, int? teacherId = null)
{
await SeedLectureAsync(db, teacherId);
db.Reviews.Add(new Review
{
Id = 1,
LectureId = 1,
UserId = 1,
Rating = ReviewRating.Like,
Text = "Original text",
LlmStatus = ReviewLlmStatus.Analyzed,
Sentiment = ReviewSentiment.Positive,
QualityScore = 0.9,
IsInformative = true,
LlmTags = ["clear"],
LlmRawOutput = "{\"quality_score\":0.9}"
});
await db.SaveChangesAsync();
}
private static AppDbContext CreateDbContext()
{
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase($"ReviewServiceTests_{Guid.NewGuid()}")
.Options;
return new AppDbContext(options);
}
}