Skip to content

Commit 59c80c4

Browse files
committed
asserts many
1 parent b16531e commit 59c80c4

File tree

4 files changed

+146
-37
lines changed

4 files changed

+146
-37
lines changed

src/Concerns/AssertsMany.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Ziadoz\AssertableHtml\Concerns;
6+
7+
use PHPUnit\Framework\AssertionFailedError;
8+
9+
trait AssertsMany
10+
{
11+
/** Perform many PHPUnit assertions in a callback, but capture any failures into a single exception. */
12+
public function assertMany(callable $callback, ?string $message = null): static
13+
{
14+
try {
15+
$callback(...)->call($this);
16+
} catch (AssertionFailedError $assertion) {
17+
throw new AssertionFailedError(message: $message ?? $assertion->getMessage(), previous: $assertion);
18+
}
19+
20+
return $this;
21+
}
22+
}

src/Dom/Elements/AssertableForm.php

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66

77
use Dom\Element;
88
use Dom\HTMLElement;
9-
use PHPUnit\Framework\Assert as PHPUnit;
9+
use Ziadoz\AssertableHtml\Concerns\AssertsMany;
1010
use Ziadoz\AssertableHtml\Contracts\PromotableAssertableElement;
1111
use Ziadoz\AssertableHtml\Dom\AssertableElement;
1212

1313
readonly class AssertableForm extends AssertableElement implements PromotableAssertableElement
1414
{
15+
use AssertsMany;
16+
1517
/*
1618
|--------------------------------------------------------------------------
1719
| Interface
@@ -30,65 +32,95 @@ public static function shouldPromote(Element|HTMLElement $element): bool
3032
|--------------------------------------------------------------------------
3133
*/
3234

33-
/** Assert the form has the given method attribute (GET or POST). */
35+
/** Assert the form has the given method attribute. */
3436
public function assertMethod(string $method, ?string $message = null): static
3537
{
3638
$method = trim(mb_strtolower($method));
3739

38-
$this->isValidMethod($method);
39-
4040
$this->assertAttribute(
4141
'method',
4242
fn (?string $value): bool => trim(mb_strtolower((string) $value)) === $method,
43-
$message ?? sprintf(
44-
"The form method doesn't equal [%s].",
45-
$method,
46-
),
43+
$message ?? sprintf("The form method doesn't equal [%s].", $method),
4744
);
4845

4946
return $this;
5047
}
5148

52-
/** Assert the form has the given hidden input method (PUT, PATCH or DELETE). */
53-
public function assertHiddenInputMethod(string $selector, string $method, ?string $message = null): static
49+
public function assertMethodGet(?string $message = null): static
5450
{
55-
$method = trim(mb_strtolower($method));
51+
$this->assertMethod('get', $message);
5652

57-
$this->isValidHiddenInputMethod($method);
53+
return $this;
54+
}
5855

59-
$this->querySelector($selector)
60-
->assertMatchesSelector('input[type="hidden"]')
61-
->assertAttribute(
62-
'value',
63-
fn (?string $value): bool => trim(mb_strtolower((string) $value)) === $method,
64-
$message ?? sprintf(
65-
"The form hidden input method doesn't equal [%s].",
66-
$method,
67-
),
68-
);
56+
public function assertMethodPost(?string $message = null): static
57+
{
58+
$this->assertMethod('post', $message);
59+
60+
return $this;
61+
}
62+
63+
public function assertMethodDialog(?string $message = null): static
64+
{
65+
$this->assertMethod('dialog', $message);
6966

7067
return $this;
7168
}
7269

7370
/*
7471
|--------------------------------------------------------------------------
75-
| Internal
72+
| Assert Hidden Method
7673
|--------------------------------------------------------------------------
7774
*/
7875

79-
/** Fail if the method isn't a valid form method. */
80-
protected function isValidMethod(string $method): void
76+
/** Assert the form has the given hidden input method. */
77+
public function assertHiddenInputMethod(string $selector, string $method, ?string $message = null): static
78+
{
79+
$this->assertMany(function () use ($selector, $method): void {
80+
$method = trim(mb_strtolower($method));
81+
82+
$this->querySelector($selector)
83+
->assertMatchesSelector('input[type="hidden"]')
84+
->assertAttribute('value', fn (?string $value): bool => trim(mb_strtolower((string) $value)) === $method);
85+
}, $message ?? sprintf("The form hidden input method doesn't equal [%s].", $method));
86+
87+
return $this;
88+
}
89+
90+
public function assertMethodPut(?string $message = null): static
8191
{
82-
if (! in_array($this->formatMethod($method), ['get', 'post', 'dialog'])) {
83-
PHPUnit::fail(sprintf("The method [%s] isn't a valid form method.", $method));
84-
}
92+
$this->assertHiddenInputMethod('input[type="hidden"][name="_method"]', 'put', $message);
93+
94+
return $this;
95+
}
96+
97+
public function assertMethodPatch(?string $message = null): static
98+
{
99+
$this->assertHiddenInputMethod('input[type="hidden"][name="_method"]', 'patch', $message);
100+
101+
return $this;
85102
}
86103

87-
/** Fail if the method isn't a valid hidden input method. */
88-
protected function isValidHiddenInputMethod(string $method): void
104+
public function assertMethodDelete(?string $message = null): static
89105
{
90-
if (! in_array($method, ['put', 'patch', 'delete'])) {
91-
PHPUnit::fail(sprintf("The method [%s] isn't a valid form method.", $method));
92-
}
106+
$this->assertHiddenInputMethod('input[type="hidden"][name="_method"]', 'delete', $message);
107+
108+
return $this;
109+
}
110+
111+
/*
112+
|--------------------------------------------------------------------------
113+
| Assert Upload
114+
|--------------------------------------------------------------------------
115+
*/
116+
117+
public function assertAcceptsUpload(?string $message = null): static
118+
{
119+
$this->assertMany(function (): void {
120+
$this->assertAttribute('enctype', fn (?string $value): bool => trim(mb_strtolower((string) $value)) === 'multipart/form-data')
121+
->assertElementsCountGreaterThanOrEqual('input[type="file"]', 1);
122+
}, $message ?? "The form doesn't accept uploads.");
123+
124+
return $this;
93125
}
94126
}

