seed(AuthorizationSeeder::class); $this->websiteType = WebsiteType::query()->create([ 'codigo' => 'test-store', 'nombre' => 'Test Store', ]); $this->websiteType->extras()->create([ 'codigo' => 'contactConfig', 'nombre' => 'Configuración de contacto', 'descripcion' => 'Datos de contacto visibles en la tienda.', 'is_required' => false, 'config_schema' => [ 'request_rules' => [ '$' => 'required|array', 'phone' => 'required|string|max:30', ], 'transforms' => [], ], ]); } public function test_authentication_is_required(): void { $this->getJson('/api/v1/adminapp/tenant/website-extras') ->assertUnauthorized(); } public function test_a_customer_cannot_access_adminapp_website_extras(): void { $customer = User::factory()->create([ 'rol_codigo' => RoleCode::User->value, 'tenant_codigo' => null, ]); Sanctum::actingAs($customer); $this->getJson('/api/v1/adminapp/tenant/website-extras') ->assertForbidden(); } public function test_adminapp_user_can_read_definitions_and_current_values(): void { $tenant = $this->createTenant('acme'); $definition = $this->websiteType->extras()->firstOrFail(); $tenant->websiteExtras()->create([ 'website_type_extra_id' => $definition->id, 'config' => ['phone' => '+54 341 555 0101'], ]); Sanctum::actingAs($this->createAdminAppUser($tenant)); $this->getJson('/api/v1/adminapp/tenant/website-extras') ->assertOk() ->assertJsonPath('data.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) ->assertJsonPath('data.definitions.contactConfig.is_enabled', null) ->assertJsonPath('data.extras.contactConfig.phone', '+54 341 555 0101') ->assertJsonPath('data.resolved_extras.contactConfig.phone', '+54 341 555 0101'); } public function test_adminapp_user_can_read_one_website_extra(): void { $tenant = $this->createTenant('acme'); $definition = $this->websiteType->extras()->firstOrFail(); $tenant->websiteExtras()->create([ 'website_type_extra_id' => $definition->id, 'config' => ['phone' => '+54 341 555 0101'], 'is_enabled' => true, ]); Sanctum::actingAs($this->createAdminAppUser($tenant)); $this->getJson('/api/v1/adminapp/tenant/website-extras/contactConfig') ->assertOk() ->assertJsonPath('data.codigo', 'contactConfig') ->assertJsonPath('data.nombre', 'Configuración de contacto') ->assertJsonPath('data.is_enabled', true) ->assertJsonPath('data.config.phone', '+54 341 555 0101') ->assertJsonPath('data.resolved_config.phone', '+54 341 555 0101'); } public function test_reading_an_unconfigured_website_extra_returns_not_found(): void { $tenant = $this->createTenant('acme'); Sanctum::actingAs($this->createAdminAppUser($tenant)); $this->getJson('/api/v1/adminapp/tenant/website-extras/contactConfig') ->assertNotFound(); } public function test_adminapp_user_updates_one_extra_without_touching_other_tenants(): void { $tenant = $this->createTenant('acme'); $otherTenant = $this->createTenant('other'); $definition = $this->websiteType->extras()->firstOrFail(); $secondaryDefinition = $this->websiteType->extras()->create([ 'codigo' => 'footerConfig', 'nombre' => 'Configuración del pie', 'descripcion' => 'Configuración adicional del pie.', 'is_required' => false, 'config_schema' => [ 'request_rules' => ['$' => 'required|array'], 'transforms' => [], ], ]); $tenant->websiteExtras()->create([ 'website_type_extra_id' => $definition->id, 'config' => ['phone' => 'old'], ]); $otherTenant->websiteExtras()->create([ 'website_type_extra_id' => $definition->id, 'config' => ['phone' => 'untouched'], ]); $tenant->websiteExtras()->create([ 'website_type_extra_id' => $secondaryDefinition->id, 'config' => ['text' => 'also untouched'], ]); Sanctum::actingAs($this->createAdminAppUser($tenant)); $this->putJson('/api/v1/adminapp/tenant/website-extras/contactConfig', [ 'config' => [ 'phone' => '+54 341 555 9999', ], ]) ->assertOk() ->assertJsonPath('data.extras.contactConfig.phone', '+54 341 555 9999'); $this->assertSame( ['phone' => '+54 341 555 9999'], $tenant->websiteExtras()->firstOrFail()->config ); $this->assertSame( ['phone' => 'untouched'], $otherTenant->websiteExtras()->firstOrFail()->config ); $this->assertSame( ['text' => 'also untouched'], $tenant->websiteExtras() ->where('website_type_extra_id', $secondaryDefinition->id) ->firstOrFail() ->config ); } public function test_adminapp_user_saves_the_banner_description_in_the_hero_extra(): void { $heroDefinition = $this->websiteType->extras()->create([ 'codigo' => 'heroConfig', 'nombre' => 'Banner principal', 'descripcion' => 'Configuración del banner principal.', 'is_required' => false, 'config_schema' => [ 'request_rules' => [ '$' => 'required|array', 'title_html' => 'nullable|string', 'description_html' => 'nullable|string', 'button_text' => 'nullable|string', 'button_href' => 'nullable|string', 'background_image_id' => 'nullable|string', ], 'transforms' => [], ], ]); $tenant = $this->createTenant('acme'); Sanctum::actingAs($this->createAdminAppUser($tenant)); $this->putJson('/api/v1/adminapp/tenant/website-extras/heroConfig', [ 'config' => [ 'title_html' => '

Evento

', 'description_html' => '

Nueva descripción del banner

', 'button_text' => 'Comprar', 'button_href' => '/tickets', 'background_image_id' => null, ], ]) ->assertOk() ->assertJsonPath( 'data.extras.heroConfig.description_html', '

Nueva descripción del banner

' ); $this->assertSame( '

Nueva descripción del banner

', $tenant->websiteExtras() ->where('website_type_extra_id', $heroDefinition->id) ->firstOrFail() ->config['description_html'] ); } public function test_update_returns_not_found_for_an_unsupported_extra_code(): void { $tenant = $this->createTenant('acme'); Sanctum::actingAs($this->createAdminAppUser($tenant)); $this->putJson('/api/v1/adminapp/tenant/website-extras/unknown', [ 'config' => ['enabled' => true], ]) ->assertNotFound(); } public function test_adminapp_user_can_toggle_an_existing_website_extra(): void { $tenant = $this->createTenant('acme'); $definition = $this->websiteType->extras()->firstOrFail(); $websiteExtra = $tenant->websiteExtras()->create([ 'website_type_extra_id' => $definition->id, 'config' => ['phone' => '+54 341 555 0101'], 'is_enabled' => false, ]); Sanctum::actingAs($this->createAdminAppUser($tenant)); $this->patchJson('/api/v1/adminapp/tenant/website-extras/contactConfig/toggle') ->assertOk() ->assertJsonPath('code', 'tenant.website_extra_toggled') ->assertJsonPath('message', 'El estado de la sección se actualizó correctamente.') ->assertJsonPath('data.definitions.contactConfig.is_enabled', true); $this->assertTrue($websiteExtra->refresh()->is_enabled); $this->patchJson('/api/v1/adminapp/tenant/website-extras/contactConfig/toggle') ->assertOk() ->assertJsonPath('data.definitions.contactConfig.is_enabled', false); $this->assertFalse($websiteExtra->refresh()->is_enabled); } public function test_toggle_enables_an_extra_without_a_tenant_value(): void { $tenant = $this->createTenant('acme'); Sanctum::actingAs($this->createAdminAppUser($tenant)); $this->patchJson('/api/v1/adminapp/tenant/website-extras/contactConfig/toggle') ->assertOk() ->assertJsonPath('data.definitions.contactConfig.is_enabled', true) ->assertJsonPath('data.extras.contactConfig', []); $this->assertDatabaseHas('websites_extras', [ 'website_code' => $tenant->codigo, 'website_type_extra_id' => $this->websiteType->extras()->firstOrFail()->id, 'is_enabled' => true, ]); } private function createTenant(string $code): Tenant { return Tenant::query()->create([ 'codigo' => $code, 'nombre' => ucfirst($code), 'dominio' => "{$code}.test", 'website_type_code' => $this->websiteType->codigo, ]); } private function createAdminAppUser(Tenant $tenant): User { return User::factory()->create([ 'rol_codigo' => RoleCode::AdminApp->value, 'tenant_codigo' => $tenant->codigo, ]); } }