seed(WebsiteTypeSeeder::class); } 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', 'extras' => [ 'eventConfig' => [ 'title' => 'Festival', 'location' => 'Buenos Aires', 'dates_text' => '10 y 11 de octubre de 2026', 'dates' => ['2026-10-10', '2026-10-11'], ], ], ])); $response ->assertCreated() ->assertJsonPath('data.website_type_code', 'onticket') ->assertJsonPath('data.website_type.codigo', 'onticket') ->assertJsonPath('data.extras.eventConfig.title', 'Festival'); $tenant = Tenant::query()->where('codigo', 'festival')->sole(); $this->assertDatabaseHas('websites_extras', [ 'website_code' => $tenant->codigo, ]); $this->assertSame( [ 'title' => 'Festival', 'location' => 'Buenos Aires', 'dates_text' => '10 y 11 de octubre de 2026', 'dates' => ['2026-10-10', '2026-10-11'], ], $tenant->websiteExtras()->sole()->config ); } 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', 'extras' => [ 'eventConfig' => [ 'title' => 'Not supported', ], ], ])) ->assertUnprocessable() ->assertJsonValidationErrors(['extras']); $this->assertDatabaseMissing('tenants', ['codigo' => 'festival']); } public function test_it_applies_the_extra_schema_rules(): void { $this->postJson('/api/tenants', array_merge($this->tenantData(), [ 'website_type_code' => 'onticket', 'extras' => [ 'eventConfig' => [ 'dates' => ['not-a-date'], ], ], ])) ->assertUnprocessable() ->assertJsonValidationErrors(['extras.eventConfig.dates.0']); $this->assertDatabaseMissing('tenants', ['codigo' => 'festival']); } public function test_it_transforms_extra_images_to_attachment_ids(): void { $image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='; $response = $this->postJson('/api/tenants', array_merge($this->tenantData(), [ 'website_type_code' => 'shopit', 'extras' => [ 'carousel' => [$image], ], ])); $response->assertCreated(); $tenant = Tenant::query() ->where('codigo', 'festival') ->sole(); $config = $tenant->websiteExtras() ->sole() ->config; $this->assertCount(1, $config); $this->assertIsInt($config[0]); $this->assertDatabaseHas('attachments', [ 'id' => $config[0], 'type' => 'image', ]); $attachment = Attachment::query()->findOrFail($config[0]); $carouselUrl = $response->json('data.extras.carousel.0'); $this->assertIsString($carouselUrl); $this->assertStringContainsString($attachment->key, $carouselUrl); app(TenantInformationService::class)->load($tenant); $this->assertInstanceOf( Attachment::class, $tenant->websiteExtras->sole()->resolvedConfig()[0] ); } public function test_it_returns_scalar_attachment_fields_as_temporary_urls(): void { $image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='; $response = $this->postJson('/api/tenants', array_merge($this->tenantData(), [ 'website_type_code' => 'onticket', 'extras' => [ 'heroConfig' => [ 'title_html' => '

Festival

', 'background_image_id' => $image, ], ], ])); $response->assertCreated(); $heroConfig = Tenant::query() ->where('codigo', 'festival') ->sole() ->websiteExtras() ->whereHas( 'websiteTypeExtra', fn ($query) => $query->where('nombre', 'heroConfig') ) ->sole() ->config; $attachment = Attachment::query()->findOrFail($heroConfig['background_image_id']); $backgroundUrl = $response->json('data.extras.heroConfig.background_image_id'); $this->assertIsString($backgroundUrl); $this->assertStringContainsString($attachment->key, $backgroundUrl); } /** * @return array */ private function tenantData(): array { $image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='; return [ 'codigo' => 'festival', 'nombre' => 'Festival', 'dominio' => 'festival.test', 'primary_color' => '#111111', 'secondary_color' => '#222222', 'danger_color' => '#333333', 'success_color' => '#444444', 'header_bg_color' => '#ffffff', 'footer_bg_color' => '#ffffff', 'header_logo' => $image, 'footer_logo' => $image, 'search_product_layout' => 'column_with_image', 'search_group_layout' => 'paginated', 'search_items_per_page' => 12, ]; } }