Passed
Push — main ( f3cfb1...17781b )
by Emil
04:34
created

UploadManagerTest::testDeleteUploadedFile()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
eloc 10
nc 2
nop 0
dl 0
loc 19
rs 9.9332
c 1
b 1
f 0
1
<?php
2
3
namespace App\Tests;
4
5
use App\UploadManager;
6
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
7
use Symfony\Component\HttpFoundation\File\UploadedFile;
8
9
class UploadManagerTest extends WebTestCase
10
{
11
    private UploadManager $uploadManager;
12
    private string $testDir;
13
14
    /**
15
     * setUp
16
     *
17
     * Add client startup to setup
18
     *
19
     * @return void
20
     */
21
    protected function setUp(): void
22
    {
23
        parent::setUp(); // Call parent setup
24
25
        // Setup a temporary directory for testing
26
        $this->testDir = __DIR__ . '/_temp/upload_manager_test';
27
28
        $this->testDir = rtrim($this->testDir, '/');
29
30
        if (!is_dir($this->testDir)) {
31
            mkdir($this->testDir, 0777, true);
32
        }
33
34
        // Instantiate UploadManager with test directory
35
        $this->uploadManager = new UploadManager($this->testDir);
36
    }
37
38
    /**
39
     * tearDown
40
     *
41
     * @return void
42
     */
43
    protected function tearDown(): void
44
    {
45
        $this->deleteDirectory($this->testDir);
46
47
        parent::tearDown();
48
    }
49
50
    /**
51
     * deleteDirectory
52
     *
53
     * Recursively delete a directory and its contents
54
     *
55
     * @param  string $dir
56
     * @return void
57
     */
58
    private function deleteDirectory(string $dir): void
59
    {
60
        if (!is_dir($dir)) {
61
            return;
62
        }
63
64
        $files = array_diff(scandir($dir), ['.', '..']);
65
66
        foreach ($files as $file) {
67
            $filePath = $dir . DIRECTORY_SEPARATOR . $file;
68
            (is_dir($filePath)) ? $this->deleteDirectory($filePath) : unlink($filePath);
69
        }
70
71
        rmdir($dir);
72
    }
73
74
    /**
75
     * testCreateObject
76
     *
77
     * Construct object and verify that the object has the expected
78
     * properties, use no arguments.
79
     *
80
     * @return void
81
     */
82
    public function testCreateObject(): void
83
    {
84
        $uploadManager = new UploadManager($this->testDir);
85
        $this->assertInstanceOf(UploadManager::class, $uploadManager);
86
    }
87
88
    /**
89
     * testConstructorException
90
     *
91
     * @return void
92
     */
93
    public function testConstructorException(): void
94
    {
95
        // If the dir don't exist
96
        if (!is_dir($this->testDir . "/public/notwritable")) {
97
            mkdir($this->testDir . "/public/notwritable", 0777, true);
98
        }
99
100
        // Change permissions to make it non-writable
101
        chmod($this->testDir . "/public/notwritable", 0555); // read and execute only
102
103
        // Expect RuntimeException
104
        $this->expectException(\RuntimeException::class);
105
        $this->expectExceptionMessage('directory is not writable.');
106
107
        // Instantiate UploadManager, should throw exception
108
        new UploadManager($this->testDir, '/notwritable');
109
110
        // Reset permissions for cleanup
111
        chmod($this->testDir . "/public/notwritable", 0777);
112
    }
113
114
    /**
115
     * testSaveUploadedFile
116
     *
117
     * @return void
118
     */
119
    public function testSaveUploadedFile(): void
120
    {
121
        // Create a mock UploadedFile
122
        $file = $this->createMock(UploadedFile::class);
123
        $file->method('isValid')->willReturn(true);
124
        $file->method('getMimeType')->willReturn('image/jpeg');
125
        $file->method('getClientOriginalName')->willReturn('test_image.jpg');
126
        $file->method('guessExtension')->willReturn('jpg');
127
128
        $targetDir = 'public/uploads'; // no leading slash
129
        $uploadDir = $this->testDir . '/' . $targetDir; // should be safe
130
131
        // Escape directory string for regex
132
        $escapedDir = '/' . preg_quote($uploadDir, '/') . '/';
133
134
        // Mock move method
135
        $file->expects($this->once())
136
            ->method('move')
137
            ->with(
138
                $this->matchesRegularExpression($escapedDir),
139
                $this->callback(function ($filename) {
140
                    return preg_match('/^test_image-.*\.jpg$/', $filename) === 1;
141
                })
142
            );
143
144
        $fileTypesSupported = ['image/jpeg', 'image/png'];
145
146
        $result = $this->uploadManager->saveUploadedFile($file, $fileTypesSupported);
147
148
        $this->assertIsString($result);
149
        $this->assertStringContainsString('/uploads/', $result);
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type null; however, parameter $haystack of PHPUnit\Framework\Assert...tStringContainsString() does only seem to accept string, 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

149
        $this->assertStringContainsString('/uploads/', /** @scrutinizer ignore-type */ $result);
Loading history...
150
    }
151
152
    /**
153
     * testSaveUploadedFileInvalidFileType
154
     *
155
     * @return void
156
     */
157
    public function testSaveUploadedFileInvalidFileType(): void
158
    {
159
        // Create a mock UploadedFile
160
        $file = $this->createMock(UploadedFile::class);
161
        $file->method('isValid')->willReturn(true);
162
        $file->method('getMimeType')->willReturn('image/jpeg');
163
        $file->method('getClientOriginalName')->willReturn('test.jpg');
164
        $file->method('guessExtension')->willReturn('jpg');
165
166
        $fileTypesSupported = ['image/png'];
167
168
        // Expect a RuntimeException for invalid file type
169
        $this->expectException(\RuntimeException::class);
170
        $this->expectExceptionMessage('Invalid file type. Filetype of image/jpeg is not allowed.');
171
172
        // Call the method - should throw exception
173
        $this->uploadManager->saveUploadedFile($file, $fileTypesSupported);
174
    }
175
176
    /**
177
     * testSaveUploadedFileMoveException
178
     *
179
     * @return void
180
     */
181
    public function testSaveUploadedFileMoveException(): void
182
    {
183
        // Create a mock UploadedFile
184
        $file = $this->createMock(UploadedFile::class);
185
        $file->method('isValid')->willReturn(true);
186
        $file->method('getMimeType')->willReturn('image/jpeg');
187
        $file->method('getClientOriginalName')->willReturn('test.jpg');
188
        $file->method('guessExtension')->willReturn('jpg');
189
190
        // Simulate exception during move
191
        $file->expects($this->once())
192
             ->method('move')
193
             ->will($this->throwException(new \Exception('Move failed')));
194
195
        $fileTypesSupported = ['image/jpeg'];
196
197
        // Expect a RuntimeException with specific message
198
        $this->expectException(\RuntimeException::class);
199
        $this->expectExceptionMessage('Error uploading file: Move failed');
200
201
        $this->uploadManager->saveUploadedFile($file, $fileTypesSupported);
202
    }
203
204
    /**
205
     * testDeleteUploadedFile
206
     *
207
     * @return void
208
     */
209
    public function testDeleteUploadedFile(): void
210
    {
211
        // Create a dummy file
212
        $filePath = '/uploads/testfile.txt';
213
        $fullPath = $this->testDir . '/public' . $filePath;
214
        if (!is_dir(dirname($fullPath))) {
215
            mkdir(dirname($fullPath), 0777, true);
216
        }
217
        file_put_contents($fullPath, 'test');
218
219
        $result = $this->uploadManager->deleteUploadedFile($filePath);
220
221
        $this->assertTrue($result);
222
        $this->assertFalse(file_exists($fullPath));
223
224
        // Test if the file don't exists
225
        $result = $this->uploadManager->deleteUploadedFile($filePath);
226
227
        $this->assertFalse($result);
228
    }
229
}
230