create(['tier_no' => 1, 'leads_in_tier' => 300, 'price_per_lead_kopecks' => 5000]); PricingTier::factory()->create(['tier_no' => 2, 'leads_in_tier' => null, 'price_per_lead_kopecks' => 4000]); } /** * Строит НАСТОЯЩУЮ карточку через ClientFacts::card() на нарочно подобранных данных: * баланс 2 000 ₽ по 50 ₽/заявку (1-я ступень) = РОВНО 40 заявок — число нарочно совпадает * с «получено в этом месяце» (12) не будучи им, чтобы ловушка «перепутанные местами * цифры» была видна: 40 в карточке РЕАЛЬНО есть (баланс), но не как «получено в этом * месяце»; 12 — другое число (месяц), не «сегодня»; 3 — третье число (сегодня). */ function guardContractRealCard(): string { guardContractPricingTiers(); $tenant = Tenant::factory()->create(['balance_rub' => '2000.00', 'delivered_in_month' => 12]); $project = Project::factory()->create([ 'tenant_id' => $tenant->id, 'is_active' => true, 'daily_limit_target' => 10, ]); Project::factory()->create([ 'tenant_id' => $tenant->id, 'is_active' => true, 'daily_limit_target' => 5, ]); $user = User::factory()->create(['tenant_id' => $tenant->id]); // Сегодня — 3 заявки (received_at внутри текущего месяца — партиции deals помесячные). Deal::factory()->count(3)->create([ 'tenant_id' => $tenant->id, 'project_id' => $project->id, 'received_at' => now()->startOfDay()->addHours(9), ]); $card = app(ClientFacts::class)->card((int) $user->id); expect($card)->not->toBeNull(); // Проверяем саму ловушку ДО сторожа: если это условие не выполняется — подстроенные // данные сломались, а не сторож (иначе тесты ниже могли бы пройти по случайной причине). expect($card)->toContain('40 заявок') ->and($card)->toContain('получено в этом месяце 12') ->and($card)->toContain('Заявки: сегодня 3'); return (string) $card; } it('а) враньё режется: «получено 40» — число из ДРУГОГО факта настоящей карточки (баланс)', function () { $card = guardContractRealCard(); $guard = app(AnswerGuard::class); expect($guard->clean('В этом месяце получено 40 заявок.', $card))->toBe(''); }); it('б) враньё режется: «сегодня 12» — число из ДРУГОГО факта настоящей карточки (месяц)', function () { $card = guardContractRealCard(); $guard = app(AnswerGuard::class); expect($guard->clean('Сегодня пришло 12 заявок.', $card))->toBe(''); }); it('в) честное остаётся: «получено 12» — ровно то число, что в настоящей карточке', function () { $card = guardContractRealCard(); $guard = app(AnswerGuard::class); expect($guard->clean('В этом месяце получено 12 заявок.', $card)) ->toBe('В этом месяце получено 12 заявок.'); }); it('г) честное остаётся: «сегодня 3» — ровно то число, что в настоящей карточке', function () { $card = guardContractRealCard(); $guard = app(AnswerGuard::class); expect($guard->clean('Сегодня пришло 3 заявки.', $card)) ->toBe('Сегодня пришло 3 заявки.'); });