Development
In case you are creating your own GraphQL module for OXID eShop, you might want to consider using the oxid-esales/graphql-module-skeleton which comes with a lot of best practices already applied.
Coding guidelines
To enforce coding standards in the project we use PHP-CS-Fixer with a very strict rule set that
you can find in the .php_cs.dist
file in all our GraphQL modules. The rule
set not only enforces PSR-12 but also
file level comments, ordering of methods, short array syntax and so on.
You can just take the distributed version and discuss with your team to fit the rule set to your needs.
Static code analysis
As it is a good thing ™ and GraphQL is fully typed anyway, we decided to also
go fully typed on all of our source code. All PHP files have declare(strict_types=1);
set.
In order to proof that we are using all types correct, we can take advantage of static code analyzers. We choose to use PHPStan, so it comes prepacked and configured, but please feel free to use anything that fits your needs.
For PHPStan to work, we added a preconfigured phpstan.neon
configuration file,
as well as the OXID eShop as a dev dependency.
Dependencies between software layers
As you might have already read in the Architecture docs, we are using a
layered architecture, aka Hexagonal or Ports and Adapters. To help us not violating
the boundaries of each layer, we use Deptrac
to validate how our layers are depending on each others. You can find a pre
configured depfile.yml
in our GraphQL modules, also in the module skeleton.
To run it, just run deptrac
in the root folder of the module.
Unit testing
To write unit tests, we included PHPUnit in the composer.json
’s
dev dependencies. As unit tests should not depend on anything outside, nothing special
applies here.
Integration testing
You have two ways to write integration tests for your GraphQL module, see below.
Those tests need the Shop to be setup and your module alongside the GraphQL Base module installed.
You can run them via
vendor/bin/phpunit -c vendor/oxid-esales/graphql-base/tests/phpunit.xml
or (for Codeception) via
vendor/bin/codecept run acceptance -c vendor/oxid-esales/graphql-base/tests/codeception.yml
.
Using PHPUnit
You can extend from the GraphQL base modules OxidEsales\GraphQL\Base\Tests\Integration\TestCase
or OxidEsales\GraphQL\Base\Tests\Integration\TokenTestCase
in order to build
integration tests for GraphQL queries you’d like to test.
<?php
/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/
declare(strict_types=1);
namespace Full\Qualified\Namespace\Tests\Integration\Context\Controller;
use OxidEsales\GraphQL\Base\Tests\Integration\TokenTestCase;
final class SampleTest extends TokenTestCase
{
public function testGetSingleActiveActionWithoutProducts(): void
{
$result = $this->query('
query {
token (username: "admin", password: "admin")
}
');
$this->assertSame(
200,
$result['status']
);
// assert that $result['body']['data']['token'] is a valid JWT
}
}
The TestCase
class exports the following methods for you to use:
query
query(string $query, ?array $variables = null, ?string $operationName = null): array
Send the GraphQL query in
$query
to theOxidEsales\GraphQL\Base\Framework\GraphQLQueryHandler
implementation an returns the result as an array.
beforeContainerCompile
protected static function beforeContainerCompile(): void
If you need to inject something into the container before it is compiled, you can override this method in you test case.
The TokenTestCase
extends the TestCase
and adds handling for auth tokens
setAuthToken
protected function setAuthToken(string $token): void
Set the JWT in
$token
to be used with the next queries.
Using Codeception
In the GraphQL module skeleton you may also find a pre configured setup to
use Codeception to write your integration tests. As this testing is just against
and HTTP API, there is no need to run a headless browser, so the acceptance.suite.yml
is pretty slim and tests are pretty fast.
# suite config
actor: AcceptanceTester
path: Acceptance
modules:
enabled:
- \Full\Qualified\Namespace\Tests\Codeception\Helper\Acceptance
- REST:
url: '%SHOP_URL%'
depends: PhpBrowser
part: Json
<?php
/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/
declare(strict_types=1);
namespace Full\Qualified\Namespace\Tests\Codeception\Acceptance;
use Full\Qualified\Namespace\Tests\Codeception\AcceptanceTester;
class CategoryQueryCest
{
public function testFetchSingleCategoryById(AcceptanceTester $I): void
{
$I->haveHTTPHeader('Content-Type', 'application/json');
$I->sendPOST('/graphql/', [
'query' => 'query {
token (username: "admin", password: "admin")
}'
]);
$I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK);
$I->seeResponseIsJson();
// assert that result is a valid JWT
}
}
Happy hacking!