using DramaLing.Api.Tests.Integration.Fixtures; using System.Net; namespace DramaLing.Api.Tests.Integration.Controllers; /// /// FlashcardsController 整合測試 /// 測試詞卡相關的 API 端點功能 /// 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"); } }