create(); $company = Company::factory()->presseecho()->create(); $category = Category::factory()->withTranslations()->create(); $user->companies()->attach($company->id, ['role' => 'owner']); Sanctum::actingAs($user, ['press-releases:write']); $this->postJson('/api/v1/press-releases', [ 'company_id' => $company->id, 'category_id' => $category->id, 'language' => 'de', 'title' => 'API Entwurf', 'text' => 'Inhalt', 'status' => 'review', // soll ignoriert werden ]) ->assertCreated() ->assertJsonPath('data.status', PressReleaseStatus::Draft->value); }); test('api submit route raises a draft to review without consuming quota and writes a log', function () { /** @var TestCase $this */ Queue::fake(); // Klassifikations-Routing separat getestet; hier nur der Submit-Übergang. $user = User::factory()->create(['press_release_quota_used_this_month' => 0]); $pressRelease = PressRelease::factory()->create([ 'user_id' => $user->id, 'status' => PressReleaseStatus::Draft->value, 'title' => 'Saubere Pressemitteilung', 'text' => 'Vollkommen unauffälliger Inhalt.', ]); Sanctum::actingAs($user, ['press-releases:write']); $this->postJson("/api/v1/press-releases/{$pressRelease->id}/submit") ->assertOk() ->assertJsonPath('data.status', PressReleaseStatus::Review->value); expect($pressRelease->fresh()->status)->toBe(PressReleaseStatus::Review); // Slot-Verbrauch erst bei Veröffentlichung (Decision-Update §3.2). expect($user->fresh()->press_release_quota_used_this_month)->toBe(0); expect(PressReleaseStatusLog::where('press_release_id', $pressRelease->id) ->where('to_status', PressReleaseStatus::Review->value) ->exists())->toBeTrue(); }); test('api submit responds 402 when the booking gate is enforced', function () { /** @var TestCase $this */ config()->set('billing.enforce_booking', true); $user = User::factory()->create(); $pressRelease = PressRelease::factory()->create([ 'user_id' => $user->id, 'status' => PressReleaseStatus::Draft->value, 'title' => 'Saubere Pressemitteilung', 'text' => 'Inhalt', ]); Sanctum::actingAs($user, ['press-releases:write']); $this->postJson("/api/v1/press-releases/{$pressRelease->id}/submit") ->assertStatus(402); expect($pressRelease->fresh()->status)->toBe(PressReleaseStatus::Draft); }); test('api submit responds 422 when the monthly quota is exhausted', function () { /** @var TestCase $this */ config()->set('billing.enforce_booking', true); $user = User::factory()->create([ 'press_release_quota_used_this_month' => 3, ]); $plan = Plan::factory()->create([ 'press_release_quota' => 3, 'stripe_price_id_monthly' => 'price_test_m_submit', ]); subscribeUserToPlan($user, $plan); $pressRelease = PressRelease::factory()->create([ 'user_id' => $user->id, 'status' => PressReleaseStatus::Draft->value, 'title' => 'Saubere Pressemitteilung', 'text' => 'Inhalt', ]); Sanctum::actingAs($user, ['press-releases:write']); $this->postJson("/api/v1/press-releases/{$pressRelease->id}/submit") ->assertStatus(422); expect($pressRelease->fresh()->status)->toBe(PressReleaseStatus::Draft); }); test('api submit auto-rejects a press release containing a banned word', function () { /** @var TestCase $this */ config()->set('blacklist.words', ['penis']); $user = User::factory()->create(); $pressRelease = PressRelease::factory()->create([ 'user_id' => $user->id, 'status' => PressReleaseStatus::Draft->value, 'title' => 'Unzulässiger Titel penis', 'text' => 'Inhalt', ]); Sanctum::actingAs($user, ['press-releases:write']); $this->postJson("/api/v1/press-releases/{$pressRelease->id}/submit") ->assertStatus(422); expect($pressRelease->fresh()->status)->toBe(PressReleaseStatus::Rejected); }); test('api submit requires the write ability', function () { /** @var TestCase $this */ $user = User::factory()->create(); $pressRelease = PressRelease::factory()->create([ 'user_id' => $user->id, 'status' => PressReleaseStatus::Draft->value, ]); Sanctum::actingAs($user, ['press-releases:read']); $this->postJson("/api/v1/press-releases/{$pressRelease->id}/submit") ->assertForbidden(); }); test('api submit rejects a press release already in review', function () { /** @var TestCase $this */ $user = User::factory()->create(); $pressRelease = PressRelease::factory()->inReview()->create([ 'user_id' => $user->id, ]); Sanctum::actingAs($user, ['press-releases:write']); $this->postJson("/api/v1/press-releases/{$pressRelease->id}/submit") ->assertStatus(409); }); test('api user cannot submit another users press release', function () { /** @var TestCase $this */ $owner = User::factory()->create(); $otherUser = User::factory()->create(); $pressRelease = PressRelease::factory()->create([ 'user_id' => $owner->id, 'status' => PressReleaseStatus::Draft->value, ]); Sanctum::actingAs($otherUser, ['press-releases:write']); $this->postJson("/api/v1/press-releases/{$pressRelease->id}/submit") ->assertForbidden(); });