Completed
Pull Request — develop (#168)
by
unknown
01:45
created

TestCase::addFile()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
cc 4
nc 8
nop 4
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
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 $name
55
     *
56
     * @return \GitElephant\Repository
57
     */
58
    protected function getRepository(string $name = null)
59
    {
60
        if ($this->repository == null) {
61
            $this->initRepository($name);
62
        }
63
        if (is_null($name)) {
64
            return $this->repository;
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 = [];
0 ignored issues
show
Documentation Bug introduced by
It seems like array() of type array is incompatible with the declared type object<GitElephant\Repository> of property $repository.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
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 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($url, $path): void
208
    {
209
        $this->getRepository()->addSubmodule($url, $path);
210
    }
211
212
    /**
213
     * @param $classname
214
     *
215
     * @return MockObject
216
     */
217
    protected function getMock($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
    protected function addOutputToMockRepo(MockObject $repo, array $output): void
258
    {
259
        $repo
260
            ->expects($this->any())
261
            ->method('getCaller')
262
            ->willReturn($this->getMockCaller('', $output));
263
    }
264
265
    protected function getMockCommand(): MockObject
266
    {
267
        $command = $this->getMock('Command', ['showCommit']);
268
        $command
269
            ->expects($this->any())
270
            ->method('showCommit')
271
            ->willReturn('');
272
273
        return $command;
274
    }
275
276
    protected function getMockRepository(): MockObject
277
    {
278
        return $this->getMock(
279
            Repository::class,
280
            [],
281
            [
282
                $this->repository->getPath(),
283
                null,
284
            ]
285
        );
286
    }
287
288
    protected function doCommitTest(
289
        Commit $commit,
290
        $sha,
291
        $tree,
292
        $author,
293
        $committer,
294
        $emailAuthor,
295
        $emailCommitter,
296
        $datetimeAuthor,
297
        $datetimeCommitter,
298
        $message
299
    ): void {
300
        $this->assertInstanceOf(Commit::class, $commit);
301
        $this->assertEquals($sha, $commit->getSha());
302
        $this->assertEquals($tree, $commit->getTree());
303
        $this->assertInstanceOf(Author::class, $commit->getAuthor());
304
        $this->assertEquals($author, $commit->getAuthor()->getName());
305
        $this->assertEquals($emailAuthor, $commit->getAuthor()->getEmail());
306
        $this->assertInstanceOf(Author::class, $commit->getCommitter());
307
        $this->assertEquals($committer, $commit->getCommitter()->getName());
308
        $this->assertEquals($emailCommitter, $commit->getCommitter()->getEmail());
309
        $this->assertInstanceOf(\DateTime::class, $commit->getDatetimeAuthor());
310
        $this->assertEquals($datetimeAuthor, $commit->getDatetimeAuthor()->format('U'));
311
        $this->assertInstanceOf(\DateTime::class, $commit->getDatetimeCommitter());
312
        $this->assertEquals($datetimeCommitter, $commit->getDatetimeCommitter()->format('U'));
313
        $this->assertEquals($message, $commit->getMessage()->getShortMessage());
314
    }
315
316
    /**
317
     * Compatibility function for PHP 7.2:
318
     * PHPUnit 9. only supports PHP >= 7.3,
319
     * but has a different compatibility regarding the assertRegex function
320
     *
321
     * @param string $pattern
322
     * @param string $string
323
     * @param string $message
324
     * @return void
325
     */
326
    protected function myAssertMatchesRegularExpression($pattern, $string, $message = '')
327
    {
328
        if (method_exists($this, 'assertMatchesRegularExpression')) {
329
            $this->assertMatchesRegularExpression($pattern, $string, $message);
330
        } else {
331
            $this->assertRegExp($pattern, $string, $message);
332
        }
333
    }
334
}
335