Skip to content

Commit 3b9b877

Browse files
committed
update data assertion methods
1 parent 7227768 commit 3b9b877

9 files changed

Lines changed: 197 additions & 84 deletions

File tree

docs/guide/testing.md

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Testing
22

3+
::: tip INFO
4+
This page documents the new Testing API. If you use the legacy one, please refer to [Testing (legacy)](../legacy/testing.md).
5+
:::
6+
37
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.
48

59
## The `SharpAssertions` trait
@@ -24,7 +28,7 @@ use Code16\Sharp\Utils\Testing\SharpAssertions;
2428

2529
pest()
2630
->extend(\Tests\TestCase::class)
27-
->use(SharpAssertions::class)
31+
->use(SharpAssertions::class);
2832
```
2933

3034
## Authentication
@@ -57,8 +61,11 @@ Starts a fluent interaction with an Entity List.
5761
$this->sharpList(Post::class)
5862
->get()
5963
->assertOk()
60-
->assertListCount(3)
61-
->assertListContains(['title' => 'My first post']);
64+
->assertListData(fn (AssertableJson $data) => $data
65+
->count(3)
66+
->has('0.title', 'My first post')
67+
->etc()
68+
);
6269
```
6370

6471
### Filtering the list
@@ -85,11 +92,15 @@ $this->sharpList(Post::class)
8592
```
8693

8794
If the command has a form, you can test it:
88-
95+
8996
```php
9097
$this->sharpList(Post::class)
9198
->entityCommand(ExportPosts::class)
9299
->getForm()
100+
->assertFormData(fn (AssertableJson $data) => $data
101+
->where('format', 'xls')
102+
->etc()
103+
)
93104
->post(['format' => 'csv'])
94105
->assertOk();
95106
```
@@ -117,6 +128,10 @@ $this->sharpList(Post::class)
117128
->post(['step1_data' => 'value'])
118129
->assertReturnsStep('step2')
119130
->getNextStepForm()
131+
->assertFormData(fn (AssertableJson $data) => $data
132+
->where('step2_field', 'default')
133+
->etc()
134+
)
120135
->post(['step2_data' => 'value'])
121136
->assertOk();
122137
```
@@ -133,10 +148,11 @@ Starts a fluent interaction with a Show Page.
133148
$this->sharpShow(Post::class, 1)
134149
->get()
135150
->assertOk()
136-
->assertShowData([
137-
'title' => 'My first post',
138-
'author' => 'John Doe'
139-
]);
151+
->assertShowData(fn (AssertableJson $data) => $data
152+
->where('title', 'My first post')
153+
->where('author', 'John Doe')
154+
->etc()
155+
);
140156
```
141157

142158
### Instance Commands from Show
@@ -148,6 +164,43 @@ $this->sharpShow(Post::class, 1)
148164
->assertOk();
149165
```
150166

167+
### List & dashboard fields
168+
169+
Show Pages can contain embedded Entity Lists or Dashboards. You can test them using `sharpListField()` and `sharpDashboardField()`.
170+
171+
#### `sharpListField(string $entityKey)`
172+
173+
```php
174+
$this->sharpShow(Post::class, 1)
175+
->sharpListField(Comment::class)
176+
->get()
177+
->assertOk()
178+
->assertListData(fn (AssertableJson $data) => $data
179+
->count(5)
180+
);
181+
```
182+
183+
#### `sharpDashboardField(string $entityKey)`
184+
185+
```php
186+
$this->sharpShow(User::class, 1)
187+
->sharpDashboardField(UserStatsDashboard::class)
188+
->get()
189+
->assertOk();
190+
```
191+
192+
### Nested shows
193+
194+
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 :
195+
196+
```php
197+
$this->sharpList(Post::class)
198+
->sharpShow(Post::class, 1)
199+
->sharpListField(Comment::class)
200+
->sharpShow(Comment::class, 1)
201+
->assertOk();
202+
```
203+
151204
## Testing Forms
152205

