Completed
Pull Request — develop (#165)
by
unknown
23:30 queued 08:34
created

TestCase::getMockCaller()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
cc 1
nc 1
nop 2
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
     * @param string      $name       file name
126
     * @param string|null $folder     folder name
127
     * @param null        $content    content
128
     * @param Repository  $repository repository to add file to
129
     *
130
     * @return void
131
     */
132
    protected function addFile(
133
        string $name,
134
        string $folder = null,
135
        string $content = null,
136
        Repository $repository = null
137
    ): void {
138
        $path = is_null($repository) ? $this->path : $repository->getPath();
139
        $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...
140
            ? $path . DIRECTORY_SEPARATOR . $name
141
            : $path . DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR . $name;
142
        $handle = fopen($filename, 'w');
143
        $fileContent = $content === null ? 'test content' : $content;
144
        $this->assertTrue(false !== fwrite($handle, $fileContent), sprintf('unable to write the file %s', $name));
145
        fclose($handle);
146
    }
147
148
    /**
149
     * remove file from repo
150
     *
151
     * @param string $name
152
     */
153
    protected function removeFile(string $name): void
154
    {
155
        $filename = $this->path . DIRECTORY_SEPARATOR . $name;
156
        $this->assertTrue(unlink($filename));
157
    }
158
159
    /**
160
     * update a file in the repository
161
     *
162
     * @param string $name    file name
163
     * @param string $content content
164
     */
165
    protected function updateFile(string $name, string $content): void
166
    {
167
        $filename = $this->path . DIRECTORY_SEPARATOR . $name;
168
        $this->assertTrue(false !== file_put_contents($filename, $content));
169
    }
170
171
    /**
172
     * rename a file in the repository
173
     *
174
     * @param string $originName file name
175
     * @param string $targetName new file name
176
     * @param bool   $gitMv      use git mv, otherwise uses php rename function (with the Filesystem component)
177
     */
178
    protected function renameFile(string $originName, string $targetName, bool $gitMv = true): void
179
    {
180
        if ($gitMv) {
181
            $this->getRepository()
182
                ->getCaller()
183
                ->execute(MvCommand::getInstance()->rename($originName, $targetName));
184
185
            return;
186
        }
187
        $origin = $this->path . DIRECTORY_SEPARATOR . $originName;
188
        $target = $this->path . DIRECTORY_SEPARATOR . $targetName;
189
        $fs = new Filesystem();
190
        $fs->rename($origin, $target);
191
    }
192
193
    /**
194
     * @param string $name name
195
     *
196
     * @return void
197
     */
198
    protected function addFolder($name): void
199
    {
200
        $fs = new Filesystem();
201
        $fs->mkdir($this->path . DIRECTORY_SEPARATOR . $name);
202
    }
203
204
    protected function addSubmodule($url, $path): void
205
    {
206
        $this->getRepository()->addSubmodule($url, $path);
207
    }
208
209
    /**
210
     * @param $classname
211
     *
212
     * @return MockObject
213
     */
214
    protected function getMock($classname): MockObject
215
    {
216
        return $this
217
            ->getMockBuilder($classname)
218
            ->disableOriginalConstructor()
219
            ->getMock();
220
    }
221
222
    /**
223
     * mock the caller
224
     *
225
     * @param string $command command
226
     * @param string $output  output
227
     *
228
     * @return MockObject
229
     */
230
    protected function getMockCaller($command, $output): MockObject
231
    {
232
        $mock = $this->createMock(CallerInterface::class);
233
        $mock
234
            ->expects($this->any())
235
            ->method('execute')
236
            ->willReturn($mock);
237
        $mock
238
            ->expects($this->any())
239
            ->method('getOutputLines')
240
            ->willReturn($output);
241
242
        return $mock;
243
    }
244
245
    protected function addCommandToMockContainer(MockObject $container, string $commandName): void
246
    {
247
        $container
248
            ->expects($this->any())
249
            ->method('get')
250
            ->with($this->equalTo($commandName))
251
            ->willReturn($this->getMockCommand());
252
    }
253
254
    protected function addOutputToMockRepo(MockObject $repo, array $output): void
255
    {
256
        $repo
257
            ->expects($this->any())
258
            ->method('getCaller')
259
            ->willReturn($this->getMockCaller('', $output));
260
    }
261
262
    protected function getMockCommand(): MockObject
263
    {
264
        $command = $this->getMock('Command', ['showCommit']);
265
        $command
266
            ->expects($this->any())
267
            ->method('showCommit')
268
            ->willReturn('');
269
270
        return $command;
271
    }
272
273
    protected function getMockRepository(): MockObject
274
    {
275
        return $this->getMock(
276
            Repository::class,
277
            [],
278
            [
279
                $this->repository->getPath(),
280
                null,
281
            ]
282
        );
283
    }
284
285
    protected function doCommitTest(
286
        Commit $commit,
287
        $sha,
288
        $tree,
289
        $author,
290
        $committer,
291
        $emailAuthor,
292
        $emailCommitter,
293
        $datetimeAuthor,
294
        $datetimeCommitter,
295
        $message
296
    ): void {
297
        $this->assertInstanceOf(Commit::class, $commit);
298
        $this->assertEquals($sha, $commit->getSha());
299
        $this->assertEquals($tree, $commit->getTree());
300
        $this->assertInstanceOf(Author::class, $commit->getAuthor());
301
        $this->assertEquals($author, $commit->getAuthor()->getName());
302
        $this->assertEquals($emailAuthor, $commit->getAuthor()->getEmail());
303
        $this->assertInstanceOf(Author::class, $commit->getCommitter());
304
        $this->assertEquals($committer, $commit->getCommitter()->getName());
305
        $this->assertEquals($emailCommitter, $commit->getCommitter()->getEmail());
306
        $this->assertInstanceOf(\DateTime::class, $commit->getDatetimeAuthor());
307
        $this->assertEquals($datetimeAuthor, $commit->getDatetimeAuthor()->format('U'));
308
        $this->assertInstanceOf(\DateTime::class, $commit->getDatetimeCommitter());
309
        $this->assertEquals($datetimeCommitter, $commit->getDatetimeCommitter()->format('U'));
310
        $this->assertEquals($message, $commit->getMessage()->getShortMessage());
311
    }
312
}
313