Last active
November 21, 2018 14:21
-
-
Save jonpugh/b2f95dd8e89b3218a20a to your computer and use it in GitHub Desktop.
This custom Behat FeatureContext includes a step called "Then every link should work". It checks every visitable link on a page for a 200 code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Drupal\DrupalExtension\Context\RawDrupalContext; | |
use Drupal\DrupalExtension\Context\DrupalContext; | |
use Behat\Behat\Context\Context; | |
use Behat\Behat\Context\SnippetAcceptingContext; | |
use Behat\Gherkin\Node\PyStringNode; | |
use Behat\Gherkin\Node\TableNode; | |
use Behat\Mink\Exception\UnsupportedDriverActionException; | |
use Behat\Mink\Exception\ExpectationException; | |
/** | |
* Defines application features from the specific context. | |
*/ | |
class FeatureContext extends RawDrupalContext implements SnippetAcceptingContext | |
{ | |
/** | |
* Initializes context. | |
* | |
* Every scenario gets its own context instance. | |
* You can also pass arbitrary arguments to the | |
* context constructor through behat.yml. | |
*/ | |
public function __construct() | |
{ | |
} | |
/** | |
* List of URLs we have visited. | |
* @var array | |
*/ | |
public $visited_links = array(); | |
/** | |
* @Then every link should work | |
*/ | |
public function everyLinkShouldWork() | |
{ | |
$elements = $this->getSession()->getPage()->findAll('xpath', '//a/@href'); | |
$count = count($elements); | |
foreach ($elements as $element) { | |
// If element or tag is empty... | |
if (empty($element->getParent())) { | |
continue; | |
} | |
$href = $element->getParent()->getAttribute('href'); | |
// Skip if empty | |
if (empty($href)) { | |
continue; | |
} | |
// Skip if already visited | |
if (isset($this->visited_links[$href])) { | |
print "Skipping visited link: $href \n\n"; | |
continue; | |
} | |
// Save URL for later to avoid duplicates. | |
$this->visited_links[$href] = $href; | |
// Skip if an anchor tag | |
if (strpos($href, '#') === 0) { | |
print "Skipping anchor link: $href \n\n"; | |
continue; | |
} | |
// Skip remote links | |
if (strpos($href, 'http') === 0) { | |
print "Skipping remote link: $href \n\n"; | |
continue; | |
} | |
// Skip mailto links | |
if (strpos($href, 'mailto') === 0) { | |
print "Skipping remote link: $href \n\n"; | |
continue; | |
} | |
print "Checking Link: " . $href . "\n"; | |
// Mimics Drupal\DrupalExtension\Context\MinkContext::assertAtPath | |
$this->getSession()->visit($this->locatePath($href)); | |
try { | |
$this->getSession()->getStatusCode(); | |
$this->assertSession()->statusCodeEquals('200'); | |
print "200 Success \n"; | |
} | |
catch (UnsupportedDriverActionException $e) { | |
// Simply continue on, as this driver doesn't support HTTP response codes. | |
} | |
catch (ExpectationException $e) { | |
print "200 Success NOT received \n"; | |
throw new \Exception("Page at URL $href did not return 200 code."); | |
} | |
catch (Behat\Mink\Exception\DriverException $e) { | |
throw new \Exception($e->getMessage()); | |
} | |
print "\n"; | |
} | |
print "Done! Checked $count Links"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for this. Exactly what I was looking for.