Skip to content

Commit

Permalink
Merge pull request #3 from QuadraEcommerce/add-attribute-exists-not-e…
Browse files Browse the repository at this point in the history
…xists

Add attribute exists and not exists assertions
  • Loading branch information
squatto authored May 31, 2023
2 parents ece325e + a410a19 commit 7d8b5db
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 56 deletions.
34 changes: 23 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ Using the following response body:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>pest-plugin-selectors test view</title>
<title>quadraecom/pest-plugin-selectors test view</title>
</head>
<body>

Expand All @@ -29,7 +30,7 @@ Using the following response body:
<li>List item 2</li>
<li>List item 3</li>
<li>List item 4</li>
<li>List item 5</li>
<li data-foo="bar">List item 5</li>
</ul>

<div class="single">
Expand Down Expand Up @@ -58,6 +59,8 @@ Using the following response body:
The following tests will all pass:

```php
use PHPUnit\Framework\AssertionFailedError;

it('gets elements matching a selector', function () {
/** @var DOMNodeList $elements */
$elements = $this->get('/')
Expand Down Expand Up @@ -115,27 +118,36 @@ it("asserts that all of a selector's matches do not equal a value")
->get('/')
->assertSelectorsAllNotEqual('main div.multiple-same .item', 'not the value');

it("asserts that a selector match's attribute equals a value")
it("asserts that an attribute exists on any of a selector's matches")
->get('/')
->assertSelectorAttributeExists('main ul li', 'data-foo');

it("asserts that an attribute does not exist on any of a selector's matches")
->get('/')
->assertSelectorAttributeNotExists('main ul li', 'data-does-not-exist');

it("asserts that an attribute equals a value on any of a selector's matches")
->get('/')
->assertSelectorAttributeEquals('footer', 'data-foo', 'bar');
->assertSelectorAttributeEquals('main ul li', 'data-foo', 'bar');

it("asserts that a selector match's attribute does not equal a value")
it("asserts that an attribute does not equal a value on any of a selector's matches")
->get('/')
->assertSelectorAttributeNotEquals('footer', 'data-foo', 'not the value');
->assertSelectorAttributeNotEquals('main ul li', 'data-foo', 'not the value');
```

---

