diff --git a/services/chat-service-net/tests/ChatService.FunctionalTests/Controllers/ConversationsControllerTests.cs b/services/chat-service-net/tests/ChatService.FunctionalTests/Controllers/ConversationsControllerTests.cs
new file mode 100644
index 00000000..025a54a1
--- /dev/null
+++ b/services/chat-service-net/tests/ChatService.FunctionalTests/Controllers/ConversationsControllerTests.cs
@@ -0,0 +1,43 @@
+using System.Net;
+using FluentAssertions;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace ChatService.FunctionalTests.Controllers;
+
+///
+/// EN: Functional tests for chat conversation endpoints.
+/// VI: Functional tests cho endpoint hội thoại chat.
+///
+public class ConversationsControllerTests : IClassFixture
+{
+ private readonly HttpClient _client;
+
+ public ConversationsControllerTests(CustomWebApplicationFactory factory)
+ {
+ _client = factory.CreateClient(new WebApplicationFactoryClientOptions
+ {
+ AllowAutoRedirect = false,
+ });
+ }
+
+ [Fact]
+ public async Task GetConversations_WithoutAuthentication_ShouldReturnUnauthorized()
+ {
+ // Act
+ var response = await _client.GetAsync("/api/conversations?userId=" + Guid.NewGuid());
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
+ }
+
+ [Fact]
+ public async Task HealthCheck_ShouldReturnHealthy()
+ {
+ // Act
+ var response = await _client.GetAsync("/health/live");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ }
+}
diff --git a/services/chat-service-net/tests/ChatService.FunctionalTests/Controllers/SamplesControllerTests.cs b/services/chat-service-net/tests/ChatService.FunctionalTests/Controllers/SamplesControllerTests.cs
deleted file mode 100644
index 48015684..00000000
--- a/services/chat-service-net/tests/ChatService.FunctionalTests/Controllers/SamplesControllerTests.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System.Net;
-using System.Net.Http.Json;
-using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using Xunit;
-
-namespace ChatService.FunctionalTests.Controllers;
-
-///
-/// EN: Functional tests for Samples API endpoints.
-/// VI: Functional tests cho các endpoints API Samples.
-///
-public class SamplesControllerTests : IClassFixture
-{
- private readonly HttpClient _client;
-
- public SamplesControllerTests(CustomWebApplicationFactory factory)
- {
- _client = factory.CreateClient(new WebApplicationFactoryClientOptions
- {
- AllowAutoRedirect = false
- });
- }
-
- [Fact]
- public async Task GetSamples_ShouldReturnOkWithEmptyList()
- {
- // Act
- var response = await _client.GetAsync("/api/v1/samples");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- var content = await response.Content.ReadFromJsonAsync>>();
- content?.Success.Should().BeTrue();
- }
-
- [Fact]
- public async Task CreateSample_WithValidData_ShouldReturnCreated()
- {
- // Arrange
- var request = new { Name = "Test Sample", Description = "Test Description" };
-
- // Act
- var response = await _client.PostAsJsonAsync("/api/v1/samples", request);
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.Created);
- var content = await response.Content.ReadFromJsonAsync>();
- content?.Success.Should().BeTrue();
- content?.Data?.Id.Should().NotBeEmpty();
- }
-
- [Fact]
- public async Task GetSample_WithInvalidId_ShouldReturnNotFound()
- {
- // Arrange
- var invalidId = Guid.NewGuid();
-
- // Act
- var response = await _client.GetAsync($"/api/v1/samples/{invalidId}");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.NotFound);
- }
-
- [Fact]
- public async Task HealthCheck_ShouldReturnHealthy()
- {
- // Act
- var response = await _client.GetAsync("/health/live");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- }
-
- // EN: Helper DTOs for deserialization
- // VI: Helper DTOs để deserialize
- private record ApiResponse(bool Success, T? Data);
- private record CreateSampleResult(Guid Id);
-}
diff --git a/services/inventory-service-net/tests/InventoryService.FunctionalTests/Controllers/InventoryControllerTests.cs b/services/inventory-service-net/tests/InventoryService.FunctionalTests/Controllers/InventoryControllerTests.cs
new file mode 100644
index 00000000..246efffd
--- /dev/null
+++ b/services/inventory-service-net/tests/InventoryService.FunctionalTests/Controllers/InventoryControllerTests.cs
@@ -0,0 +1,53 @@
+using System.Net;
+using FluentAssertions;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace InventoryService.FunctionalTests.Controllers;
+
+///
+/// EN: Functional tests for inventory endpoints.
+/// VI: Functional tests cho các endpoint inventory.
+///
+public class InventoryControllerTests : IClassFixture
+{
+ private readonly HttpClient _client;
+
+ public InventoryControllerTests(CustomWebApplicationFactory factory)
+ {
+ _client = factory.CreateClient(new WebApplicationFactoryClientOptions
+ {
+ AllowAutoRedirect = false,
+ });
+ }
+
+ [Fact]
+ public async Task GetInventory_WithoutShopId_ShouldReturnBadRequest()
+ {
+ // Act
+ var response = await _client.GetAsync("/api/v1/inventory");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
+ }
+
+ [Fact]
+ public async Task GetLowStockItems_ShouldReturnOk()
+ {
+ // Act
+ var response = await _client.GetAsync("/api/v1/inventory/low-stock");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ }
+
+ [Fact]
+ public async Task HealthCheck_ShouldReturnHealthy()
+ {
+ // Act
+ var response = await _client.GetAsync("/health/live");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ }
+}
diff --git a/services/inventory-service-net/tests/InventoryService.FunctionalTests/Controllers/SamplesControllerTests.cs b/services/inventory-service-net/tests/InventoryService.FunctionalTests/Controllers/SamplesControllerTests.cs
deleted file mode 100644
index 64f1ecfc..00000000
--- a/services/inventory-service-net/tests/InventoryService.FunctionalTests/Controllers/SamplesControllerTests.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System.Net;
-using System.Net.Http.Json;
-using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using Xunit;
-
-namespace InventoryService.FunctionalTests.Controllers;
-
-///
-/// EN: Functional tests for Samples API endpoints.
-/// VI: Functional tests cho các endpoints API Samples.
-///
-public class SamplesControllerTests : IClassFixture
-{
- private readonly HttpClient _client;
-
- public SamplesControllerTests(CustomWebApplicationFactory factory)
- {
- _client = factory.CreateClient(new WebApplicationFactoryClientOptions
- {
- AllowAutoRedirect = false
- });
- }
-
- [Fact]
- public async Task GetSamples_ShouldReturnOkWithEmptyList()
- {
- // Act
- var response = await _client.GetAsync("/api/v1/samples");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- var content = await response.Content.ReadFromJsonAsync>>();
- content?.Success.Should().BeTrue();
- }
-
- [Fact]
- public async Task CreateSample_WithValidData_ShouldReturnCreated()
- {
- // Arrange
- var request = new { Name = "Test Sample", Description = "Test Description" };
-
- // Act
- var response = await _client.PostAsJsonAsync("/api/v1/samples", request);
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.Created);
- var content = await response.Content.ReadFromJsonAsync>();
- content?.Success.Should().BeTrue();
- content?.Data?.Id.Should().NotBeEmpty();
- }
-
- [Fact]
- public async Task GetSample_WithInvalidId_ShouldReturnNotFound()
- {
- // Arrange
- var invalidId = Guid.NewGuid();
-
- // Act
- var response = await _client.GetAsync($"/api/v1/samples/{invalidId}");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.NotFound);
- }
-
- [Fact]
- public async Task HealthCheck_ShouldReturnHealthy()
- {
- // Act
- var response = await _client.GetAsync("/health/live");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- }
-
- // EN: Helper DTOs for deserialization
- // VI: Helper DTOs để deserialize
- private record ApiResponse(bool Success, T? Data);
- private record CreateSampleResult(Guid Id);
-}
diff --git a/services/mission-service-net/tests/MissionService.FunctionalTests/Controllers/MissionsControllerTests.cs b/services/mission-service-net/tests/MissionService.FunctionalTests/Controllers/MissionsControllerTests.cs
new file mode 100644
index 00000000..1a83cfa1
--- /dev/null
+++ b/services/mission-service-net/tests/MissionService.FunctionalTests/Controllers/MissionsControllerTests.cs
@@ -0,0 +1,53 @@
+using System.Net;
+using FluentAssertions;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace MissionService.FunctionalTests.Controllers;
+
+///
+/// EN: Functional tests for mission endpoints.
+/// VI: Functional tests cho các endpoint mission.
+///
+public class MissionsControllerTests : IClassFixture
+{
+ private readonly HttpClient _client;
+
+ public MissionsControllerTests(CustomWebApplicationFactory factory)
+ {
+ _client = factory.CreateClient(new WebApplicationFactoryClientOptions
+ {
+ AllowAutoRedirect = false,
+ });
+ }
+
+ [Fact]
+ public async Task GetByCategory_ShouldReturnOk()
+ {
+ // Act
+ var response = await _client.GetAsync("/api/v1/missions/category/daily");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ }
+
+ [Fact]
+ public async Task GetAvailableMissions_WithoutAuthentication_ShouldReturnUnauthorized()
+ {
+ // Act
+ var response = await _client.GetAsync("/api/v1/missions");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
+ }
+
+ [Fact]
+ public async Task HealthCheck_ShouldReturnHealthy()
+ {
+ // Act
+ var response = await _client.GetAsync("/health/live");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ }
+}
diff --git a/services/mission-service-net/tests/MissionService.FunctionalTests/Controllers/SamplesControllerTests.cs b/services/mission-service-net/tests/MissionService.FunctionalTests/Controllers/SamplesControllerTests.cs
deleted file mode 100644
index 8a0bf933..00000000
--- a/services/mission-service-net/tests/MissionService.FunctionalTests/Controllers/SamplesControllerTests.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System.Net;
-using System.Net.Http.Json;
-using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using Xunit;
-
-namespace MissionService.FunctionalTests.Controllers;
-
-///
-/// EN: Functional tests for Samples API endpoints.
-/// VI: Functional tests cho các endpoints API Samples.
-///
-public class SamplesControllerTests : IClassFixture
-{
- private readonly HttpClient _client;
-
- public SamplesControllerTests(CustomWebApplicationFactory factory)
- {
- _client = factory.CreateClient(new WebApplicationFactoryClientOptions
- {
- AllowAutoRedirect = false
- });
- }
-
- [Fact]
- public async Task GetSamples_ShouldReturnOkWithEmptyList()
- {
- // Act
- var response = await _client.GetAsync("/api/v1/samples");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- var content = await response.Content.ReadFromJsonAsync>>();
- content?.Success.Should().BeTrue();
- }
-
- [Fact]
- public async Task CreateSample_WithValidData_ShouldReturnCreated()
- {
- // Arrange
- var request = new { Name = "Test Sample", Description = "Test Description" };
-
- // Act
- var response = await _client.PostAsJsonAsync("/api/v1/samples", request);
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.Created);
- var content = await response.Content.ReadFromJsonAsync>();
- content?.Success.Should().BeTrue();
- content?.Data?.Id.Should().NotBeEmpty();
- }
-
- [Fact]
- public async Task GetSample_WithInvalidId_ShouldReturnNotFound()
- {
- // Arrange
- var invalidId = Guid.NewGuid();
-
- // Act
- var response = await _client.GetAsync($"/api/v1/samples/{invalidId}");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.NotFound);
- }
-
- [Fact]
- public async Task HealthCheck_ShouldReturnHealthy()
- {
- // Act
- var response = await _client.GetAsync("/health/live");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- }
-
- // EN: Helper DTOs for deserialization
- // VI: Helper DTOs để deserialize
- private record ApiResponse(bool Success, T? Data);
- private record CreateSampleResult(Guid Id);
-}
diff --git a/services/mkt-facebook-service-net/tests/FacebookService.FunctionalTests/Controllers/ConversationsControllerTests.cs b/services/mkt-facebook-service-net/tests/FacebookService.FunctionalTests/Controllers/ConversationsControllerTests.cs
new file mode 100644
index 00000000..810df51f
--- /dev/null
+++ b/services/mkt-facebook-service-net/tests/FacebookService.FunctionalTests/Controllers/ConversationsControllerTests.cs
@@ -0,0 +1,53 @@
+using System.Net;
+using FluentAssertions;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace FacebookService.FunctionalTests.Controllers;
+
+///
+/// EN: Functional tests for Facebook conversation endpoints.
+/// VI: Functional tests cho endpoint hội thoại Facebook.
+///
+public class ConversationsControllerTests : IClassFixture
+{
+ private readonly HttpClient _client;
+
+ public ConversationsControllerTests(CustomWebApplicationFactory factory)
+ {
+ _client = factory.CreateClient(new WebApplicationFactoryClientOptions
+ {
+ AllowAutoRedirect = false,
+ });
+ }
+
+ [Fact]
+ public async Task GetConversations_ShouldReturnOk()
+ {
+ // Act
+ var response = await _client.GetAsync("/api/v1/conversations");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ }
+
+ [Fact]
+ public async Task GetConversation_WithUnknownId_ShouldReturnNotFound()
+ {
+ // Act
+ var response = await _client.GetAsync($"/api/v1/conversations/{Guid.NewGuid()}");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.NotFound);
+ }
+
+ [Fact]
+ public async Task HealthCheck_ShouldReturnHealthy()
+ {
+ // Act
+ var response = await _client.GetAsync("/health/live");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ }
+}
diff --git a/services/mkt-facebook-service-net/tests/FacebookService.FunctionalTests/Controllers/SamplesControllerTests.cs b/services/mkt-facebook-service-net/tests/FacebookService.FunctionalTests/Controllers/SamplesControllerTests.cs
deleted file mode 100644
index a5f8f862..00000000
--- a/services/mkt-facebook-service-net/tests/FacebookService.FunctionalTests/Controllers/SamplesControllerTests.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System.Net;
-using System.Net.Http.Json;
-using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using Xunit;
-
-namespace FacebookService.FunctionalTests.Controllers;
-
-///
-/// EN: Functional tests for Samples API endpoints.
-/// VI: Functional tests cho các endpoints API Samples.
-///
-public class SamplesControllerTests : IClassFixture
-{
- private readonly HttpClient _client;
-
- public SamplesControllerTests(CustomWebApplicationFactory factory)
- {
- _client = factory.CreateClient(new WebApplicationFactoryClientOptions
- {
- AllowAutoRedirect = false
- });
- }
-
- [Fact]
- public async Task GetSamples_ShouldReturnOkWithEmptyList()
- {
- // Act
- var response = await _client.GetAsync("/api/v1/samples");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- var content = await response.Content.ReadFromJsonAsync>>();
- content?.Success.Should().BeTrue();
- }
-
- [Fact]
- public async Task CreateSample_WithValidData_ShouldReturnCreated()
- {
- // Arrange
- var request = new { Name = "Test Sample", Description = "Test Description" };
-
- // Act
- var response = await _client.PostAsJsonAsync("/api/v1/samples", request);
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.Created);
- var content = await response.Content.ReadFromJsonAsync>();
- content?.Success.Should().BeTrue();
- content?.Data?.Id.Should().NotBeEmpty();
- }
-
- [Fact]
- public async Task GetSample_WithInvalidId_ShouldReturnNotFound()
- {
- // Arrange
- var invalidId = Guid.NewGuid();
-
- // Act
- var response = await _client.GetAsync($"/api/v1/samples/{invalidId}");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.NotFound);
- }
-
- [Fact]
- public async Task HealthCheck_ShouldReturnHealthy()
- {
- // Act
- var response = await _client.GetAsync("/health/live");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- }
-
- // EN: Helper DTOs for deserialization
- // VI: Helper DTOs để deserialize
- private record ApiResponse(bool Success, T? Data);
- private record CreateSampleResult(Guid Id);
-}
diff --git a/services/promotion-service-net/tests/PromotionService.FunctionalTests/Controllers/CampaignsControllerTests.cs b/services/promotion-service-net/tests/PromotionService.FunctionalTests/Controllers/CampaignsControllerTests.cs
new file mode 100644
index 00000000..be381770
--- /dev/null
+++ b/services/promotion-service-net/tests/PromotionService.FunctionalTests/Controllers/CampaignsControllerTests.cs
@@ -0,0 +1,53 @@
+using System.Net;
+using FluentAssertions;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace PromotionService.FunctionalTests.Controllers;
+
+///
+/// EN: Functional tests for promotion campaign endpoints.
+/// VI: Functional tests cho các endpoint campaign khuyến mãi.
+///
+public class CampaignsControllerTests : IClassFixture
+{
+ private readonly HttpClient _client;
+
+ public CampaignsControllerTests(CustomWebApplicationFactory factory)
+ {
+ _client = factory.CreateClient(new WebApplicationFactoryClientOptions
+ {
+ AllowAutoRedirect = false,
+ });
+ }
+
+ [Fact]
+ public async Task GetCampaigns_ShouldReturnOk()
+ {
+ // Act
+ var response = await _client.GetAsync("/api/v1/campaigns");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ }
+
+ [Fact]
+ public async Task GetCampaign_WithUnknownId_ShouldReturnNotFound()
+ {
+ // Act
+ var response = await _client.GetAsync($"/api/v1/campaigns/{Guid.NewGuid()}");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.NotFound);
+ }
+
+ [Fact]
+ public async Task HealthCheck_ShouldReturnHealthy()
+ {
+ // Act
+ var response = await _client.GetAsync("/health/live");
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.OK);
+ }
+}
diff --git a/services/promotion-service-net/tests/PromotionService.FunctionalTests/Controllers/SamplesControllerTests.cs b/services/promotion-service-net/tests/PromotionService.FunctionalTests/Controllers/SamplesControllerTests.cs
deleted file mode 100644
index aad48206..00000000
--- a/services/promotion-service-net/tests/PromotionService.FunctionalTests/Controllers/SamplesControllerTests.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System.Net;
-using System.Net.Http.Json;
-using FluentAssertions;
-using Microsoft.AspNetCore.Mvc.Testing;
-using Xunit;
-
-namespace PromotionService.FunctionalTests.Controllers;
-
-///
-/// EN: Functional tests for Samples API endpoints.
-/// VI: Functional tests cho các endpoints API Samples.
-///
-public class SamplesControllerTests : IClassFixture
-{
- private readonly HttpClient _client;
-
- public SamplesControllerTests(CustomWebApplicationFactory factory)
- {
- _client = factory.CreateClient(new WebApplicationFactoryClientOptions
- {
- AllowAutoRedirect = false
- });
- }
-
- [Fact]
- public async Task GetSamples_ShouldReturnOkWithEmptyList()
- {
- // Act
- var response = await _client.GetAsync("/api/v1/samples");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- var content = await response.Content.ReadFromJsonAsync>>();
- content?.Success.Should().BeTrue();
- }
-
- [Fact]
- public async Task CreateSample_WithValidData_ShouldReturnCreated()
- {
- // Arrange
- var request = new { Name = "Test Sample", Description = "Test Description" };
-
- // Act
- var response = await _client.PostAsJsonAsync("/api/v1/samples", request);
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.Created);
- var content = await response.Content.ReadFromJsonAsync>();
- content?.Success.Should().BeTrue();
- content?.Data?.Id.Should().NotBeEmpty();
- }
-
- [Fact]
- public async Task GetSample_WithInvalidId_ShouldReturnNotFound()
- {
- // Arrange
- var invalidId = Guid.NewGuid();
-
- // Act
- var response = await _client.GetAsync($"/api/v1/samples/{invalidId}");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.NotFound);
- }
-
- [Fact]
- public async Task HealthCheck_ShouldReturnHealthy()
- {
- // Act
- var response = await _client.GetAsync("/health/live");
-
- // Assert
- response.StatusCode.Should().Be(HttpStatusCode.OK);
- }
-
- // EN: Helper DTOs for deserialization
- // VI: Helper DTOs để deserialize
- private record ApiResponse(bool Success, T? Data);
- private record CreateSampleResult(Guid Id);
-}