Completed
Push — master ( 4ccb7a...3447cd )
by
unknown
04:37 queued 02:40
created

FunctionalTestCase::assertGeneratedFileHasContent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 8
cts 8
cp 1
rs 9.8333
c 0
b 0
f 0
cc 2
nc 2
nop 3
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
6
namespace Sculpin\Tests\Functional;
7
8
use PHPUnit\Framework\TestCase;
9
use Symfony\Component\DomCrawler\Crawler;
10
use Symfony\Component\Filesystem\Filesystem;
11
use Symfony\Component\Process\Process;
12
13
/**
14
 * This test case allows you to create a test project on the fly,
15
 * and run the sculpin binary against it. Test project files
16
 * will automatically be created and removed with every test.
17
 */
18
class FunctionalTestCase extends TestCase
19
{
20
    protected const PROJECT_DIR = '/__SculpinTestProject__';
21
22
    /** @var Filesystem */
23
    protected static $fs;
24
25
    /** @var string */
26
    protected $executeOutput;
27
28
    public static function setUpBeforeClass(): void
29
    {
30
        static::$fs = new Filesystem();
31
    }
32
33 11
    public function setUp(): void
34
    {
35 11
        parent::setUp();
36
37 11
        $this->setUpTestProject();
38
    }
39
40 11
    protected function setUpTestProject(): void
41
    {
42 11
        $this->tearDownTestProject();
43
44
        $projectFiles = [
45 11
            '/config/sculpin_kernel.yml',
46
            '/config/sculpin_site.yml',
47
            '/source/_layouts/default.html.twig',
48
            '/source/_layouts/raw.html.twig',
49
        ];
50
51 11
        foreach ($projectFiles as $file) {
52 11
            $this->addProjectFile($file);
53
        }
54
55 11
        $this->writeToProjectFile('/source/_layouts/default.html.twig', '{% block content %}{% endblock content %}');
56 11
        $this->writeToProjectFile(
57 11
            '/source/_layouts/raw.html.twig',
58 11
            '{% extends "default" %}{% block content %}{% endblock content %}'
59
        );
60
    }
61
62 13
    protected function tearDownTestProject(): void
63
    {
64 13
        $projectDir = static::projectDir();
65 13
        if (static::$fs->exists($projectDir)) {
66 11
            static::$fs->remove($projectDir);
67
        }
68
    }
69
70
    /**
71
     * Execute a command against the sculpin binary
72
     * @param string $command
73
     */
74 13
    protected function executeSculpin($command): void
75
    {
76 13
        $binPath    = __DIR__ . '/../../../../bin';
77 13
        $projectDir = static::projectDir();
78 13
        exec("$binPath/sculpin $command --project-dir $projectDir --env=test", $this->executeOutput);
79
    }
80
81
    /**
82
     * Asynchronously execute a command against the sculpin binary
83
     *
84
     * Remember to stop the process when finished!
85
     *
86
     * @param string   $command
87
     * @param bool     $start     Default: start the process right away
88
     * @param callable $callback
89
     *
90
     * @return Process
91
     */
92 1
    protected function executeSculpinAsync(string $command, bool $start = true, ?callable $callback = null): Process
93
    {
94 1
        $binPath    = __DIR__ . '/../../../../bin';
95 1
        $projectDir = static::projectDir();
96 1
        $process    = new Process("$binPath/sculpin $command --project-dir $projectDir --env=test");
97
98 1
        if ($start) {
99 1
            $process->start($callback);
100
        }
101
102 1
        return $process;
103
    }
104
105
    /**
106
     * @param string $path
107
     * @param bool $recursive
108
     */
109 13
    protected function addProjectDirectory(string $path, bool $recursive = true): void
110
    {
111 13
        $pathParts = explode('/', $path);
112
        // Remove leading slash
113 13
        array_shift($pathParts);
114
115 13
        $projectDir = static::projectDir();
116
117 13
        if (!$recursive) {
118 2
            static::$fs->mkdir("$projectDir/$path");
119 2
            return;
120
        }
121
122 11
        $currPath = "$projectDir/";
123 11
        foreach ($pathParts as $dir) {
124 11
            $currPath .= "$dir/";
125 11
            if (!static::$fs->exists($currPath)) {
126 11
                static::$fs->mkdir($currPath);
127
            }
128
        }
129
    }
130
131
    /**
132
     * @param string $filePath
133
     * @param string $content
134
     */
135 11
    protected function addProjectFile(string $filePath, ?string $content = null): void
136
    {
137 11
        $dirPathParts = explode('/', $filePath);
138
        // Remove leading slash
139 11
        array_shift($dirPathParts);
140
        // Remove file name
141 11
        array_pop($dirPathParts);
142
143
        // Add the file directories
144 11
        $hasDirectoryPath = !empty($dirPathParts);
145 11
        if ($hasDirectoryPath) {
146 11
            $dirPath = '/' . join('/', $dirPathParts);
147 11
            $this->addProjectDirectory($dirPath);
148
        }
149
150
        // Create the file
151 11
        static::$fs->touch(static::projectDir() . $filePath);
152
153
        // Add content to the file
154 11
        if (!is_null($content)) {
155 2
            $this->writeToProjectFile($filePath, $content);
156
        }
157
    }
158
159
    /**
160
     * @param string $fixturePath
161
     * @param string $projectPath
162
     */
163 9
    protected function copyFixtureToProject(string $fixturePath, string $projectPath): void
164
    {
165 9
        static::$fs->copy($fixturePath, static::projectDir() . $projectPath);
166
    }
167
168
    /**
169
     * @param string        $filePath
170
     * @param string|null   $msg
171
     */
172 9
    protected function assertProjectHasFile(string $filePath, ?string $msg = null): void
173
    {
174 9
        $msg = $msg ?: "Expected project to contain file at path $filePath.";
175
176 9
        $this->assertTrue(static::$fs->exists(static::projectDir() . $filePath), $msg);
177
    }
178
179
    /**
180
     * @param string        $filePath
181
     * @param string|null   $msg
182
     */
183 4
    protected function assertProjectLacksFile(string $filePath, ?string $msg = null): void
184
    {
185 4
        $msg = $msg ?: "Expected project to NOT contain file at path $filePath.";
186
187 4
        $this->assertFalse(static::$fs->exists(static::projectDir() . $filePath), $msg);
188
    }
189
190
    /**
191
     * @param string $filePath
192
     * @param string|null $msg
193
     */
194 7
    protected function assertProjectHasGeneratedFile(string $filePath, ?string $msg = null): void
195
    {
196 7
        $outputDir = '/output_test';
197
198 7
        $msg = $msg ?: "Expected project to have generated file at path $filePath.";
199 7
        $this->assertProjectHasFile($outputDir . $filePath, $msg);
200
    }
201
202
    /**
203
     * @param string $filePath
204
     * @param string $expected
205
     * @param string|null $msg
206
     */
207 3
    protected function assertGeneratedFileHasContent(string $filePath, string $expected, ?string $msg = null): void
208
    {
209 3
        $outputDir = '/output_test';
210
211 3
        $msg        = $msg ?: "Expected generated file at path $filePath to have content '$expected'.";
212 3
        $fullPath   = static::projectDir() . $outputDir . $filePath;
213 3
        $fileExists = static::$fs->exists($fullPath);
214
215 3
        $this->assertTrue($fileExists, $msg . ' (File Not Found!)');
216
217 3
        $contents = file_get_contents($fullPath);
218 3
        $this->assertContains($expected, $contents, $msg);
219
    }
220
221
    /**
222
     * @param string $filePath
223
     * @param string $content
224
     */
225 11
    protected function writeToProjectFile(string $filePath, string $content): void
226
    {
227 11
        static::$fs->dumpFile(static::projectDir() . $filePath, $content);
228
    }
229
230
    /**
231
     * @param string $filePath
232
     * @return Crawler
233
     */
234 3
    protected function crawlGeneratedProjectFile(string $filePath): Crawler
235
    {
236 3
        return $this->crawlProjectFile('/output_test' . $filePath);
237
    }
238
239
    /**
240
     * @param string $filePath
241
     * @return Crawler
242
     */
243 3
    protected function crawlProjectFile(string $filePath): Crawler
244
    {
245 3
        return $this->crawlFile(static::projectDir() . $filePath);
246
    }
247
248
    /**
249
     * @param string $filePath
250
     * @return Crawler
251
     */
252 3
    private function crawlFile(string $filePath): Crawler
253
    {
254 3
        $content = $this->readFile($filePath);
255
256 3
        return new Crawler($content);
257
    }
258
259
    /**
260
     * @param $filePath
261
     * @return string
262
     */
263 3
    private function readFile(string $filePath): string
264
    {
265 3
        if (!static::$fs->exists($filePath)) {
266
            throw new \PHPUnit\Framework\Exception("Unable to read file at path $filePath: file does not exist");
267
        }
268
269 3
        $content = file_get_contents($filePath);
270 3
        if ($content === false) {
271
            throw new \PHPUnit\Framework\Exception("Unable to read file at path $filePath: failed to read file.");
272
        }
273
274 3
        return $content;
275
    }
276
277
    /**
278
     * @return string
279
     */
280 14
    protected static function projectDir(): string
281
    {
282 14
        return __DIR__ . static::PROJECT_DIR;
283
    }
284
}
285