> If you want to start testing your application with Pest, visit the main **[Pest Repository](https://github.com/pestphp/pest)**.
> If you want to start testing your application with Pest, visit the main
> **[Pest Repository](https://github.com/pestphp/pest)**.
### Package Author

This package was created and is maintained by [Quadra Ecommerce](https://github.com/QuadraEcommerce).
This package was created and is maintained by [Quadra, Inc](https://github.com/QuadraEcommerce).

- Website: **[QuadraEcom.com](https://quadraecom.com)**
- Website: **[GoQuadra.com](https://goquadra.com)**
- GitHub: **[QuadraEcommerce](https://github.com/QuadraEcommerce)**

[The original test assertions](src/Plugin.php) were based on code originally written
[The test assertions](src/Plugin.php) were inspired by code written
by [Liam Hammett (@ImLiam)](https://github.com/ImLiam) that can be found in
[this post on his blog](https://liamhammett.com/laravel-testing-css-selector-assertion-macros-D9o0YAQJ).
*Thank you, Liam!* 🙌🏻
7 changes: 4 additions & 3 deletions resources/views/welcome.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>pest-plugin-selectors test view</title>
<title>quadraecom/pest-plugin-selectors test view</title>
</head>
<body>

Expand All @@ -14,7 +15,7 @@
<li>List item 2</li>
<li>List item 3</li>
<li>List item 4</li>
<li>List item 5</li>
<li data-foo="bar">List item 5</li>
</ul>

<div class="single">
Expand Down
133 changes: 95 additions & 38 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Illuminate\Testing\TestResponse;
use Symfony\Component\CssSelector\CssSelectorConverter;

// The functions below are based on the functions found at the following URL:
// The functions below are inspired by the functions found at the following URL:
// https://liamhammett.com/laravel-testing-css-selector-assertion-macros-D9o0YAQJ

TestResponse::macro('getSelectorMatches', function (string $selector): DOMNodeList {
Expand All @@ -37,9 +37,10 @@
});

TestResponse::macro('assertSelectorExists', function (string $selector): TestResponse {
$selectorContents = $this->getSelectorMatches($selector);
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (! count($selectorContents)) {
if (! count($nodes)) {
PHPUnit::fail("The selector '$selector' was not found in the response.");
}

Expand All @@ -49,9 +50,10 @@
});

TestResponse::macro('assertSelectorNotExists', function (string $selector): TestResponse {
$selectorContents = $this->getSelectorMatches($selector);
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (count($selectorContents)) {
if (count($nodes)) {
PHPUnit::fail("The selector '$selector' was found in the response.");
}

Expand All @@ -61,8 +63,9 @@
});

TestResponse::macro('assertSelectorCount', function (string $selector, int $expectedCount): TestResponse {
$selectorContents = $this->getSelectorMatches($selector);
$actualCount = count($selectorContents);
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);
$actualCount = count($nodes);

if ($actualCount !== $expectedCount) {
PHPUnit::fail("The selector '$selector' has a count of $actualCount, not the expected count of $expectedCount.");
Expand All @@ -74,14 +77,15 @@
});

TestResponse::macro('assertSelectorContains', function (string $selector, string $value): TestResponse {
$selectorContents = $this->getSelectorMatches($selector);
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (! count($selectorContents)) {
if (! count($nodes)) {
PHPUnit::fail("The selector '$selector' was not found in the response.");
}

foreach ($selectorContents as $element) {
if (Str::contains($element->textContent, $value)) {
foreach ($nodes as $node) {
if (Str::contains($node->textContent, $value)) {
PHPUnit::assertTrue(true);

return $this;
Expand All @@ -92,14 +96,15 @@
});

TestResponse::macro('assertSelectorsAllContain', function (string $selector, string $value): TestResponse {
$selectorContents = $this->getSelectorMatches($selector);
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (! count($selectorContents)) {
if (! count($nodes)) {
PHPUnit::fail("The selector '$selector' was not found in the response.");
}

foreach ($selectorContents as $element) {
if (! Str::contains($element->textContent, $value)) {
foreach ($nodes as $node) {
if (! Str::contains($node->textContent, $value)) {
PHPUnit::fail("The selector '$selector' did not contain the value '$value'.");
}
}
Expand All @@ -110,14 +115,15 @@
});

TestResponse::macro('assertSelectorEquals', function (string $selector, string $value): TestResponse {
$selectorContents = $this->getSelectorMatches($selector);
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (! count($selectorContents)) {
if (! count($nodes)) {
PHPUnit::fail("The selector '$selector' was not found in the response.");
}

foreach ($selectorContents as $element) {
if (trim($element->textContent) === $value) {
foreach ($nodes as $node) {
if (trim($node->textContent) === $value) {
PHPUnit::assertTrue(true);

return $this;
Expand All @@ -128,14 +134,15 @@
});

TestResponse::macro('assertSelectorsAllEqual', function (string $selector, string $value): TestResponse {
$selectorContents = $this->getSelectorMatches($selector);
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (! count($selectorContents)) {
if (! count($nodes)) {
PHPUnit::fail("The selector '$selector' was not found in the response.");
}

foreach ($selectorContents as $element) {
if (trim($element->textContent) !== $value) {
foreach ($nodes as $node) {
if (trim($node->textContent) !== $value) {
PHPUnit::fail("One or more matches of the selector '$selector' did not equal the value '$value'.");
}
}
Expand All @@ -146,14 +153,15 @@
});

TestResponse::macro('assertSelectorNotEquals', function (string $selector, string $value): TestResponse {
$selectorContents = $this->getSelectorMatches($selector);
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (! count($selectorContents)) {
if (! count($nodes)) {
PHPUnit::fail("The selector '$selector' was not found in the response.");
}

foreach ($selectorContents as $element) {
if (trim($element->textContent) !== $value) {
foreach ($nodes as $node) {
if (trim($node->textContent) !== $value) {
PHPUnit::assertTrue(true);

return $this;
Expand All @@ -164,14 +172,15 @@
});

TestResponse::macro('assertSelectorsAllNotEqual', function (string $selector, string $value): TestResponse {
$selectorContents = $this->getSelectorMatches($selector);
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (! count($selectorContents)) {
if (! count($nodes)) {
PHPUnit::fail("The selector '$selector' was not found in the response.");
}

foreach ($selectorContents as $element) {
if (trim($element->textContent) === $value) {
foreach ($nodes as $node) {
if (trim($node->textContent) === $value) {
PHPUnit::fail("One or more matches of the selector '$selector' did equal the value '$value'.");
}
}
Expand All @@ -181,30 +190,78 @@
return $this;
});

TestResponse::macro('assertSelectorAttributeExists', function (string $selector, string $attribute): TestResponse {
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (! count($nodes)) {
PHPUnit::fail("The selector '$selector' was not found in the response.");
}

foreach ($nodes as $node) {
if ($node->attributes->getNamedItem($attribute) !== null) {
PHPUnit::assertTrue(true);

return $this;
}
}

PHPUnit::fail("The attribute '$attribute' does not exist on the selector '$selector'.");
});

TestResponse::macro('assertSelectorAttributeNotExists', function (string $selector, string $attribute): TestResponse {
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (! count($nodes)) {
PHPUnit::fail("The selector '$selector' was not found in the response.");
}

foreach ($nodes as $node) {
if ($node->attributes->getNamedItem($attribute) !== null) {
PHPUnit::fail("The attribute '$attribute' exists on the selector '$selector'.");
}
}

PHPUnit::assertTrue(true);

return $this;
});

TestResponse::macro('assertSelectorAttributeEquals', function (string $selector, string $attribute, $expected): TestResponse {
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (count($nodes) === 0) {
if (! count($nodes)) {
PHPUnit::fail("The selector '$selector was not found in the response.");
}

$firstNode = $nodes[0];
foreach ($nodes as $node) {
if ($node->getAttribute($attribute) === $expected) {
PHPUnit::assertTrue(true);

PHPUnit::assertEquals($expected, $firstNode->getAttribute($attribute));
return $this;
}
}

return $this;
PHPUnit::fail("None of the matches of selector '$selector' have an attribute '$attribute' that equals the value '$expected'.");
});

TestResponse::macro('assertSelectorAttributeNotEquals', function (string $selector, string $attribute, $expected): TestResponse {
/** @var DOMNodeList $nodes */
$nodes = $this->getSelectorMatches($selector);

if (count($nodes) === 0) {
if (! count($nodes)) {
PHPUnit::fail("The selector '$selector was not found in the response.");
}

$firstNode = $nodes[0];
foreach ($nodes as $node) {
if ($node->getAttribute($attribute) === $expected) {
PHPUnit::fail("One of the matches of selector '$selector' has an attribute '$attribute' that equals the value '$expected'.");
}
}

PHPUnit::assertNotEquals($expected, $firstNode->getAttribute($attribute));
PHPUnit::assertTrue(true);

return $this;
});
2 changes: 2 additions & 0 deletions tests/Autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
'assertSelectorNotEquals',
'assertSelectorsAllEqual',
'assertSelectorsAllNotEqual',
'assertSelectorAttributeExists',
'assertSelectorAttributeNotExists',
'assertSelectorAttributeEquals',
'assertSelectorAttributeNotEquals',
]);
16 changes: 12 additions & 4 deletions tests/Selectors.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,18 @@
->get('/')
->assertSelectorsAllNotEqual('main div.multiple-same .item', 'not the value');

it("asserts that a selector match's attribute equals a value")
it("asserts that an attribute exists on any of a selector's matches")
->get('/')
->assertSelectorAttributeEquals('footer', 'data-foo', 'bar');
->assertSelectorAttributeExists('main ul li', 'data-foo');

it("asserts that a selector match's attribute does not equal a value")
it("asserts that an attribute does not exist on any of a selector's matches")
->get('/')
->assertSelectorAttributeNotEquals('footer', 'data-foo', 'not the value');
->assertSelectorAttributeNotExists('main ul li', 'data-does-not-exist');

it("asserts that an attribute equals a value on any of a selector's matches")
->get('/')
->assertSelectorAttributeEquals('main ul li', 'data-foo', 'bar');

it("asserts that an attribute does not equal a value on any of a selector's matches")
->get('/')
->assertSelectorAttributeNotEquals('main ul li', 'data-foo', 'not the value');

0 comments on commit 7d8b5db

Please sign in to comment.