153206
Use `sharpForm()` to test your Forms.
@@ -180,7 +233,10 @@ If you want to test that the form displays correctly:
180233
$this->sharpForm(Post::class, 1)
181234
->edit()
182235
->assertOk()
183-
->assertFormData(['title' => 'Existing Post']);
236+
->assertFormData(fn (AssertableJson $data) => $data
237+
->where('title', 'Existing Post')
238+
->etc()
239+
);
184240
```
185241

186242
From an `AssertableForm` (the result of `edit()` or `create()`), you can also call `update()` or `store()`:
@@ -223,26 +279,3 @@ $this->sharpDashboard(MyDashboard::class)
223279
->post()
224280
->assertOk();
225281
```
226-
227-
## Testing Embedded Components
228-
229-
Show Pages can contain embedded Entity Lists or Dashboards. You can test them using `sharpListField()` and `sharpDashboardField()`.
230-
231-
### `sharpListField(string $entityKey)`
232-
233-
```php
234-
$this->sharpShow(Post::class, 1)
235-
->sharpListField(Comment::class)
236-
->get()
237-
->assertOk()
238-
->assertListCount(5);
239-
```
240-
241-
### `sharpDashboardField(string $entityKey)`
242-
243-
```php
244-
$this->sharpShow(User::class, 1)
245-
->sharpDashboardField(UserStatsDashboard::class)
246-
->get()
247-
->assertOk();
248-
```

src/Data/Commands/CommandFormData.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function __construct(
2323
/** @var array<string> */
2424
public ?array $locales = null,
2525
public ?PageAlertData $pageAlert = null,
26+
public ?array $_rawData = null,
2627
) {}
2728

2829
public static function from(array $form): self
@@ -36,6 +37,7 @@ public static function from(array $form): self
3637
layout: FormLayoutData::optional($form['layout'] ?? null),
3738
locales: $form['locales'] ?? null,
3839
pageAlert: PageAlertData::optional($form['pageAlert']),
40+
_rawData: $form['_rawData'] ?? null,
3941
);
4042
}
4143
}

src/Http/Controllers/Api/Commands/HandlesCommandForm.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ protected function getCommandForm(InstanceCommand|EntityCommand|DashboardCommand
3333
'locales' => $commandHandler->hasDataLocalizations()
3434
? $commandHandler->getDataLocalizations()
3535
: null,
36+
...app()->environment('testing') ? [
37+
'_rawData' => $formData,
38+
] : [],
3639
];
3740
}
3841
}

