First commit

This commit is contained in:
Kevin Adametz 2025-10-20 17:50:35 +02:00
commit 7cf3558ba7
12933 changed files with 1180047 additions and 0 deletions

View file

@ -0,0 +1,30 @@
<?php
namespace FluxCms\Core\Tests\Unit\Admin;
use FluxCms\Core\Models\User;
use FluxCms\Core\Models\BlogPost;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Orchestra\Testbench\TestCase;
class BlogControllerTest extends TestCase
{
use RefreshDatabase;
protected User $adminUser;
protected function setUp(): void
{
parent::setUp();
$this->adminUser = User::factory()->create(['is_admin' => true]);
$this->actingAs($this->adminUser);
}
public function test_can_display_blog_posts_index()
{
BlogPost::factory()->count(3)->create();
$response = $this->get(route('admin.cms.blog.index'));
$response->assertOk();
$response->assertViewHas('posts');
}
}

View file

@ -0,0 +1,29 @@
<?php
namespace FluxCms\Core\Tests\Unit\Admin;
use FluxCms\Core\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Orchestra\Testbench\TestCase;
class DashboardControllerTest extends TestCase
{
use RefreshDatabase;
protected User $adminUser;
protected function setUp(): void
{
parent::setUp();
$this->adminUser = User::factory()->create(['is_admin' => true]);
$this->actingAs($this->adminUser);
}
public function test_admin_can_see_dashboard()
{
$response = $this->get(route('admin.cms.index'));
$response->assertOk();
$response->assertViewHas('stats');
$response->assertViewHas('recentPages');
}
}

View file

@ -0,0 +1,123 @@
<?php
namespace FluxCms\Core\Tests\Unit\Admin;
use FluxCms\Core\Models\User;
use FluxCms\Core\Models\Page;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Orchestra\Testbench\TestCase;
class PageControllerTest extends TestCase
{
use RefreshDatabase;
protected User $adminUser;
protected function setUp(): void
{
parent::setUp();
$this->adminUser = User::factory()->create(['is_admin' => true]);
$this->actingAs($this->adminUser);
}
public function test_can_display_pages_index()
{
Page::factory()->count(3)->create();
$response = $this->get(route('admin.cms.pages.index'));
$response->assertOk();
$response->assertViewHas('pages');
}
public function test_can_show_create_page_form()
{
$response = $this->get(route('admin.cms.pages.create'));
$response->assertOk();
}
public function test_can_store_a_new_page()
{
$pageData = [
'domain_key' => 'default',
'title' => ['en' => 'New Page'],
'slugs' => ['en' => '/new-page'],
'is_published' => true,
];
$response = $this->post(route('admin.cms.pages.store'), $pageData);
$this->assertDatabaseHas('flux_cms_pages', ['title' => '{"en":"New Page"}']);
$this->assertDatabaseHas('flux_cms_slugs', ['slug' => '/new-page']);
$response->assertRedirect();
}
public function test_store_fails_with_invalid_data()
{
$response = $this->post(route('admin.cms.pages.store'), [
'title' => ['en' => ''], // Invalid: title is required
]);
$response->assertSessionHasErrors('title.en');
$response->assertStatus(302); // Should redirect back
}
public function test_unauthorized_user_cannot_create_page()
{
$user = User::factory()->create(); // Non-admin user
$this->actingAs($user);
$response = $this->get(route('admin.cms.pages.create'));
$response->assertStatus(403);
$response = $this->post(route('admin.cms.pages.store'), []);
$response->assertStatus(403);
}
public function test_can_show_edit_page_form()
{
$page = Page::factory()->create();
$response = $this->get(route('admin.cms.pages.edit', $page));
$response->assertOk();
$response->assertViewHas('page', $page);
}
public function test_can_update_a_page()
{
$page = Page::factory()->create();
$page->slugs()->create(['locale' => 'en', 'slug' => '/old-slug']);
$updateData = [
'title' => ['en' => 'Updated Title'],
'slugs' => ['en' => '/updated-slug'],
];
$response = $this->put(route('admin.cms.pages.update', $page), $updateData);
$this->assertDatabaseHas('flux_cms_pages', ['id' => $page->id, 'title' => '{"en":"Updated Title"}']);
$this->assertDatabaseHas('flux_cms_slugs', ['slug' => '/updated-slug']);
$response->assertRedirect();
}
public function test_unauthorized_user_cannot_edit_or_delete_page()
{
$user = User::factory()->create(); // Non-admin user
$page = Page::factory()->create();
$this->actingAs($user);
$response = $this->get(route('admin.cms.pages.edit', $page));
$response->assertStatus(403);
$response = $this->put(route('admin.cms.pages.update', $page), []);
$response->assertStatus(403);
$response = $this->delete(route('admin.cms.pages.destroy', $page));
$response->assertStatus(403);
}
public function test_can_delete_a_page()
{
$page = Page::factory()->create();
$response = $this->delete(route('admin.cms.pages.destroy', $page));
$this->assertModelMissing($page);
$response->assertRedirect(route('admin.cms.pages.index'));
}
}

View file

