274 lines
12 KiB
TypeScript
274 lines
12 KiB
TypeScript
/**
|
|
* Integration Test: Sponsor Dashboard Use Case Orchestration
|
|
*
|
|
* Tests the orchestration logic of sponsor dashboard-related Use Cases:
|
|
* - GetDashboardOverviewUseCase: Retrieves dashboard overview
|
|
* - GetDashboardMetricsUseCase: Retrieves dashboard metrics
|
|
* - GetRecentActivityUseCase: Retrieves recent activity
|
|
* - GetPendingActionsUseCase: Retrieves pending actions
|
|
* - Validates that Use Cases correctly interact with their Ports (Repositories, Event Publishers)
|
|
* - Uses In-Memory adapters for fast, deterministic testing
|
|
*
|
|
* Focus: Business logic orchestration, NOT UI rendering
|
|
*/
|
|
|
|
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
|
import { InMemorySponsorRepository } from '../../../adapters/sponsors/persistence/inmemory/InMemorySponsorRepository';
|
|
import { InMemoryCampaignRepository } from '../../../adapters/sponsors/persistence/inmemory/InMemoryCampaignRepository';
|
|
import { InMemoryBillingRepository } from '../../../adapters/billing/persistence/inmemory/InMemoryBillingRepository';
|
|
import { InMemoryEventPublisher } from '../../../adapters/events/InMemoryEventPublisher';
|
|
import { GetDashboardOverviewUseCase } from '../../../core/sponsors/use-cases/GetDashboardOverviewUseCase';
|
|
import { GetDashboardMetricsUseCase } from '../../../core/sponsors/use-cases/GetDashboardMetricsUseCase';
|
|
import { GetRecentActivityUseCase } from '../../../core/sponsors/use-cases/GetRecentActivityUseCase';
|
|
import { GetPendingActionsUseCase } from '../../../core/sponsors/use-cases/GetPendingActionsUseCase';
|
|
import { GetDashboardOverviewQuery } from '../../../core/sponsors/ports/GetDashboardOverviewQuery';
|
|
import { GetDashboardMetricsQuery } from '../../../core/sponsors/ports/GetDashboardMetricsQuery';
|
|
import { GetRecentActivityQuery } from '../../../core/sponsors/ports/GetRecentActivityQuery';
|
|
import { GetPendingActionsQuery } from '../../../core/sponsors/ports/GetPendingActionsQuery';
|
|
|
|
describe('Sponsor Dashboard Use Case Orchestration', () => {
|
|
let sponsorRepository: InMemorySponsorRepository;
|
|
let campaignRepository: InMemoryCampaignRepository;
|
|
let billingRepository: InMemoryBillingRepository;
|
|
let eventPublisher: InMemoryEventPublisher;
|
|
let getDashboardOverviewUseCase: GetDashboardOverviewUseCase;
|
|
let getDashboardMetricsUseCase: GetDashboardMetricsUseCase;
|
|
let getRecentActivityUseCase: GetRecentActivityUseCase;
|
|
let getPendingActionsUseCase: GetPendingActionsUseCase;
|
|
|
|
beforeAll(() => {
|
|
// TODO: Initialize In-Memory repositories and event publisher
|
|
// sponsorRepository = new InMemorySponsorRepository();
|
|
// campaignRepository = new InMemoryCampaignRepository();
|
|
// billingRepository = new InMemoryBillingRepository();
|
|
// eventPublisher = new InMemoryEventPublisher();
|
|
// getDashboardOverviewUseCase = new GetDashboardOverviewUseCase({
|
|
// sponsorRepository,
|
|
// campaignRepository,
|
|
// billingRepository,
|
|
// eventPublisher,
|
|
// });
|
|
// getDashboardMetricsUseCase = new GetDashboardMetricsUseCase({
|
|
// sponsorRepository,
|
|
// campaignRepository,
|
|
// billingRepository,
|
|
// eventPublisher,
|
|
// });
|
|
// getRecentActivityUseCase = new GetRecentActivityUseCase({
|
|
// sponsorRepository,
|
|
// campaignRepository,
|
|
// billingRepository,
|
|
// eventPublisher,
|
|
// });
|
|
// getPendingActionsUseCase = new GetPendingActionsUseCase({
|
|
// sponsorRepository,
|
|
// campaignRepository,
|
|
// billingRepository,
|
|
// eventPublisher,
|
|
// });
|
|
});
|
|
|
|
beforeEach(() => {
|
|
// TODO: Clear all In-Memory repositories before each test
|
|
// sponsorRepository.clear();
|
|
// campaignRepository.clear();
|
|
// billingRepository.clear();
|
|
// eventPublisher.clear();
|
|
});
|
|
|
|
describe('GetDashboardOverviewUseCase - Success Path', () => {
|
|
it('should retrieve dashboard overview for a sponsor', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Sponsor with complete dashboard data
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has company name "Test Company"
|
|
// And: The sponsor has 5 campaigns
|
|
// And: The sponsor has billing data
|
|
// When: GetDashboardOverviewUseCase.execute() is called with sponsor ID
|
|
// Then: The result should show company name
|
|
// And: The result should show welcome message
|
|
// And: The result should show quick action buttons
|
|
// And: EventPublisher should emit DashboardOverviewAccessedEvent
|
|
});
|
|
|
|
it('should retrieve overview with minimal data', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Sponsor with minimal data
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has company name "Test Company"
|
|
// And: The sponsor has no campaigns
|
|
// And: The sponsor has no billing data
|
|
// When: GetDashboardOverviewUseCase.execute() is called with sponsor ID
|
|
// Then: The result should show company name
|
|
// And: The result should show welcome message
|
|
// And: EventPublisher should emit DashboardOverviewAccessedEvent
|
|
});
|
|
});
|
|
|
|
describe('GetDashboardOverviewUseCase - Error Handling', () => {
|
|
it('should throw error when sponsor does not exist', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Non-existent sponsor
|
|
// Given: No sponsor exists with the given ID
|
|
// When: GetDashboardOverviewUseCase.execute() is called with non-existent sponsor ID
|
|
// Then: Should throw SponsorNotFoundError
|
|
// And: EventPublisher should NOT emit any events
|
|
});
|
|
});
|
|
|
|
describe('GetDashboardMetricsUseCase - Success Path', () => {
|
|
it('should retrieve dashboard metrics for a sponsor', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Sponsor with complete metrics
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has 5 total sponsorships
|
|
// And: The sponsor has 2 active sponsorships
|
|
// And: The sponsor has total investment of $5000
|
|
// And: The sponsor has total impressions of 100000
|
|
// When: GetDashboardMetricsUseCase.execute() is called with sponsor ID
|
|
// Then: The result should show total sponsorships: 5
|
|
// And: The result should show active sponsorships: 2
|
|
// And: The result should show total investment: $5000
|
|
// And: The result should show total impressions: 100000
|
|
// And: EventPublisher should emit DashboardMetricsAccessedEvent
|
|
});
|
|
|
|
it('should retrieve metrics with zero values', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Sponsor with no metrics
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has no campaigns
|
|
// When: GetDashboardMetricsUseCase.execute() is called with sponsor ID
|
|
// Then: The result should show total sponsorships: 0
|
|
// And: The result should show active sponsorships: 0
|
|
// And: The result should show total investment: $0
|
|
// And: The result should show total impressions: 0
|
|
// And: EventPublisher should emit DashboardMetricsAccessedEvent
|
|
});
|
|
});
|
|
|
|
describe('GetDashboardMetricsUseCase - Error Handling', () => {
|
|
it('should throw error when sponsor does not exist', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Non-existent sponsor
|
|
// Given: No sponsor exists with the given ID
|
|
// When: GetDashboardMetricsUseCase.execute() is called with non-existent sponsor ID
|
|
// Then: Should throw SponsorNotFoundError
|
|
// And: EventPublisher should NOT emit any events
|
|
});
|
|
});
|
|
|
|
describe('GetRecentActivityUseCase - Success Path', () => {
|
|
it('should retrieve recent activity for a sponsor', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Sponsor with recent activity
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has recent sponsorship updates
|
|
// And: The sponsor has recent billing activity
|
|
// And: The sponsor has recent campaign changes
|
|
// When: GetRecentActivityUseCase.execute() is called with sponsor ID
|
|
// Then: The result should contain recent sponsorship updates
|
|
// And: The result should contain recent billing activity
|
|
// And: The result should contain recent campaign changes
|
|
// And: EventPublisher should emit RecentActivityAccessedEvent
|
|
});
|
|
|
|
it('should retrieve activity with empty result', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Sponsor with no recent activity
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has no recent activity
|
|
// When: GetRecentActivityUseCase.execute() is called with sponsor ID
|
|
// Then: The result should be empty
|
|
// And: EventPublisher should emit RecentActivityAccessedEvent
|
|
});
|
|
});
|
|
|
|
describe('GetRecentActivityUseCase - Error Handling', () => {
|
|
it('should throw error when sponsor does not exist', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Non-existent sponsor
|
|
// Given: No sponsor exists with the given ID
|
|
// When: GetRecentActivityUseCase.execute() is called with non-existent sponsor ID
|
|
// Then: Should throw SponsorNotFoundError
|
|
// And: EventPublisher should NOT emit any events
|
|
});
|
|
});
|
|
|
|
describe('GetPendingActionsUseCase - Success Path', () => {
|
|
it('should retrieve pending actions for a sponsor', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Sponsor with pending actions
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has sponsorships awaiting approval
|
|
// And: The sponsor has pending payments
|
|
// And: The sponsor has action items
|
|
// When: GetPendingActionsUseCase.execute() is called with sponsor ID
|
|
// Then: The result should show sponsorships awaiting approval
|
|
// And: The result should show pending payments
|
|
// And: The result should show action items
|
|
// And: EventPublisher should emit PendingActionsAccessedEvent
|
|
});
|
|
|
|
it('should retrieve pending actions with empty result', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Sponsor with no pending actions
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has no pending actions
|
|
// When: GetPendingActionsUseCase.execute() is called with sponsor ID
|
|
// Then: The result should be empty
|
|
// And: EventPublisher should emit PendingActionsAccessedEvent
|
|
});
|
|
});
|
|
|
|
describe('GetPendingActionsUseCase - Error Handling', () => {
|
|
it('should throw error when sponsor does not exist', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Non-existent sponsor
|
|
// Given: No sponsor exists with the given ID
|
|
// When: GetPendingActionsUseCase.execute() is called with non-existent sponsor ID
|
|
// Then: Should throw SponsorNotFoundError
|
|
// And: EventPublisher should NOT emit any events
|
|
});
|
|
});
|
|
|
|
describe('Dashboard Data Orchestration', () => {
|
|
it('should correctly aggregate dashboard metrics', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Dashboard metrics aggregation
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has 3 campaigns with investments: $1000, $2000, $3000
|
|
// And: The sponsor has 3 campaigns with impressions: 50000, 30000, 20000
|
|
// When: GetDashboardMetricsUseCase.execute() is called
|
|
// Then: Total sponsorships should be 3
|
|
// And: Active sponsorships should be calculated correctly
|
|
// And: Total investment should be $6000
|
|
// And: Total impressions should be 100000
|
|
// And: EventPublisher should emit DashboardMetricsAccessedEvent
|
|
});
|
|
|
|
it('should correctly format recent activity', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Recent activity formatting
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has recent activity from different sources
|
|
// When: GetRecentActivityUseCase.execute() is called
|
|
// Then: Activity should be sorted by date (newest first)
|
|
// And: Each activity should have correct type and details
|
|
// And: EventPublisher should emit RecentActivityAccessedEvent
|
|
});
|
|
|
|
it('should correctly identify pending actions', async () => {
|
|
// TODO: Implement test
|
|
// Scenario: Pending actions identification
|
|
// Given: A sponsor exists with ID "sponsor-123"
|
|
// And: The sponsor has sponsorships awaiting approval
|
|
// And: The sponsor has pending payments
|
|
// When: GetPendingActionsUseCase.execute() is called
|
|
// Then: All pending actions should be identified
|
|
// And: Each action should have correct priority
|
|
// And: EventPublisher should emit PendingActionsAccessedEvent
|
|
});
|
|
});
|
|
});
|