Skip to content

Instantly share code, notes, and snippets.

@Gisleburt
Created April 14, 2015 09:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gisleburt/54e4a3b70b665c8ee053 to your computer and use it in GitHub Desktop.
Save Gisleburt/54e4a3b70b665c8ee053 to your computer and use it in GitHub Desktop.
A possible method of E2E testing Aye Aye Api
<?php
namespace AyeAye\Tests\Behat;
use Behat\Behat\Context\Context;
use Behat\Behat\Context\SnippetAcceptingContext;
use Behat\Behat\Tester\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;
use Guzzle\Http\Client;
use GuzzleHttp\Message\Request;
use GuzzleHttp\Message\Response;
/**
* Defines application features from the specific context.
*/
class FeatureContext implements Context, SnippetAcceptingContext
{
/**
* @var array
*/
protected $config = [];
/**
* @var Client
*/
protected $client;
/**
* @var Request
*/
protected $request;
/**
* @var Response
*/
protected $response;
/**
* @var []
*/
protected $parameters;
/**
* Initializes context.
*
* Every scenario gets its own context instance.
* You can also pass arbitrary arguments to the
* context constructor through behat.yml.
*
* @param array $parameters
*/
public function __construct(array $parameters = [])
{
$this->config = $parameters;
$this->client = new Client($this->getConfig('base_url'), $this->getConfig('guzzle'));
$this->request = $this->client->createRequest();
}
/**
* Look up a parameter
* @param string $name
* @param mixed $default
* @return mixed
*/
protected function getConfig($name, $default = null)
{
if (array_key_exists($name, $this->config)) {
return $this->config[$name];
}
return $default;
}
/**
* @Given I create a new request
*/
public function createNewRequest()
{
$this->request = $this->client->createRequest();
return $this;
}
/**
* @Given I create a new :method request
* @param string $method
* @return $this
*/
public function iCreateANewRequest($method = 'GET')
{
$this->request = $this->client->createRequest(strtoupper($method));
$this->parameters = [];
return $this;
}
/**
* @When I set the :header header to :value
* @param $header
* @param $value
* @return $this
*/
public function iSetTheHeaderTo($header, $value)
{
$this->request->setHeader($header, $value);
return $this;
}
/**
* @When I set :variable to :value
* @param string $variable
* @param mixed $value
* @return $this
*/
public function iSetVariableToValue($variable, $value)
{
$this->parameters[$variable] = $value;
return $this;
}
/**
* @When I send the request to :url
* @param string $url
* @return $this
*/
public function iSendTheRequestTo($url)
{
// Add FQDN if required
if(!preg_match('/^\w+\:/', $url)) {
if($url[0] != '/') {
$url = "/$url";
}
$url = $this->getConfig('base_url').$url;
}
$this->request->setUrl($url);
// Add parameters
switch($this->request->getMethod()) {
case 'GET':
$this->request->setUrl(
$this->request->getUrl(true)->setQuery($this->parameters)
);
break;
}
// Send the request
$this->response = $this->client->send($this->request);
return $this;
}
/**
* @Then the content-type of the request will be :contentType
* @param string $contentType
* @return $this
*/
public function theContentTypeOfTheRequestWillBe($contentType)
{
$this->request->setHeader('Content-type', $contentType);
return $this;
}
/**
* @Then I expect the content to to be :contentType
* @param $expectedContentType
* @throws \Exception
* @return $this
*/
public function iExpectTheResponseContentTypeToBe($expectedContentType)
{
$actualContentType = $this->response->getHeader('Content-Type');
if($actualContentType != $expectedContentType) {
throw new \Exception("Expected Content-Type '$expectedContentType', received '$actualContentType'");
}
return $this;
}
/**
* @Then I expect the status code to be :code
* @param $expectedCode
* @throws \Exception
* @return $this
*/
public function iExpectTheStatusCodeToBe($expectedCode)
{
$actualCode = $this->response->getStatusCode();
if($actualCode != $expectedCode) {
throw new \Exception("Expected status code '$expectedCode', received '$actualCode'");
}
return $this;
}
/**
* @Then I expect :property to equal :value
* @param $property
* @param $value
* @throws \Exception
* @returns $this
*/
public function iExpectPropertyToBeEqualTo($property, $value)
{
$response = $this->stringToObject($this->response->getBody(true));
$testValue = $this->getNestedValue($response, $property);
if($testValue != $value) {
throw new \Exception("Expected to '$property' to equal '$value' but it was '$testValue'");
}
return $this;
}
/**
* @Then I expect :property to contain :size value(s)
* @param $property
* @param $size
* @throws \Exception
* @returns $this
*/
public function iExpectPropertyToBeOfSize($property, $size)
{
$response = $this->stringToObject($this->response->getBody(true));
$testArray = (array)$this->getNestedValue($response, $property);
$count = count($testArray);
if($count != $size) {
throw new \Exception("Expected to find '$size' items in '$property' but found '$count'");
}
return $this;
}
/**
* @Then I expect :property to contain :value
* @param $property
* @param $value
* @throws \Exception
* @returns $this
*/
public function iExpectPropertyToContain($property, $value)
{
$exception = new \Exception("Expected to find '$value' in '$property' but could not");
$response = $this->stringToObject($this->response->getBody(true));
$testValue = $this->getNestedValue($response, $property);
if(is_scalar($testValue)) {
if(strpos($testValue, $value) === false) {
throw $exception;
}
return $this;
}
$testValue = (array)$testValue;
if(!in_array($value, $testValue) && !array_key_exists($value, $testValue)) {
throw $exception;
}
return $this;
}
/**
* @Then I expect :property not to contain :value
* @param $property
* @param $value
* @throws \Exception
* @returns $this
*/
public function iExpectPropertyNotToContain($property, $value)
{
$response = $this->stringToObject($this->response->getBody(true));
$testArray = (array)$this->getNestedValue($response, $property);
if(in_array($value, $testArray) || array_key_exists($value, $testArray)) {
throw new \Exception("Did not expected to find '$value' in '$property' but did");
}
return $this;
}
/**
* Hacky, should be replaced
* @param $string
* @return \stdClass
*/
protected function stringToObject($string) {
$request = new \AyeAye\Api\Request();
return $request->stringToObject($string);
}
/**
* Find the value of a nested property in an object or array
* @param $objectOrArray
* @param $propertyChain
* @return object
* @throws \Exception
*/
protected function getNestedValue($objectOrArray, $propertyChain) {
if(!$propertyChain) {
return $objectOrArray;
}
if(!is_object($objectOrArray)) {
// A straight cast here doesn't seem to work for numeric keys
// $objectOrArray = (object)$objectOrArray
$object = new \stdClass();
foreach($objectOrArray as $k => $v) {
$object->$k = $v;
}
$objectOrArray = $object;
}
if(is_string($propertyChain)) {
$propertyChain = explode('.', $propertyChain);
}
if(!$propertyChain) {
throw new \Exception("Property missing");
}
$nextProperty = array_shift($propertyChain);
if(!property_exists($objectOrArray, $nextProperty)) {
throw new \Exception("Property '$nextProperty' does not exist");
}
return $this->getNestedValue($objectOrArray->$nextProperty, $propertyChain);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment