Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/.vitepress/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ export function sidebar(): DefaultTheme.SidebarItem[] {
{ text: 'Sharp Context', link: '/guide/context.md' },
{ text: 'Sharp built-in solution for uploads', link: '/guide/sharp-uploads.md' },
{ text: 'Data localization in Form and Show Page', link: '/guide/data-localization.md' },
{ text: 'Testing with Sharp', link: '/guide/testing-with-sharp.md' },
{ text: 'Testing', link: '/guide/testing.md' },
{ text: 'Testing (legacy API)', link: '/guide/testing-legacy.md' },
{ text: 'Artisan Generators', link: '/guide/artisan-generators.md' },
{ text: 'Style & Visual Theme', link: '/guide/style-visual-theme.md' }
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Testing with Sharp
# Testing with Sharp (legacy API)

::: warning
This page documents the old Testing API, we recommend using the new [Testing API](/guide/testing).
:::

Sharp provides a few assertions and helpers to help you test your Sharp code.

Expand Down
248 changes: 248 additions & 0 deletions docs/guide/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
# Testing

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.

## The `SharpAssertions` trait

To use Sharp's testing helpers, include the `Code16\Sharp\Utils\Testing\SharpAssertions` trait in your TestCase class:

```php
use Code16\Sharp\Utils\Testing\SharpAssertions;

abstract class TestCase extends BaseTestCase
{
use SharpAssertions;

// ...
}
```

or in `Pest.php`:

```php
use Code16\Sharp\Utils\Testing\SharpAssertions;

pest()
->extend(\Tests\TestCase::class)
->use(SharpAssertions::class)
```

## Authentication

### `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.

```php
it('allows the user to access the list', function () {
$user = User::factory()->create();

$this
->loginAsSharpUser($user)
->sharpList(Post::class)
->get()
->assertOk();
});
```

## Testing Entity Lists

Use `sharpList()` to test your Entity Lists.

### `sharpList(string $entityKey)`

Starts a fluent interaction with an Entity List.

```php
$this->sharpList(Post::class)
->get()
->assertOk()
->assertListCount(3)
->assertListContains(['title' => 'My first post']);
```

### Filtering the list

You can use `withFilter()` to apply filters to the list before calling `get()` or a command.

```php
$this->sharpList(Post::class)
->withFilter(CategoryFilter::class, 1)
->get()
->assertOk();
```

### Entity Commands

You can call an Entity Command directly from the list:

```php
$this->sharpList(Post::class)
->entityCommand(ExportPosts::class)
->post()
->assertOk()
->assertReturnsDownload('posts.csv');
```

If the command has a form, you can test it:

```php
$this->sharpList(Post::class)
->entityCommand(ExportPosts::class)
->getForm()
->post(['format' => 'csv'])
->assertOk();
```

### Instance Commands

Similarly, you can call an Instance Command:

```php
$this->sharpList(Post::class)
->instanceCommand(PublishPost::class, 1)
->post()
->assertOk()
->assertReturnsReload();
```

### Multi-step Commands (Wizards)

For commands that have multiple steps, you can use `getNextStepForm()`:

```php
$this->sharpList(Post::class)
->entityCommand(MyWizardCommand::class)
->getForm()
->post(['step1_data' => 'value'])
->assertReturnsStep('step2')
->getNextStepForm()
->post(['step2_data' => 'value'])
->assertOk();
```

## Testing Show Pages

Use `sharpShow()` to test your Show Pages.

### `sharpShow(string $entityKey, $instanceId)`

Starts a fluent interaction with a Show Page.

```php
$this->sharpShow(Post::class, 1)
->get()
->assertOk()
->assertShowData([
'title' => 'My first post',
'author' => 'John Doe'
]);
```

### Instance Commands from Show

```php
$this->sharpShow(Post::class, 1)
->instanceCommand(PublishPost::class)
->post()
->assertOk();
```

## Testing Forms

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.

### Creating and Updating

```php
// Create
$this->sharpForm(Post::class)
->store(['title' => 'New Post'])
->assertValid()
->assertRedirect();

// Update
$this->sharpForm(Post::class, 1)
->update(['title' => 'Updated Post'])
->assertValid()
->assertRedirect();
```

### Testing the "Creation" or "Edit" request itself

If you want to test that the form displays correctly:

```php
$this->sharpForm(Post::class, 1)
->edit()
->assertOk()
->assertFormData(['title' => 'Existing Post']);
```

From an `AssertableForm` (the result of `edit()` or `create()`), you can also call `update()` or `store()`:

```php
$this->sharpForm(Post::class, 1)
->edit()
->update(['title' => 'New title'])
->assertValid();
```

## Testing Dashboards

Use `sharpDashboard()` to test your Dashboards.

### `sharpDashboard(string $entityKey)`

Starts a fluent interaction with a Dashboard.

```php
$this->sharpDashboard(MyDashboard::class)
->get()
->assertOk();
```

### Filtering the dashboard

```php
$this->sharpDashboard(MyDashboard::class)
->withFilter(PeriodFilter::class, ['start' => '2023-01-01', 'end' => '2023-01-31'])
->get()
->assertOk();
```

### Dashboard Commands

```php
$this->sharpDashboard(MyDashboard::class)
->dashboardCommand(RefreshStats::class)
->post()
->assertOk();
```

## Testing Embedded Components

Show Pages can contain embedded Entity Lists or Dashboards. You can test them using `sharpListField()` and `sharpDashboardField()`.

### `sharpListField(string $entityKey)`

```php
$this->sharpShow(Post::class, 1)
->sharpListField(Comment::class)
->get()
->assertOk()
->assertListCount(5);
```

### `sharpDashboardField(string $entityKey)`

```php
$this->sharpShow(User::class, 1)
->sharpDashboardField(UserStatsDashboard::class)
->get()
->assertOk();
```
2 changes: 1 addition & 1 deletion docs/guide/upgrading/9.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ All assertions, like for instance `assertSharpHasAuthorization`, were removed be

This means you also need to remove all `$this->initSharpAssertions()` calls from your tests.

Of course, the test helpers remain available, see the dedicated [testing documentation](../testing-with-sharp.md).
Of course, the test helpers remain available, see the dedicated [testing documentation](../testing.md).

Also take note that the `withSharpCurrentBreadcrumb()` method is now deprecated, in favor of the new `withSharpBreadcrumb()` method also documented in the section linked above.

Expand Down
11 changes: 11 additions & 0 deletions ide.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@
"parameters": [
1
]
},
{
"classFqn": [
"Code16\\Sharp\\Utils\\Testing\\Commands\\AssertableCommand"
],
"methodNames": [
"assertReturnsView"
],
"parameters": [
1
]
}
]
},
Expand Down
4 changes: 4 additions & 0 deletions src/Http/Controllers/ShowController.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ public function show(string $globalFilter, string $parentUri, EntityKey $entityK

$this->addPreloadHeadersForShowEntityLists($payload);

if (app()->environment('testing')) {
Inertia::share('_rawData', $showData);
}

return Inertia::render('Show/Show', [
'show' => $payload,
'breadcrumb' => BreadcrumbData::from([
Expand Down
4 changes: 4 additions & 0 deletions src/Http/Controllers/SingleShowController.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public function show(string $globalFilter, EntityKey $entityKey)

$this->addPreloadHeadersForShowEntityLists($payload);

if (app()->environment('testing')) {
Inertia::share('_rawData', $showData);
}

return Inertia::render('Show/Show', [
'show' => $payload,
'breadcrumb' => BreadcrumbData::from([
Expand Down
1 change: 1 addition & 0 deletions src/Show/Fields/SharpShowEntityListField.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ public function toArray(): array
]),
function (array &$options) {
$options['endpointUrl'] = route('code16.sharp.api.list', [
'globalFilter' => sharp()->context()->globalFilterUrlSegmentValue(),
'entityKey' => $this->entityListKey,
'current_page_url' => request()->url(),
...app(SharpEntityManager::class)
Expand Down
Loading
Loading