test(tenant): cover split website types and migration

This commit is contained in:
2026-09-17 14:25:54 -03:00
parent 6bc784519f
commit 486129a92f
36 changed files with 335 additions and 307 deletions

View File

@@ -9,7 +9,7 @@ use App\Domains\Auth\Models\User;
use App\Domains\Authorization\Enums\RoleCode;
use App\Domains\Notification\Events\PasswordResetRequested;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event;
@@ -30,14 +30,14 @@ class AdministratorControllerTest extends TestCase
Event::fake([PasswordResetRequested::class]);
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
AdminWebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
$headerLogo = $this->createAttachment('header.png');
$footerLogo = $this->createAttachment('footer.png');
$this->tenant = Tenant::query()->create([
'codigo' => 'acme',
'nombre' => 'Acme',
'dominio' => 'acme.test',
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
'primary_color' => '#111111',
'secondary_color' => '#222222',
'danger_color' => '#cc0000',

View File

@@ -10,7 +10,8 @@ use App\Domains\Catalog\Enums\ProductLayout;
use App\Domains\Catalog\Models\Category;
use App\Domains\Catalog\Models\FeaturedGroup;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Tenant\Models\StorefrontWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
@@ -25,14 +26,15 @@ class OnTicketFeaturedGroupControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create([
StorefrontWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
WebsiteType::query()->create([
StorefrontWebsiteType::query()->create([
'codigo' => 'shopit',
'nombre' => 'Shopit',
]);
AdminWebsiteType::query()->create(['codigo' => 'shopit', 'nombre' => 'Shopit Admin']);
}
public function test_authentication_is_required(): void
@@ -230,7 +232,8 @@ class OnTicketFeaturedGroupControllerTest extends TestCase
'codigo' => $code,
'nombre' => ucfirst($code),
'dominio' => "{$code}.test",
'website_type_code' => $websiteType,
'admin_website_type_code' => 'shopit',
'storefront_website_type_code' => $websiteType,
]);
}

View File

@@ -16,7 +16,7 @@ use App\Domains\Catalog\Models\Variant;
use App\Domains\Menu\Models\Menu;
use App\Domains\Shared\Enums\FieldType;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
@@ -33,7 +33,7 @@ class EntryControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -183,7 +183,7 @@ class EntryControllerTest extends TestCase
'codigo' => $tenantCode,
'nombre' => 'Desfile',
'dominio' => "{$tenantCode}.test",
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
$menu = Menu::query()->firstOrCreate(
['code' => 'adminapp.desfile.entradas'],

View File

@@ -16,7 +16,7 @@ use App\Domains\Event\Events\EventDateRescheduled;
use App\Domains\Event\Events\EventDateSuspended;
use App\Domains\Purchase\Services\Checkout\CatalogSelectionResolver;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Ticket\Enums\ValidityTimeType;
use App\Domains\Ticket\Models\Ticket;
use Database\Seeders\AuthorizationSeeder;
@@ -38,7 +38,7 @@ class AdminAppEventControllerTest extends TestCase
parent::setUp();
$this->seed([AuthorizationSeeder::class, SocialMediaSeeder::class]);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -761,7 +761,7 @@ class AdminAppEventControllerTest extends TestCase
'codigo' => $code,
'nombre' => ucfirst($code),
'dominio' => "{$code}.test",
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
'primary_color' => '#000000',
'secondary_color' => '#000000',
'danger_color' => '#000000',

View File

@@ -12,7 +12,7 @@ use App\Domains\Catalog\Models\Variant;
use App\Domains\Menu\Models\Menu;
use App\Domains\Shared\Enums\FieldType;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
@@ -27,7 +27,7 @@ class AccommodationControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -222,7 +222,7 @@ class AccommodationControllerTest extends TestCase
'footer_bg_color' => '#111111',
'header_logo_id' => $headerLogo->id,
'footer_logo_id' => $footerLogo->id,
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
$attribute = Attribute::query()->create([
'tenant_codigo' => $tenant->codigo,

View File

@@ -12,7 +12,7 @@ use App\Domains\Catalog\Models\Variant;
use App\Domains\Menu\Models\Menu;
use App\Domains\Shared\Enums\FieldType;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
@@ -27,7 +27,7 @@ class EntryControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -420,7 +420,7 @@ class EntryControllerTest extends TestCase
'codigo' => $code,
'nombre' => ucfirst($code),
'dominio' => "{$code}.test",
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
}

View File

@@ -13,7 +13,7 @@ use App\Domains\Event\Services\EventService;
use App\Domains\Menu\Models\Menu;
use App\Domains\Shared\Enums\FieldType;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
@@ -29,7 +29,7 @@ class FoodControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -323,7 +323,7 @@ class FoodControllerTest extends TestCase
'codigo' => 'fiesta_futbol_infantil',
'nombre' => 'Fiesta Fútbol Infantil',
'dominio' => 'fiesta.test',
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
$eventDateAttribute = Attribute::query()->create([
'tenant_codigo' => $tenant->codigo,

View File

@@ -11,7 +11,7 @@ use App\Domains\Catalog\Models\Variant;
use App\Domains\Menu\Models\Menu;
use App\Domains\Shared\Enums\FieldType;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
@@ -26,7 +26,7 @@ class MerchandiseControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -262,7 +262,7 @@ class MerchandiseControllerTest extends TestCase
'footer_bg_color' => '#111111',
'header_logo_id' => $headerLogo->id,
'footer_logo_id' => $footerLogo->id,
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
$colorAttribute = Attribute::query()->create([
'tenant_codigo' => $tenant->codigo,

View File

@@ -6,7 +6,7 @@ use App\Domains\Auth\Models\User;
use App\Domains\Authorization\Enums\RoleCode;
use App\Domains\Event\Models\EventDate;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
@@ -21,7 +21,7 @@ class AdminAppEntryFormControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
AdminWebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
}
public function test_authentication_is_required(): void
@@ -62,7 +62,7 @@ class AdminAppEntryFormControllerTest extends TestCase
'codigo' => $code,
'nombre' => ucfirst($code),
'dominio' => "{$code}.test",
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
}

View File

@@ -5,7 +5,7 @@ namespace Tests\Feature\Forms;
use App\Domains\Auth\Models\User;
use App\Domains\Authorization\Enums\RoleCode;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Database\Seeders\SocialMediaSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
@@ -21,7 +21,7 @@ class AdminAppEventFormControllerTest extends TestCase
parent::setUp();
$this->seed([AuthorizationSeeder::class, SocialMediaSeeder::class]);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -38,7 +38,7 @@ class AdminAppEventFormControllerTest extends TestCase
'codigo' => 'acme',
'nombre' => 'Acme',
'dominio' => 'acme.test',
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
$tenant->socialMedia()->attach('instagram', [
'url' => 'https://instagram.com/acme',

View File

@@ -7,7 +7,7 @@ use App\Domains\Authorization\Enums\RoleCode;
use App\Domains\Catalog\Models\Attribute;
use App\Domains\Shared\Enums\FieldType;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
@@ -21,7 +21,7 @@ class AdminAppFoodFormControllerTest extends TestCase
{
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
AdminWebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
}
public function test_authentication_is_required(): void
@@ -36,7 +36,7 @@ class AdminAppFoodFormControllerTest extends TestCase
'codigo' => 'fiesta',
'nombre' => 'Fiesta',
'dominio' => 'fiesta.test',
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
$eventDate = $tenant->eventDates()->create([
'date' => '2026-10-09',
@@ -73,7 +73,7 @@ class AdminAppFoodFormControllerTest extends TestCase
'codigo' => 'fiesta',
'nombre' => 'Fiesta',
'dominio' => 'fiesta.test',
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
$available = $tenant->eventDates()->create([
'date' => '2026-10-09',

View File

@@ -7,7 +7,7 @@ use App\Domains\Authorization\Enums\RoleCode;
use App\Domains\Catalog\Models\Attribute;
use App\Domains\Shared\Enums\FieldType;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
@@ -22,7 +22,7 @@ class AdminAppMerchandiseFormControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -83,7 +83,7 @@ class AdminAppMerchandiseFormControllerTest extends TestCase
'codigo' => $code,
'nombre' => ucfirst($code),
'dominio' => "{$code}.test",
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
}

View File

@@ -8,7 +8,7 @@ use App\Domains\Auth\Models\User;
use App\Domains\Authorization\Enums\RoleCode;
use App\Domains\Purchase\Models\Purchase;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
@@ -23,7 +23,7 @@ class AdminAppSaleFormControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -81,7 +81,7 @@ class AdminAppSaleFormControllerTest extends TestCase
'footer_bg_color' => '#000000',
'header_logo_id' => $headerLogo->id,
'footer_logo_id' => $footerLogo->id,
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
}

View File

@@ -6,7 +6,7 @@ use App\Domains\Auth\Models\User;
use App\Domains\Authorization\Enums\RoleCode;
use App\Domains\Catalog\Models\Category;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
@@ -21,7 +21,7 @@ class AdminAppStaffFormControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
]);
@@ -78,7 +78,7 @@ class AdminAppStaffFormControllerTest extends TestCase
'codigo' => $code,
'nombre' => ucfirst($code),
'dominio' => "{$code}.test",
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
}
}

View File

@@ -14,7 +14,8 @@ use App\Domains\Integration\Services\IntegrationAssociationService;
use App\Domains\Integration\Services\IntegrationInstanceService;
use App\Domains\Integration\Services\TelepagosIntegrationService;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Tenant\Models\StorefrontWebsiteType;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
@@ -40,19 +41,19 @@ class IntegrationInstanceTest extends TestCase
public function test_management_requires_an_authenticated_global_admin(): void
{
Client::create(['code' => 'acme', 'name' => 'Acme']);
WebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
AdminWebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
$this->getJson('/api/clients/acme/integrations')->assertUnauthorized();
Sanctum::actingAs(User::factory()->create());
$this->getJson('/api/clients/acme/integrations')->assertForbidden();
$this->getJson('/api/website-types/demo/integrations')->assertForbidden();
$this->getJson('/api/admin-website-types/demo/integrations')->assertForbidden();
}
public function test_only_owner_endpoints_can_manage_configuration(): void
{
$this->admin();
$client = Client::create(['code' => 'acme', 'name' => 'Acme']);
$type = WebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
$type = AdminWebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
$this->getJson('/api/integrations')->assertNotFound();
$this->getJson('/api/integration-instances')->assertNotFound();
@@ -60,7 +61,7 @@ class IntegrationInstanceTest extends TestCase
$this->putJson('/api/clients/acme/integrations/test', ['integration_data' => []])
->assertUnprocessable()->assertJsonValidationErrors('integration_data.api_key');
$this->putJson('/api/website-types/demo/integrations/test', ['integration_data' => []])
$this->putJson('/api/admin-website-types/demo/integrations/test', ['integration_data' => []])
->assertUnprocessable()->assertJsonValidationErrors('integration_data.api_key');
$this->putJson('/api/clients/acme/integrations/test', [
@@ -69,22 +70,22 @@ class IntegrationInstanceTest extends TestCase
$clientInstanceId = $client->integrations()->firstOrFail()->integration_instance_id;
self::assertSame('client-secret', IntegrationInstance::findOrFail($clientInstanceId)->integration_data['api_key']);
$this->putJson('/api/website-types/demo/integrations/test', [
$this->putJson('/api/admin-website-types/demo/integrations/test', [
'integration_data' => ['api_key' => 'type-secret'],
])->assertCreated()
->assertJsonPath('data.integration_instance.name', 'Test / Demo')
->assertJsonMissingPath('data.integration_instance.integration_data');
$typeInstanceId = $type->integrations()->firstOrFail()->integration_instance_id;
$this->getJson('/api/website-types/demo/integrations/test')
$this->getJson('/api/admin-website-types/demo/integrations/test')
->assertOk()->assertJsonPath('data.integration_instance_id', $typeInstanceId);
$this->deleteJson('/api/clients/acme/integrations/test')->assertNoContent();
$this->deleteJson('/api/website-types/demo/integrations/test')->assertNoContent();
$this->deleteJson('/api/admin-website-types/demo/integrations/test')->assertNoContent();
}
public function test_tenant_prefers_client_then_type_and_client_context_does_not_inherit(): void
{
$type = WebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
$type = AdminWebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
$tenant = $this->tenantForType($type);
$associations = new IntegrationAssociationService;
$associations->associate($type, 'test', $this->makeInstance('type'));
@@ -105,8 +106,10 @@ class IntegrationInstanceTest extends TestCase
public function test_required_configuration_can_come_from_the_website_type(): void
{
$this->integration->update(['requires_configuration' => true]);
$type = WebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
$type = AdminWebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
$tenant = $this->tenantForType($type);
$storefront = StorefrontWebsiteType::create(['codigo' => 'different-storefront', 'nombre' => 'Storefront']);
$tenant->update(['storefront_website_type_code' => $storefront->codigo]);
(new IntegrationAssociationService)->associate($type, 'test', $this->makeInstance('type'));
self::assertSame('type', $this->probe()->forTenant($tenant->codigo)->setting());
}
@@ -142,7 +145,7 @@ class IntegrationInstanceTest extends TestCase
public function test_an_instance_is_deleted_only_after_its_last_association_is_removed(): void
{
$client = Client::create(['code' => 'acme', 'name' => 'Acme']);
$type = WebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
$type = AdminWebsiteType::create(['codigo' => 'demo', 'nombre' => 'Demo']);
$shared = $this->makeInstance('shared');
$associations = new IntegrationAssociationService;
@@ -180,7 +183,7 @@ class IntegrationInstanceTest extends TestCase
Http::assertSentCount(2);
}
private function tenantForType(WebsiteType $type): Tenant
private function tenantForType(AdminWebsiteType $type): Tenant
{
$logo = Attachment::create([
'path' => 'tenants/logo.png', 'filename' => 'logo.png',
@@ -190,7 +193,7 @@ class IntegrationInstanceTest extends TestCase
return Tenant::create([
'codigo' => 'acme', 'nombre' => 'Acme', 'dominio' => 'acme.test',
'website_type_code' => $type->codigo,
'admin_website_type_code' => $type->codigo,
'primary_color' => '#112233', 'secondary_color' => '#445566',
'danger_color' => '#ff0000', 'success_color' => '#00ff00',
'header_bg_color' => '#112233', 'footer_bg_color' => '#112233',

View File

@@ -10,7 +10,7 @@ use App\Domains\Integration\Services\ClientIntegrationService;
use App\Domains\Integration\Services\IntegrationAssociationService;
use App\Domains\Integration\Services\MailService;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailer;
@@ -127,8 +127,8 @@ class MailServiceTest extends TestCase
Mail::fake();
$tenant = $this->createTenant();
$this->createEmailIntegration();
$type = WebsiteType::create(['codigo' => 'mail-brand', 'nombre' => 'Mail Brand']);
$tenant->update(['website_type_code' => $type->codigo]);
$type = AdminWebsiteType::create(['codigo' => 'mail-brand', 'nombre' => 'Mail Brand']);
$tenant->update(['admin_website_type_code' => $type->codigo]);
$instance = IntegrationInstance::create([
'integration_code' => 'email', 'name' => 'Brand SMTP', 'integration_data' => $this->emailData(),
]);

View File

@@ -15,29 +15,9 @@ class SetWebsiteTypeFaviconTest extends TestCase
{
Storage::fake('s3');
DB::table('website_type')->insert([
[
'codigo' => 'shopit',
'nombre' => 'ShopIt',
'created_at' => now(),
'updated_at' => now(),
],
[
'codigo' => 'onticket',
'nombre' => 'OnTicket',
'created_at' => now(),
'updated_at' => now(),
],
]);
$this->seed(\Database\Seeders\WebsiteTypeSeeder::class);
$migration = require database_path(
'migrations/2026_08_26_000000_set_website_type_favicon.php'
);
$migration->up();
$migration->up();
$faviconIds = DB::table('website_type')
$faviconIds = DB::table('admin_website_types')
->whereIn('codigo', ['shopit', 'onticket'])
->pluck('favicon_id');

View File

@@ -0,0 +1,94 @@
<?php
namespace Tests\Feature\Migrations;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
class SplitWebsiteTypesMigrationTest extends TestCase
{
public function test_it_preserves_existing_associations_and_browser_branding(): void
{
Schema::create('website_type', function (Blueprint $table): void {
$table->id();
$table->string('codigo')->unique();
$table->string('nombre');
$table->string('site_title')->nullable();
$table->unsignedBigInteger('favicon_id')->nullable();
$table->timestamps();
});
Schema::create('tenants', function (Blueprint $table): void {
$table->id();
$table->string('website_type_code')->nullable();
$table->string('site_title')->nullable();
$table->unsignedBigInteger('favicon_id')->nullable();
$table->timestamps();
$table->foreign('website_type_code')->references('codigo')->on('website_type')->nullOnDelete();
});
Schema::create('website_type_extras', function (Blueprint $table): void {
$table->id();
$table->string('website_type_code');
$table->string('codigo')->nullable();
$table->string('nombre');
$table->text('descripcion');
$table->boolean('is_required')->default(false);
$table->json('config_schema');
$table->timestamps();
$table->foreign('website_type_code')->references('codigo')->on('website_type')->cascadeOnDelete();
});
Schema::create('websites_extras', function (Blueprint $table): void {
$table->id();
$table->string('website_code');
$table->foreignId('website_type_extra_id')->constrained('website_type_extras')->cascadeOnDelete();
$table->json('config');
$table->timestamps();
});
Schema::create('website_type_integrations', function (Blueprint $table): void {
$table->id();
$table->string('website_type_code');
$table->string('integration_code');
$table->unsignedBigInteger('integration_instance_id');
$table->timestamps();
$table->foreign('website_type_code')->references('codigo')->on('website_type')->cascadeOnDelete();
});
DB::table('website_type')->insert(['id' => 10, 'codigo' => 'onticket', 'nombre' => 'OnTicket', 'site_title' => 'Old title', 'favicon_id' => 42]);
DB::table('tenants')->insert([
['id' => 1, 'website_type_code' => 'onticket', 'site_title' => null, 'favicon_id' => null],
['id' => 2, 'website_type_code' => null, 'site_title' => null, 'favicon_id' => null],
['id' => 3, 'website_type_code' => 'onticket', 'site_title' => 'Custom title', 'favicon_id' => 99],
]);
DB::table('website_type_extras')->insert(['id' => 20, 'website_type_code' => 'onticket', 'codigo' => 'heroConfig', 'nombre' => 'Hero', 'descripcion' => 'Hero', 'config_schema' => '{}']);
DB::table('websites_extras')->insert(['id' => 30, 'website_code' => 'test', 'website_type_extra_id' => 20, 'config' => '{}']);
DB::table('website_type_integrations')->insert(['id' => 40, 'website_type_code' => 'onticket', 'integration_code' => 'email', 'integration_instance_id' => 50]);
$migration = require database_path('migrations/2026_09_17_000000_split_website_types.php');
$migration->up();
$this->assertDatabaseHas('tenants', ['id' => 1, 'admin_website_type_code' => 'onticket', 'storefront_website_type_code' => 'onticket', 'site_title' => 'Old title', 'favicon_id' => 42]);
$this->assertDatabaseHas('tenants', ['id' => 2, 'admin_website_type_code' => null, 'storefront_website_type_code' => null]);
$this->assertDatabaseHas('tenants', ['id' => 3, 'site_title' => 'Custom title', 'favicon_id' => 99]);
$this->assertDatabaseHas('storefront_website_type_extras', ['id' => 20, 'storefront_website_type_code' => 'onticket']);
$this->assertDatabaseHas('websites_extras', ['id' => 30, 'website_type_extra_id' => 20]);
$this->assertDatabaseHas('admin_website_type_integrations', ['id' => 40, 'admin_website_type_code' => 'onticket']);
DB::table('storefront_website_types')->insert(['codigo' => 'new-store', 'nombre' => 'New Store']);
DB::table('storefront_website_type_extras')->insert([
'storefront_website_type_code' => 'new-store',
'codigo' => 'banner',
'nombre' => 'Banner',
'descripcion' => 'Banner',
'config_schema' => '{}',
]);
$this->assertDatabaseHas('storefront_website_type_extras', ['storefront_website_type_code' => 'new-store', 'codigo' => 'banner']);
DB::table('storefront_website_types')->where('codigo', 'onticket')->delete();
$this->assertDatabaseMissing('storefront_website_type_extras', ['id' => 20]);
$this->assertDatabaseMissing('websites_extras', ['id' => 30]);
$this->assertDatabaseHas('tenants', ['id' => 1, 'admin_website_type_code' => 'onticket', 'storefront_website_type_code' => null]);
$this->assertDatabaseHas('admin_website_type_integrations', ['id' => 40, 'admin_website_type_code' => 'onticket']);
}
}

View File

@@ -12,7 +12,7 @@ use App\Domains\Notification\Events\PasswordResetRequested;
use App\Domains\Notification\Services\NotificationMailService;
use App\Domains\Purchase\Models\Purchase;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Ticket\Models\Ticket;
use Barryvdh\DomPDF\ServiceProvider as DomPdfServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
@@ -74,7 +74,7 @@ class NotificationMailServiceTest extends TestCase
public function test_it_sends_a_branded_welcome_email(): void
{
$this->useWebsiteTypeBranding();
$this->useAdminWebsiteTypeBranding();
app(NotificationMailService::class)->sendWelcome($this->user->id, $this->tenant->codigo);
app(NotificationMailService::class)->sendWelcome($this->user->id, $this->tenant->codigo);
@@ -83,18 +83,17 @@ class NotificationMailServiceTest extends TestCase
Mail::assertSent(Mailable::class, function (Mailable $mail): bool {
$mail->assertTo('ada@example.com');
$mail->assertHasSubject('Bienvenido a OnTicket');
$mail->assertHasSubject('Bienvenido a Mail Tenant');
return str_contains($mail->render(), 'Ada Lovelace')
&& str_contains($mail->render(), 'OnTicket')
&& ! str_contains($mail->render(), 'Mail Tenant')
&& str_contains($mail->render(), 'border-top: 4px solid #ff7006');
&& str_contains($mail->render(), 'Mail Tenant')
&& str_contains($mail->render(), 'border-top: 4px solid #112233');
});
}
public function test_it_sends_a_branded_password_reset_email(): void
{
$this->useWebsiteTypeBranding();
$this->useAdminWebsiteTypeBranding();
$attempt = $this->user->resetPasswordAttempts()->create([
'codigo' => '0123',
]);
@@ -112,15 +111,13 @@ class NotificationMailServiceTest extends TestCase
Mail::assertSent(Mailable::class, function (Mailable $mail): bool {
$mail->assertTo('ada@example.com');
$mail->assertHasSubject('Código para recuperar tu contraseña - OnTicket');
$mail->assertHasSubject('Código para recuperar tu contraseña - Mail Tenant');
$rendered = $mail->render();
return str_contains($rendered, '0123')
&& str_contains($rendered, 'Ada Lovelace')
&& str_contains($rendered, 'OnTicket')
&& ! str_contains($rendered, 'Mail Tenant')
&& str_contains($rendered, '#ff7006')
&& ! str_contains($rendered, 'border: 2px solid #112233');
&& str_contains($rendered, 'Mail Tenant')
&& str_contains($rendered, '#112233');
});
}
@@ -147,13 +144,13 @@ class NotificationMailServiceTest extends TestCase
public function test_it_links_scanner_password_resets_to_the_scanner_domain(): void
{
$websiteType = WebsiteType::query()->create([
$websiteType = AdminWebsiteType::query()->create([
'codigo' => 'scanner-mail',
'nombre' => 'Scanner Mail',
'dominio' => 'admin.mail.local',
'scanner_domain' => 'scanner.mail.local',
]);
$this->tenant->update(['website_type_code' => $websiteType->codigo]);
$this->tenant->update(['admin_website_type_code' => $websiteType->codigo]);
$attempt = $this->user->resetPasswordAttempts()->create([
'codigo' => '0123',
'reason' => ResetPasswordAttempt::REASON_STAFF_CREATED,
@@ -181,11 +178,11 @@ class NotificationMailServiceTest extends TestCase
public function test_administrator_creation_has_custom_copy_and_the_existing_code_and_link(): void
{
$websiteType = WebsiteType::query()->create([
$websiteType = AdminWebsiteType::query()->create([
'codigo' => 'admin-mail', 'nombre' => 'Admin Mail',
'dominio' => 'admin.mail.local', 'scanner_domain' => 'scanner.mail.local',
]);
$this->tenant->update(['website_type_code' => $websiteType->codigo]);
$this->tenant->update(['admin_website_type_code' => $websiteType->codigo]);
$attempt = $this->user->resetPasswordAttempts()->create([
'codigo' => '0456', 'reason' => ResetPasswordAttempt::REASON_ADMINISTRATOR_CREATED,
]);
@@ -226,7 +223,7 @@ class NotificationMailServiceTest extends TestCase
public function test_it_sends_one_purchase_confirmation_with_generated_tickets_attached(): void
{
$this->useWebsiteTypeBranding();
$this->useAdminWebsiteTypeBranding();
$purchase = Purchase::query()->create([
'tenant_codigo' => $this->tenant->codigo,
'user_id' => $this->user->id,
@@ -443,9 +440,9 @@ class NotificationMailServiceTest extends TestCase
]);
}
private function useWebsiteTypeBranding(): void
private function useAdminWebsiteTypeBranding(): void
{
$websiteType = WebsiteType::query()->create([
$websiteType = AdminWebsiteType::query()->create([
'codigo' => 'onticket',
'nombre' => 'OnTicket',
'dominio' => 'onticket.local',
@@ -456,7 +453,7 @@ class NotificationMailServiceTest extends TestCase
'login_header_footer_color' => '#838383',
]);
$this->tenant->update(['website_type_code' => $websiteType->codigo]);
$this->tenant->unsetRelation('websiteType');
$this->tenant->update(['admin_website_type_code' => $websiteType->codigo]);
$this->tenant->unsetRelation('adminWebsiteType');
}
}

View File

@@ -18,7 +18,7 @@ use App\Domains\Purchase\Models\Purchase;
use App\Domains\Purchase\Models\PurchaseItem;
use App\Domains\Purchase\Services\CheckoutService;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Ticket\Models\Ticket;
use App\Domains\Ticket\Models\TicketRefund;
use Database\Seeders\AuthorizationSeeder;
@@ -36,7 +36,7 @@ class AdminAppSaleControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
AdminWebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
}
public function test_sale_modifications_use_sale_filters_and_resulting_status(): void
@@ -757,7 +757,7 @@ class AdminAppSaleControllerTest extends TestCase
'footer_bg_color' => '#000000',
'header_logo_id' => $headerLogo->id,
'footer_logo_id' => $footerLogo->id,
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
}

View File

@@ -32,7 +32,7 @@ class DesfilePuraTendenciaSeederTest extends TestCase
'codigo' => 'desfile_pura_tendencia',
'nombre' => 'Desfile Pura Tendencia',
'dominio' => 'desfile-pura-tendencia.localhost',
'website_type_code' => 'onticket',
'storefront_website_type_code' => 'onticket',
'event_title' => 'Desfile Pura Tendencia',
'event_location' => 'Salón Centro Recreativo Luz y Fuerza',
'event_date_text' => '16 de Octubre 2026',
@@ -82,13 +82,13 @@ class DesfilePuraTendenciaSeederTest extends TestCase
$hero = DB::table('websites_extras')
->join(
'website_type_extras',
'website_type_extras.id',
'storefront_website_type_extras',
'storefront_website_type_extras.id',
'=',
'websites_extras.website_type_extra_id',
)
->where('websites_extras.website_code', 'desfile_pura_tendencia')
->where('website_type_extras.codigo', 'heroConfig')
->where('storefront_website_type_extras.codigo', 'heroConfig')
->value('websites_extras.config');
$hero = json_decode($hero, true, flags: JSON_THROW_ON_ERROR);

View File

@@ -3,7 +3,7 @@
namespace Tests\Feature\Seeders;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Database\Seeders\SocialMediaSeeder;
use Database\Seeders\TenantSeeder;
use Database\Seeders\WebsiteTypeSeeder;
@@ -25,11 +25,12 @@ class TenantSeederTest extends TestCase
TenantSeeder::class,
]);
$websiteType = WebsiteType::query()->where('codigo', 'onticket')->sole();
$websiteType = AdminWebsiteType::query()->where('codigo', 'onticket')->sole();
$tenant = Tenant::query()->where('codigo', 'onticket')->sole();
$this->assertSame('onticket', $tenant->client->code);
$this->assertSame($websiteType->codigo, $tenant->website_type_code);
$this->assertSame($websiteType->codigo, $tenant->admin_website_type_code);
$this->assertSame($websiteType->codigo, $tenant->storefront_website_type_code);
$this->assertSame($websiteType->nombre, $tenant->nombre);
$this->assertSame($websiteType->dominio, $tenant->dominio);
$this->assertSame($websiteType->site_title, $tenant->site_title);
@@ -94,7 +95,8 @@ class TenantSeederTest extends TestCase
->with('websiteExtras.websiteTypeExtra')
->sole();
$this->assertSame('shopit', $sonder->website_type_code);
$this->assertSame('shopit', $sonder->storefront_website_type_code);
$this->assertSame('shopit', $sonder->admin_website_type_code);
$this->assertSame('quantity_and_remove', $sonder->cart_editing_policy->value);
$this->assertSame('disabled', $sonder->checkout_editing_policy->value);
@@ -116,7 +118,8 @@ class TenantSeederTest extends TestCase
->with('websiteExtras.websiteTypeExtra')
->sole();
$this->assertSame('onticket', $fiesta->website_type_code);
$this->assertSame('onticket', $fiesta->storefront_website_type_code);
$this->assertSame('onticket', $fiesta->admin_website_type_code);
$this->assertSame('full', $fiesta->cart_editing_policy->value);
$this->assertSame('disabled', $fiesta->checkout_editing_policy->value);

View File

@@ -3,7 +3,8 @@
namespace Tests\Feature\Seeders;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Tenant\Models\StorefrontWebsiteType;
use Database\Seeders\WebsiteTypeSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
@@ -20,7 +21,8 @@ class WebsiteTypeSeederTest extends TestCase
$this->seed(WebsiteTypeSeeder::class);
$this->seed(WebsiteTypeSeeder::class);
$this->assertSame(2, WebsiteType::query()->count());
$this->assertSame(2, AdminWebsiteType::query()->count());
$this->assertSame(2, StorefrontWebsiteType::query()->count());
$this->assertSame(5, Attachment::query()->count());
$expectedPresentation = [
@@ -36,9 +38,8 @@ class WebsiteTypeSeederTest extends TestCase
'border_color' => '#EAEAEA',
];
$shopIt = WebsiteType::query()
$shopIt = AdminWebsiteType::query()
->where('codigo', 'shopit')
->with('extras')
->sole();
$this->assertSame('ShopIt', $shopIt->nombre);
@@ -51,8 +52,9 @@ class WebsiteTypeSeederTest extends TestCase
Storage::disk('s3')->assertExists($shopIt->footerLogo->path);
$this->assertSame('onticket_favicon.svg', $shopIt->favicon->filename);
Storage::disk('s3')->assertExists($shopIt->favicon->path);
$this->assertSame(['carousel'], $shopIt->extras->pluck('codigo')->all());
$this->assertSame('Carrusel principal', $shopIt->extras->sole()->nombre);
$shopItStorefront = StorefrontWebsiteType::query()->where('codigo', 'shopit')->with('extras')->sole();
$this->assertSame(['carousel'], $shopItStorefront->extras->pluck('codigo')->all());
$this->assertSame('Carrusel principal', $shopItStorefront->extras->sole()->nombre);
$this->assertSame([
'request_rules' => [
'$' => 'required|array|max:10',
@@ -64,11 +66,10 @@ class WebsiteTypeSeederTest extends TestCase
'attachment_type' => 'image',
],
],
], $shopIt->extras->sole()->config_schema);
], $shopItStorefront->extras->sole()->config_schema);
$onTicket = WebsiteType::query()
$onTicket = AdminWebsiteType::query()
->where('codigo', 'onticket')
->with('extras')
->sole();
$this->assertSame('OnTicket', $onTicket->nombre);
@@ -83,12 +84,13 @@ class WebsiteTypeSeederTest extends TestCase
$this->assertNotSame($shopIt->footer_logo, $onTicket->footer_logo);
$this->assertSame($shopIt->favicon_id, $onTicket->favicon_id);
$this->assertSame('onticket_favicon.svg', $onTicket->favicon->filename);
$onTicketStorefront = StorefrontWebsiteType::query()->where('codigo', 'onticket')->with('extras')->sole();
$this->assertEqualsCanonicalizing(
['heroConfig', 'eventConfig', 'additionalInfoConfig'],
$onTicket->extras->pluck('codigo')->all(),
$onTicketStorefront->extras->pluck('codigo')->all(),
);
$heroSchema = $onTicket->extras->firstWhere('codigo', 'heroConfig')->config_schema;
$heroSchema = $onTicketStorefront->extras->firstWhere('codigo', 'heroConfig')->config_schema;
$this->assertSame([
'request_rules' => [
'$' => 'required|array',
@@ -106,7 +108,7 @@ class WebsiteTypeSeederTest extends TestCase
],
], $heroSchema);
$eventSchema = $onTicket->extras->firstWhere('codigo', 'eventConfig')->config_schema;
$eventSchema = $onTicketStorefront->extras->firstWhere('codigo', 'eventConfig')->config_schema;
$this->assertSame([
'request_rules' => [
'$' => 'required|array',
@@ -126,7 +128,7 @@ class WebsiteTypeSeederTest extends TestCase
'transforms' => [],
], $eventSchema);
$additionalInfoSchema = $onTicket->extras
$additionalInfoSchema = $onTicketStorefront->extras
->firstWhere('codigo', 'additionalInfoConfig')
->config_schema;
$this->assertSame([

View File

@@ -11,7 +11,7 @@ use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\Category;
use App\Domains\Notification\Events\PasswordResetRequested;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Ticket\Enums\ScanAttemptResult;
use App\Domains\Ticket\Models\ScanAttempt;
use App\Domains\Ticket\Models\Ticket;
@@ -36,14 +36,14 @@ class StaffControllerTest extends TestCase
Event::fake([PasswordResetRequested::class]);
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
AdminWebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
$headerLogo = $this->createAttachment('header.png');
$footerLogo = $this->createAttachment('footer.png');
$this->tenant = Tenant::query()->create([
'codigo' => 'acme',
'nombre' => 'Acme',
'dominio' => 'acme.test',
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
'primary_color' => '#111111',
'secondary_color' => '#222222',
'danger_color' => '#cc0000',
@@ -179,7 +179,7 @@ class StaffControllerTest extends TestCase
'codigo' => 'other',
'nombre' => 'Other',
'dominio' => 'other.test',
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
'primary_color' => '#111111',
'secondary_color' => '#222222',
'danger_color' => '#cc0000',

View File

@@ -7,7 +7,7 @@ use App\Domains\Attachable\Models\AttachmentCrop;
use App\Domains\Auth\Models\User;
use App\Domains\Authorization\Enums\RoleCode;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\StorefrontWebsiteType;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
@@ -19,7 +19,7 @@ class AdminAppWebsiteExtraControllerTest extends TestCase
{
use RefreshDatabase;
private WebsiteType $websiteType;
private StorefrontWebsiteType $websiteType;
protected function setUp(): void
{
@@ -27,7 +27,7 @@ class AdminAppWebsiteExtraControllerTest extends TestCase
$this->seed(AuthorizationSeeder::class);
$this->websiteType = WebsiteType::query()->create([
$this->websiteType = StorefrontWebsiteType::query()->create([
'codigo' => 'test-store',
'nombre' => 'Test Store',
]);
@@ -79,7 +79,7 @@ class AdminAppWebsiteExtraControllerTest extends TestCase
$this->getJson('/api/v1/adminapp/tenant/website-extras')
->assertOk()
->assertJsonPath('data.website_type.codigo', 'test-store')
->assertJsonPath('data.storefront_website_type.codigo', 'test-store')
->assertJsonPath('data.definitions.contactConfig.codigo', 'contactConfig')
->assertJsonPath('data.definitions.contactConfig.nombre', 'Configuración de contacto')
->assertJsonPath('data.definitions.contactConfig.is_required', false)
@@ -407,7 +407,7 @@ class AdminAppWebsiteExtraControllerTest extends TestCase
'codigo' => $code,
'nombre' => ucfirst($code),
'dominio' => "{$code}.test",
'website_type_code' => $this->websiteType->codigo,
'storefront_website_type_code' => $this->websiteType->codigo,
]);
}

View File

@@ -2,13 +2,13 @@
namespace Tests\Feature\Tenant;
use App\Domains\Tenant\Services\WebsiteTypeService;
use App\Domains\Tenant\Services\AdminWebsiteTypeService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class WebsiteTypeServiceTest extends TestCase
class AdminWebsiteTypeServiceTest extends TestCase
{
use RefreshDatabase;
@@ -16,7 +16,7 @@ class WebsiteTypeServiceTest extends TestCase
{
Storage::fake('s3');
$websiteType = app(WebsiteTypeService::class)->create([
$websiteType = app(AdminWebsiteTypeService::class)->create([
'codigo' => 'marketplace',
'nombre' => 'Marketplace',
'dominio' => 'marketplace.test',
@@ -46,13 +46,13 @@ class WebsiteTypeServiceTest extends TestCase
$this->assertSame($siteLogo->id, $websiteType->site_logo);
$this->assertSame($footerLogo->id, $websiteType->footer_logo);
$this->assertSame($favicon->id, $websiteType->favicon_id);
$this->assertStringStartsWith('website-types/', $siteLogo->path);
$this->assertStringStartsWith('website-types/', $footerLogo->path);
$this->assertStringStartsWith('website-types/', $favicon->path);
$this->assertStringStartsWith('admin-website-types/', $siteLogo->path);
$this->assertStringStartsWith('admin-website-types/', $footerLogo->path);
$this->assertStringStartsWith('admin-website-types/', $favicon->path);
Storage::disk('s3')->assertExists($siteLogo->path);
Storage::disk('s3')->assertExists($footerLogo->path);
Storage::disk('s3')->assertExists($favicon->path);
$this->assertDatabaseHas('website_type', [
$this->assertDatabaseHas('admin_website_types', [
'codigo' => 'marketplace',
'dominio' => 'marketplace.test',
'scanner_domain' => 'scanner.marketplace.test',
@@ -74,7 +74,7 @@ class WebsiteTypeServiceTest extends TestCase
{
Storage::fake('s3');
$service = app(WebsiteTypeService::class);
$service = app(AdminWebsiteTypeService::class);
$shopIt = $service->create([
'codigo' => 'shopit',
'nombre' => 'ShopIt',

View File

@@ -3,7 +3,7 @@
namespace Tests\Feature\Tenant;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
@@ -16,7 +16,7 @@ class BootstrapAdminAppControllerTest extends TestCase
$footerLogo = Attachment::factory()->create();
$favicon = Attachment::factory()->create();
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'shopit',
'nombre' => 'ShopIt',
'dominio' => 'admin.shopit.test',
@@ -38,7 +38,7 @@ class BootstrapAdminAppControllerTest extends TestCase
$this->getJson('/api/v1/adminapp/bootstrap/ADMIN.SHOPIT.TEST')
->assertOk()
->assertJsonPath('data.website_type_code', 'shopit')
->assertJsonPath('data.admin_website_type_code', 'shopit')
->assertJsonPath('data.site_title', 'ShopIt Website Type')
->assertJsonPath('data.primary_color', '#112233')
->assertJsonPath('data.warning_color', '#ffaa00')

View File

@@ -3,7 +3,7 @@
namespace Tests\Feature\Tenant;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
@@ -16,7 +16,7 @@ class BootstrapScannerControllerTest extends TestCase
$siteLogo = Attachment::factory()->create();
$favicon = Attachment::factory()->create();
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'shopit',
'nombre' => 'ShopIt',
'dominio' => 'admin.shopit.test',
@@ -39,7 +39,7 @@ class BootstrapScannerControllerTest extends TestCase
$this->getJson('/api/v1/scanner/bootstrap/SCANNER.SHOPIT.TEST')
->assertOk()
->assertJsonPath('data.website_type_code', 'shopit')
->assertJsonPath('data.admin_website_type_code', 'shopit')
->assertJsonPath('data.site_title', 'ShopIt Website Type')
->assertJsonPath('data.primary_color', '#112233')
->assertJsonPath('data.site_logo', $siteLogo->getTemporaryUrl(1440))
@@ -53,7 +53,7 @@ class BootstrapScannerControllerTest extends TestCase
public function test_it_does_not_match_the_admin_app_domain(): void
{
WebsiteType::query()->create([
AdminWebsiteType::query()->create([
'codigo' => 'shopit',
'nombre' => 'ShopIt',
'dominio' => 'admin.shopit.test',

View File

@@ -10,7 +10,8 @@ use App\Domains\Authorization\Models\Role;
use App\Domains\Catalog\Models\Category;
use App\Domains\Menu\Models\Menu;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Tenant\Models\StorefrontWebsiteType;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
@@ -217,50 +218,31 @@ class BootstrapTenantControllerTest extends TestCase
$this->getJson('/api/tenants/bootstrap/acme.com')->assertNotFound();
}
public function test_it_resolves_browser_branding_from_the_tenant_before_the_website_type(): void
public function test_storefront_branding_comes_from_tenant_even_with_a_different_admin_type(): void
{
$typeFavicon = Attachment::query()->create([
'key' => (string) Str::uuid(),
'path' => 'website-types/type-favicon.png',
'filename' => 'type-favicon.png',
'type' => AttachmentType::Image,
'mime_type' => 'image/png',
$admin = AdminWebsiteType::query()->create([
'codigo' => 'admin-brand',
'nombre' => 'Admin Brand',
'site_title' => 'Admin title',
]);
$tenantFavicon = Attachment::query()->create([
$favicon = Attachment::query()->create([
'key' => (string) Str::uuid(),
'path' => 'tenants/tenant-favicon.png',
'filename' => 'tenant-favicon.png',
'type' => AttachmentType::Image,
'mime_type' => 'image/png',
]);
$websiteType = WebsiteType::query()->create([
'codigo' => 'store',
'nombre' => 'Tienda',
'site_title' => 'Website type title',
'favicon_id' => $typeFavicon->id,
]);
$tenant = $this->createTenant([
'website_type_code' => $websiteType->codigo,
]);
$typeResponse = $this->getJson('/api/tenants/bootstrap?dominio=acme.com&path=%2F');
$typeResponse
->assertOk()
->assertJsonPath('data.site_title', 'Website type title');
$this->assertStringContainsString($typeFavicon->key, $typeResponse->json('data.favicon'));
$tenant->update([
$this->createTenant([
'admin_website_type_code' => $admin->codigo,
'site_title' => 'Tenant title',
'favicon_id' => $tenantFavicon->id,
'favicon_id' => $favicon->id,
]);
$tenantResponse = $this->getJson('/api/tenants/bootstrap?dominio=acme.com&path=%2F');
$tenantResponse
->assertOk()
->assertJsonPath('data.site_title', 'Tenant title');
$this->assertStringContainsString($tenantFavicon->key, $tenantResponse->json('data.favicon'));
$response = $this->getJson('/api/tenants/bootstrap?dominio=acme.com&path=%2F');
$response->assertOk()
->assertJsonPath('data.site_title', 'Tenant title')
->assertJsonPath('data.admin_website_type_code', 'admin-brand');
$this->assertStringContainsString($favicon->key, $response->json('data.favicon'));
}
public function test_it_uses_default_browser_branding_when_none_is_configured(): void
@@ -315,11 +297,11 @@ class BootstrapTenantControllerTest extends TestCase
public function test_it_returns_only_enabled_website_extras_in_the_bootstrap(): void
{
$tenant = $this->createTenant();
$websiteType = WebsiteType::query()->create([
$websiteType = StorefrontWebsiteType::query()->create([
'codigo' => 'store',
'nombre' => 'Tienda',
]);
$tenant->update(['website_type_code' => $websiteType->codigo]);
$tenant->update(['storefront_website_type_code' => $websiteType->codigo]);
$enabledExtra = $websiteType->extras()->create([
'codigo' => 'contact',
@@ -355,11 +337,11 @@ class BootstrapTenantControllerTest extends TestCase
{
Storage::fake('s3');
$tenant = $this->createTenant();
$websiteType = WebsiteType::query()->create([
$websiteType = StorefrontWebsiteType::query()->create([
'codigo' => 'event-store',
'nombre' => 'Eventos',
]);
$tenant->update(['website_type_code' => $websiteType->codigo]);
$tenant->update(['storefront_website_type_code' => $websiteType->codigo]);
$heroDefinition = $websiteType->extras()->create([
'codigo' => 'heroConfig',
'nombre' => 'Banner',

View File

@@ -25,7 +25,8 @@ class StoreTenantWithExtrasTest extends TestCase
public function test_it_creates_a_tenant_and_validates_and_stores_its_website_extras(): void
{
$response = $this->postJson('/api/tenants', array_merge($this->tenantData(), [
'website_type_code' => 'onticket',
'admin_website_type_code' => 'shopit',
'storefront_website_type_code' => 'onticket',
'extras' => [
'eventConfig' => [
'title' => 'Festival',
@@ -49,7 +50,8 @@ class StoreTenantWithExtrasTest extends TestCase
$response
->assertCreated()
->assertJsonPath('data.website_type_code', 'onticket')
->assertJsonPath('data.admin_website_type_code', 'shopit')
->assertJsonPath('data.storefront_website_type_code', 'onticket')
->assertJsonMissingPath('data.website_type')
->assertJsonPath('data.extras.eventConfig.title', 'Festival');
@@ -83,7 +85,7 @@ class StoreTenantWithExtrasTest extends TestCase
public function test_it_rejects_an_extra_not_supported_by_the_selected_website_type(): void
{
$this->postJson('/api/tenants', array_merge($this->tenantData(), [
'website_type_code' => 'shopit',
'storefront_website_type_code' => 'shopit',
'extras' => [
'eventConfig' => [
'title' => 'Not supported',
@@ -99,7 +101,7 @@ class StoreTenantWithExtrasTest extends TestCase
public function test_it_applies_the_extra_schema_rules(): void
{
$this->postJson('/api/tenants', array_merge($this->tenantData(), [
'website_type_code' => 'onticket',
'storefront_website_type_code' => 'onticket',
'extras' => [
'eventConfig' => [
'dates' => [[
@@ -121,7 +123,7 @@ class StoreTenantWithExtrasTest extends TestCase
$image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
$response = $this->postJson('/api/tenants', array_merge($this->tenantData(), [
'website_type_code' => 'shopit',
'storefront_website_type_code' => 'shopit',
'extras' => [
'carousel' => [$image],
],
@@ -162,7 +164,7 @@ class StoreTenantWithExtrasTest extends TestCase
$image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
$response = $this->postJson('/api/tenants', array_merge($this->tenantData(), [
'website_type_code' => 'onticket',
'storefront_website_type_code' => 'onticket',
'extras' => [
'heroConfig' => [
'title_html' => '<h1>Festival</h1>',

View File

@@ -5,7 +5,8 @@ namespace Tests\Feature\Tenant;
use App\Domains\Attachable\Enums\AttachmentType;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Tenant\Models\StorefrontWebsiteType;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;
@@ -16,32 +17,15 @@ class WebsiteExtrasTest extends TestCase
public function test_website_extra_tables_have_the_expected_columns(): void
{
$this->assertTrue(Schema::hasColumn('tenants', 'website_type_code'));
$this->assertTrue(Schema::hasColumn('tenants', 'storefront_website_type_code'));
$this->assertTrue(Schema::hasColumn('tenants', 'admin_website_type_code'));
$this->assertEqualsCanonicalizing(['id', 'codigo', 'nombre', 'created_at', 'updated_at'], Schema::getColumnListing('storefront_website_types'));
$this->assertTrue(Schema::hasColumn('admin_website_types', 'dominio'));
$this->assertEqualsCanonicalizing([
'id',
'codigo',
'nombre',
'dominio',
'primary_color',
'secondary_color',
'danger_color',
'success_color',
'warning_color',
'body_color',
'darker_body_color',
'surface_color',
'background_color',
'border_color',
'login_header_footer_color',
'site_logo',
'created_at',
'updated_at',
], Schema::getColumnListing('website_type'));
$this->assertEqualsCanonicalizing([
'id',
'website_type_code',
'storefront_website_type_code',
'codigo',
'nombre',
'descripcion',
@@ -49,7 +33,7 @@ class WebsiteExtrasTest extends TestCase
'config_schema',
'created_at',
'updated_at',
], Schema::getColumnListing('website_type_extras'));
], Schema::getColumnListing('storefront_website_type_extras'));
$this->assertEqualsCanonicalizing([
'id',
@@ -62,85 +46,45 @@ class WebsiteExtrasTest extends TestCase
], Schema::getColumnListing('websites_extras'));
}
public function test_models_map_the_diagram_relations_and_casts(): void
public function test_models_keep_admin_branding_and_storefront_extras_independent(): void
{
$siteLogo = Attachment::query()->create([
'key' => '92bb3986-fb22-4871-b98c-fc5663d78aa6',
'path' => 'website-types/site-logo.png',
'filename' => 'site-logo.png',
'type' => AttachmentType::Image,
'mime_type' => 'image/png',
$admin = AdminWebsiteType::query()->create([
'codigo' => 'admin-brand',
'nombre' => 'Admin Brand',
'dominio' => 'admin.test',
]);
$type = WebsiteType::query()->create([
$storefront = StorefrontWebsiteType::query()->create([
'codigo' => 'store',
'nombre' => 'Tienda',
'dominio' => 'store.test',
'primary_color' => '#111111',
'secondary_color' => '#222222',
'danger_color' => '#ff0000',
'success_color' => '#00aa55',
'warning_color' => '#ffaa00',
'body_color' => '#666666',
'darker_body_color' => '#333333',
'surface_color' => '#ffffff',
'background_color' => '#f8f8f8',
'border_color' => '#dddddd',
'login_header_footer_color' => '#333333',
'site_logo' => $siteLogo->id,
]);
$typeExtra = $type->extras()->create([
$definition = $storefront->extras()->create([
'codigo' => 'whatsapp',
'nombre' => 'WhatsApp',
'descripcion' => 'Configuracion del canal de WhatsApp',
'descripcion' => 'Canal de WhatsApp',
'is_required' => true,
'config_schema' => [
'type' => 'object',
'required' => ['phone'],
],
'config_schema' => ['type' => 'object'],
]);
$tenant = $this->createTenant();
$tenant->websiteType()->associate($type)->save();
$websiteExtra = $tenant->websiteExtras()->create([
'website_type_extra_id' => $typeExtra->id,
$tenant->adminWebsiteType()->associate($admin);
$tenant->storefrontWebsiteType()->associate($storefront);
$tenant->save();
$value = $tenant->websiteExtras()->create([
'website_type_extra_id' => $definition->id,
'config' => ['phone' => '+5491112345678'],
'is_enabled' => true,
]);
$this->assertTrue($type->extras()->firstOrFail()->is($typeExtra));
$this->assertSame('store.test', $type->dominio);
$this->assertSame('#111111', $type->primary_color);
$this->assertSame('#222222', $type->secondary_color);
$this->assertSame('#ff0000', $type->danger_color);
$this->assertSame('#00aa55', $type->success_color);
$this->assertSame('#ffaa00', $type->warning_color);
$this->assertSame('#666666', $type->body_color);
$this->assertSame('#333333', $type->darker_body_color);
$this->assertSame('#ffffff', $type->surface_color);
$this->assertSame('#f8f8f8', $type->background_color);
$this->assertSame('#dddddd', $type->border_color);
$this->assertSame('#333333', $type->login_header_footer_color);
$this->assertTrue($type->siteLogo()->firstOrFail()->is($siteLogo));
$this->assertSame($type->codigo, $typeExtra->website_type_code);
$this->assertSame('whatsapp', $typeExtra->codigo);
$this->assertTrue($type->tenants()->firstOrFail()->is($tenant));
$this->assertTrue($tenant->websiteType()->firstOrFail()->is($type));
$this->assertSame($type->codigo, $tenant->website_type_code);
$this->assertTrue($typeExtra->websiteType()->firstOrFail()->is($type));
$this->assertTrue($typeExtra->websiteExtras()->firstOrFail()->is($websiteExtra));
$this->assertTrue($websiteExtra->website()->firstOrFail()->is($tenant));
$this->assertTrue($websiteExtra->websiteTypeExtra()->firstOrFail()->is($typeExtra));
$this->assertTrue($typeExtra->is_required);
$this->assertSame([
'type' => 'object',
'required' => ['phone'],
], $typeExtra->config_schema);
$this->assertSame(['phone' => '+5491112345678'], $websiteExtra->config);
$this->assertTrue($websiteExtra->is_enabled);
$this->assertTrue($tenant->adminWebsiteType->is($admin));
$this->assertTrue($tenant->storefrontWebsiteType->is($storefront));
$this->assertTrue($definition->storefrontWebsiteType->is($storefront));
$this->assertTrue($definition->websiteExtras()->firstOrFail()->is($value));
$this->assertSame('store', $tenant->storefront_website_type_code);
$this->assertSame('admin-brand', $tenant->admin_website_type_code);
}
public function test_deleting_a_type_cascades_its_definitions_and_website_values(): void
{
$type = WebsiteType::query()->create([
$type = StorefrontWebsiteType::query()->create([
'codigo' => 'store',
'nombre' => 'Tienda',
]);
@@ -157,7 +101,7 @@ class WebsiteExtrasTest extends TestCase
$type->delete();
$this->assertDatabaseMissing('website_type_extras', ['id' => $typeExtra->id]);
$this->assertDatabaseMissing('storefront_website_type_extras', ['id' => $typeExtra->id]);
$this->assertDatabaseMissing('websites_extras', ['id' => $websiteExtra->id]);
}

View File

@@ -15,7 +15,7 @@ use App\Domains\Purchase\Models\Purchase;
use App\Domains\Purchase\Models\PurchaseItem;
use App\Domains\Shared\Enums\FieldType;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Ticket\Models\Ticket;
use App\Domains\Ticket\Models\TicketRefund;
use Barryvdh\DomPDF\ServiceProvider as DomPdfServiceProvider;
@@ -39,7 +39,7 @@ class AdminAppTicketControllerTest extends TestCase
$this->app->register(DomPdfServiceProvider::class);
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
AdminWebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
}
public function test_authentication_is_required(): void
@@ -1106,7 +1106,7 @@ class AdminAppTicketControllerTest extends TestCase
'codigo' => $code,
'nombre' => ucfirst($code),
'dominio' => "{$code}.test",
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
'primary_color' => '#111111',
'secondary_color' => '#222222',
'danger_color' => '#333333',

View File

@@ -6,7 +6,7 @@ use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\Category;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Ticket\Models\Ticket;
use Database\Seeders\AuthorizationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
@@ -23,7 +23,7 @@ class PrepareLoadTestTicketsCommandTest extends TestCase
{
Storage::fake('local');
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
AdminWebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
$tenant = $this->createTenant('acme');
$category = Category::query()->create([
'tenant_code' => $tenant->codigo,
@@ -101,7 +101,7 @@ class PrepareLoadTestTicketsCommandTest extends TestCase
'footer_bg_color' => '#313131',
'header_logo_id' => $logo->id,
'footer_logo_id' => $logo->id,
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
}
}

View File

@@ -9,7 +9,7 @@ use App\Domains\Authorization\Enums\RoleCode;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\Category;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use App\Domains\Ticket\Enums\ScanAttemptResult;
use App\Domains\Ticket\Models\ScanAttempt;
use App\Domains\Ticket\Models\Ticket;
@@ -36,7 +36,7 @@ class ScannerTicketControllerTest extends TestCase
parent::setUp();
$this->seed(AuthorizationSeeder::class);
WebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
AdminWebsiteType::query()->create(['codigo' => 'onticket', 'nombre' => 'OnTicket']);
$this->tenant = $this->createTenant('acme');
$this->scanner = User::factory()->create([
'rol_codigo' => RoleCode::Scanner->value,
@@ -521,7 +521,7 @@ class ScannerTicketControllerTest extends TestCase
'footer_bg_color' => '#313131',
'header_logo_id' => $logo->id,
'footer_logo_id' => $logo->id,
'website_type_code' => 'onticket',
'admin_website_type_code' => 'onticket',
]);
}
}

View File

@@ -3,14 +3,14 @@
namespace Tests\Unit\Bootstrap;
use App\Domains\Bootstrap\Resources\AdminAppBootstrapResource;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Tests\TestCase;
class AdminAppBootstrapResourceTest extends TestCase
{
public function test_it_exposes_the_website_type(): void
{
$websiteType = new WebsiteType([
$websiteType = new AdminWebsiteType([
'codigo' => 'shopit',
'nombre' => 'ShopIt',
'dominio' => 'admin.shopit.test',
@@ -23,7 +23,7 @@ class AdminAppBootstrapResourceTest extends TestCase
'website_type' => $websiteType,
])->resolve(request());
$this->assertSame('shopit', $data['website_type_code']);
$this->assertSame('shopit', $data['admin_website_type_code']);
$this->assertSame('ShopIt Website Type', $data['site_title']);
$this->assertNull($data['favicon']);
$this->assertArrayNotHasKey('forms', $data);

View File

@@ -5,8 +5,8 @@ namespace Tests\Unit;
use App\Domains\Integration\Models\ClientIntegration;
use App\Domains\Integration\Models\Integration;
use App\Domains\Integration\Models\IntegrationInstance;
use App\Domains\Integration\Models\WebsiteTypeIntegration;
use App\Domains\Tenant\Models\WebsiteType;
use App\Domains\Integration\Models\AdminWebsiteTypeIntegration;
use App\Domains\Tenant\Models\AdminWebsiteType;
use Illuminate\Config\Repository;
use Illuminate\Container\Container;
use Illuminate\Database\Capsule\Manager;
@@ -75,10 +75,21 @@ class IntegrationInstanceSchemaTest extends TestCase
$db->table('client_integrations')->insert([
'client_id' => 1, 'integration_code' => 'email', 'integration_data' => 'existing-ciphertext',
]);
$this->migrations = array_map(fn (string $file) => require $file, glob(__DIR__.'/../../database/migrations/2026_09_04_*.php'));
$migrationDir = __DIR__.'/../../database/migrations/';
$this->migrations = array_map(fn (string $file) => require $migrationDir.$file, [
'2026_09_04_000000_create_integration_instances_table.php',
'2026_09_04_000001_move_client_configuration_to_integration_instances.php',
'2026_09_04_000002_create_website_type_integrations_table.php',
'2026_09_04_000003_rename_integration_configuration_requirement.php',
]);
foreach ($this->migrations as $migration) {
$migration->up();
}
$schema->rename('website_type', 'admin_website_types');
$schema->rename('website_type_integrations', 'admin_website_type_integrations');
$schema->table('admin_website_type_integrations', function (Blueprint $table): void {
$table->renameColumn('website_type_code', 'admin_website_type_code');
});
}
protected function tearDown(): void
@@ -97,6 +108,13 @@ class IntegrationInstanceSchemaTest extends TestCase
self::assertSame('existing-ciphertext', $db->table('integration_instances')->where('id', $association->integration_instance_id)->value('integration_data'));
self::assertFalse($db->getSchemaBuilder()->hasColumn('client_integrations', 'integration_data'));
$schema = $db->getSchemaBuilder();
$schema->table('admin_website_type_integrations', function (Blueprint $table): void {
$table->renameColumn('admin_website_type_code', 'website_type_code');
});
$schema->rename('admin_website_type_integrations', 'website_type_integrations');
$schema->rename('admin_website_types', 'website_type');
foreach (array_reverse($this->migrations) as $migration) {
$migration->down();
}
@@ -111,11 +129,11 @@ class IntegrationInstanceSchemaTest extends TestCase
self::assertNotSame('private-value', $instance->getRawOriginal('integration_data'));
self::assertSame(['password' => 'private-value'], $instance->fresh()->integration_data);
self::assertArrayNotHasKey('integration_data', $instance->toArray());
WebsiteTypeIntegration::create([
'website_type_code' => 'onticket', 'integration_code' => 'email', 'integration_instance_id' => $instance->id,
AdminWebsiteTypeIntegration::create([
'admin_website_type_code' => 'onticket', 'integration_code' => 'email', 'integration_instance_id' => $instance->id,
]);
self::assertTrue(ClientIntegration::firstOrFail()->integrationInstance->is($instance));
self::assertTrue(WebsiteType::firstOrFail()->integrations->first()->integrationInstance->is($instance));
self::assertTrue(AdminWebsiteType::firstOrFail()->integrations->first()->integrationInstance->is($instance));
self::assertSame(1, $instance->clientIntegrations()->count());
self::assertSame(1, $instance->websiteTypeIntegrations()->count());
self::assertTrue(Integration::where('integration_code', 'email')->firstOrFail()->instances->first()->is($instance));
@@ -147,8 +165,8 @@ class IntegrationInstanceSchemaTest extends TestCase
public function test_association_rejects_an_instance_from_another_integration(): void
{
$this->expectException(QueryException::class);
WebsiteTypeIntegration::create([
'website_type_code' => 'onticket', 'integration_code' => 'telepagos', 'integration_instance_id' => IntegrationInstance::firstOrFail()->id,
AdminWebsiteTypeIntegration::create([
'admin_website_type_code' => 'onticket', 'integration_code' => 'telepagos', 'integration_instance_id' => IntegrationInstance::firstOrFail()->id,
]);
}
@@ -161,13 +179,13 @@ class IntegrationInstanceSchemaTest extends TestCase
public function test_website_type_cannot_have_two_instances_of_the_same_integration(): void
{
WebsiteTypeIntegration::create([
'website_type_code' => 'onticket', 'integration_code' => 'email', 'integration_instance_id' => IntegrationInstance::firstOrFail()->id,
AdminWebsiteTypeIntegration::create([
'admin_website_type_code' => 'onticket', 'integration_code' => 'email', 'integration_instance_id' => IntegrationInstance::firstOrFail()->id,
]);
$instance = IntegrationInstance::create(['integration_code' => 'email', 'name' => 'Second']);
$this->expectException(QueryException::class);
WebsiteTypeIntegration::create([
'website_type_code' => 'onticket', 'integration_code' => 'email', 'integration_instance_id' => $instance->id,
AdminWebsiteTypeIntegration::create([
'admin_website_type_code' => 'onticket', 'integration_code' => 'email', 'integration_instance_id' => $instance->id,
]);
}
}