diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithPages.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithPages.php index 914244c22324..6ea659a79ec7 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithPages.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithPages.php @@ -2,6 +2,7 @@ namespace Illuminate\Foundation\Testing\Concerns; +use Closure; use Exception; use Illuminate\Support\Str; use InvalidArgumentException; @@ -20,6 +21,13 @@ trait InteractsWithPages */ protected $crawler; + /** + * Subcrawler instances used by the within method. + * + * @var array + */ + protected $subCrawlers = []; + /** * All of the stored inputs for the current page. * @@ -67,6 +75,8 @@ protected function makeRequest($method, $uri, $parameters = [], $cookies = [], $ $this->crawler = new Crawler($this->response->getContent(), $uri); + $this->subCrawlers = []; + return $this; } @@ -169,6 +179,34 @@ protected function assertPageLoaded($uri, $message = null) } } + /** + * Get the right crawler according to the current test context. + * + * @return \Symfony\Component\DomCrawler\Crawler + */ + protected function getCrawler() + { + return ! empty($this->subCrawlers) + ? end($this->subCrawlers) + : $this->crawler; + } + + /** + * Narrow the test content to a specific area of the page. + * + * @param string $element + * @param \Closure $callback + * @return $this + */ + public function within($element, Closure $callback) + { + $this->subCrawlers[] = $this->getCrawler()->filter($element); + + $callback(); + + array_pop($this->subCrawlers); + } + /** * Assert that a given string is seen on the page. * @@ -187,7 +225,7 @@ protected function see($text, $negate = false) $pattern = $rawPattern == $escapedPattern ? $rawPattern : "({$rawPattern}|{$escapedPattern})"; - $this->$method("/$pattern/i", $this->response->getContent()); + $this->$method("/$pattern/i", $this->getCrawler()->html()); return $this; } @@ -251,7 +289,7 @@ public function dontSeeInElement($element, $text) */ protected function hasInElement($element, $text) { - $elements = $this->crawler->filter($element); + $elements = $this->getCrawler()->filter($element); $rawPattern = preg_quote($text, '/'); @@ -320,7 +358,7 @@ public function dontSeeLink($text, $url = null) */ protected function hasLink($text, $url = null) { - $links = $this->crawler->selectLink($text); + $links = $this->getCrawler()->selectLink($text); if ($links->count() == 0) { return false; @@ -592,7 +630,7 @@ protected function isChecked($selector) */ protected function click($name) { - $link = $this->crawler->selectLink($name); + $link = $this->getCrawler()->selectLink($name); if (! count($link)) { $link = $this->filterByNameOrId($name, 'a'); @@ -725,10 +763,10 @@ protected function getForm($buttonText = null) { try { if ($buttonText) { - return $this->crawler->selectButton($buttonText)->form(); + return $this->getCrawler()->selectButton($buttonText)->form(); } - return $this->crawler->filter('form')->form(); + return $this->getCrawler()->filter('form')->form(); } catch (InvalidArgumentException $e) { throw new InvalidArgumentException( "Could not find a form that has submit button [{$buttonText}]." @@ -792,7 +830,7 @@ protected function filterByNameOrId($name, $elements = '*') $element = "{$element}#{$id}, {$element}[name='{$name}']"; }); - return $this->crawler->filter(implode(', ', $elements)); + return $this->getCrawler()->filter(implode(', ', $elements)); } /** diff --git a/tests/Foundation/FoundationInteractsWithPagesTest.php b/tests/Foundation/FoundationInteractsWithPagesTest.php index e1369a8d20ed..a62553f61bb8 100644 --- a/tests/Foundation/FoundationInteractsWithPagesTest.php +++ b/tests/Foundation/FoundationInteractsWithPagesTest.php @@ -7,18 +7,20 @@ class FoundationCrawlerTraitIntegrationTest extends PHPUnit_Framework_TestCase { use MakesHttpRequests; - public function testSeeInElement() + protected function setCrawler($html) { - $this->crawler = new Crawler( - '
Laravel was created by Taylor Otwell
' - ); + $this->crawler = new Crawler($html); + } + public function testSeeInElement() + { + $this->setCrawler('
Laravel was created by Taylor Otwell
'); $this->seeInElement('strong', 'Taylor'); } public function testSeeInElementSearchInAllElements() { - $this->crawler = new Crawler( + $this->setCrawler( '
Laravel is a PHP framework created by Taylor Otwell @@ -30,7 +32,7 @@ public function testSeeInElementSearchInAllElements() public function testSeeInElementSearchInHtmlTags() { - $this->crawler = new Crawler( + $this->setCrawler( '
' @@ -41,7 +43,7 @@ public function testSeeInElementSearchInHtmlTags() public function testdontSeeInElement() { - $this->crawler = new Crawler( + $this->setCrawler( '
Laravel was created by Taylor Otwell
' ); @@ -51,7 +53,7 @@ public function testdontSeeInElement() public function testSeeLink() { - $this->crawler = new Crawler( + $this->setCrawler( 'Laravel' ); @@ -61,7 +63,7 @@ public function testSeeLink() public function testDontSeeLink() { - $this->crawler = new Crawler( + $this->setCrawler( 'Laravel' ); @@ -76,13 +78,13 @@ protected function getInputHtml() public function testSeeInInput() { - $this->crawler = new Crawler($this->getInputHtml()); + $this->setCrawler($this->getInputHtml()); $this->seeInField('framework', 'Laravel'); } public function testDontSeeInInput() { - $this->crawler = new Crawler($this->getInputHtml()); + $this->setCrawler($this->getInputHtml()); $this->dontSeeInField('framework', 'Rails'); } @@ -93,13 +95,13 @@ protected function getInputArrayHtml() public function testSeeInInputArray() { - $this->crawler = new Crawler($this->getInputArrayHtml()); + $this->setCrawler($this->getInputArrayHtml()); $this->seeInField('framework[]', 'Laravel'); } public function testDontSeeInInputArray() { - $this->crawler = new Crawler($this->getInputArrayHtml()); + $this->setCrawler($this->getInputArrayHtml()); $this->dontSeeInField('framework[]', 'Rails'); } @@ -110,13 +112,13 @@ protected function getTextareaHtml() public function testSeeInTextarea() { - $this->crawler = new Crawler($this->getTextareaHtml()); + $this->setCrawler($this->getTextareaHtml()); $this->seeInField('description', 'Laravel is awesome'); } public function testDontSeeInTextarea() { - $this->crawler = new Crawler($this->getTextareaHtml()); + $this->setCrawler($this->getTextareaHtml()); $this->dontSeeInField('description', 'Rails is awesome'); } @@ -131,13 +133,13 @@ protected function getSelectHtml() public function testSeeOptionIsSelected() { - $this->crawler = new Crawler($this->getSelectHtml()); + $this->setCrawler($this->getSelectHtml()); $this->seeIsSelected('availability', 'full_time'); } public function testDontSeeOptionIsSelected() { - $this->crawler = new Crawler($this->getSelectHtml()); + $this->setCrawler($this->getSelectHtml()); $this->dontSeeIsSelected('availability', 'partial_time'); } @@ -150,13 +152,13 @@ protected function getRadiosHtml() public function testSeeRadioIsChecked() { - $this->crawler = new Crawler($this->getRadiosHtml()); + $this->setCrawler($this->getRadiosHtml()); $this->seeIsSelected('availability', 'full_time'); } public function testDontSeeRadioIsChecked() { - $this->crawler = new Crawler($this->getRadiosHtml()); + $this->setCrawler($this->getRadiosHtml()); $this->dontSeeIsSelected('availability', 'partial_time'); } @@ -169,13 +171,63 @@ protected function getCheckboxesHtml() public function testSeeCheckboxIsChecked() { - $this->crawler = new Crawler($this->getCheckboxesHtml()); + $this->setCrawler($this->getCheckboxesHtml()); $this->seeIsChecked('terms'); } public function testDontSeeCheckboxIsChecked() { - $this->crawler = new Crawler($this->getCheckboxesHtml()); + $this->setCrawler($this->getCheckboxesHtml()); $this->dontSeeIsChecked('list'); } + + protected function getLayoutHtml() + { + return + '
+

Laravel

+
+
+

The PHP Framework For Web Artisans

+

Elegant applications delivered at warp speed.

+
+ '; + } + + public function testWithin() + { + $this->setCrawler($this->getLayoutHtml()); + + // Limit the search to the "header" area + $this->within('header', function () { + $this->see('Laravel') + ->dontSeeInElement('h2', 'PHP Framework'); + }); + + // Make sure we are out of the within context + $this->seeLink('Documentation'); + + // Test other methods as well + $this->within('#features', function () { + $this->seeInElement('h2', 'PHP Framework') + ->dontSee('Laravel') + ->dontSeeLink('Documentation'); + }); + } + + public function testNestedWithin() + { + $this->setCrawler($this->getLayoutHtml()); + + $this->within('#features', function () { + $this->dontSee('Laravel') + ->see('Web Artisans') + ->within('h2', function () { + $this->see('PHP Framework') + ->dontSee('Elegant applications'); + }); + }); + } }