140 lines
4.7 KiB
C#
140 lines
4.7 KiB
C#
using DramaLing.Api.Tests.Integration.Fixtures;
|
||
using System.Net;
|
||
|
||
namespace DramaLing.Api.Tests.Integration.Controllers;
|
||
|
||
/// <summary>
|
||
/// FlashcardsController 整合測試
|
||
/// 測試詞卡相關的 API 端點功能
|
||
/// </summary>
|
||
public class FlashcardsControllerTests : IntegrationTestBase
|
||
{
|
||
public FlashcardsControllerTests(DramaLingWebApplicationFactory factory) : base(factory)
|
||
{
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetDueFlashcards_WithValidUser_ShouldReturnFlashcards()
|
||
{
|
||
// Arrange
|
||
var client = CreateTestUser1Client();
|
||
|
||
// Act
|
||
var response = await client.GetAsync("/api/flashcards/due");
|
||
|
||
// Assert
|
||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||
var content = await response.Content.ReadAsStringAsync();
|
||
content.Should().NotBeNullOrEmpty();
|
||
content.Should().Contain("flashcards");
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetDueFlashcards_WithoutAuth_ShouldReturn401()
|
||
{
|
||
// Arrange
|
||
var client = HttpClient; // 未認證的 client
|
||
|
||
// Act
|
||
var response = await client.GetAsync("/api/flashcards/due");
|
||
|
||
// Assert
|
||
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetAllFlashcards_WithValidUser_ShouldReturnUserFlashcards()
|
||
{
|
||
// Arrange
|
||
var client = CreateTestUser1Client();
|
||
|
||
// Act
|
||
var response = await client.GetAsync("/api/flashcards");
|
||
|
||
// Assert
|
||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||
var content = await response.Content.ReadAsStringAsync();
|
||
content.Should().NotBeNullOrEmpty();
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetFlashcardById_WithValidUserAndId_ShouldReturnFlashcard()
|
||
{
|
||
// Arrange
|
||
var client = CreateTestUser1Client();
|
||
var flashcardId = TestDataSeeder.TestFlashcard1Id;
|
||
|
||
// Act
|
||
var response = await client.GetAsync($"/api/flashcards/{flashcardId}");
|
||
|
||
// Assert
|
||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||
var content = await response.Content.ReadAsStringAsync();
|
||
content.Should().Contain("hello"); // 測試資料中的詞彙
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetFlashcardById_WithDifferentUser_ShouldReturn404()
|
||
{
|
||
// Arrange - TestUser2 嘗試存取 TestUser1 的詞卡
|
||
var client = CreateTestUser2Client();
|
||
var user1FlashcardId = TestDataSeeder.TestFlashcard1Id; // 屬於 TestUser1
|
||
|
||
// Act
|
||
var response = await client.GetAsync($"/api/flashcards/{user1FlashcardId}");
|
||
|
||
// Assert
|
||
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task MarkWordMastered_WithValidFlashcard_ShouldUpdateReview()
|
||
{
|
||
// Arrange
|
||
var client = CreateTestUser1Client();
|
||
var flashcardId = TestDataSeeder.TestFlashcard1Id;
|
||
|
||
// Act
|
||
var response = await client.PostAsync($"/api/flashcards/{flashcardId}/mastered", null);
|
||
|
||
// Assert
|
||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||
var content = await response.Content.ReadAsStringAsync();
|
||
content.Should().Contain("success");
|
||
|
||
// 驗證資料庫中的複習記錄是否更新
|
||
using var context = GetDbContext();
|
||
var review = context.FlashcardReviews
|
||
.First(r => r.FlashcardId == flashcardId && r.UserId == TestDataSeeder.TestUser1Id);
|
||
review.SuccessCount.Should().BeGreaterThan(0);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task UserDataIsolation_ShouldBeEnforced()
|
||
{
|
||
// Arrange
|
||
var user1Client = CreateTestUser1Client();
|
||
var user2Client = CreateTestUser2Client();
|
||
|
||
// Act - 兩個用戶分別取得詞卡
|
||
var user1Response = await user1Client.GetAsync("/api/flashcards");
|
||
var user2Response = await user2Client.GetAsync("/api/flashcards");
|
||
|
||
// Assert
|
||
user1Response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||
user2Response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||
|
||
var user1Content = await user1Response.Content.ReadAsStringAsync();
|
||
var user2Content = await user2Response.Content.ReadAsStringAsync();
|
||
|
||
// TestUser1 有 2 張詞卡,TestUser2 有 1 張詞卡
|
||
user1Content.Should().Contain("hello");
|
||
user1Content.Should().Contain("beautiful");
|
||
user2Content.Should().Contain("sophisticated");
|
||
|
||
// 確保用戶間資料隔離
|
||
user1Content.Should().NotContain("sophisticated");
|
||
user2Content.Should().NotContain("hello");
|
||
user2Content.Should().NotContain("beautiful");
|
||
}
|
||
} |