code16/sharp
Code-driven CMS framework for Laravel (PHP 8.3+/Laravel 11+). Build admin/CMS sections with a clean UI and strong DX: CRUD with validation, search/sort/filter, bulk or custom commands, and authorization—no front-end code required, data-agnostic.
::: tip INFO This page documents the new Testing API. If you use the legacy one, please refer to Testing (legacy). :::
Sharp provides a fluent testing API to help you test your Sharp code. These assertions and helpers are designed to be used in Feature tests.
SharpAssertions traitTo use Sharp's testing helpers, include the Code16\Sharp\Utils\Testing\SharpAssertions trait in your TestCase class:
use Code16\Sharp\Utils\Testing\SharpAssertions;
abstract class TestCase extends BaseTestCase
{
use SharpAssertions;
// ...
}
or in Pest.php:
use Code16\Sharp\Utils\Testing\SharpAssertions;
pest()
->extend(\Tests\TestCase::class)
->use(SharpAssertions::class);
loginAsSharpUser($user)Sharp provides a helper to log in a user. By default, it will use the SharpAssertions internal logic to ensure the user is authorized to access Sharp.
it('allows the user to access the list', function () {
$user = User::factory()->create();
$this
->loginAsSharpUser($user)
->sharpList(Post::class)
->get()
->assertOk();
});
Use sharpList() to test your Entity Lists.
sharpList(string $entityKey)Starts a fluent interaction with an Entity List.
$this->sharpList(Post::class)
->get()
->assertOk()
->assertListData(fn (AssertableJson $data) => $data
->count(3)
->has('0.title', 'My first post')
->etc()
);
You can use withFilter() to apply filters to the list before calling get() or a command.
$this->sharpList(Post::class)
->withFilter(CategoryFilter::class, 1)
->get()
->assertOk();
You can call an Entity Command directly from the list:
$this->sharpList(Post::class)
->entityCommand(ExportPosts::class)
->post()
->assertOk()
->assertReturnsDownload('posts.csv');
If the command has a form, you can test it:
$this->sharpList(Post::class)
->entityCommand(ExportPosts::class)
->getForm()
->assertFormData(fn (AssertableJson $data) => $data
->where('format', 'xls')
->etc()
)
->post(['format' => 'csv'])
->assertOk();
Similarly, you can call an Instance Command:
$this->sharpList(Post::class)
->instanceCommand(PublishPost::class, 1)
->post()
->assertOk()
->assertReturnsReload();
For commands that have multiple steps, you can use getNextStepForm():
$this->sharpList(Post::class)
->entityCommand(MyWizardCommand::class)
->getForm()
->post(['step1_data' => 'value'])
->assertReturnsStep('step2')
->getNextStepForm()
->assertFormData(fn (AssertableJson $data) => $data
->where('step2_field', 'default')
->etc()
)
->post(['step2_data' => 'value'])
->assertOk();
Use sharpShow() to test your Show Pages.
sharpShow(string $entityKey, $instanceId)Starts a fluent interaction with a Show Page.
$this->sharpShow(Post::class, 1)
->get()
->assertOk()
->assertShowData(fn (AssertableJson $data) => $data
->where('title', 'My first post')
->where('author', 'John Doe')
->etc()
);
$this->sharpShow(Post::class, 1)
->instanceCommand(PublishPost::class)
->post()
->assertOk();
Show Pages can contain embedded Entity Lists or Dashboards. You can test them using sharpListField() and sharpDashboardField().
sharpListField(string $entityKey)$this->sharpShow(Post::class, 1)
->sharpListField(Comment::class)
->get()
->assertOk()
->assertListData(fn (AssertableJson $data) => $data
->count(5)
);
sharpDashboardField(string $entityKey)$this->sharpShow(User::class, 1)
->sharpDashboardField(UserStatsDashboard::class)
->get()
->assertOk();
There are some cases where you have nested shows by navigating through Show List fields. You can chain sharpShow() calls to simulate the correct breadcrumb :
$this->sharpList(Post::class)
->sharpShow(Post::class, 1)
->sharpListField(Comment::class)
->sharpShow(Comment::class, 1)
->assertOk();
Use sharpForm() to test your Forms.
sharpForm(string $entityKey, $instanceId = null)Starts a fluent interaction with a Form. If $instanceId is provided, it targets an edit form; otherwise, it targets a creation form.
// Create
$this->sharpForm(Post::class)
->store(['title' => 'New Post'])
->assertValid()
->assertRedirect();
// Update
$this->sharpForm(Post::class, 1)
->update(['title' => 'Updated Post'])
->assertValid()
->assertRedirect();
If you want to test that the form displays correctly:
$this->sharpForm(Post::class, 1)
->edit()
->assertOk()
->assertFormData(fn (AssertableJson $data) => $data
->where('title', 'Existing Post')
->etc()
);
From an AssertableForm (the result of edit() or create()), you can also call update() or store():
$this->sharpForm(Post::class, 1)
->edit()
->update(['title' => 'New title'])
->assertValid();
Use sharpDashboard() to test your Dashboards.
sharpDashboard(string $entityKey)Starts a fluent interaction with a Dashboard.
$this->sharpDashboard(MyDashboard::class)
->get()
->assertOk();
$this->sharpDashboard(MyDashboard::class)
->withFilter(PeriodFilter::class, ['start' => '2023-01-01', 'end' => '2023-01-31'])
->get()
->assertOk();
$this->sharpDashboard(MyDashboard::class)
->dashboardCommand(RefreshStats::class)
->post()
->assertOk();
If your app contains global filters, you should be able to test normally, but it will be set to its default value. If you need, you can set a specific value using withGlobalFilter():
$this->withSharpGlobalFilter(CompanyFilter::class, 'apple')
->sharpList(Post::class)
//...
How can I help you explore Laravel packages today?