|
| 1 | +# Testing |
| 2 | + |
| 3 | +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. |
| 4 | + |
| 5 | +## The `SharpAssertions` trait |
| 6 | + |
| 7 | +To use Sharp's testing helpers, include the `Code16\Sharp\Utils\Testing\SharpAssertions` trait in your test class: |
| 8 | + |
| 9 | +```php |
| 10 | +use Code16\Sharp\Utils\Testing\SharpAssertions; |
| 11 | + |
| 12 | +class PostFormTest extends TestCase |
| 13 | +{ |
| 14 | + use SharpAssertions; |
| 15 | + |
| 16 | + // ... |
| 17 | +} |
| 18 | +``` |
| 19 | + |
| 20 | +## Authentication |
| 21 | + |
| 22 | +### `loginAsSharpUser($user)` |
| 23 | + |
| 24 | +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. |
| 25 | + |
| 26 | +```php |
| 27 | +it('allows the user to access the list', function () { |
| 28 | + $user = User::factory()->create(); |
| 29 | + |
| 30 | + $this |
| 31 | + ->loginAsSharpUser($user) |
| 32 | + ->sharpList(Post::class) |
| 33 | + ->get() |
| 34 | + ->assertOk(); |
| 35 | +}); |
| 36 | +``` |
| 37 | + |
| 38 | +## Testing Entity Lists |
| 39 | + |
| 40 | +Use `sharpList()` to test your Entity Lists. |
| 41 | + |
| 42 | +### `sharpList(string $entityKey)` |
| 43 | + |
| 44 | +Starts a fluent interaction with an Entity List. |
| 45 | + |
| 46 | +```php |
| 47 | +$this->sharpList(Post::class) |
| 48 | + ->get() |
| 49 | + ->assertOk() |
| 50 | + ->assertListCount(3) |
| 51 | + ->assertListContains(['title' => 'My first post']); |
| 52 | +``` |
| 53 | + |
| 54 | +### Filtering the list |
| 55 | + |
| 56 | +You can use `withFilter()` to apply filters to the list before calling `get()` or a command. |
| 57 | + |
| 58 | +```php |
| 59 | +$this->sharpList(Post::class) |
| 60 | + ->withFilter('category', 1) |
| 61 | + ->get() |
| 62 | + ->assertOk(); |
| 63 | +``` |
| 64 | + |
| 65 | +### Entity Commands |
| 66 | + |
| 67 | +You can call an Entity Command directly from the list: |
| 68 | + |
| 69 | +```php |
| 70 | +$this->sharpList(Post::class) |
| 71 | + ->callEntityCommand(ExportPosts::class, ['format' => 'csv']) |
| 72 | + ->assertOk() |
| 73 | + ->assertReturnsDownload('posts.csv'); |
| 74 | +``` |
| 75 | + |
| 76 | +### Instance Commands |
| 77 | + |
| 78 | +Similarly, you can call an Instance Command: |
| 79 | + |
| 80 | +```php |
| 81 | +$this->sharpList(Post::class) |
| 82 | + ->callInstanceCommand(1, PublishPost::class) |
| 83 | + ->assertOk() |
| 84 | + ->assertReturnsReload(); |
| 85 | +``` |
| 86 | + |
| 87 | +### Multi-step Commands (Wizards) |
| 88 | + |
| 89 | +For commands that have multiple steps, you can use `callNextStep()`: |
| 90 | + |
| 91 | +```php |
| 92 | +$this->sharpList(Post::class) |
| 93 | + ->callEntityCommand(MyWizardCommand::class, ['step1_data' => 'value']) |
| 94 | + ->assertReturnsStep('step2') |
| 95 | + ->callNextStep(['step2_data' => 'value']) |
| 96 | + ->assertOk(); |
| 97 | +``` |
| 98 | + |
| 99 | +## Testing Show Pages |
| 100 | + |
| 101 | +Use `sharpShow()` to test your Show Pages. |
| 102 | + |
| 103 | +### `sharpShow(string $entityKey, $instanceId)` |
| 104 | + |
| 105 | +Starts a fluent interaction with a Show Page. |
| 106 | + |
| 107 | +```php |
| 108 | +$this->sharpShow(Post::class, 1) |
| 109 | + ->get() |
| 110 | + ->assertOk() |
| 111 | + ->assertShowData([ |
| 112 | + 'title' => 'My first post', |
| 113 | + 'author' => 'John Doe' |
| 114 | + ]); |
| 115 | +``` |
| 116 | + |
| 117 | +### Instance Commands from Show |
| 118 | + |
| 119 | +```php |
| 120 | +$this->sharpShow(Post::class, 1) |
| 121 | + ->callInstanceCommand(PublishPost::class) |
| 122 | + ->assertOk(); |
| 123 | +``` |
| 124 | + |
| 125 | +## Testing Forms |
| 126 | + |
| 127 | +Use `sharpForm()` to test your Forms. |
| 128 | + |
| 129 | +### `sharpForm(string $entityKey, $instanceId = null)` |
| 130 | + |
| 131 | +Starts a fluent interaction with a Form. If `$instanceId` is provided, it targets an edit form; otherwise, it targets a creation form. |
| 132 | + |
| 133 | +### Creating and Updating |
| 134 | + |
| 135 | +```php |
| 136 | +// Create |
| 137 | +$this->sharpForm(Post::class) |
| 138 | + ->store(['title' => 'New Post']) |
| 139 | + ->assertValid() |
| 140 | + ->assertRedirect(); |
| 141 | + |
| 142 | +// Update |
| 143 | +$this->sharpForm(Post::class, 1) |
| 144 | + ->update(['title' => 'Updated Post']) |
| 145 | + ->assertValid() |
| 146 | + ->assertRedirect(); |
| 147 | +``` |
| 148 | + |
| 149 | +### Testing the "Creation" or "Edit" request itself |
| 150 | + |
| 151 | +If you want to test that the form displays correctly: |
| 152 | + |
| 153 | +```php |
| 154 | +$this->sharpForm(Post::class, 1) |
| 155 | + ->edit() |
| 156 | + ->assertOk() |
| 157 | + ->assertFormData(['title' => 'Existing Post']); |
| 158 | +``` |
| 159 | + |
| 160 | +From an `AssertableForm` (the result of `edit()` or `create()`), you can also call `update()` or `store()`: |
| 161 | + |
| 162 | +```php |
| 163 | +$this->sharpForm(Post::class, 1) |
| 164 | + ->edit() |
| 165 | + ->update(['title' => 'New title']) |
| 166 | + ->assertValid(); |
| 167 | +``` |
| 168 | + |
| 169 | +## Testing Dashboards |
| 170 | + |
| 171 | +Use `sharpDashboard()` to test your Dashboards. |
| 172 | + |
| 173 | +### `sharpDashboard(string $entityKey)` |
| 174 | + |
| 175 | +Starts a fluent interaction with a Dashboard. |
| 176 | + |
| 177 | +```php |
| 178 | +$this->sharpDashboard(MyDashboard::class) |
| 179 | + ->get() |
| 180 | + ->assertOk(); |
| 181 | +``` |
| 182 | + |
| 183 | +### Filtering the dashboard |
| 184 | + |
| 185 | +```php |
| 186 | +$this->sharpDashboard(MyDashboard::class) |
| 187 | + ->withFilter('period', '2023') |
| 188 | + ->get() |
| 189 | + ->assertOk(); |
| 190 | +``` |
| 191 | + |
| 192 | +### Dashboard Commands |
| 193 | + |
| 194 | +```php |
| 195 | +$this->sharpDashboard(MyDashboard::class) |
| 196 | + ->callDashboardCommand(RefreshStats::class) |
| 197 | + ->assertOk(); |
| 198 | +``` |
| 199 | + |
| 200 | +## Testing Embedded Components |
| 201 | + |
| 202 | +Show Pages can contain embedded Entity Lists or Dashboards. You can test them using `sharpListField()` and `sharpDashboardField()`. |
| 203 | + |
| 204 | +### `sharpListField(string $entityKey)` |
| 205 | + |
| 206 | +```php |
| 207 | +$this->sharpShow(Post::class, 1) |
| 208 | + ->sharpListField(Comment::class) |
| 209 | + ->get() |
| 210 | + ->assertOk() |
| 211 | + ->assertListCount(5); |
| 212 | +``` |
| 213 | + |
| 214 | +### `sharpDashboardField(string $entityKey)` |
| 215 | + |
| 216 | +```php |
| 217 | +$this->sharpShow(User::class, 1) |
| 218 | + ->sharpDashboardField(UserStatsDashboard::class) |
| 219 | + ->get() |
| 220 | + ->assertOk(); |
| 221 | +``` |
| 222 | + |
| 223 | +## Advanced: Breadcrumbs and Context |
| 224 | + |
| 225 | +Most of the time, Sharp handles the breadcrumb automatically. However, you might need to simulate a specific breadcrumb context. |
| 226 | + |
| 227 | +### `withSharpBreadcrumb(Closure $callback)` |
| 228 | + |
| 229 | +```php |
| 230 | +use Code16\Sharp\Utils\Links\BreadcrumbBuilder; |
| 231 | + |
| 232 | +$this->withSharpBreadcrumb(function (BreadcrumbBuilder $builder) { |
| 233 | + return $builder |
| 234 | + ->appendEntityList(Category::class) |
| 235 | + ->appendShowPage(Category::class, 1); |
| 236 | +}) |
| 237 | + ->sharpShow(Post::class, 1) |
| 238 | + ->get() |
| 239 | + ->assertOk(); |
| 240 | +``` |
0 commit comments