instance = new AssetManager(); } public function tearDown(): void { $this->instance = null; } /** * @dataProvider loadAssetHandlerProvider */ public function testLoadAssetHandler($itemSource, $expected, $exception = false) { if ($exception) { $this->expectException($exception); } $this->assertInstanceOf(AssetManager::class, $this->instance->loadAssetHandler($itemSource)); if (!$exception) { $reflectionClass = new \ReflectionClass(AssetManager::class); $reflectionProperty = $reflectionClass->getProperty('assetHandlers'); $reflectionProperty->setAccessible(true); $assetHandlers = $reflectionProperty->getValue($this->instance); $this->assertInstanceOf($expected, reset($assetHandlers)); } } public function loadAssetHandlerProvider() { return [ [new SharedStimulusAssetHandler(), SharedStimulusAssetHandler::class], [new \stdClass(), null, AssetManagerException::class], [new LocalAssetHandler(new LocalItemSource(['item' => 'itemFixture', 'lang' => 'langFixture'])), LocalAssetHandler::class], ]; } public function testGetSetSource() { $sourceFixture = 'sourceFixture'; $this->expectException(AssetManagerException::class); $this->instance->getSource(); $this->assertInstanceOf(AssetManager::class, $this->instance->setSource($sourceFixture)); $this->assertEquals($sourceFixture, $this->instance->getSource()); } public function testGetSetItemContent() { $itemContentFixture = 'itemContentFixture'; $this->assertInstanceOf(AssetManager::class, $this->instance->setItemContent($itemContentFixture)); $this->assertEquals($itemContentFixture, $this->instance->getItemContent()); } /** * @dataProvider getAbsolutePathProvider */ public function testGetAbsolutePath($source, $pathFixture, $expected, $exception) { if ($source) { $this->instance->setSource($source); } if ($exception) { $this->expectException($exception); } $reflectionClass = new \ReflectionClass(AssetManager::class); $reflectionMethod = $reflectionClass->getMethod('getAbsolutePath'); $reflectionMethod->setAccessible(true); if ($exception) { $reflectionMethod->invoke($this->instance, $pathFixture); } else { $this->assertEquals($expected, $reflectionMethod->invoke($this->instance, $pathFixture)); } } public function getAbsolutePathProvider() { return [ ['root/', 'polop/polop/polop', 'root/' . 'polop' . DIRECTORY_SEPARATOR . 'polop' . DIRECTORY_SEPARATOR . 'polop', false], ['root/', 'polop', 'root/' . 'polop', false], [false, 'pathFixture', null, AssetManagerException::class], ]; } /** * @dataProvider getRelativePathProvider */ public function testGetRelativePath($path1, $path2, $expected) { $reflectionClass = new \ReflectionClass(AssetManager::class); $reflectionMethod = $reflectionClass->getMethod('getRelativePath'); $reflectionMethod->setAccessible(true); $expected = str_replace(DIRECTORY_SEPARATOR, '/', $expected); $this->assertEquals($expected, $reflectionMethod->invokeArgs($this->instance, [$path1, $path2])); } public function getRelativePathProvider() { $ds = DIRECTORY_SEPARATOR; return [ ["{$ds}path{$ds}to{$ds}absolute{$ds}path", "{$ds}path{$ds}to{$ds}absolute{$ds}path{$ds}in{$ds}package{$ds}polop.txt", 'path' . $ds . 'in' . $ds . 'package' . $ds . 'polop.txt'], ["{$ds}path{$ds}to{$ds}absolute{$ds}path", "{$ds}path{$ds}to{$ds}in{$ds}package{$ds}polop.txt", '..' . $ds . 'in' . $ds . 'package' . $ds . 'polop.txt'], ]; } /** * @dataProvider importAuxiliaryFilesProvider */ public function testImportAuxiliaryFiles($source, $qtiFile, $auxiliaryFilesFixtures, $expectedCalls) { $assetManagerMock = $this->getMockBuilder(AssetManager::class) ->setMethods(['importAsset']) ->getMock(); $qtiResourceMock = $this->getMockBuilder(QtiResource::class) ->disableOriginalConstructor() ->setMethods(['getAuxiliaryFiles', 'getFile']) ->getMock(); if (!$source) { $this->expectException(AssetManagerException::class); } else { $assetManagerMock ->expects($this->exactly(count($auxiliaryFilesFixtures))) ->method('importAsset') ->withConsecutive($expectedCalls); $qtiResourceMock ->expects($this->once()) ->method('getFile') ->willReturn($qtiFile); $qtiResourceMock ->expects($this->once()) ->method('getAuxiliaryFiles') ->willReturn($auxiliaryFilesFixtures); $assetManagerMock->setSource($source); } $this->assertInstanceOf(AssetManager::class, $assetManagerMock->importAuxiliaryFiles($qtiResourceMock)); } public function importAuxiliaryFilesProvider() { return [ [ __DIR__ . '/../samples/auxiliaryFiles/', 'qti/file/fixture.txt', ['qti/file/path1', 'qti/file/path2', 'qti/file/path3'], [__DIR__ . '/../samples/auxiliaryFiles/qti/file/path1', 'path1'], [__DIR__ . '/../samples/auxiliaryFiles/qti/file/path2', 'path2'], [__DIR__ . '/../samples/auxiliaryFiles/qti/file/path3', 'path3'], ], [ null, null, null, null ] ]; } /** * @dataProvider importDependencyFilesProvider */ public function testImportDependencyFiles($source, $qtiFile, $fileFixtures, $expectedCalls, $dependencies, $expectedImportCallCount) { $assetManagerMock = $this->getMockBuilder(AssetManager::class) ->setMethods(['importAsset']) ->getMock(); $qtiResourceMock = $this->getMockBuilder(QtiResource::class) ->disableOriginalConstructor() ->setMethods(['getDependencies', 'getFile']) ->getMock(); if (!$source) { $this->expectException(AssetManagerException::class); } else { $assetManagerMock ->expects($this->exactly($expectedImportCallCount)) ->method('importAsset') ->withConsecutive($expectedCalls); $qtiResourceMock ->expects($this->once()) ->method('getFile') ->willReturn($qtiFile); $qtiResourceMock ->expects($this->once()) ->method('getDependencies') ->willReturn($fileFixtures); $assetManagerMock->setSource($source); } $this->assertInstanceOf(AssetManager::class, $assetManagerMock->importDependencyFiles($qtiResourceMock, $dependencies)); } public function importDependencyFilesProvider() { $mock = $this->getMockBuilder(QtiResource::class) ->disableOriginalConstructor() ->setMethods(['getFile']) ->getMock(); $mock ->expects($this->any()) ->method('getFile') ->willReturn('path4'); return [ [ '/source/fixture/', 'qti/file/fixture.txt', ['path1', 'path2', 'path3'], # [ # [$this->equalTo('/source/fixture/path1'), $this->equalTo('../../path1')] # ], ['/source/fixture/path4', '../../path4'], ['path1' => $mock, 'path3' => $mock], 2 ], [ null, null, null, null, null, 0 ] ]; } /** * @dataProvider importAssetProvider */ public function testImportAsset($assetHandlers, $absPath, $relPath, $exception = null, $uri = null) { $reflectionClass = new \ReflectionClass(AssetManager::class); $reflectionProperty = $reflectionClass->getProperty('assetHandlers'); $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($this->instance, $assetHandlers); $reflectionClass = new \ReflectionClass(AssetManager::class); $reflectionMethod = $reflectionClass->getMethod('importAsset'); $reflectionMethod->setAccessible(true); if ($exception) { $this->expectException($exception); } if ($uri) { $this->instance->setItemContent($relPath . '/polop.txt'); } $reflectionMethod->invokeArgs($this->instance, [$absPath, $relPath]); if ($uri) { $this->assertEquals($uri . '/polop.txt', $this->instance->getItemContent()); } } public function importAssetProvider() { return [ [ [ $this->getAssetHandler('fail', 'failure/path'), $this->getAssetHandler('fail', 'failure/path') ], 'other/path', 'failure/path', AssetManagerException::class ], [ [ $this->getAssetHandler('fail', 'success/path'), $this->getAssetHandler('success', 'success/path', 'other/path') ], 'other/path', 'success/path' ], [ [ $this->getAssetHandler('fail', 'success/path'), $this->getAssetHandler('success', 'success/path', 'other/path', 'polop/way'), $this->getAssetHandler('never') ], 'other/path', 'success/path', null, 'polop/way' ] ]; } protected function getAssetHandler($type = 'success', $relPath = 'pathFixture', $absPath = 'pathFixture', $uri = 'polop') { $mock = $this->getMockBuilder(LocalAssetHandler::class) ->setMethods(['isApplicable', 'handle']) ->getMock(); if ($type == 'success') { $mock->expects($this->once()) ->method('isApplicable') ->with($relPath) ->will($this->returnValue(true)); $mock->expects($this->once()) ->method('handle') ->with($absPath, $relPath) ->will($this->returnValue(['uri' => $uri])); } if ($type == 'fail') { $mock->expects($this->once()) ->method('isApplicable') ->with($relPath) ->will($this->returnValue(false)); $mock->expects($this->never()) ->method('handle'); } if ($type == 'never') { $mock->expects($this->never()) ->method('isApplicable'); $mock->expects($this->never()) ->method('handle'); } return $mock; } }