Resolves the AiPostWizard conflict and completes the feature: - i18n parity: brand_colors_label + brand_colors_description in all 15 locales (was en/es/pt-BR only, which broke LocalizationParityTest). - Reworked the two-button toggle into a Switch with an explanatory description (matches the settings Switch/card pattern). - Only shown for templates that honor the flag: added appliesBrandVisuals() to the AiContentTemplate contract (ImageCard=true, tweet cards=false), exposed as applies_brand_visuals in the create-page DTO, and gated the toggle on it — so it no longer appears (as a no-op) for tweet-card styles. - Tests: TemplateContractTest covers appliesBrandVisuals for all templates.
52 lines
1.9 KiB
PHP
52 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Ai\Templates\ImageCardTemplate;
|
|
use App\Ai\Templates\TemplateContext;
|
|
use App\Ai\Templates\TweetCardImageTemplate;
|
|
use App\Ai\Templates\TweetCardTemplate;
|
|
use App\Enums\Ai\ContentStyle;
|
|
use App\Models\Workspace;
|
|
use Illuminate\JsonSchema\JsonSchemaTypeFactory;
|
|
|
|
test('image card template exposes its identity', function () {
|
|
$t = new ImageCardTemplate;
|
|
$workspace = Workspace::factory()->create();
|
|
$context = new TemplateContext($workspace, null, 'instagram_feed', 0, false);
|
|
|
|
expect($t->style())->toBe(ContentStyle::ImageCard)
|
|
->and($t->key())->toBe('image_card')
|
|
->and($t->needsAccount())->toBeFalse()
|
|
->and($t->appliesBrandVisuals())->toBeTrue()
|
|
->and($t->promptView($context))->toBe('prompts.post_content.generator')
|
|
->and($t->supportedFormats())->toBe([]);
|
|
});
|
|
|
|
test('tweet-card templates do not apply brand visuals', function () {
|
|
expect((new TweetCardTemplate)->appliesBrandVisuals())->toBeFalse()
|
|
->and((new TweetCardImageTemplate)->appliesBrandVisuals())->toBeFalse();
|
|
});
|
|
|
|
test('image card carousel context returns carousel schema shape', function () {
|
|
$t = new ImageCardTemplate;
|
|
$workspace = Workspace::factory()->create();
|
|
$context = new TemplateContext($workspace, null, 'instagram_carousel', 3, true);
|
|
|
|
$schema = new JsonSchemaTypeFactory;
|
|
$result = $t->schema($schema, $context);
|
|
|
|
expect($result)->toHaveKeys(['caption', 'slides'])
|
|
->and($t->promptView($context))->toBe('prompts.post_content.generator');
|
|
});
|
|
|
|
test('image card single context returns single schema shape', function () {
|
|
$t = new ImageCardTemplate;
|
|
$workspace = Workspace::factory()->create();
|
|
$context = new TemplateContext($workspace, null, 'instagram_feed', 1, false);
|
|
|
|
$schema = new JsonSchemaTypeFactory;
|
|
$result = $t->schema($schema, $context);
|
|
|
|
expect($result)->toHaveKeys(['content', 'image_title', 'image_body', 'image_keywords']);
|
|
});
|