@ -0,0 +1,165 @@
<?php
namespace FluxCms\Core\Tests\Unit;
use FluxCms\Core\Services\ComponentRegistry;
use FluxCms\Core\FieldTypes\TextField;
use FluxCms\Core\FieldTypes\MediaField;
use Orchestra\Testbench\TestCase;
use Livewire\Component;
use Mockery;
class ComponentRegistryTest extends TestCase
{
protected ComponentRegistry $registry;
protected function setUp(): void
{
parent::setUp();
$this->registry = new ComponentRegistry();
}
public function test_can_detect_valid_component()
{
$componentClass = TestComponent::class;
$this->assertTrue($this->registry->isValidComponent($componentClass));
}
public function test_can_get_component_config()
{
$componentClass = TestComponent::class;
$config = $this->registry->getComponentConfig($componentClass);
$this->assertIsArray($config);
$this->assertEquals('Test Component', $config['name']);
$this->assertEquals('Testing', $config['category']);
$this->assertCount(2, $config['fields']);
}
public function test_can_validate_component_content()
{
$componentClass = TestComponent::class;
// Valid content
$validContent = [
'title' => ['de' => 'Test Titel', 'en' => 'Test Title'],
'image' => 123
];
$errors = $this->registry->validateComponentContent($componentClass, $validContent);
$this->assertEmpty($errors);
// Invalid content (missing required field)
$invalidContent = [
'image' => 123
];
$errors = $this->registry->validateComponentContent($componentClass, $invalidContent);
$this->assertNotEmpty($errors);
}
public function test_can_search_components()
{
// Mock some components in registry
$components = [
TestComponent::class => [
'name' => 'Test Component',
'category' => 'Testing',
'description' => 'A test component',
'tags' => ['test', 'example']
]
];
$registry = Mockery::mock(ComponentRegistry::class)->makePartial();
$registry->shouldReceive('getAvailableComponents')->andReturn($components);
$results = $registry->searchComponents('test');
$this->assertCount(1, $results);
$this->assertArrayHasKey(TestComponent::class, $results);
}
public function test_can_get_components_by_category()
{
$components = [
TestComponent::class => [
'name' => 'Test Component',
'category' => 'Testing',
],
AnotherTestComponent::class => [
'name' => 'Another Component',
'category' => 'Layout',
]
];
$registry = Mockery::mock(ComponentRegistry::class)->makePartial();
$registry->shouldReceive('getAvailableComponents')->andReturn($components);
$categorized = $registry->getComponentsByCategory();
$this->assertArrayHasKey('Testing', $categorized);
$this->assertArrayHasKey('Layout', $categorized);
$this->assertCount(1, $categorized['Testing']);
$this->assertCount(1, $categorized['Layout']);
}
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
}
// Test component classes
class TestComponent extends Component
{
public static function getCmsName(): string
{
return 'Test Component';
}
public static function getCmsCategory(): string
{
return 'Testing';
}
public static function getCmsFields(): array
{
return [
TextField::make('title', 'Title')->translatable()->required(),
MediaField::make('image', 'Image')->images(),
];
}
public function render()
{
return '<div>Test Component</div>';
}
}
class AnotherTestComponent extends Component
{
public static function getCmsName(): string
{
return 'Another Component';
}
public static function getCmsCategory(): string
{
return 'Layout';
}
public static function getCmsFields(): array
{
return [
TextField::make('content', 'Content'),
];
}
public function render()
{
return '<div>Another Component</div>';
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace FluxCms\Core\Tests\Unit\Models;
use FluxCms\Core\Models\BlogPost;
use FluxCms\Core\Models\User;
use Spatie\Tags\Tag;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Orchestra\Testbench\TestCase;
class BlogPostTest extends TestCase
{
use RefreshDatabase;
public function test_blog_post_has_author_relationship()
{
$user = User::factory()->create();
$post = BlogPost::factory()->create([
'author_id' => $user->id,
'author_type' => User::class
]);
$this->assertInstanceOf(User::class, $post->author);
}
public function test_can_attach_and_retrieve_tags()
{
$post = BlogPost::factory()->create();
$post->attachTag('Laravel');
$this->assertCount(1, $post->tags);
$this->assertEquals('Laravel', $post->tags->first()->name);
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace FluxCms\Core\Tests\Unit\Models;
use FluxCms\Core\Models\Page;
use FluxCms\Core\Models\Slug;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Orchestra\Testbench\TestCase;
class PageTest extends TestCase
{
use RefreshDatabase;
public function test_page_has_slugs_relationship()
{
$page = Page::factory()->create();
Slug::factory()->create([
'model_id' => $page->id,
'model_type' => Page::class
]);
$this->assertInstanceOf(Slug::class, $page->slugs->first());
}
public function test_published_scope_returns_only_published_pages()
{
Page::factory()->create(['is_published' => true]);
Page::factory()->create(['is_published' => false]);
$this->assertEquals(1, Page::published()->count());
}
public function test_for_domain_scope_returns_pages_for_correct_domain()
{
Page::factory()->create(['domain_key' => 'domain-a']);
Page::factory()->create(['domain_key' => 'domain-b']);
$this->assertEquals(1, Page::forDomain('domain-a')->count());
}
public function test_by_slug_with_fallback_scope_finds_page_by_slug()
{
$page = Page::factory()->create();
$page->slugs()->create(['locale' => 'en', 'slug' => 'test-slug']);
$foundPage = Page::bySlugWithFallback('test-slug', 'en')->first();
$this->assertNotNull($foundPage);
$this->assertEquals($page->id, $foundPage->id);
}
}