tests/Integration/AssertableFormTest.php

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,34 @@ class AssertableFormTest extends TestCase
1212
public function test_assertable_form(): void
1313
{
1414
// Form Methods
15-
AssertableDocument::createFromString('<form method="get"></form>', LIBXML_HTML_NOIMPLIED)
15+
AssertableDocument::createFromString('<form method="GET"></form>', LIBXML_HTML_NOIMPLIED)
1616
->querySelector('form')
17-
->assertMethod('get');
17+
->assertMethodGet();
1818

19-
AssertableDocument::createFromString('<form><input type="hidden" name="_method" value="put"></form>', LIBXML_HTML_NOIMPLIED)
19+
AssertableDocument::createFromString('<form method="POST"></form>', LIBXML_HTML_NOIMPLIED)
2020
->querySelector('form')
21-
->assertHiddenInputMethod('input[name="_method"]', 'put');
21+
->assertMethodPost();
22+
23+
AssertableDocument::createFromString('<form method="DIALOG"></form>', LIBXML_HTML_NOIMPLIED)
24+
->querySelector('form')
25+
->assertMethodDialog();
26+
27+
AssertableDocument::createFromString('<form><input type="hidden" name="_method" value="PUT"></form>', LIBXML_HTML_NOIMPLIED)
28+
->querySelector('form')
29+
->assertMethodPut();
30+
31+
AssertableDocument::createFromString('<form><input type="hidden" name="_method" value="PATCH"></form>', LIBXML_HTML_NOIMPLIED)
32+
->querySelector('form')
33+
->assertMethodPatch();
34+
35+
AssertableDocument::createFromString('<form><input type="hidden" name="_method" value="DELETE"></form>', LIBXML_HTML_NOIMPLIED)
36+
->querySelector('form')
37+
->assertMethodDelete();
38+
39+
// Form Uploads
40+
AssertableDocument::createFromString('<form enctype="multipart/form-data"><input type="file"></form>', LIBXML_HTML_NOIMPLIED)
41+
->querySelector('form')
42+
->assertAcceptsUpload();
2243
}
2344

2445
// <form method="get" action="/foo/bar" enctype="multipart/form-data" id="foo" class="bar">
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Ziadoz\AssertableHtml\Tests\Unit\Concerns\Asserts;
6+
7+
use PHPUnit\Framework\Assert as PHPUnit;
8+
use PHPUnit\Framework\AssertionFailedError;
9+
use PHPUnit\Framework\TestCase;
10+
use Ziadoz\AssertableHtml\Concerns\AssertsMany;
11+
12+
class AssertsManyTest extends TestCase
13+
{
14+
public function test_asserts_many(): void
15+
{
16+
try {
17+
$object = $this->getAssertsMany();
18+
$object->assertMany(function () {
19+
PHPUnit::assertSame('Foo', 'Bar', 'Foo is not Bar');
20+
}, 'The test assertion failed');
21+
} catch (AssertionFailedError $exception) {
22+
$this->assertSame('The test assertion failed', $exception->getMessage());
23+
$this->assertSame('Foo is not Bar' . "\n" . 'Failed asserting that two strings are identical.', $exception->getPrevious()->getMessage());
24+
}
25+
}
26+
27+
private function getAssertsMany(): object
28+
{
29+
return new class
30+
{
31+
use AssertsMany;
32+
};
33+
}
34+
}

0 commit comments

Comments
 (0)