Passed
Push — master ( 5cd32c...1a1aa9 )
by Rafael
05:46
created

ApiTestCase::getClient()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*******************************************************************************
4
 *  This file is part of the GraphQL Bundle package.
5
 *
6
 *  (c) YnloUltratech <[email protected]>
7
 *
8
 *  For the full copyright and license information, please view the LICENSE
9
 *  file that was distributed with this source code.
10
 ******************************************************************************/
11
12
namespace Ynlo\GraphQLBundle\Test;
13
14
use Doctrine\Common\DataFixtures\ReferenceRepository;
15
use PHPUnit\Util\Blacklist;
16
use Symfony\Bundle\FrameworkBundle\Client;
17
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\Stopwatch\Stopwatch;
21
use Ynlo\GraphQLBundle\Definition\Registry\DefinitionRegistry;
22
use Ynlo\GraphQLBundle\Model\ID;
23
use Ynlo\GraphQLBundle\Model\NodeInterface;
24
use Ynlo\GraphQLBundle\Test\Assert\DoctrineAssertTrait;
25
use Ynlo\GraphQLBundle\Test\Assert\JsonAssertTrait;
26
use Ynlo\GraphQLBundle\Test\Assert\ResponseAssertTrait;
27
use Ynlo\GraphQLBundle\Test\FixtureLoader\FixtureLoader;
28
use Ynlo\GraphQLBundle\Test\Helper\DoctrineHelperTrait;
29
use Ynlo\GraphQLBundle\Test\Helper\JsonHelperTrait;
30
use Ynlo\GraphQLBundle\Test\Helper\ResponseHelperTrait;
31
use Ynlo\GraphQLBundle\Util\IDEncoder;
32
33
/**
34
 * @deprecated in favor of Behat tests
35
 */
