Completed
Push — master ( c1a738...2c88a4 )
by
unknown
02:35 queued 01:13
created

TestCase::myAssertMatchesRegularExpression()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 3
1
<?php
2
3
/**
4
 * This file is part of the GitElephant package.
5
 *
6
 * (c) Matteo Giachino <[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
 * Just for fun...
12
 */
13
14
namespace GitElephant;
15
16
use GitElephant\Command\Caller\Caller;
17
use GitElephant\Command\Caller\CallerInterface;
18
use GitElephant\Command\MvCommand;
19
use GitElephant\Objects\Author;
20
use GitElephant\Objects\Commit;
21
use Mockery as m;
22
use PHPUnit\Framework\MockObject\MockObject;
23
use Symfony\Component\Filesystem\Filesystem;
24
use Symfony\Component\Finder\Finder;
25
26
/**
27
 * Class TestCase
28
 *
29
 * @package GitElephant
30
 */
31
class TestCase extends \PHPUnit\Framework\TestCase
32
{
33
    /**
34
     * @var \GitElephant\Command\Caller\CallerInterface
35
     */
36
    protected $caller;
37
38
    /**
39
     * @var Repository|array<Repository>
40
     */
41
    protected $repository;
42
43
    /**
44
     * @var string
45
     */
46
    protected $path;
47
48
    /**
49
     * @var Finder
50
     */
51
    protected $finder;
52
53
    /**
54
     * @param string|int|null $name the name or index of the repository
55
     *
56
     * @return \GitElephant\Repository
57
     */
58
    protected function getRepository($name = null)
59
    {
60
        if ($this->repository == null) {
61
            $this->initRepository($name);
62
        }
63
        if (is_null($name)) {
64
            return $this->repository;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->repository; of type GitElephant\Repository|GitElephant\Repository[] adds the type GitElephant\Repository[] to the return on line 64 which is incompatible with the return type documented by GitElephant\TestCase::getRepository of type GitElephant\Repository.
Loading history...
65
        } else {
66
            return $this->repository[$name];
67
        }
68
    }
69
70
    /**
71
     * @return CallerInterface the real/not mocked caller
72
     */
73
    protected function getCaller(): CallerInterface
74
    {
75
        if ($this->caller == null) {
76
            $this->initRepository();
77
        }
78
79
        return $this->caller;
80
    }
81
82
    /**
83
     * @param null|string $name  the folder name
84
     * @param int         $index the repository index (for getting them back)
85
     *
86
     * @return void
87
     */
88
    protected function initRepository(string $name = null, int $index = null): void
89
    {
90
        $tempDir = realpath(sys_get_temp_dir());
91
        $tempName = null === $name
92
            ? tempnam($tempDir, 'gitelephant')
93
            : $tempDir . DIRECTORY_SEPARATOR . $name;
94
        $this->path = $tempName;
95
        @unlink($this->path);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
96
        $fs = new Filesystem();
97
        $fs->mkdir($this->path);
98
        $this->caller = new Caller(null, $this->path);
99
        if (is_null($index)) {
100
            $this->repository = Repository::open($this->path);
101
            $this->assertInstanceOf(Repository::class, $this->repository);
102
        } else {
103
            if (!is_array($this->repository)) {
104
                $this->repository = [];
105
            }
106
            $this->repository[$index] = Repository::open($this->path);
107
            $this->assertInstanceOf(Repository::class, $this->repository[$index]);
108
        }
109
    }
110
111
    protected function tearDown(): void
112
    {
113
        $fs = new Filesystem();
114
        if (is_array($this->repository)) {
115
            array_map(function (Repository $repo) use ($fs) {
116
                $fs->remove($repo->getPath());
117
            }, $this->repository);
118
        } else {
119
            $fs->remove($this->path);
120
        }
121
        m::close();
122
    }
123
124
    /**
125
     * Write to file. Creates the file if not existing.
126
     * Overwrites content if already existing.
127
     *
128
     * @param string      $name       file name
129
     * @param string|null $folder     folder name
130
     * @param string|null        $content    content
131
     * @param Repository  $repository repository to add file to
132
     *
133
     * @return void
134
     */
135
    protected function addFile(
136
        string $name,
137
        string $folder = null,
138
        string $content = null,
139
        Repository $repository = null
140
    ): void {
141
        $path = is_null($repository) ? $this->path : $repository->getPath();
142
        $filename = $folder == null
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $folder of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
143
            ? $path . DIRECTORY_SEPARATOR . $name
144
            : $path . DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR . $name;
145
        $handle = fopen($filename, 'w');
146
        $fileContent = $content === null ? 'test content' : $content;
147
        $this->assertTrue(false !== fwrite($handle, $fileContent), sprintf('unable to write the file %s', $name));
148
        fclose($handle);
149
    }
150
151
    /**
152
     * remove file from repo
153
     *
154
     * @param string $name
155
     */
156
    protected function removeFile(string $name): void
157
    {
158
        $filename = $this->path . DIRECTORY_SEPARATOR . $name;
159
        $this->assertTrue(unlink($filename));
160
    }
161
162
    /**
163
     * update a file in the repository
164
     *
165
     * @param string $name    file name
166
     * @param string $content content
167
     */
168
    protected function updateFile(string $name, string $content): void
169
    {
170
        $filename = $this->path . DIRECTORY_SEPARATOR . $name;
171
        $this->assertTrue(false !== file_put_contents($filename, $content));
172
    }
173
174
    /**
175
     * rename a file in the repository
176
     *
177
     * @param string $originName file name
178
     * @param string $targetName new file name
179
     * @param bool   $gitMv      use git mv, otherwise uses php rename function (with the Filesystem component)
180
     */
181
    protected function renameFile(string $originName, string $targetName, bool $gitMv = true): void
182
    {
183
        if ($gitMv) {
184
            $this->getRepository()
185
                ->getCaller()
186
                ->execute(MvCommand::getInstance()->rename($originName, $targetName));
187
188
            return;
189
        }
190
        $origin = $this->path . DIRECTORY_SEPARATOR . $originName;
191
        $target = $this->path . DIRECTORY_SEPARATOR . $targetName;
192
        $fs = new Filesystem();
193
        $fs->rename($origin, $target);
194
    }
195
196
    /**
197
     * @param string $name name
198
     *
199
     * @return void
200
     */
201
    protected function addFolder($name): void
202
    {
203
        $fs = new Filesystem();
204
        $fs->mkdir($this->path . DIRECTORY_SEPARATOR . $name);
205
    }
206
207
    protected function addSubmodule(string $url, string $path): void
208
    {
209
        $this->getRepository()->addSubmodule($url, $path);
210
    }
211
212
    /**
213
     * @param string $classname
214
     *
215
     * @return MockObject
216
     */
217
    protected function getMock(string $classname): MockObject
218
    {
219
        return $this
220
            ->getMockBuilder($classname)
221
            ->disableOriginalConstructor()
222
            ->getMock();
223
    }
224
225
    /**
226
     * mock the caller
227
     *
228
     * @param string $command command
229
     * @param string $output  output
230
     *
231
     * @return MockObject
232
     */
233
    protected function getMockCaller($command, $output): MockObject
234
    {
235
        $mock = $this->createMock(CallerInterface::class);
236
        $mock
237
            ->expects($this->any())
238
            ->method('execute')
239
            ->willReturn($mock);
240
        $mock
241
            ->expects($this->any())
242
            ->method('getOutputLines')
243
            ->willReturn($output);
244
245
        return $mock;
246
    }
247
248
    protected function addCommandToMockContainer(MockObject $container, string $commandName): void
249
    {
250
        $container
251
            ->expects($this->any())
252
            ->method('get')
253
            ->with($this->equalTo($commandName))
254
            ->willReturn($this->getMockCommand());
255
    }
256
257
    /**
258
     *
259
     * @param MockObject $repo
260
     * @param string|array $output
261
     * @return void
262
     */
263
    protected function addOutputToMockRepo(MockObject $repo, $output): void
264
    {
265
        $repo
266
            ->expects($this->any())
267
            ->method('getCaller')
268
            ->willReturn($this->getMockCaller('', $output));
269
    }
270
271
    protected function getMockCommand(): MockObject
272
    {
273
        $command = $this->getMock('Command', ['showCommit']);
274
        $command
275
            ->expects($this->any())
276
            ->method('showCommit')
277
            ->willReturn('');
278
279
        return $command;
280
    }
281
282
    protected function getMockRepository(): MockObject
283
    {
284
        return $this->getMock(
285
            Repository::class,
286
            [],
287
            [
288
                $this->repository->getPath(),
289
                null,
290
            ]
291
        );
292
    }
293
294
    /**
295
     * Do a test on a certain commit
296
     *
297
     * @param Commit $commit the commit to test
298
     * @param string $sha
299
     * @param string $tree
300
     * @param string $author the name of the author
301
     * @param string $committer the name of the committer
302
     * @param string $emailAuthor
303
     * @param string $emailCommitter
304
     * @param integer $datetimeAuthor
305
     * @param integer $datetimeCommitter
306
     * @param string $message
307
     * @return void
308
     */
309
    protected function doCommitTest(
310
        Commit $commit,
311
        string $sha,
312
        string $tree,
313
        string $author,
314
        string $committer,
315
        string $emailAuthor,
316
        string $emailCommitter,
317
        int $datetimeAuthor,
318
        int $datetimeCommitter,
319
        string $message
320
    ): void {
321
        $this->assertInstanceOf(Commit::class, $commit);
322
        $this->assertEquals($sha, $commit->getSha());
323
        $this->assertEquals($tree, $commit->getTree());
324
        $this->assertInstanceOf(Author::class, $commit->getAuthor());
325
        $this->assertEquals($author, $commit->getAuthor()->getName());
326
        $this->assertEquals($emailAuthor, $commit->getAuthor()->getEmail());
327
        $this->assertInstanceOf(Author::class, $commit->getCommitter());
328
        $this->assertEquals($committer, $commit->getCommitter()->getName());
329
        $this->assertEquals($emailCommitter, $commit->getCommitter()->getEmail());
330
        $this->assertInstanceOf(\DateTime::class, $commit->getDatetimeAuthor());
331
        $this->assertEquals($datetimeAuthor, $commit->getDatetimeAuthor()->format('U'));
332
        $this->assertInstanceOf(\DateTime::class, $commit->getDatetimeCommitter());
333
        $this->assertEquals($datetimeCommitter, $commit->getDatetimeCommitter()->format('U'));
334
        $this->assertEquals($message, $commit->getMessage()->getShortMessage());
335
    }
336
337
    /**
338
     * Compatibility function for PHP 7.2:
339
     * PHPUnit 9. only supports PHP >= 7.3,
340
     * but has a different compatibility regarding the assertRegex function
341
     *
342
     * @param string $pattern
343
     * @param string $string
344
     * @param string $message
345
     * @return void
346
     */
347
    protected function myAssertMatchesRegularExpression($pattern, $string, $message = '')
348
    {
349
        if (method_exists($this, 'assertMatchesRegularExpression')) {
350
            $this->assertMatchesRegularExpression($pattern, $string, $message);
351
        } else {
352
            $this->assertRegExp($pattern, $string, $message);
353
        }
354
    }
355
}
356