diff --git a/tests/Service/AwsServiceTest.php b/tests/Service/AwsServiceTest.php new file mode 100644 index 0000000..f0a6075 --- /dev/null +++ b/tests/Service/AwsServiceTest.php @@ -0,0 +1,235 @@ +mockHandler = new MockHandler(); + + // 2. Create a History container to capture the requests sent + $this->history = new History(); + + // 3. Instantiate S3Client passing the MockHandler DIRECTLY to 'handler' + $s3Client = new S3Client([ + 'region' => 'eu-west-3', + 'version' => 'latest', + 'handler' => $this->mockHandler, + 'credentials' => [ + 'key' => 'test', + 'secret' => 'test', + ], + ]); + + // 4. Attach the History middleware + $s3Client->getHandlerList()->appendSign(Middleware::history($this->history)); + + $this->service = new AwsService( + $s3Client, + 'https://s3.eu-west-3.amazonaws.com' + ); + } + + public function testGenerateUUIDv4(): void + { + $uuid = $this->service->generateUUIDv4(); + // Matches the static string we defined at the top of this file + $this->assertEquals('78832168-3015-4673-952c-745143093202', $uuid); + } + + public function testGetPublicUrl(): void + { + $result = $this->service->getPublicUrl('my-bucket'); + $this->assertEquals('https://my-bucket.s3.eu-west-3.amazonaws.com/', $result); + } + + // ========================================== + // TEST: createBucket + // ========================================== + + public function testCreateBucketSuccess(): void + { + // Queue a success response (200 OK) + $this->mockHandler->append(new Result(['@metadata' => ['statusCode' => 200]])); + + $result = $this->service->createBucket(); + + // Since we mocked uuid_create, we know EXACTLY what the bucket name will be + $expectedBucketName = '78832168-3015-4673-952c-745143093202'; + $this->assertEquals($expectedBucketName, $result); + + $this->assertCount(1, $this->history); + /** @var CommandInterface $cmd */ + $cmd = $this->history->getLastCommand(); + + $this->assertEquals('CreateBucket', $cmd->getName()); + $this->assertEquals('BucketOwnerPreferred', $cmd['ObjectOwnership']); + $this->assertEquals($expectedBucketName, $cmd['Bucket']); + } + + public function testCreateBucketFailure(): void + { + $this->mockHandler->append(new Result(['@metadata' => ['statusCode' => 403]])); + + $result = $this->service->createBucket(); + + $this->assertIsArray($result); + $this->assertEquals(403, $result['statusCode']); + } + + // ========================================== + // TEST: DeleteBucket + // ========================================== + + public function testDeleteBucket(): void + { + $this->mockHandler->append(new Result(['@metadata' => ['statusCode' => 200]])); + + $result = $this->service->DeleteBucket('test-bucket'); + + $this->assertEquals('test-bucket', $result); + + $cmd = $this->history->getLastCommand(); + $this->assertEquals('DeleteBucket', $cmd->getName()); + $this->assertEquals('test-bucket', $cmd['Bucket']); + } + + // ========================================== + // TEST: getListObject + // ========================================== + + public function testGetListObjectReturnsContents(): void + { + $this->mockHandler->append(new Result([ + 'Contents' => [ + ['Key' => 'file1.txt'], + ['Key' => 'file2.jpg'], + ] + ])); + + $result = $this->service->getListObject('my-bucket', 'prefix'); + + $this->assertCount(2, $result); + $this->assertEquals('file1.txt', $result[0]['Key']); + + $cmd = $this->history->getLastCommand(); + $this->assertEquals('ListObjectsV2', $cmd->getName()); + $this->assertEquals('my-bucket', $cmd['Bucket']); + $this->assertEquals('prefix', $cmd['Prefix']); + } + + // ========================================== + // TEST: PutDocObj + // ========================================== + + public function testPutDocObj(): void + { + $tempFile = tempnam(sys_get_temp_dir(), 'test_s3'); + file_put_contents($tempFile, 'dummy content'); + + $this->mockHandler->append(new Result(['@metadata' => ['statusCode' => 200]])); + + // Helper object to bypass strictly typed generic object hint + fopen + $fileObj = new class($tempFile) { + public function __construct(private $path) {} + public function __toString() { return $this->path; } + }; + + $status = $this->service->PutDocObj( + 'my-bucket', + $fileObj, + 'image.png', + 'image/png', + 'folder/' + ); + + $this->assertEquals(200, $status); + + $cmd = $this->history->getLastCommand(); + $this->assertEquals('PutObject', $cmd->getName()); + $this->assertEquals('folder/image.png', $cmd['Key']); + $this->assertNotEmpty($cmd['ChecksumSHA256']); + + @unlink($tempFile); + } + + // ========================================== + // TEST: renameDocObj + // ========================================== + + public function testRenameDocObj(): void + { + $this->mockHandler->append( + new Result(['@metadata' => ['statusCode' => 200]]), + new Result(['@metadata' => ['statusCode' => 204]]) + ); + + $status = $this->service->renameDocObj('b', 'old.txt', 'new.txt', 'p/'); + + $this->assertEquals(200, $status); + + $this->assertCount(2, $this->history); + $requests = iterator_to_array($this->history); + + /** @var CommandInterface $cmdCopy */ + $cmdCopy = $requests[0]['command']; + $this->assertEquals('CopyObject', $cmdCopy->getName()); + $this->assertEquals('p/new.txt', $cmdCopy['Key']); + + /** @var CommandInterface $cmdDelete */ + $cmdDelete = $requests[1]['command']; + $this->assertEquals('DeleteObject', $cmdDelete->getName()); + $this->assertEquals('p/old.txt', $cmdDelete['Key']); + } + + // ========================================== + // TEST: moveDocObj + // ========================================== + + public function testMoveDocObj(): void + { + $this->mockHandler->append( + new Result(['@metadata' => ['statusCode' => 200]]), + new Result(['@metadata' => ['statusCode' => 204]]) + ); + + $status = $this->service->moveDocObj('b', 'file.txt', 'old/', 'new/'); + + $this->assertEquals(200, $status); + + $requests = iterator_to_array($this->history); + + $cmdCopy = $requests[0]['command']; + $this->assertEquals('new/file.txt', $cmdCopy['Key']); + } +} \ No newline at end of file