36
class ApiTestCase extends WebTestCase
37
{
38
    // helpers
39
    use DoctrineHelperTrait;
0 ignored issues
show
Deprecated Code introduced by
The trait Ynlo\GraphQLBundle\Test\Helper\DoctrineHelperTrait has been deprecated: in favor of Behat tests ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

39
    use /** @scrutinizer ignore-deprecated */ DoctrineHelperTrait;

This trait has been deprecated. The supplier of the trait has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the trait will be removed and what other trait to use instead.

Loading history...
40
    use JsonHelperTrait;
0 ignored issues
show
Deprecated Code introduced by
The trait Ynlo\GraphQLBundle\Test\Helper\JsonHelperTrait has been deprecated: in favor of Behat tests ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

40
    use /** @scrutinizer ignore-deprecated */ JsonHelperTrait;

This trait has been deprecated. The supplier of the trait has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the trait will be removed and what other trait to use instead.

Loading history...
41
    use ResponseHelperTrait;
0 ignored issues
show
Deprecated Code introduced by
The trait Ynlo\GraphQLBundle\Test\Helper\ResponseHelperTrait has been deprecated: in favor of Behat tests ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

41
    use /** @scrutinizer ignore-deprecated */ ResponseHelperTrait;

This trait has been deprecated. The supplier of the trait has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the trait will be removed and what other trait to use instead.

Loading history...
42
43
    // asserts
44
    use DoctrineAssertTrait;
0 ignored issues
show
Deprecated Code introduced by
The trait Ynlo\GraphQLBundle\Test\Assert\DoctrineAssertTrait has been deprecated: in favor of Behat tests ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

44
    use /** @scrutinizer ignore-deprecated */ DoctrineAssertTrait;

This trait has been deprecated. The supplier of the trait has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the trait will be removed and what other trait to use instead.

Loading history...
45
    use JsonAssertTrait;
0 ignored issues
show
Deprecated Code introduced by
The trait Ynlo\GraphQLBundle\Test\Assert\JsonAssertTrait has been deprecated: in favor of Behat tests ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

45
    use /** @scrutinizer ignore-deprecated */ JsonAssertTrait;

This trait has been deprecated. The supplier of the trait has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the trait will be removed and what other trait to use instead.

Loading history...
46
    use ResponseAssertTrait;
0 ignored issues
show
Bug introduced by
The trait Ynlo\GraphQLBundle\Test\Assert\ResponseAssertTrait requires the property $headers which is not provided by Ynlo\GraphQLBundle\Test\ApiTestCase.
Loading history...
Deprecated Code introduced by
The trait Ynlo\GraphQLBundle\Test\Assert\ResponseAssertTrait has been deprecated: in favor of Behat tests ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

46
    use /** @scrutinizer ignore-deprecated */ ResponseAssertTrait;

This trait has been deprecated. The supplier of the trait has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the trait will be removed and what other trait to use instead.

Loading history...
47
48
    /**
49
     * @var ReferenceRepository
50
     */
51
    protected static $referenceRepository;
52
53
    /**
54
     * @var Client
55
     */
56
    protected static $client;
57
58
    /**
59
     * Whether to insulate each request or not.
60
     * The request ran into a separate process to avoid
61
     * any conflict (cache, container, doctrine etc..) with previous requests.
62
     *
63
     * NOTE: should be disabled for debugging
64
     *
65
     * @var bool
66
     */
67
    protected static $insulateRequests = false;
68
69
    /**
70
     * Endpoint where the API is available, e.g. /api
71
     *
72
     * @var string
73
     */
74
    protected static $endpoint = '';
75
76
    private static $lastQuery;
77
78
    private static $lastQueryExecutionTime = 0;
79
80
    public function __construct(string $name = null, array $data = [], string $dataName = '')
81
    {
82
        parent::__construct($name, $data, $dataName);
83
84
        Blacklist::$blacklistedClassNames['Ynlo\GraphQLBundle\Test\ApiTestCase'] = 1;
85
    }
86
87
    final public static function setUpBeforeClass()
88
    {
89
        static::$client = null;
90
    }
91
92 22
    final public function setUp()
93
    {
94 22
        parent::setUp();
95
96 22
        self::$lastQuery = null;
97 22
        self::$lastQueryExecutionTime = 0;
98
99 22
        static::loadFixtures();
100 22
        $this->before();
101 22
    }
102
103
    /**
104
     * This method is called before a test is executed.
105
     */
106
    public function before()
107
    {
108
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 22
    final protected function tearDown()
115
    {
116 22
        parent::tearDown();
117 22
        static::$client = null;
118 22
        $this->after();
119 22
    }
120
121
    /**
122
     * This method is called after a test is executed.
123
     */
124 22
    public function after()
125
    {
126
127 22
    }
128
129 22
    protected static function createClient(array $options = [], array $server = [])
130
    {
131 22
        return static::$client = parent::createClient($options, $server);
132
    }
133
134 22
    protected static function getClient(): Client
135
    {
136 22
        return static::$client ?? static::createClient();
137
    }
138
139 22
    protected static function loadFixtures($classNames = [])
140
    {
141
        /** @var Client $client */
142 22
        $client = static::getClient();
143 22
        $container = $client->getContainer();
144 22
        if ($container) {
145 22
            $fixtureLoader = new FixtureLoader($container, $container->get('doctrine'));
146 22
            static::$referenceRepository = $fixtureLoader->loadFixtures($classNames);
147
        }
148 22
    }
149
150 22
    protected static function getFixtureReference(string $name)
151
    {
152 22
        return self::$referenceRepository->getReference($name);
153
    }
154
155
    /**
156
     * @param string    $query     query or mutation in GraphQL format
157
     * @param array     $variables array of variables
158
     * @param bool|null $insulate  Whether to insulate the requests or not. Leave null to use default value.
159
     *                             The request ran into a separate process to avoid
160
     *                             any conflict (cache, container, doctrine etc..) with previous requests.
161
     *                             NOTE: should be disabled for debugging
162
     *
163
     * @return Response
164
     */
165 22
    protected static function send($query, array $variables = [], $insulate = null): Response
166
    {
167 22
        self::$lastQuery = ['query' => $query, 'variables' => $variables];
168
169 22
        if (null === $insulate) {
170 22
            $insulate = static::$insulateRequests;
171
        }
172
173 22
        $client = static::getClient();
174 22
        $client->insulate($insulate);
175
176 22
        $watch = new Stopwatch();
177 22
        $watch->start('query');
178 22
        $client->request(Request::METHOD_POST, self::$endpoint, [], [], [], json_encode(self::$lastQuery));
179 22
        $watch->stop('query');
180 22
        self::$lastQueryExecutionTime = $watch->getEvent('query')->getDuration();
181
182 22
        return $client->getResponse();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $client->getResponse() could return the type null which is incompatible with the type-hinted return Symfony\Component\HttpFoundation\Response. Consider adding an additional type-check to rule them out.
Loading history...
183
    }
184
185
    /**
186
     * Use this method to get the global ID of a existent fixture
187
     *
188
     * getFixtureGlobalId('user1') => VXNlcjox
189
     */
190 3
    protected static function getFixtureGlobalId(string $name): string
191
    {
192 3
        $fixture = static::getFixtureReference($name);
193 3
        if ($fixture instanceof NodeInterface) {
194 3
            return static::encodeID($fixture);
195
        }
196
197
        throw new \RuntimeException(sprintf('The fixture must implements %s', NodeInterface::class));
198
    }
199
200
    /**
201
     * Encode given id or node interface to global ID
202
     *
203
     * encodeID($user) => VXNlcjox
204
     * encodeID(1, 'User') => VXNlcjox
205
     *
206
     * @param string|NodeInterface $node     id of the node or instance
207
     * @param string               $nodeType required in case the first argument is scalar
208
     *
209
     * @return string
210
     */
211 11
    protected static function encodeID($node, $nodeType = null)
212
    {
213 11
        if (!is_object($node) && !$nodeType) {
214
            throw new \RuntimeException('Node type is required when use scalar ID as node');
215
        }
216
217 11
        if (!$node instanceof NodeInterface) {
218
            $nodeClass = static::getClient()
219
                               ->getContainer()
220
                               ->get(DefinitionRegistry::class)
221
                               ->getEndpoint()
222
                               ->getClassForType($nodeType);
223
224
            $node = self::getDoctrine()->getEntityManager()->getReference($nodeClass, $node);
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\Bundle\Doctrine...try::getEntityManager() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

224
            $node = /** @scrutinizer ignore-deprecated */ self::getDoctrine()->getEntityManager()->getReference($nodeClass, $node);
Loading history...
225
        }
226
227 11
        return IDEncoder::encode($node);
228
    }
229
230
    /**
231
     * Decode globalId to get type and real database id
232
     *
233
     * @deprecated since v1.1 use IDEncoder utility instead
234
     */
235
    protected static function decodeID(string $globalID): ID
236
    {
237
        return ID::createFromString($globalID);
0 ignored issues
show
Deprecated Code introduced by
The function Ynlo\GraphQLBundle\Model\ID::createFromString() has been deprecated: since v1.1 IDEncoder::decode() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

237
        return /** @scrutinizer ignore-deprecated */ ID::createFromString($globalID);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
238
    }
239
240
    /**
241
     * Print helpful debug information for latest executed query
242
     */
243
    protected static function debugLastQuery()
244
    {
245
        if (self::$lastQuery) {
246
            $query = self::$lastQuery['query'] ?? null;
247
248
            $type = 'QUERY';
249
            if (preg_match('/^\s*mutation/', $query)) {
250
                $type = 'MUTATION';
251
            }
252
253
            $variables = self::$lastQuery['variables'] ?? null;
254
255
            print_r("\033[43m\n\n----------------------- $type ---------------------\n\n\033[0m");
256
            print_r($query ?? null);
257
            print_r("\n\n");
258
            print_r("\033[46m------------------- VARIABLES-----------------------\n\n\033[0m");
259
            print_r(json_encode($variables, JSON_PRETTY_PRINT));
260
            print_r("\n\n");
261
262
            /** @var Response $response */
263
            $response = static::getClient()->getResponse();
264
            $bg = $response->getStatusCode() >= 400 ? 41: 42;
265
            print_r("\033[{$bg}m-------------------- RESPONSE ----------------------\n\n\033[0m");
266
            print_r(sprintf("STATUS: [%s] %s \n", $response->getStatusCode(), Response::$statusTexts[$response->getStatusCode()] ?? 'Unknown Status'));
267
            print_r(sprintf("TIME: %s ms \n\n", self::$lastQueryExecutionTime));
268
269
            $content = $response->getContent();
270
            $json = @json_decode($content, true);
271
            if ($json) {
272
                print_r(json_encode($json, JSON_PRETTY_PRINT));
273
            } else {
274
                print_r($content);
275
            }
276
            print_r("\n\n");
277
            print_r("-----------------------------------------------------\n\n");
278
        } else {
279
            throw new \RuntimeException('Does not exist any executed query on current test, try use this method after "send" the query.');
280
        }
281
    }
282
283 22
    protected function runTest()
284
    {
285
        try {
286 22
            parent::runTest();
287
        } catch (\Exception $exception) {
288
            if (self::$lastQuery) {
289
                self::debugLastQuery();
290
            }
291
292
            throw $exception;
293
        }
294 22
    }
295
}
296
297