Optimize academy

This commit is contained in:
2026-06-09 13:16:01 +02:00
parent f89ee937c0
commit 5af95f6533
109 changed files with 6862 additions and 719 deletions

View File

@@ -4,9 +4,12 @@ declare(strict_types=1);
namespace Tests\Feature\Academy;
use App\Mail\AcademyAccessIssue;
use App\Http\Middleware\ConditionalValidateCsrfToken;
use App\Models\StaffApplication;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Mail;
use Inertia\Testing\AssertableInertia;
use Laravel\Cashier\SubscriptionBuilder;
use Mockery;
@@ -182,6 +185,49 @@ final class AcademyBillingCheckoutTest extends TestCase
->assertRedirect(route('academy.billing.portal'));
}
public function test_support_report_sends_mail_immediately_and_stores_record(): void
{
Mail::fake();
config()->set('mail.from.address', 'info@skinbase.org');
$user = User::factory()->create([
'email_verified_at' => now(),
'name' => 'Billing Tester',
'email' => 'tester@example.com',
]);
$this->actingAs($user)
->from(route('academy.billing.account'))
->post(route('academy.billing.report_issue'), [
'issue_type' => 'access',
'contact_email' => 'reply@example.com',
'session_id' => 'cs_test_123',
'message' => 'I paid but access did not update.',
])
->assertRedirect(route('academy.billing.account'))
->assertSessionHas('success', 'Support request sent — we will verify and activate your access shortly.');
Mail::assertSent(AcademyAccessIssue::class, function (AcademyAccessIssue $mail) use ($user): bool {
return $mail->user->is($user)
&& $mail->issueType === 'access'
&& $mail->contactEmail === 'reply@example.com'
&& $mail->sessionId === 'cs_test_123'
&& $mail->message === 'I paid but access did not update.';
});
$this->assertDatabaseHas('staff_applications', [
'topic' => 'contact',
'email' => 'reply@example.com',
'role' => 'academy_billing_support',
]);
$application = StaffApplication::query()->latest('created_at')->first();
$this->assertNotNull($application);
$this->assertSame('academy_billing', data_get($application?->payload, 'data.source'));
$this->assertSame('access', data_get($application?->payload, 'data.issue_type'));
}
private function configureBilling(): void
{
config()->set('academy.enabled', true);
@@ -209,4 +255,4 @@ final class AcademyBillingCheckoutTest extends TestCase
],
]);
}
}
}

View File

@@ -1654,6 +1654,61 @@ final class AcademyFeatureTest extends TestCase
}
}
public function test_filled_examples_are_visible_only_to_pro_and_staff_users(): void
{
$prompt = AcademyPromptTemplate::query()->create([
'title' => 'Filled Example Prompt',
'slug' => 'filled-example-prompt',
'excerpt' => 'Prompt with pro-only filled examples.',
'prompt' => 'Base prompt body available to free users.',
'difficulty' => 'beginner',
'access_level' => 'free',
'filled_examples' => [[
'title' => 'Mountain lake sunrise',
'description' => 'A filled example for scenic output.',
'placeholder_values' => [
'LOCATION' => 'Lake Bled',
],
'prompt' => 'Create a sunrise landscape of Lake Bled with calm reflections and alpine light.',
'negative_prompt' => 'muddy water, flat light',
]],
'active' => true,
'published_at' => now()->subMinute(),
]);
$this->get(route('academy.prompts.show', ['slug' => $prompt->slug]))
->assertOk()
->assertInertia(fn (AssertableInertia $page) => $page
->where('item.has_filled_examples', true)
->where('item.can_access_filled_examples', false)
->where('item.filled_examples', []));
$creator = User::factory()->create(['role' => 'academy_creator']);
$this->actingAs($creator)
->get(route('academy.prompts.show', ['slug' => $prompt->slug]))
->assertOk()
->assertInertia(fn (AssertableInertia $page) => $page
->where('item.has_filled_examples', true)
->where('item.can_access_filled_examples', false)
->where('item.filled_examples', []));
foreach ([
User::factory()->create(['role' => 'academy_pro']),
User::factory()->create(['role' => 'admin']),
] as $user) {
$this->actingAs($user)
->get(route('academy.prompts.show', ['slug' => $prompt->slug]))
->assertOk()
->assertInertia(fn (AssertableInertia $page) => $page
->where('item.has_filled_examples', true)
->where('item.can_access_filled_examples', true)
->where('item.filled_examples.0.title', 'Mountain lake sunrise')
->where('item.filled_examples.0.placeholder_values.LOCATION', 'Lake Bled')
->where('item.filled_examples.0.prompt', 'Create a sunrise landscape of Lake Bled with calm reflections and alpine light.'));
}
}
public function test_challenge_routes_are_hidden_when_challenges_are_disabled(): void
{
config(['academy.challenges_enabled' => false]);