-
-
Save gooh/4e9b2cb5a30ce9a684580c1b419caf0e to your computer and use it in GitHub Desktop.
version of webtestcase with all the project info removed
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 | |
namespace Acme\ApiBundle\Tests; | |
use Exception; | |
use Acme\CoreBundle\Tests\DatabaseTestCase; | |
use Symfony\Bundle\FrameworkBundle\Client; | |
use Acme\ApiBundle\Tests\Helper\IgnoreValue; | |
use Acme\FrameworkBundle\Tests\Exception\FixtureFileNotMatchingException; | |
use Symfony\Component\BrowserKit\Cookie; | |
abstract class ApiTestCase extends DatabaseTestCase | |
{ | |
/** | |
* Belongs to User Id 156 | |
*/ | |
const DEFAULT_ACCESS_TOKEN_STRING = '****'; | |
const ROLE_USER_ACCESS_TOKEN_STRING = 'role_user_token'; | |
const COOKIE_TOKEN_KEY = 'x-token'; | |
const HEADER_TOKEN_KEY = 'HTTP_X_TOKEN'; | |
/** | |
* @var string | |
*/ | |
protected $resultsDir = 'ExpectedResults/'; | |
/** | |
* @var array | |
*/ | |
protected static $validLoginData = [ | |
"username" => "***@example.com", | |
"password" => "***" | |
]; | |
public function setUp() | |
{ | |
$this->setupTestToUseFullFixtureSet(); | |
parent::setUp(); | |
} | |
/** | |
* Returns the Symfony Client | |
* | |
* Usually you will not need this method. Use {@see getLastResponseBody} or | |
* {@see assertHttpStatusCode} or {@see doJsonRequest} to interact with the | |
* client instead. | |
* | |
* @return Client | |
*/ | |
protected function getClient() | |
{ | |
return $this->client; | |
} | |
/** | |
* @param string $method | |
* @param string $uri | |
* @param array $queryParams | |
* @param mixed $jsonBody | |
*/ | |
protected function doJsonRequest($method, $uri, array $queryParams = [], $jsonBody = null) | |
{ | |
$this->client->request( | |
$method, | |
empty($queryParams) ? $uri : $uri . '?'. http_build_query($queryParams), | |
[ /* no params */ ], | |
[ /* no files */ ], | |
['CONTENT_TYPE' => 'application/json'], | |
is_null($jsonBody) ? $jsonBody : json_encode($jsonBody) | |
); | |
} | |
/** | |
* Assert StatusCode in last fetched Response matches given StatusCode | |
* | |
* @param int $expectedStatusCode | |
*/ | |
protected function assertHttpStatusCode($expectedStatusCode) | |
{ | |
$this->assertEquals( | |
$expectedStatusCode, | |
$this->getLastResponseCode(), | |
$this->getLastResponseBody() | |
); | |
} | |
/** | |
* Returns the Response Body of the last Response | |
* | |
* This is a convenience method to allow direct access to the Response body | |
* of the current Response. You can also call this via the client, fetching | |
* the Response and then the Content. This one is shorter. | |
* | |
* @return string | |
*/ | |
protected function getLastResponseBody() | |
{ | |
return $this->client->getResponse()->getContent(); | |
} | |
/** | |
* Returns the Http Status Code of the last Response | |
* | |
* This is not part of the API and hence private. You are not supposed to | |
* use this method in your derived Testcases. Use assertHttpStatusCode() | |
* to verify Http status codes. | |
* | |
* @return int | |
*/ | |
private function getLastResponseCode() | |
{ | |
return $this->getClient()->getResponse()->getStatusCode(); | |
} | |
/** | |
* Asserts the last Response matches a given file from the fixtures folder | |
* | |
* @param null $variant Variant of the fixture file. Defaults to test method name. | |
* @throws \Acme\FrameworkBundle\Tests\Exception\FixtureFileNotMatchingException | |
*/ | |
protected function assertLastResponseEqualsFixtureFile($variant = null) | |
{ | |
/* | |
* @internal the output of assertJsonStringEqualsJsonString is better | |
* for debugging than it's counterparts that assert on Files. This is | |
* why we use it here and load the expected results file. | |
*/ | |
try { | |
$this->assertJsonStringEqualsJsonString( | |
file_get_contents($this->getExpectedResultsFile($variant)), | |
$this->getLastResponseBody() | |
); | |
} catch (\PHPUnit_Framework_ExpectationFailedException $e) { | |
$newException = new FixtureFileNotMatchingException($e->getMessage(), $e->getComparisonFailure()); | |
$newException->setFixtureFileName($this->getExpectedResultsFile($variant)); | |
throw $newException; | |
} | |
} | |
/** | |
* Returns the file path based to a fixture file | |
* | |
* The convention is to store fixtures in the results dir in a subfolder | |
* named after the short class name of the Test class followed by the | |
* test method name, e.g. | |
* | |
* db/fixtures/ExpectedResults/SomeControllerTest/testSomething.json | |
* | |
* @param string $variant Variant of the test, omitting will use just the test name | |
* @param string $fileExtension Extension of the result file, default is json | |
* @return string | |
*/ | |
protected function getExpectedResultsFile($variant = null, $fileExtension = "json") | |
{ | |
$reflectionClass = new \ReflectionClass($this); | |
$resultsDir = $this->getFixturesDir() . $this->resultsDir; | |
if (strpos($variant, $this->getName(false)) !== false) { | |
$variant = str_replace($this->getName(false), '', $variant); | |
} | |
return sprintf( | |
"%s%s/%s%s.%s", | |
$resultsDir, | |
$reflectionClass->getShortName(), | |
$this->getName(false), | |
$variant, | |
$fileExtension | |
); | |
} | |
/** | |
* Adds an Access Token for authentication to Server Params | |
* | |
* Note that this has to be written as HTTP_X_TOKEN in order for Symfony | |
* to pick it up as x-token. The token has to exist in the database and | |
* reference a valid user in order to work. | |
* | |
* If no $accessTokenString is passed, the token used will be the one | |
* defined in the class constant DEFAULT_ACCESS_TOKEN_STRING. | |
* | |
* @link https://github.com/symfony/symfony/issues/5074 | |
* | |
* @param string $accessTokenString | |
* | |
* @return void | |
*/ | |
protected function enableAuthentication($accessTokenString = null) | |
{ | |
$accessTokenString = $this->getAccessTokenString($accessTokenString); | |
$this->client->setServerParameter(static::HEADER_TOKEN_KEY, $accessTokenString); | |
} | |
/** | |
* enable authentification with cookie. Used for file downloads | |
* | |
* @param null $accessTokenString | |
*/ | |
protected function enableCookieAuthentification($accessTokenString = null) | |
{ | |
$accessTokenString = $this->getAccessTokenString($accessTokenString); | |
$cookie = new Cookie(static::COOKIE_TOKEN_KEY, $accessTokenString); | |
$this->client->getCookieJar()->set($cookie); | |
} | |
/** | |
* Returns the given accessTokenString or as default the one | |
* defined in the class constant DEFAULT_ACCESS_TOKEN_STRING. | |
* | |
* @param null $accessTokenString | |
* @return null|string | |
*/ | |
protected function getAccessTokenString($accessTokenString = null) | |
{ | |
$accessTokenString = is_null($accessTokenString) | |
? static::DEFAULT_ACCESS_TOKEN_STRING | |
: $accessTokenString; | |
return $accessTokenString; | |
} | |
/** | |
* @see IgnoreValue | |
* @param array $fieldList | |
* @param string $dataKey Default "data" | |
*/ | |
protected function assertLastResponseBodyIsJsonAndContainsFields(array $fieldList, $dataKey = 'data') | |
{ | |
$responseBody = $this->getLastResponseBody(); | |
$this->assertJson($responseBody); | |
$decodedData = json_decode($responseBody)->$dataKey; | |
foreach ($fieldList as $fieldName => $value) { | |
$this->assertObjectHasAttribute( | |
$fieldName, | |
$decodedData, | |
"Field [$fieldName] not in object" | |
); | |
if (false === $value instanceof IgnoreValue) { | |
$this->assertEquals( | |
$value, | |
$decodedData->$fieldName, | |
"Expecting [$value] got: [{$decodedData->$fieldName}]" | |
); | |
} | |
} | |
} | |
/** | |
* Asserts the last Response contains an empty data property. | |
* | |
* @param string $message Message in case Assertions fails | |
*/ | |
protected function assertEmptyData($message = '') | |
{ | |
$this->assertJsonStringEqualsJsonString( | |
'{"data": []}', | |
$this->getLastResponseBody(), | |
$message | |
); | |
} | |
/** | |
* Asserts that the given paramter of a POST or PUT request, which was matched | |
* against a form, contains errors. | |
* | |
* @param $parameterName | |
*/ | |
protected function assertRequestFormHasErrorForParameter($parameterName) | |
{ | |
$responseObjAsArray = json_decode($this->getLastResponseBody(), true); | |
$this->assertArrayHasKey( | |
"errors", | |
$responseObjAsArray, | |
"Response does not contain any errors." | |
); | |
$this->assertArrayHasKey( | |
"children", | |
$responseObjAsArray["errors"], | |
"Response errors does not contain any children" | |
); | |
$this->assertArrayHasKey( | |
$parameterName, | |
$responseObjAsArray["errors"]["children"], | |
"Response errors does not contain the field $parameterName" | |
); | |
$this->assertArrayHasKey( | |
"errors", | |
$responseObjAsArray["errors"]["children"][$parameterName], | |
"Field $parameterName does not have any Errors" | |
); | |
} | |
/** | |
* Generates an expected fixture file | |
* | |
* This method will take the response returned by a test and write it to | |
* the expected fixture file. The filename and path used follows our | |
* convention for expected result files. The $fileNumber parameter can be | |
* passed for tests that use dataProviders to create numbered files. | |
* | |
* Calling this method will cause your test to raise a warning. Verify the | |
* fixture you generated, then remove this method from your test. It should | |
* never be kept in a test. | |
* | |
* @param string $variant | |
* @param string $extension | |
*/ | |
protected function generateExpectedResultsFile($variant = null, $extension = 'json') | |
{ | |
$fileName = $this->getExpectedResultsFile($variant, $extension); | |
$dirName = dirname($fileName); | |
if (false === is_dir($dirName)) { | |
mkdir($dirName); | |
} | |
file_put_contents($fileName, $this->getLastResponseBody()); | |
trigger_error(__METHOD__ . ' should never be kept in a test', E_USER_WARNING); | |
} | |
/** | |
* This method is run after a test was not successful. | |
* | |
* If the Environment variable 'RECREATEFIXTURES' is set it will recreate | |
* fixtures for tests which have failed. | |
* | |
* @param Exception $e | |
* @throws Exception | |
*/ | |
protected function onNotSuccessfulTest(Exception $e) | |
{ | |
$recreateFixtureFiles = getenv('RECREATEFIXTURES'); | |
if ($e instanceof FixtureFileNotMatchingException && $recreateFixtureFiles) { | |
file_put_contents($e->getFixtureFileName(), $this->getLastResponseBody()); | |
} | |
parent::onNotSuccessfulTest($e); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment