assertEqualsCanonicalizing([ 'id', 'code', 'icon', 'name', 'created_at', 'updated_at', ], Schema::getColumnListing('social_media')); $this->assertEqualsCanonicalizing([ 'id', 'tenant_code', 'social_media_code', 'url', 'orden', 'created_at', 'updated_at', ], Schema::getColumnListing('tenant_social_media')); } public function test_a_tenant_can_have_social_media_with_its_own_url(): void { $tenant = $this->createTenant(); $instagram = SocialMedia::query()->create([ 'code' => 'instagram', 'icon' => 'instagram', 'name' => 'Instagram', ]); $tenant->socialMedia()->attach($instagram->code, [ 'url' => 'https://instagram.com/acme', 'orden' => 3, ]); $this->assertTrue($tenant->socialMedia()->firstOrFail()->is($instagram)); $this->assertSame( 'https://instagram.com/acme', $tenant->socialMedia()->firstOrFail()->pivot->url ); $this->assertSame(3, $tenant->socialMedia()->firstOrFail()->pivot->orden); $this->assertTrue($instagram->tenants()->firstOrFail()->is($tenant)); } public function test_deleting_a_social_media_deletes_its_tenant_associations(): void { $tenant = $this->createTenant(); $instagram = SocialMedia::query()->create([ 'code' => 'instagram', 'icon' => 'instagram', 'name' => 'Instagram', ]); $tenant->socialMedia()->attach($instagram->code, [ 'url' => 'https://instagram.com/acme', ]); $instagram->delete(); $this->assertDatabaseMissing('tenant_social_media', [ 'tenant_code' => $tenant->codigo, 'social_media_code' => $instagram->code, ]); } public function test_tenant_update_synchronizes_social_media_and_returns_pivot_urls(): void { $tenant = $this->createTenant(); $instagram = $this->createSocialMedia('instagram', 'Instagram'); $facebook = $this->createSocialMedia('facebook', 'Facebook'); $tenant->socialMedia()->attach($facebook->code, [ 'url' => 'https://facebook.com/old-acme', ]); $this->putJson("/api/tenants/{$tenant->codigo}", [ 'social_media' => [ [ 'code' => $instagram->code, 'url' => 'https://instagram.com/acme', 'orden' => 4, ], ], ]) ->assertOk() ->assertJsonPath('data.social_media.0.code', 'instagram') ->assertJsonPath('data.social_media.0.icon', 'instagram') ->assertJsonPath('data.social_media.0.name', 'Instagram') ->assertJsonPath('data.social_media.0.url', 'https://instagram.com/acme') ->assertJsonCount(1, 'data.social_media'); $this->assertDatabaseHas('tenant_social_media', [ 'tenant_code' => $tenant->codigo, 'social_media_code' => $instagram->code, 'url' => 'https://instagram.com/acme', 'orden' => 4, ]); $this->assertDatabaseMissing('tenant_social_media', [ 'tenant_code' => $tenant->codigo, 'social_media_code' => $facebook->code, ]); } public function test_tenant_social_media_are_returned_in_configured_order(): void { $tenant = $this->createTenant(); $instagram = $this->createSocialMedia('instagram', 'Instagram'); $facebook = $this->createSocialMedia('facebook', 'Facebook'); $this->putJson("/api/tenants/{$tenant->codigo}", [ 'social_media' => [ [ 'code' => $instagram->code, 'url' => 'https://instagram.com/acme', 'orden' => 20, ], [ 'code' => $facebook->code, 'url' => 'https://facebook.com/acme', 'orden' => 10, ], ], ]) ->assertOk() ->assertJsonPath('data.social_media.0.code', 'facebook') ->assertJsonPath('data.social_media.1.code', 'instagram') ->assertJsonMissingPath('data.social_media.0.orden') ->assertJsonMissingPath('data.social_media.1.orden'); } public function test_tenant_store_synchronizes_social_media(): void { $instagram = $this->createSocialMedia('instagram', 'Instagram'); $headerLogo = $this->createAttachment('new-header.png'); $footerLogo = $this->createAttachment('new-footer.png'); $this->postJson('/api/tenants', [ 'codigo' => 'new-acme', 'nombre' => 'New Acme', 'dominio' => 'new-acme.com', 'primary_color' => '#111111', 'secondary_color' => '#222222', 'danger_color' => '#333333', 'success_color' => '#444444', 'header_bg_color' => '#ffffff', 'footer_bg_color' => '#ffffff', 'header_logo' => $headerLogo->key, 'footer_logo' => $footerLogo->key, 'social_media' => [ [ 'code' => $instagram->code, 'url' => 'https://instagram.com/new-acme', ], ], ]) ->assertCreated() ->assertJsonPath('data.social_media.0.code', 'instagram') ->assertJsonPath('data.social_media.0.url', 'https://instagram.com/new-acme'); $this->assertDatabaseHas('tenant_social_media', [ 'tenant_code' => 'new-acme', 'social_media_code' => $instagram->code, 'url' => 'https://instagram.com/new-acme', ]); } public function test_tenant_update_can_clear_social_media(): void { $tenant = $this->createTenant(); $instagram = $this->createSocialMedia('instagram', 'Instagram'); $tenant->socialMedia()->attach($instagram->code, [ 'url' => 'https://instagram.com/acme', ]); $this->putJson("/api/tenants/{$tenant->codigo}", [ 'social_media' => [], ]) ->assertOk() ->assertJsonPath('data.social_media', []); $this->assertDatabaseMissing('tenant_social_media', [ 'tenant_code' => $tenant->codigo, ]); } public function test_tenant_update_validates_social_media_codes_and_urls(): void { $tenant = $this->createTenant(); $this->putJson("/api/tenants/{$tenant->codigo}", [ 'social_media' => [ [ 'code' => 'unknown', 'url' => 'not-a-url', ], ], ]) ->assertUnprocessable() ->assertJsonValidationErrors([ 'social_media.0.code', 'social_media.0.url', ]); } private function createTenant(): Tenant { $headerLogo = $this->createAttachment('header.png'); $footerLogo = $this->createAttachment('footer.png'); return Tenant::query()->create([ 'codigo' => 'acme', 'nombre' => 'Acme', 'dominio' => 'acme.com', 'primary_color' => '#111111', 'secondary_color' => '#222222', 'danger_color' => '#333333', 'success_color' => '#444444', 'header_bg_color' => '#ffffff', 'footer_bg_color' => '#ffffff', 'header_logo_id' => $headerLogo->id, 'footer_logo_id' => $footerLogo->id, ]); } private function createAttachment(string $filename): Attachment { return Attachment::query()->create([ 'path' => "test/{$filename}", 'filename' => $filename, 'type' => AttachmentType::Image, 'mime_type' => 'image/png', ]); } private function createSocialMedia(string $code, string $name): SocialMedia { return SocialMedia::query()->create([ 'code' => $code, 'icon' => $code, 'name' => $name, ]); } }