src/Http/Controllers/FormController.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public function create(string $globalFilter, string $parentUri, EntityKey $entit
3737
$form->buildFormConfig();
3838
$formData = $form->newInstance();
3939

40+
if (app()->environment('testing')) {
41+
Inertia::share('_rawData', $formData);
42+
}
43+
4044
return Inertia::render('Form/Form', [
4145
'form' => FormData::from([
4246
...$this->buildFormData($form, $formData, $entityKey),
@@ -90,6 +94,10 @@ public function edit(string $globalFilter, string $parentUri, EntityKey $entityK
9094
->breadcrumb()
9195
->getParentShowCachedBreadcrumbLabel() ?: $entity->getLabelOrFail($entityKey->multiformKey());
9296

97+
if (app()->environment('testing')) {
98+
Inertia::share('_rawData', $formData);
99+
}
100+
93101
return Inertia::render('Form/Form', [
94102
'form' => FormData::from([
95103
...$this->buildFormData($form, $formData, $entityKey, $instanceId),

src/Utils/Testing/Commands/AssertableCommandForm.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Code16\Sharp\EntityList\SharpEntityList;
88
use Code16\Sharp\Show\SharpShow;
99
use Code16\Sharp\Utils\Testing\DelegatesToResponse;
10+
use Illuminate\Testing\Fluent\AssertableJson;
1011
use Illuminate\Testing\TestResponse;
1112

1213
class AssertableCommandForm
@@ -35,7 +36,20 @@ public function post(array $data = []): AssertableCommand
3536
);
3637
}
3738

38-
public function formData(): ?array
39+
/**
40+
* @param Closure(AssertableJson): mixed $callback
41+
*/
42+
public function assertFormData(Closure $callback): static
43+
{
44+
$this->response->assertJson(fn (AssertableJson $json) => $json
45+
->has('_rawData', $callback)
46+
->etc()
47+
);
48+
49+
return $this;
50+
}
51+
52+
protected function formData(): ?array
3953
{
4054
return $this->response->json('data');
4155
}

src/Utils/Testing/EntityList/AssertableEntityList.php

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
namespace Code16\Sharp\Utils\Testing\EntityList;
44

5+
use Closure;
56
use Code16\Sharp\Utils\Testing\DelegatesToResponse;
67
use Code16\Sharp\Utils\Testing\Show\PendingShow;
8+
use Illuminate\Testing\Fluent\AssertableJson;
79
use Illuminate\Testing\TestResponse;
8-
use PHPUnit\Framework\Assert as PHPUnit;
10+
use Inertia\Testing\AssertableInertia;
911

1012
class AssertableEntityList
1113
{
@@ -16,33 +18,23 @@ public function __construct(
1618
protected PendingEntityList $pendingEntityList,
1719
) {}
1820

19-
public function assertListCount(int $count): self
21+
/**
22+
* @param Closure(AssertableJson): mixed $callback
23+
*/
24+
public function assertListData(Closure $closure): static
2025
{
21-
PHPUnit::assertCount($count, $this->listData());
26+
if ($this->pendingEntityList->parent instanceof PendingShow) {
27+
$this->response->assertJson(fn (AssertableJson $json) => $json
28+
->has('data', $closure)
29+
->etc()
30+
);
31+
} else {
32+
$this->response->assertInertia(fn (AssertableInertia $page) => $page
33+
->has('entityList.data', $closure)
34+
->etc()
35+
);
36+
}
2237

2338
return $this;
2439
}
25-
26-
public function assertListContains(array $attributes): self
27-
{
28-
PHPUnit::assertTrue(
29-
collect($this->listData())
30-
->contains(fn ($item) => collect($attributes)
31-
->every(fn ($value, $key) => isset($item[$key]) && $item[$key] === $value)
32-
),
33-
sprintf(
34-
'Failed asserting that data contains an item with attributes: %s',
35-
json_encode($attributes)
36-
)
37-
);
38-
39-
return $this;
40-
}
41-
42-
protected function listData(): array
43-
{
44-
return $this->pendingEntityList->parent instanceof PendingShow
45-
? $this->response->json('data')
46-
: $this->response->inertiaProps('entityList.data');
47-
}
4840
}

src/Utils/Testing/Form/AssertableForm.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
namespace Code16\Sharp\Utils\Testing\Form;
44

5+
use Closure;
56
use Code16\Sharp\Utils\Testing\DelegatesToResponse;
7+
use Illuminate\Testing\Fluent\AssertableJson;
68
use Illuminate\Testing\TestResponse;
9+
use Inertia\Testing\AssertableInertia;
710

811
class AssertableForm
912
{
@@ -29,7 +32,20 @@ public function update(array $data = []): TestResponse
2932
);
3033
}
3134

32-
public function formData(): array
35+
/**
36+
* @param Closure(AssertableJson): mixed $callback
37+
*/
38+
public function assertFormData(Closure $callback): static
39+
{
40+
$this->response->assertInertia(fn (AssertableInertia $page) => $page
41+
->has('_rawData', fn (AssertableJson $json) => $callback($json))
42+
->etc()
43+
);
44+
45+
return $this;
46+
}
47+
48+
protected function formData(): array
3349
{
3450
return $this->response->inertiaProps('form.data');
3551
}

src/Utils/Testing/Show/AssertableShow.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Code16\Sharp\Utils\Testing\Show;
44

5+
use Closure;
56
use Code16\Sharp\Utils\Testing\DelegatesToResponse;
67
use Illuminate\Testing\Fluent\AssertableJson;
78
use Illuminate\Testing\TestResponse;
@@ -15,15 +16,14 @@ public function __construct(
1516
protected TestResponse $response,
1617
) {}
1718

18-
public function showData(): array
19-
{
20-
return $this->response->inertiaProps('_rawData');
21-
}
22-
23-
public function assertShowData(array $expectedData): self
19+
/**
20+
* @param Closure(AssertableJson): mixed $callback
21+
*/
22+
public function assertShowData(Closure $callback): static
2423
{
2524
$this->response->assertInertia(fn (AssertableInertia $page) => $page
26-
->has('_rawData', fn (AssertableJson $json) => $json->whereAll($expectedData)->etc())
25+
->has('_rawData', fn (AssertableJson $json) => $callback($json))
26+
->etc()
2727
);
2828

2929
return $this;

0 commit comments

Comments
 (0)