Passed
Push — master ( c5d212...10120e )
by jelmer
300:24 queued 293:08
created

WebTestCase::createClient()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
nc 4
nop 2
dl 0
loc 15
ccs 9
cts 9
cp 1
crap 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Common;
4
5
use ForkCMS\App\AppKernel;
6
use ForkCMS\App\BaseModel;
7
use SpoonDatabase;
8
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase;
9
use Symfony\Component\FileSystem\Filesystem;
10
use Symfony\Bundle\FrameworkBundle\Client;
11
use Symfony\Component\DomCrawler\Form;
12
use Symfony\Component\DomCrawler\Crawler;
13
use Backend\Core\Engine\Authentication;
14
15
/**
16
 * WebTestCase is the base class for functional tests.
17
 */
18
abstract class WebTestCase extends BaseWebTestCase
19
{
20
    /**
21
     * Attempts to guess the kernel location.
22
     *
23
     * When the Kernel is located, the file is required.
24
     *
25
     * @todo Remove this when Fork has no custom Kernel class anymore
26
     *
27
     * @throws \RuntimeException
28
     *
29
     * @return string The Kernel class name
30
     */
31 1
    protected static function getKernelClass(): string
32
    {
33 1
        return AppKernel::class;
34
    }
35
36
    /**
37
     * Creates a Client.
38
     *
39
     * @param array $options An array of options to pass to the createKernel class
40
     * @param array $server An array of server parameters
41
     *
42
     * @return Client A Client instance
43
     */
44 83
    protected static function createClient(array $options = [], array $server = []): Client
45
    {
46 83
        if (null !== static::$kernel) {
47 10
            static::$kernel->shutdown();
48
        }
49
50 83
        if (!array_key_exists('environment', $options)) {
51 82
            $options['environment'] = 'test';
52
        }
53
54 83
        $client = parent::createClient($options, $server);
55 83
        static::$kernel = $client->getKernel();
56 83
        BaseModel::setContainer(static::$kernel->getContainer());
57
58 83
        return $client;
59
    }
60
61
    /**
62
     * Fully empties the test database
63
     *
64
     * @param SpoonDatabase $database
65
     */
66 13
    protected function emptyTestDatabase(SpoonDatabase $database)
67
    {
68 13
        foreach ($database->getTables() as $table) {
69 13
            $database->execute(
70 13
                'SET FOREIGN_KEY_CHECKS = 0; DROP TABLE IF EXISTS ' . $table . '; SET FOREIGN_KEY_CHECKS = 1;'
71
            );
72
        }
73 13
    }
74
75
    /**
76
     * Executes sql in the database
77
     *
78
     * @param SpoonDatabase $database
79
     * @param string $sql
80
     */
81 12
    protected function importSQL(SpoonDatabase $database, string $sql)
82
    {
83 12
        $database->execute(trim($sql));
84 12
    }
85
86 12
    protected function loadFixtures(Client $client, array $fixtureClasses = [])
87
    {
88 12
        $database = $client->getContainer()->get('database');
89
90
        // make sure our database has a clean state (freshly installed Fork)
91 12
        $this->emptyTestDatabase($database);
0 ignored issues
show
Bug introduced by
It seems like $database can also be of type null; however, parameter $database of Common\WebTestCase::emptyTestDatabase() does only seem to accept SpoonDatabase, maybe add an additional type check? ( Ignorable by Annotation )

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

91
        $this->emptyTestDatabase(/** @scrutinizer ignore-type */ $database);
Loading history...
92 12
        $kernelDir = $client->getContainer()->getParameter('kernel.project_dir') . '/app';
93 12
        $this->importSQL(
94 12
            $client->getContainer()->get('database'),
0 ignored issues
show
Bug introduced by
It seems like $client->getContainer()->get('database') can also be of type null; however, parameter $database of Common\WebTestCase::importSQL() does only seem to accept SpoonDatabase, maybe add an additional type check? ( Ignorable by Annotation )

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

94
            /** @scrutinizer ignore-type */ $client->getContainer()->get('database'),
Loading history...
95 12
            file_get_contents($kernelDir . '/../tests/data/test_db.sql')
96
        );
97
98
        // load all the fixtures
99 12
        foreach ($fixtureClasses as $class) {
100 11
            $fixture = new $class();
101 11
            $fixture->load($database);
102
        }
103 12
    }
104
105
    /**
106
     * Copies the parameters.yml file to a backup version
107
     *
108
     * @param string $kernelDir
109
     * @param Filesystem $filesystem
110
     */
111 1
    protected function backupParametersFile(Filesystem $filesystem, string $kernelDir)
112
    {
113 1
        if ($filesystem->exists($kernelDir . '/config/parameters.yml')) {
114 1
            $filesystem->copy(
115 1
                $kernelDir . '/config/parameters.yml',
116 1
                $kernelDir . '/config/parameters.yml~backup'
117
            );
118
        }
119 1
        if ($filesystem->exists($kernelDir . '/cache/test')) {
120
            $filesystem->remove($kernelDir . '/cache/test');
121
        }
122 1
    }
123
124
    /**
125
     * Puts the backed up parameters.yml file back
126
     *
127
     * @param string $kernelDir
128
     * @param Filesystem $filesystem
129
     */
130 1
    protected function putParametersFileBack(Filesystem $filesystem, string $kernelDir)
131
    {
132 1
        if ($filesystem->exists($kernelDir . '/config/parameters.yml~backup')) {
133 1
            $filesystem->copy(
134 1
                $kernelDir . '/config/parameters.yml~backup',
135 1
                $kernelDir . '/config/parameters.yml',
136 1
                true
137
            );
138 1
            $filesystem->remove($kernelDir . '/config/parameters.yml~backup');
139
        }
140 1
        if ($filesystem->exists($kernelDir . '/cache/test')) {
141
            $filesystem->remove($kernelDir . '/cache/test');
142
        }
143 1
    }
144
145 9
    protected function assertIs404(Client $client)
146
    {
147 9
        self::assertEquals(
148 9
            404,
149 9
            $client->getResponse()->getStatusCode()
150
        );
151 9
    }
152
153
    /**
154
     * Submits the form and mimics the GET parameters, since they aren't added
155
     * by default in the functional tests
156
     *
157
     * @param Client $client
158
     * @param Form $form
159
     * @param array $data
160
     */
161 37
    protected function submitForm(Client $client, Form $form, array $data = []): void
162
    {
163
        // Get parameters should be set manually. Symfony uses the request object,
164
        // but spoon still checks the $_GET and $_POST parameters
165 37
        foreach ($data as $key => $value) {
166 37
            $_GET[$key] = $value;
167 37
            $_POST[$key] = $value;
168
        }
169
170 37
        $client->submit($form);
171
172 37
        foreach ($data as $key => $value) {
173 37
            unset($_GET[$key]);
174 37
            unset($_POST[$key]);
175
        }
176 37
    }
177
178
    /**
179
     * Edits the data of a form
180
     *
181
     * @param Client $client
182
     * @param Form $form
183
     * @param array $data
184
     */
185 5
    protected function submitEditForm(Client $client, Form $form, array $data = []): void
186
    {
187 5
        $originalData = [];
188 5
        foreach ($form->all() as $fieldName => $formField) {
189 5
            $originalData[$fieldName] = $formField->getValue();
190
        }
191
192 5
        $data = array_merge($originalData, $data);
193
194 5
        $this->submitForm($client, $form, $data);
195 5
    }
196
197
    /**
198
     * Do a request with the given GET parameters
199
     *
200
     * @param Client $client
201
     * @param string $url
202
     * @param array $data
203
     *
204
     * @return Crawler
205
     */
206
    protected function requestWithGetParameters(
207
        Client $client,
208
        string $url,
209
        array $data = []
210
    ): Crawler {
211
        $this->setGetParameters($data);
212
        $request = $client->request('GET', $url, $data);
213
        $this->unsetGetParameters($data);
214
215
        return $request;
216
    }
217
218
    /**
219
     * Set the GET parameters, as some of the old code relies on GET
220
     *
221
     * @param array $data
222
     */
223
    protected function setGetParameters(array $data = []): void
224
    {
225
        foreach ((array) $data as $key => $value) {
226
            $_GET[$key] = $value;
227
        }
228
    }
229
230
    /**
231
     * Unset the GET parameters, as some of the old code relies on GET
232
     *
233
     * @param array $data
234
     */
235
    protected function unsetGetParameters(array $data = []): void
236
    {
237
        if (empty($data)) {
238
            $_GET = [];
239
240
            return;
241
        }
242
243
        foreach ($data as $key => $value) {
244
            unset($_GET[$key]);
245
        }
246
    }
247
248
    /**
249
     * Logs the client in
250
     *
251
     * Logging in using the forms is tested in the Authentication module
252
     *
253
     * @param Client $client
254
     */
255 31
    protected function login(Client $client): void
256
    {
257 31
        Authentication::tearDown();
258 31
        $crawler = $client->request('GET', '/private/en/authentication');
259
260 31
        $form = $crawler->selectButton('login')->form();
261 31
        $this->submitForm($client, $form, [
262 31
            'form' => 'authenticationIndex',
263 31
            'backend_email' => '[email protected]',
264 31
            'backend_password' => 'fork',
265 31
            'form_token' => $form['form_token']->getValue(),
266
        ]);
267 31
    }
268
269
    /**
270
     * Logs the client out
271
     *
272
     * @param Client $client
273
     */
274 25
    protected function logout(Client $client): void
275
    {
276 25
        $client->setMaxRedirects(-1);
277 25
        $client->request('GET', '/private/en/authentication/logout');
278 25
        Authentication::tearDown();
279 25
    }
280
}
281