Skip to content

Instantly share code, notes, and snippets.

@jonpugh
Last active November 21, 2018 14:21
Show Gist options
  • Save jonpugh/b2f95dd8e89b3218a20a to your computer and use it in GitHub Desktop.
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.
<?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";
}
}
@justinlevi
Copy link

Thanks for this. Exactly what I was looking for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment