-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add testing for new layouts paradigm
Kurt Friars
committed
Nov 21, 2023
1 parent
915b875
commit 948b82f
Showing
37 changed files
with
487 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
<?php | ||
|
||
return [ | ||
|
||
'model' => \Plank\Contentable\Models\Content::class, | ||
'cache' => [ | ||
'ttl' => 10800, | ||
'content' => [ | ||
'model' => \Plank\Contentable\Models\Content::class, | ||
], | ||
'layouts' => [ | ||
'folder' => 'layouts', | ||
'mode' => \Plank\Contentable\Enums\LayoutMode::Blade, | ||
'model' => \Plank\Contentable\Models\Layout::class, | ||
], | ||
'cache' => [ | ||
'ttl' => 10800, | ||
], | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<?php | ||
|
||
use Plank\Contentable\Enums\LayoutType; | ||
use Plank\Contentable\Tests\Helper\Models\Layout; | ||
use Plank\Contentable\Tests\Helper\Models\Page; | ||
use Plank\Contentable\Tests\Helper\Models\Product; | ||
|
||
use function Pest\Laravel\artisan; | ||
|
||
describe('It syncs Layouts for Blade', function () { | ||
beforeEach(function () { | ||
setBladePath('sync'); | ||
}); | ||
|
||
it('creates global and layoutable layouts on sync', function () { | ||
artisan('contentable:sync') | ||
->assertExitCode(0); | ||
|
||
expect($layout = Layout::where('key', 'default')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Default'); | ||
expect($layout->type)->toBe(LayoutType::Global); | ||
expect($layout->layoutable)->toBeNull(); | ||
|
||
expect($layout = Layout::where('key', 'holidays')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Holidays'); | ||
expect($layout->type)->toBe(LayoutType::Global); | ||
expect($layout->layoutable)->toBeNull(); | ||
|
||
expect($layout = Layout::where('key', 'pages.index')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Page Index'); | ||
expect($layout->type)->toBe(LayoutType::Index); | ||
expect($layout->layoutable)->toBe(Page::layoutKey()); | ||
|
||
expect($layout = Layout::where('key', 'pages.show')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Page Details'); | ||
expect($layout->type)->toBe(LayoutType::Show); | ||
expect($layout->layoutable)->toBe(Page::layoutKey()); | ||
|
||
expect($layout = Layout::where('key', 'pages.landing')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Landing Page'); | ||
expect($layout->type)->toBe(LayoutType::Custom); | ||
expect($layout->layoutable)->toBe(Page::layoutKey()); | ||
|
||
expect($layout = Layout::where('key', 'products.index')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Product Index'); | ||
expect($layout->type)->toBe(LayoutType::Index); | ||
expect($layout->layoutable)->toBe(Product::layoutKey()); | ||
|
||
expect($layout = Layout::where('key', 'products.show')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Product Details'); | ||
expect($layout->type)->toBe(LayoutType::Show); | ||
expect($layout->layoutable)->toBe(Product::layoutKey()); | ||
|
||
expect($layout = Layout::where('key', 'products.promo')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Promo Product'); | ||
expect($layout->type)->toBe(LayoutType::Custom); | ||
expect($layout->layoutable)->toBe(Product::layoutKey()); | ||
}); | ||
|
||
it('does not delete missing global layouts on sync', function () { | ||
Layout::factory()->create([ | ||
'key' => 'custom.global', | ||
'name' => 'Custom Global', | ||
'type' => LayoutType::Custom, | ||
]); | ||
|
||
artisan('contentable:sync') | ||
->assertExitCode(0); | ||
|
||
expect(Layout::where('key', 'custom.global')->exists())->toBeTrue(); | ||
}); | ||
|
||
it('does not delete missing layoutable layouts on sync', function () { | ||
Layout::factory()->create([ | ||
'key' => 'pages.y2k', | ||
'name' => 'Y2K Page', | ||
'type' => LayoutType::Custom, | ||
'layoutable' => Page::layoutKey(), | ||
]); | ||
|
||
artisan('contentable:sync') | ||
->assertExitCode(0); | ||
|
||
expect(Layout::where('key', 'pages.y2k')->exists())->toBeTrue(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,202 @@ | ||
<?php | ||
|
||
use Plank\Contentable\Enums\LayoutMode; | ||
use Plank\Contentable\Enums\LayoutType; | ||
use Plank\Contentable\Exceptions\MissingLayoutException; | ||
use Plank\Contentable\Tests\Helper\Models\Layout; | ||
use Plank\Contentable\Tests\Helper\Models\Page; | ||
use Plank\Contentable\Tests\Helper\Models\Post; | ||
use Plank\Contentable\Tests\Helper\Models\Product; | ||
|
||
beforeEach(function () { | ||
Layout::factory()->create([ | ||
'identifier' => 'pages.show', | ||
]); | ||
use function Pest\Laravel\artisan; | ||
|
||
Layout::factory()->create([ | ||
'identifier' => 'pages.index', | ||
]); | ||
describe('It throws errors when layouts do not exist', function () { | ||
it('throws an error when the Detail layout doesnt exist', function () { | ||
Product::factory()->create()->layout(); | ||
})->throws(MissingLayoutException::class); | ||
|
||
Layout::factory()->create([ | ||
'identifier' => 'promotions', | ||
]); | ||
it('throws an error when the Index layout doesnt exist', function () { | ||
Product::indexLayout(); | ||
})->throws(MissingLayoutException::class); | ||
}); | ||
|
||
it('finds the show layout using the default key', function () { | ||
$page = Page::factory()->create(); | ||
describe('It returns Blade Layouts for Layoutables', function () { | ||
beforeEach(function () { | ||
setBladePath('sync'); | ||
artisan('contentable:sync')->assertExitCode(0); | ||
}); | ||
|
||
expect($layout = $page->layout())->toBeInstanceOf(Layout::class); | ||
expect($layout->layoutKey())->toBe('pages.show'); | ||
expect($layout->bladeTemplate())->toBe('layouts.pages.show'); | ||
expect($layout->inertiaComponent())->toBe('Pages/Show'); | ||
it('can return a global Blade Layout', function () { | ||
$layout = Layout::query() | ||
->where('key', 'default') | ||
->first(); | ||
|
||
$page = Page::factory()->create([ | ||
'layout_id' => $layout->id, | ||
]); | ||
|
||
expect($layout = $page->layout())->not->toBeNull(); | ||
expect($layout->name)->toBe('Default'); | ||
expect($layout->type)->toBe(LayoutType::Global); | ||
expect($layout->layoutable)->toBeNull(); | ||
}); | ||
|
||
it('can return a layoutable Blade Layout', function () { | ||
$layout = Layout::query() | ||
->where('key', 'pages.landing') | ||
->first(); | ||
|
||
$page = Page::factory()->create([ | ||
'layout_id' => $layout->id, | ||
]); | ||
|
||
expect($layout = $page->layout())->not->toBeNull(); | ||
expect($layout->name)->toBe('Landing Page'); | ||
expect($layout->type)->toBe(LayoutType::Custom); | ||
expect($layout->layoutable)->toBe(Page::layoutKey()); | ||
}); | ||
|
||
it('can return an index Blade layout', function () { | ||
expect($layout = Product::indexLayout())->not->toBeNull(); | ||
expect($layout->name)->toBe('Product Index'); | ||
expect($layout->type)->toBe(LayoutType::Index); | ||
expect($layout->layoutable)->toBe(Product::layoutKey()); | ||
}); | ||
}); | ||
|
||
it('finds the index layout using the default key', function () { | ||
expect($layout = Page::indexLayout())->toBeInstanceOf(Layout::class); | ||
expect($layout->layoutKey())->toBe('pages.index'); | ||
expect($layout->bladeTemplate())->toBe('layouts.pages.index'); | ||
expect($layout->inertiaComponent())->toBe('Pages/Index'); | ||
describe('It returns Inertia Layouts for Layoutables', function () { | ||
beforeEach(function () { | ||
config()->set('contentable.layouts.mode', LayoutMode::InertiaJsx); | ||
setInertiaPath('Sync'); | ||
|
||
artisan('contentable:sync')->assertExitCode(0); | ||
}); | ||
|
||
it('can return a global Inertia Layout', function () { | ||
$layout = Layout::query() | ||
->where('key', 'Default') | ||
->first(); | ||
|
||
|
||
$page = Page::factory()->create([ | ||
'layout_id' => $layout->id, | ||
]); | ||
|
||
expect($layout = $page->layout())->not->toBeNull(); | ||
expect($layout->name)->toBe('Default'); | ||
expect($layout->type)->toBe(LayoutType::Global); | ||
expect($layout->layoutable)->toBeNull(); | ||
}); | ||
|
||
it('can return a layoutable Inertia Layout', function () { | ||
$layout = Layout::query() | ||
->where('key', 'Pages/Landing') | ||
->first(); | ||
|
||
$page = Page::factory()->create([ | ||
'layout_id' => $layout->id, | ||
]); | ||
|
||
expect($layout = $page->layout())->not->toBeNull(); | ||
expect($layout->name)->toBe('Landing Page'); | ||
expect($layout->type)->toBe(LayoutType::Custom); | ||
expect($layout->layoutable)->toBe(Page::layoutKey()); | ||
}); | ||
|
||
it('can return an index Inertia layout', function () { | ||
expect($layout = Product::indexLayout())->not->toBeNull(); | ||
expect($layout->name)->toBe('Product Index'); | ||
expect($layout->type)->toBe(LayoutType::Index); | ||
expect($layout->layoutable)->toBe(Product::layoutKey()); | ||
}); | ||
}); | ||
|
||
it('finds the show layout using a custom key', function () { | ||
$page = Page::factory()->create([ | ||
'title' => 'Promotions', | ||
]); | ||
describe('It returns layout options for blade', function () { | ||
beforeEach(function () { | ||
setBladePath('sync'); | ||
artisan('contentable:sync')->assertExitCode(0); | ||
}); | ||
|
||
it('returns all but excluded layouts for models that include global layouts', function () { | ||
$page = Page::factory()->create(); | ||
|
||
expect($layouts = $page->layouts())->toHaveCount(4); | ||
|
||
expect($layout = $layouts->where('key', 'holidays')->first())->toBeNull(); | ||
|
||
expect($layout = $layouts->where('key', 'default')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Default'); | ||
expect($layout->type)->toBe(LayoutType::Global); | ||
expect($layout->layoutable)->toBeNull(); | ||
|
||
expect($layout = $layouts->where('key', 'pages.index')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Page Index'); | ||
expect($layout->type)->toBe(LayoutType::Index); | ||
expect($layout->layoutable)->toBe(Page::layoutKey()); | ||
|
||
expect($layout = $layouts->where('key', 'pages.show')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Page Details'); | ||
expect($layout->type)->toBe(LayoutType::Show); | ||
expect($layout->layoutable)->toBe(Page::layoutKey()); | ||
|
||
expect($layout = $layouts->where('key', 'pages.landing')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Landing Page'); | ||
expect($layout->type)->toBe(LayoutType::Custom); | ||
expect($layout->layoutable)->toBe(Page::layoutKey()); | ||
}); | ||
|
||
it('excludes all global layouts for layoutables which should not use them', function () { | ||
$post = Post::factory()->create(); | ||
|
||
expect($layouts = $post->layouts())->toHaveCount(3); | ||
|
||
expect($layout = $layouts->where('key', 'holidays')->first())->toBeNull(); | ||
expect($layout = $layouts->where('key', 'default')->first())->toBeNull(); | ||
|
||
expect($layout = $layouts->where('key', 'posts.index')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Post Index'); | ||
expect($layout->type)->toBe(LayoutType::Index); | ||
expect($layout->layoutable)->toBe(Post::layoutKey()); | ||
|
||
expect($layout = $layouts->where('key', 'posts.show')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Post Details'); | ||
expect($layout->type)->toBe(LayoutType::Show); | ||
expect($layout->layoutable)->toBe(Post::layoutKey()); | ||
|
||
expect($layout = $layouts->where('key', 'posts.featured')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Featured Post'); | ||
expect($layout->type)->toBe(LayoutType::Custom); | ||
expect($layout->layoutable)->toBe(Post::layoutKey()); | ||
}); | ||
|
||
it('shows all layouts when global layouts are available and non are excluded', function () { | ||
$product = Product::factory()->create(); | ||
|
||
expect($layouts = $product->layouts())->toHaveCount(5); | ||
|
||
expect($layout = $layouts->where('key', 'holidays')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Holidays'); | ||
expect($layout->type)->toBe(LayoutType::Global); | ||
expect($layout->layoutable)->toBeNull(); | ||
|
||
expect($layout = $layouts->where('key', 'default')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Default'); | ||
expect($layout->type)->toBe(LayoutType::Global); | ||
expect($layout->layoutable)->toBeNull(); | ||
|
||
expect($layout = $layouts->where('key', 'products.index')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Product Index'); | ||
expect($layout->type)->toBe(LayoutType::Index); | ||
expect($layout->layoutable)->toBe(Product::layoutKey()); | ||
|
||
expect($layout = $layouts->where('key', 'products.show')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Product Details'); | ||
expect($layout->type)->toBe(LayoutType::Show); | ||
expect($layout->layoutable)->toBe(Product::layoutKey()); | ||
|
||
expect($layout = $page->layout())->toBeInstanceOf(Layout::class); | ||
expect($layout->layoutKey())->toBe('promotions'); | ||
expect($layout->bladeTemplate())->toBe('layouts.promotions'); | ||
expect($layout->inertiaComponent())->toBe('Promotions'); | ||
expect($layout = $layouts->where('key', 'products.promo')->first())->not->toBeNull(); | ||
expect($layout->name)->toBe('Promo Product'); | ||
expect($layout->type)->toBe(LayoutType::Custom); | ||
expect($layout->layoutable)->toBe(Product::layoutKey()); | ||
}); | ||
}); |
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?php | ||
|
||
namespace Plank\Contentable\Tests\Helper\Database\Factories; | ||
|
||
use Illuminate\Database\Eloquent\Factories\Factory; | ||
use Plank\Contentable\Tests\Helper\Models\Post; | ||
|
||
class PostFactory extends Factory | ||
{ | ||
protected $model = Post::class; | ||
|
||
public function definition() | ||
{ | ||
return [ | ||
'title' => $title = $this->faker->sentence, | ||
'slug' => str($title)->slug(), | ||
]; | ||
} | ||
|
||
public function configure() | ||
{ | ||
return $this->afterMaking(function (Post $post) { | ||
$post->slug = (string) str($post->title)->slug(); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace Plank\Contentable\Tests\Helper\Database\Factories; | ||
|
||
use Illuminate\Database\Eloquent\Factories\Factory; | ||
use Plank\Contentable\Tests\Helper\Models\Product; | ||
|
||
class ProductFactory extends Factory | ||
{ | ||
protected $model = Product::class; | ||
|
||
public function definition() | ||
{ | ||
return [ | ||
'title' => $this->faker->words(3, true), | ||
'code' => $this->faker->unique()->numberBetween(10000, 99999), | ||
'price_in_cents' => $this->faker->numberBetween(99, 99999), | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
|
||
use Illuminate\Database\Migrations\Migration; | ||
use Illuminate\Database\Schema\Blueprint; | ||
use Illuminate\Support\Facades\Schema; | ||
|
||
return new class extends Migration | ||
{ | ||
public function up() | ||
{ | ||
Schema::create('posts', function (Blueprint $table) { | ||
$table->id(); | ||
$table->string('title'); | ||
$table->string('slug'); | ||
$table->foreignId('layout_id')->nullable()->constrained(); | ||
$table->timestamps(); | ||
}); | ||
} | ||
|
||
public function down() | ||
{ | ||
Schema::dropIfExists('posts'); | ||
} | ||
}; |
25 changes: 25 additions & 0 deletions
25
tests/Helper/Database/Migrations/create_products_table.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php | ||
|
||
use Illuminate\Database\Migrations\Migration; | ||
use Illuminate\Database\Schema\Blueprint; | ||
use Illuminate\Support\Facades\Schema; | ||
|
||
return new class extends Migration | ||
{ | ||
public function up() | ||
{ | ||
Schema::create('products', function (Blueprint $table) { | ||
$table->id(); | ||
$table->string('title'); | ||
$table->string('code'); | ||
$table->integer('price_in_cents'); | ||
$table->foreignId('layout_id')->nullable()->constrained(); | ||
$table->timestamps(); | ||
}); | ||
} | ||
|
||
public function down() | ||
{ | ||
Schema::dropIfExists('products'); | ||
} | ||
}; |
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace Plank\Contentable\Tests\Helper\Models; | ||
|
||
use Illuminate\Database\Eloquent\Factories\HasFactory; | ||
use Illuminate\Database\Eloquent\Model; | ||
use Plank\Contentable\Concerns\HasContent; | ||
use Plank\Contentable\Concerns\HasLayouts; | ||
use Plank\Contentable\Contracts\Contentable; | ||
use Plank\Contentable\Contracts\Layoutable; | ||
|
||
class Post extends Model implements Contentable, Layoutable | ||
{ | ||
use HasContent; | ||
use HasFactory; | ||
use HasLayouts; | ||
|
||
protected $guarded = ['id']; | ||
|
||
protected bool $globalLayouts = false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php | ||
|
||
namespace Plank\Contentable\Tests\Helper\Models; | ||
|
||
use Illuminate\Database\Eloquent\Factories\HasFactory; | ||
use Illuminate\Database\Eloquent\Model; | ||
use Plank\Contentable\Concerns\HasContent; | ||
use Plank\Contentable\Concerns\HasLayouts; | ||
use Plank\Contentable\Contracts\Contentable; | ||
use Plank\Contentable\Contracts\Layoutable; | ||
|
||
class Product extends Model implements Contentable, Layoutable | ||
{ | ||
use HasContent; | ||
use HasFactory; | ||
use HasLayouts; | ||
|
||
protected $guarded = ['id']; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters