File: /home/xedaptot/ai.naniguide.com/tests/Feature/AdCampaignFeatureTest.php
<?php
use App\Model\AdCampaign;
use App\Model\AdCampaignPlatform;
use App\Model\AdCreative;
// ── AdCampaign Model Tests ──────────────────────────────────────────────
test('ad campaign objectives are valid', function () {
expect(AdCampaign::OBJECTIVES)->toBe([
'awareness', 'traffic', 'engagement', 'leads', 'sales', 'app_installs',
]);
});
test('ad campaign statuses are valid', function () {
expect(AdCampaign::STATUSES)->toBe([
'draft', 'review', 'active', 'paused', 'completed', 'error', 'archived',
]);
});
test('ad campaign bid strategies are valid', function () {
expect(AdCampaign::BID_STRATEGIES)->toBe([
'auto', 'lowest_cost', 'cost_cap', 'bid_cap',
]);
});
test('ad campaign objective labels exist for all objectives', function () {
foreach (AdCampaign::OBJECTIVES as $obj) {
expect(AdCampaign::OBJECTIVE_LABELS)->toHaveKey($obj);
}
});
test('ad campaign status badge map exists for all statuses', function () {
foreach (AdCampaign::STATUSES as $status) {
expect(AdCampaign::STATUS_BADGE_MAP)->toHaveKey($status);
expect(AdCampaign::STATUS_BADGE_MAP[$status])->toBeIn(['green', 'orange', 'red', 'blue']);
}
});
test('ad campaign fillable fields are correct', function () {
$campaign = new AdCampaign();
expect($campaign->getFillable())->toContain('name', 'objective', 'customer_id', 'daily_budget', 'settings');
});
test('ad campaign casts are correct', function () {
$campaign = new AdCampaign();
$casts = $campaign->getCasts();
expect($casts)->toHaveKey('settings');
expect($casts['settings'])->toBe('json');
expect($casts)->toHaveKey('schedule_start');
expect($casts)->toHaveKey('published_at');
});
test('ad campaign objective label accessor works', function () {
$campaign = new AdCampaign();
$campaign->objective = AdCampaign::OBJECTIVE_TRAFFIC;
expect($campaign->objective_label)->toBe('Website Traffic');
});
test('ad campaign status badge accessor works', function () {
$campaign = new AdCampaign();
$campaign->status = AdCampaign::STATUS_ACTIVE;
expect($campaign->status_badge)->toBe('green');
$campaign->status = AdCampaign::STATUS_DRAFT;
expect($campaign->status_badge)->toBe('orange');
$campaign->status = AdCampaign::STATUS_ERROR;
expect($campaign->status_badge)->toBe('red');
});
test('ad campaign budget display shows daily budget', function () {
$campaign = new AdCampaign();
$campaign->daily_budget = 50.00;
$campaign->budget_currency = 'USD';
expect($campaign->budget_display)->toContain('USD')->toContain('50.00')->toContain('/day');
});
test('ad campaign budget display shows lifetime budget', function () {
$campaign = new AdCampaign();
$campaign->daily_budget = null;
$campaign->lifetime_budget = 1000.00;
$campaign->budget_currency = 'EUR';
expect($campaign->budget_display)->toContain('EUR')->toContain('1,000.00')->toContain('total');
});
test('ad campaign helper methods work', function () {
$campaign = new AdCampaign();
$campaign->status = AdCampaign::STATUS_DRAFT;
expect($campaign->isDraft())->toBeTrue();
expect($campaign->isActive())->toBeFalse();
$campaign->status = AdCampaign::STATUS_ACTIVE;
expect($campaign->isActive())->toBeTrue();
$campaign->status = AdCampaign::STATUS_PAUSED;
expect($campaign->isPaused())->toBeTrue();
$campaign->status = AdCampaign::STATUS_ARCHIVED;
expect($campaign->isArchived())->toBeTrue();
});
test('ad campaign can be created via factory', function () {
$campaign = AdCampaign::factory()->make(['customer_id' => 1]);
expect($campaign->name)->not->toBeEmpty();
expect($campaign->objective)->toBeIn(AdCampaign::OBJECTIVES);
expect($campaign->status)->toBe(AdCampaign::STATUS_DRAFT);
});
test('ad campaign factory active state works', function () {
$campaign = AdCampaign::factory()->active()->make(['customer_id' => 1]);
expect($campaign->status)->toBe(AdCampaign::STATUS_ACTIVE);
expect($campaign->published_at)->not->toBeNull();
})->skip(fn () => !app()->bound('db'), 'Requires full app bootstrap');
// ── AdCampaignPlatform Model Tests ──────────────────────────────────────
test('ad campaign platform statuses are valid', function () {
expect(AdCampaignPlatform::STATUSES)->toBe([
'pending', 'submitted', 'active', 'paused', 'rejected', 'error',
]);
});
test('ad campaign platform casts metadata as json', function () {
$cp = new AdCampaignPlatform();
$casts = $cp->getCasts();
expect($casts)->toHaveKey('metadata');
expect($casts['metadata'])->toBe('json');
});
// ── AdCreative Model Tests ──────────────────────────────────────────────
test('ad creative types are valid', function () {
expect(AdCreative::TYPES)->toBe(['image', 'video', 'carousel', 'html']);
});
test('ad creative type labels exist for all types', function () {
foreach (AdCreative::TYPES as $type) {
expect(AdCreative::TYPE_LABELS)->toHaveKey($type);
}
});
test('ad creative CTA options are non-empty', function () {
expect(AdCreative::CTA_OPTIONS)->not->toBeEmpty();
expect(AdCreative::CTA_OPTIONS)->toHaveKey('learn_more');
expect(AdCreative::CTA_OPTIONS)->toHaveKey('shop_now');
});
test('ad creative fillable fields are correct', function () {
$creative = new AdCreative();
expect($creative->getFillable())->toContain('name', 'type', 'headline', 'destination_url', 'builder_content');
});
test('ad creative casts are correct', function () {
$creative = new AdCreative();
$casts = $creative->getCasts();
expect($casts['builder_content'])->toBe('json');
expect($casts['carousel_cards'])->toBe('json');
expect($casts['metadata'])->toBe('json');
});
test('ad creative type label accessor works', function () {
$creative = new AdCreative();
$creative->type = AdCreative::TYPE_CAROUSEL;
expect($creative->type_label)->toBe('Carousel');
});
test('ad creative can be created via factory', function () {
$creative = AdCreative::factory()->make(['customer_id' => 1]);
expect($creative->name)->not->toBeEmpty();
expect($creative->type)->toBeIn(AdCreative::TYPES);
});