Skip to content

Commit d41ce78

Browse files
committed
feat(testing): Add view data assertions
1 parent c6237db commit d41ce78

File tree

4 files changed

+136
-4
lines changed

4 files changed

+136
-4
lines changed

src/Tempest/Framework/Testing/Http/TestResponseHelper.php

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function assertHeaderContains(string $name, mixed $value): self
5959
Assert::assertContains(
6060
$value,
6161
$header->values,
62-
sprintf('Failed to assert that response header [%s] value contains %s. These header values were found: %s', $name, $value, $headerString),
62+
sprintf('Failed to assert that response header [%s] value contains [%s]. These header values were found: %s', $name, $value, $headerString),
6363
);
6464

6565
return $this;
@@ -132,7 +132,7 @@ public function assertHasSession(string $key, ?Closure $test = null): self
132132
Assert::assertNotNull(
133133
$data,
134134
sprintf(
135-
'No session value was set for %s, available session keys: %s',
135+
'No session value was set for [%s], available session keys: %s',
136136
$key,
137137
implode(', ', array_keys($session->data)),
138138
),
@@ -156,7 +156,7 @@ public function assertHasValidationError(string $key, ?Closure $test = null): se
156156
$key,
157157
$validationErrors,
158158
sprintf(
159-
'No validation error was set for %s, available validation errors: %s',
159+
'No validation error was set for [%s], available validation errors: %s',
160160
$key,
161161
implode(', ', array_keys($validationErrors)),
162162
),
@@ -219,6 +219,78 @@ public function assertNotSee(string $search): self
219219
return $this;
220220
}
221221

222+
public function assertViewData(string $key, ?Closure $test = null): self
223+
{
224+
$data = $this->body->data;
225+
$value = $data[$key];
226+
227+
Assert::assertArrayHasKey(
228+
key: $key,
229+
array: $data,
230+
message: sprintf(
231+
'No view data was set for [%s], available view data keys: %s',
232+
$key,
233+
implode(', ', array_keys($data)),
234+
),
235+
);
236+
237+
if ($test !== null) {
238+
$test($data, $value);
239+
}
240+
241+
return $this;
242+
}
243+
244+
public function assertViewDataMissing(string $key): self
245+
{
246+
$data = $this->body->data;
247+
248+
Assert::assertArrayNotHasKey(
249+
key: $key,
250+
array: $data,
251+
message: sprintf('Failed asserting that view data key [%s] was not set', $key),
252+
);
253+
254+
return $this;
255+
}
256+
257+
public function assertViewDataAll(Closure $test): self
258+
{
259+
$data = $this->body->data;
260+
261+
$test($data);
262+
263+
return $this;
264+
}
265+
266+
public function assertView(string $view): self
267+
{
268+
if (! ($this->body instanceof View)) {
269+
Assert::fail(sprintf('Response is not a %s', View::class));
270+
}
271+
272+
Assert::assertEquals(
273+
expected: $view,
274+
actual: $this->body->path,
275+
);
276+
277+
return $this;
278+
}
279+
280+
public function assertViewModel(string $expected, ?Closure $test = null): self
281+
{
282+
Assert::assertInstanceOf(
283+
expected: $expected,
284+
actual: $this->body,
285+
);
286+
287+
if ($test !== null) {
288+
$test($this->body);
289+
}
290+
291+
return $this;
292+
}
293+
222294
public function dd(): void
223295
{
224296
// @phpstan-ignore disallowed.function

tests/Fixtures/Controllers/TestController.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Tempest\Router\Put;
2121
use Tempest\Router\Trace;
2222
use Tempest\View\View;
23+
use Tests\Tempest\Fixtures\Views\ViewModel;
2324
use Tests\Tempest\Fixtures\Views\ViewWithResponseData;
2425

2526
use function Tempest\view;
@@ -96,4 +97,10 @@ public function viewWithResponseData(): Response
9697
return new Created(new ViewWithResponseData())
9798
->addHeader('x-from-view', 'true');
9899
}
100+
101+
#[Get('/view-model')]
102+
public function viewModel(): Response
103+
{
104+
return new Ok(new ViewModel('Brent'));
105+
}
99106
}

tests/Fixtures/Views/ViewModel.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ final class ViewModel implements View
1414
public function __construct(
1515
public readonly string $name,
1616
) {
17-
$this->path = __DIR__ . '/withViewModel.php';
17+
$this->path = 'withViewModel.php';
18+
$this->relativeRootPath = __DIR__;
1819
}
1920

2021
public function currentDate(): string
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Integration\Http;
6+
7+
use Tempest\View\GenericView;
8+
use Tests\Tempest\Fixtures\Controllers\RelativeViewController;
9+
use Tests\Tempest\Fixtures\Controllers\TestController;
10+
use Tests\Tempest\Fixtures\Views\ViewModel;
11+
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
12+
13+
use function Tempest\uri;
14+
15+
/**
16+
* @internal
17+
*/
18+
final class ViewDataTest extends FrameworkIntegrationTestCase
19+
{
20+
public function test_can_assert_view_data(): void
21+
{
22+
$this->http
23+
->get(uri([TestController::class, 'withView']))
24+
->assertViewData('name')
25+
->assertViewData('name', function (array $data, string $value): void {
26+
$this->assertEquals(['name' => 'Brent'], $data);
27+
$this->assertEquals('Brent', $value);
28+
})
29+
->assertViewDataMissing('email')
30+
->assertViewDataAll(function (array $data): void {
31+
$this->assertEquals(['name' => 'Brent'], $data);
32+
});
33+
}
34+
35+
public function test_can_assert_generic_view_model(): void
36+
{
37+
$this->http
38+
->get(uri([RelativeViewController::class, 'asFunction']))
39+
->assertViewModel(GenericView::class)
40+
->assertView('./relative-view.view.php');
41+
}
42+
43+
public function test_can_assert_view_model(): void
44+
{
45+
$this->http
46+
->get(uri([TestController::class, 'viewModel']))
47+
->assertViewModel(ViewModel::class, function (ViewModel $model): void {
48+
$this->assertEquals('Brent', $model->name);
49+
})
50+
->assertView('withViewModel.php');
51+
}
52+
}

0 commit comments

Comments
 (0)