Passed
Pull Request — master (#9)
by Rafael
03:29
created

DoctrineContext::getDoctrine()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
crap 2
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Behat\Context;
12
13
use Behat\Behat\Context\Context;
14
use Doctrine\Bundle\DoctrineBundle\Registry;
15
use Doctrine\Common\Persistence\ObjectRepository;
16
use Doctrine\ORM\EntityRepository;
17
use PHPUnit\Framework\Assert;
18
use Symfony\Component\HttpKernel\KernelInterface;
19
use Ynlo\GraphQLBundle\Behat\Client\ClientAwareInterface;
20
use Ynlo\GraphQLBundle\Behat\Client\ClientAwareTrait;
21
use Ynlo\GraphQLBundle\Behat\Gherkin\YamlStringNode;
22
use Ynlo\GraphQLBundle\Behat\Storage\StorageAwareInterface;
23
use Ynlo\GraphQLBundle\Behat\Storage\StorageAwareTrait;
24
25
/**
26
 * Context for Doctrine integration
27
 *
28
 * @property KernelInterface $kernel
29
 */
30
final class DoctrineContext implements Context, ClientAwareInterface, StorageAwareInterface
31
{
32
    use ClientAwareTrait;
33
    use StorageAwareTrait;
34
35
    /**
36
     * Use a YAML syntax to create a criteria to match a record in given repository
37
     *
38
     * Example: Then should exist in repository "AppBundle:Post" a record matching:
39
     *   """
40
     *   title: "Welcome"
41
     *   body: "Welcome to web page"
42
     *   """
43
     *
44
     * Expression syntax is allowed
45
     *
46
     * Example: Then should exist in table "post" a record matching:
47
     *   """
48
     *   title: "{variables.input.title}"
49
     *   body: "{variables.input.body}"
50
     *   """
51
     *
52
     * @Given /^should exist in repository "([^"]*)" a record matching:$/
53
     */
54
    public function shouldExistInRepositoryARecordMatching($repo, YamlStringNode $criteria)
55
    {
56
        $exists = (boolean) $this->getDoctrine()->getRepository($repo)->findOneBy($criteria->toArray());
57
        Assert::assertTrue($exists, sprintf('Does not exist any record in the repository "%s" matching given conditions', $repo));
58
    }
59
60
    /**
61
     * Grab a set of records from database in a temp variable inside the `"storage"` in order to use latter in an expression
62
     *
63
     * The prefix `"grab in"` is optional and can be used in "Then" for readability
64
     *
65
     * <code>
66
     * Given "users" from ....
67
     * Then grab in "users" from ...
68
     * </code>
69
     *
70
     * The suffix `"matching:"` is optional too and can be used to set array of conditions to match.
71
     *
72
     * ### Placeholders:
73
     * - **$variable:** `(string)` name of the variable to save in the storage
74
     * - **$entity:** `(string)` name of the entity using bundle notation `"AppBundle:Entity"` or FQN
75
     * - **$limitAndOffset:** `(int|string)` amount of records to fetch `"limit"` or use `"limit:offset"` to use pagination
76
     * - **$orderBy:** `(string|array)` string like `"title:ASC"` or array inside expression like `"{ [{status: 'DESC', title: 'ASC'}] }"`
77
     * - **$criteria:** `(yaml)` YAML node to convert to array of criteria
78
     *
79
     * ### Examples:
80
     *
81
     * <code>
82
     * - Given "orderedUsers" from repository "AppBundle:User" first 5 records ordered by "username:ASC" matching:
83
     *          """
84
     *          enabled: true
85
     *          """
86
     * - Given "orderedUsers" from repository "AppBundle:User" first 5 records ordered by "username:ASC"
87
     * - And "orderedUsersWithOffset" from repository "AppBundle:User" first "10:20" records ordered by "username:ASC"
88
     * - Then grab in "orderedPosts" from repository "AppBundle:Post" first 10 records ordered by "{ [{status: 'DESC', title: 'ASC'}] }"
89
     * </code>
90
     *
91
     * and later can be used:
92
     *
93
     * <code>
94
     * - And "{orderedUsers[0].getUsername()}" should be equal to "{response.data.users.all.edges[0].node.login}"
95
     * </code>
96
     *
97
     * @Given /^(?:grab in )?"([^"]*)" from repository "([^"]*)" first "?([^"]*)"? records ordered by "([^"]*)"(?: matching:)?$/
98
     */
99
    public function grabInFromRepositoryFirstRecordsOrderedByMatching($variable, $repo, $limitAndOffset = null, $orderBy = null, YamlStringNode $criteria = null)
100
    {
101
        //support to use "limit:offset"
102
        if (strpos($limitAndOffset, ':') !== false) {
103
            list($limit, $offset) = explode(':', $limitAndOffset);
104
        } else {
105
            $limit = $limitAndOffset;
106
            $offset = null;
107
        }
108
        // support field:ORDER, eg. name:ASC
109
        if (is_string($orderBy)) {
110
            list($field, $order) = explode(':', $orderBy);
111
            $orderBy = [$field => $order];
112
        }
113
        $records = $this->getDoctrine()
114
                        ->getRepository($repo)
115
                        ->findBy($criteria ? $criteria->toArray() : [], $orderBy, $limit, $offset);
116
        $this->storage->setValue($variable, $records);
117
    }
118
119
    public function getDoctrine(): Registry
120
    {
121
        return $this->client->getContainer()->get('doctrine');
122
    }
123
124
    /**
125
     * @param string $class
126
     *
127
     * @return ObjectRepository|EntityRepository
128
     */
129
    public function getRepository(string $class): ObjectRepository
130
    {
131
        return $this->getDoctrine()->getRepository($class);
132
    }
133
}
134