Files
portal/app/tests/Feature/Integration/SchemaV8_18Test.php
T

106 lines
3.7 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
uses(DatabaseTransactions::class);
test('supplier_leads table exists with required columns', function () {
expect(Schema::hasTable('supplier_leads'))->toBeTrue();
expect(Schema::hasColumns('supplier_leads', [
'id',
'supplier_project_id',
'platform',
'raw_payload',
'vid',
'phone',
'received_at',
'source',
'processed_at',
'deals_created_count',
]))->toBeTrue();
});
test('supplier_leads has FK to supplier_projects with ON DELETE SET NULL', function () {
$row = DB::selectOne(
"SELECT c.confdeltype
FROM pg_constraint c
JOIN pg_class t ON c.conrelid = t.oid
JOIN pg_class r ON c.confrelid = r.oid
WHERE t.relname = 'supplier_leads'
AND r.relname = 'supplier_projects'
AND c.contype = 'f'"
);
expect($row)->not->toBeNull();
// confdeltype: 'a'=NO ACTION, 'r'=RESTRICT, 'c'=CASCADE, 'n'=SET NULL, 'd'=SET DEFAULT
expect($row->confdeltype)->toBe('n');
});
test('supplier_leads.source has CHECK enum', function () {
// Valid source: должно пройти.
$insertedId = DB::table('supplier_leads')->insertGetId([
'platform' => 'B1',
'raw_payload' => json_encode(['test' => 'valid_source']),
'vid' => 1000001,
'phone' => '+79991234567',
'source' => 'webhook',
]);
expect($insertedId)->toBeGreaterThan(0);
DB::table('supplier_leads')->where('id', $insertedId)->delete();
// Invalid source: должно отклониться CHECK constraint'ом.
expect(fn () => DB::table('supplier_leads')->insert([
'platform' => 'B1',
'raw_payload' => json_encode(['test' => 'invalid']),
'vid' => 1000002,
'phone' => '+79991234568',
'source' => 'invalid_source',
]))->toThrow(QueryException::class);
});
test('projects.delivered_today exists with default 0', function () {
expect(Schema::hasColumn('projects', 'delivered_today'))->toBeTrue();
$col = DB::selectOne(
"SELECT column_default
FROM information_schema.columns
WHERE table_name = 'projects' AND column_name = 'delivered_today'"
);
expect($col)->not->toBeNull();
expect($col->column_default)->toContain('0');
});
test('UNIQUE INDEX on vid prevents duplicate inserts (idempotency)', function () {
DB::statement("INSERT INTO supplier_leads (platform, raw_payload, vid, phone, received_at, source) VALUES ('B1', '{}', 999000111, '79991234567', NOW(), 'webhook')");
expect(fn () => DB::statement(
"INSERT INTO supplier_leads (platform, raw_payload, vid, phone, received_at, source) VALUES ('B2', '{}', 999000111, '79991234567', NOW(), 'webhook')"
))->toThrow(QueryException::class);
});
test('system_settings seed rows exist for supplier_webhook_secret + supplier_ip_allowlist', function () {
$secret = DB::table('system_settings')
->where('key', 'supplier_webhook_secret')
->first();
expect($secret)->not->toBeNull();
expect($secret->type)->toBe('string');
// Placeholder only valid in dev/test — production must override via deploy script.
// Real secret strength validation belongs to a deploy-time validator (out of scope).
expect($secret->value)->toBe('__SET_ON_DEPLOY__');
$allowlist = DB::table('system_settings')
->where('key', 'supplier_ip_allowlist')
->first();
expect($allowlist)->not->toBeNull();
expect($allowlist->type)->toBe('json');
$decoded = json_decode($allowlist->value, true);
expect($decoded)->toBeArray();
});