update
This commit is contained in:
28
tests/Feature/Countries/CountryMigrationTest.php
Normal file
28
tests/Feature/Countries/CountryMigrationTest.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
it('creates the countries table and user country relation column', function (): void {
|
||||
expect(Schema::hasTable('countries'))->toBeTrue();
|
||||
expect(Schema::hasColumns('countries', [
|
||||
'id',
|
||||
'iso2',
|
||||
'iso3',
|
||||
'numeric_code',
|
||||
'name_common',
|
||||
'name_official',
|
||||
'region',
|
||||
'subregion',
|
||||
'flag_svg_url',
|
||||
'flag_png_url',
|
||||
'flag_emoji',
|
||||
'active',
|
||||
'sort_order',
|
||||
'is_featured',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
]))->toBeTrue();
|
||||
expect(Schema::hasColumn('users', 'country_id'))->toBeTrue();
|
||||
});
|
||||
90
tests/Feature/Countries/CountrySyncServiceTest.php
Normal file
90
tests/Feature/Countries/CountrySyncServiceTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\User;
|
||||
use App\Services\Countries\CountryCatalogService;
|
||||
use App\Services\Countries\CountryRemoteProviderInterface;
|
||||
use App\Services\Countries\CountrySyncService;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
it('syncs countries updates cache and backfills users from legacy country codes', function (): void {
|
||||
config()->set('skinbase-countries.deactivate_missing', true);
|
||||
|
||||
Country::query()->where('iso2', 'SI')->update([
|
||||
'iso' => 'SI',
|
||||
'iso3' => 'SVN',
|
||||
'name' => 'Old Slovenia',
|
||||
'name_common' => 'Old Slovenia',
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
$user = User::factory()->create();
|
||||
|
||||
DB::table('user_profiles')->insert([
|
||||
'user_id' => $user->id,
|
||||
'country_code' => 'SI',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
$catalog = app(CountryCatalogService::class);
|
||||
expect(collect($catalog->profileSelectOptions())->firstWhere('iso2', 'SI')['name'])->toBe('Old Slovenia');
|
||||
|
||||
app()->instance(CountryRemoteProviderInterface::class, new class implements CountryRemoteProviderInterface {
|
||||
public function fetchAll(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'iso2' => 'SI',
|
||||
'iso3' => 'SVN',
|
||||
'numeric_code' => '705',
|
||||
'name_common' => 'Slovenia',
|
||||
'name_official' => 'Republic of Slovenia',
|
||||
'region' => 'Europe',
|
||||
'subregion' => 'Central Europe',
|
||||
'flag_svg_url' => 'https://flags.test/si.svg',
|
||||
'flag_png_url' => 'https://flags.test/si.png',
|
||||
'flag_emoji' => '🇸🇮',
|
||||
],
|
||||
[
|
||||
'iso2' => '',
|
||||
'name_common' => 'Invalid',
|
||||
],
|
||||
[
|
||||
'iso2' => 'SI',
|
||||
'name_common' => 'Duplicate Slovenia',
|
||||
],
|
||||
[
|
||||
'iso2' => 'ZZ',
|
||||
'iso3' => 'ZZZ',
|
||||
'numeric_code' => '999',
|
||||
'name_common' => 'Zedland',
|
||||
'name_official' => 'Republic of Zedland',
|
||||
'region' => 'Europe',
|
||||
'subregion' => 'Nowhere',
|
||||
'flag_svg_url' => 'https://flags.test/zz.svg',
|
||||
'flag_png_url' => 'https://flags.test/zz.png',
|
||||
'flag_emoji' => '🏳️',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function normalizePayload(array $payload): array
|
||||
{
|
||||
return $payload;
|
||||
}
|
||||
});
|
||||
|
||||
$summary = app(CountrySyncService::class)->sync(allowFallback: false, deactivateMissing: true);
|
||||
|
||||
expect($summary['updated'])->toBe(1)
|
||||
->and($summary['inserted'])->toBe(1)
|
||||
->and($summary['invalid'])->toBe(1)
|
||||
->and($summary['skipped'])->toBe(1)
|
||||
->and($summary['backfilled_users'])->toBe(1);
|
||||
|
||||
expect(collect($catalog->profileSelectOptions())->firstWhere('iso2', 'SI')['name'])->toBe('Slovenia');
|
||||
expect($user->fresh()->country_id)->toBe(Country::query()->where('iso2', 'SI')->value('id'));
|
||||
});
|
||||
86
tests/Feature/Countries/ProfileCountryPersistenceTest.php
Normal file
86
tests/Feature/Countries/ProfileCountryPersistenceTest.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Http\Middleware\ForumBotProtectionMiddleware;
|
||||
use App\Models\Country;
|
||||
use App\Models\User;
|
||||
|
||||
it('stores a selected country on the personal settings endpoint', function (): void {
|
||||
$this->withoutMiddleware(ForumBotProtectionMiddleware::class);
|
||||
|
||||
$user = User::factory()->create();
|
||||
$country = Country::query()->where('iso2', 'SI')->firstOrFail();
|
||||
$country->update([
|
||||
'iso' => 'SI',
|
||||
'iso3' => 'SVN',
|
||||
'name' => 'Slovenia',
|
||||
'name_common' => 'Slovenia',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->postJson('/settings/personal/update', [
|
||||
'birthday' => '1990-01-02',
|
||||
'gender' => 'm',
|
||||
'country_id' => $country->id,
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
|
||||
$user->refresh();
|
||||
|
||||
expect($user->country_id)->toBe($country->id);
|
||||
expect(optional($user->profile)->country_code)->toBe('SI');
|
||||
});
|
||||
|
||||
it('rejects invalid country identifiers on the personal settings endpoint', function (): void {
|
||||
$this->withoutMiddleware(ForumBotProtectionMiddleware::class);
|
||||
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this->actingAs($user)->postJson('/settings/personal/update', [
|
||||
'country_id' => 999999,
|
||||
]);
|
||||
|
||||
$response->assertStatus(422)
|
||||
->assertJsonValidationErrors(['country_id']);
|
||||
});
|
||||
|
||||
it('loads countries on the dashboard profile settings page', function (): void {
|
||||
$this->withoutMiddleware(ForumBotProtectionMiddleware::class);
|
||||
|
||||
$user = User::factory()->create();
|
||||
Country::query()->where('iso2', 'SI')->update([
|
||||
'iso' => 'SI',
|
||||
'iso3' => 'SVN',
|
||||
'name' => 'Slovenia',
|
||||
'name_common' => 'Slovenia',
|
||||
'flag_emoji' => '🇸🇮',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->get('/dashboard/profile');
|
||||
|
||||
$response->assertOk()->assertSee('Slovenia');
|
||||
});
|
||||
|
||||
it('supports country persistence through the legacy profile update endpoint', function (): void {
|
||||
$user = User::factory()->create();
|
||||
$country = Country::query()->where('iso2', 'DE')->firstOrFail();
|
||||
$country->update([
|
||||
'iso' => 'DE',
|
||||
'iso3' => 'DEU',
|
||||
'name' => 'Germany',
|
||||
'name_common' => 'Germany',
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)
|
||||
->from('/profile/edit')
|
||||
->patch('/profile', [
|
||||
'name' => 'Updated User',
|
||||
'email' => $user->email,
|
||||
'country_id' => $country->id,
|
||||
]);
|
||||
|
||||
$response->assertSessionHasNoErrors();
|
||||
expect($user->fresh()->country_id)->toBe($country->id);
|
||||
expect(optional($user->fresh()->profile)->country_code)->toBe('DE');
|
||||
});
|
||||
56
tests/Feature/Countries/SyncCountriesCommandTest.php
Normal file
56
tests/Feature/Countries/SyncCountriesCommandTest.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Models\Country;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
it('sync command imports countries from the configured remote source', function (): void {
|
||||
config()->set('skinbase-countries.endpoint', 'https://countries.test/all');
|
||||
config()->set('skinbase-countries.fallback_seed_enabled', false);
|
||||
|
||||
Http::fake([
|
||||
'https://countries.test/all' => Http::response([
|
||||
[
|
||||
'cca2' => 'SI',
|
||||
'cca3' => 'SVN',
|
||||
'ccn3' => '705',
|
||||
'name' => ['common' => 'Slovenia', 'official' => 'Republic of Slovenia'],
|
||||
'region' => 'Europe',
|
||||
'subregion' => 'Central Europe',
|
||||
'flags' => ['svg' => 'https://flags.test/si.svg', 'png' => 'https://flags.test/si.png'],
|
||||
'flag' => '🇸🇮',
|
||||
],
|
||||
], 200),
|
||||
]);
|
||||
|
||||
$this->artisan('skinbase:sync-countries')->assertSuccessful();
|
||||
|
||||
expect(Country::query()->where('iso2', 'SI')->value('name_common'))->toBe('Slovenia');
|
||||
});
|
||||
|
||||
it('sync command fails when the remote source errors and fallback is disabled', function (): void {
|
||||
config()->set('skinbase-countries.endpoint', 'https://countries.test/all');
|
||||
config()->set('skinbase-countries.fallback_seed_enabled', false);
|
||||
|
||||
Http::fake([
|
||||
'https://countries.test/all' => Http::response(['message' => 'server error'], 500),
|
||||
]);
|
||||
|
||||
$this->artisan('skinbase:sync-countries')
|
||||
->assertExitCode(1);
|
||||
});
|
||||
|
||||
it('sync command fails gracefully when the payload contains no valid country records', function (): void {
|
||||
config()->set('skinbase-countries.endpoint', 'https://countries.test/all');
|
||||
config()->set('skinbase-countries.fallback_seed_enabled', false);
|
||||
|
||||
Http::fake([
|
||||
'https://countries.test/all' => Http::response([
|
||||
['bad' => 'payload'],
|
||||
], 200),
|
||||
]);
|
||||
|
||||
$this->artisan('skinbase:sync-countries')
|
||||
->assertExitCode(1);
|
||||
});
|
||||
Reference in New Issue
Block a user