Files
portal/app/tests/Feature/Console/PhoneRangesImportCommandTest.php
T

89 lines
3.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Tests\Concerns\SharesSupplierPdo;
uses(DatabaseTransactions::class);
uses(SharesSupplierPdo::class);
function rossvyazFixture(): string
{
return base_path('tests/Fixtures/rossvyaz/sample.csv');
}
it('dry-run parses csv, maps regions to subject_code, builds staging, does not swap', function (): void {
$this->artisan('phone-ranges:import', ['--file' => rossvyazFixture(), '--dry-run' => true])
->assertSuccessful();
// Staging построен (dry-run не свапает и не дропает staging — данные видны в той же tx).
expect(DB::table('phone_ranges_staging')->count())->toBe(3);
$r495 = DB::selectOne('SELECT subject_code FROM phone_ranges_staging WHERE def_code = 495');
$r921 = DB::selectOne('SELECT subject_code FROM phone_ranges_staging WHERE def_code = 921');
$r999 = DB::selectOne('SELECT subject_code FROM phone_ranges_staging WHERE def_code = 999');
expect((int) $r495->subject_code)->toBe(82) // Москва
->and((int) $r921->subject_code)->toBe(83) // Санкт-Петербург
->and($r999->subject_code)->toBeNull(); // Атлантида — не маппится
// Живой phone_ranges не тронут (свапа не было).
expect(DB::table('phone_ranges')->count())->toBe(0);
// Журнал импорта: dry-run → rolled_back, несматчившийся регион в error.
$imp = DB::table('phone_ranges_imports')->orderByDesc('id')->first();
expect($imp->status)->toBe('rolled_back')
->and($imp->error)->toContain('Атлантида');
});
it('maps all matched rows and counts unmatched separately', function (): void {
$this->artisan('phone-ranges:import', ['--file' => rossvyazFixture(), '--dry-run' => true])
->assertSuccessful();
$matched = DB::table('phone_ranges_staging')->whereNotNull('subject_code')->count();
$unmatched = DB::table('phone_ranges_staging')->whereNull('subject_code')->count();
expect($matched)->toBe(2)->and($unmatched)->toBe(1);
});
it('skips swap when checksum matches a completed import (idempotency)', function (): void {
$checksum = hash_file('sha256', rossvyazFixture());
DB::table('phone_ranges_imports')->insert([
'source_url' => 'https://rossvyaz.gov.ru/prev',
'checksum_sha256' => $checksum,
'status' => 'completed',
'imported_at' => now(),
'completed_at' => now(),
]);
// Не dry-run: но checksum совпал с completed → короткое замыкание ДО свапа.
$this->artisan('phone-ranges:import', ['--file' => rossvyazFixture()])
->assertSuccessful();
expect(DB::table('phone_ranges')->count())->toBe(0); // свапа не было
$latest = DB::table('phone_ranges_imports')->orderByDesc('id')->first();
expect($latest->status)->toBe('rolled_back');
});
it('force flag bypasses idempotency note even with matching checksum', function (): void {
// С --dry-run + --force: идемпотентность игнорируется, но dry-run всё равно не свапает.
$checksum = hash_file('sha256', rossvyazFixture());
DB::table('phone_ranges_imports')->insert([
'source_url' => 'https://rossvyaz.gov.ru/prev',
'checksum_sha256' => $checksum,
'status' => 'completed',
'imported_at' => now(),
'completed_at' => now(),
]);
$this->artisan('phone-ranges:import', ['--file' => rossvyazFixture(), '--dry-run' => true, '--force' => true])
->assertSuccessful();
// --force обошёл idempotency → staging построен заново (3 строки), но dry-run не свапнул.
expect(DB::table('phone_ranges_staging')->count())->toBe(3);
expect(DB::table('phone_ranges')->count())->toBe(0);
});