* @package taoItems */ class QtiItemPackerTest extends TaoPhpUnitTestRunner { public function setUp(): void { \common_ext_ExtensionsManager::singleton()->getExtensionById('taoQtiItem'); } /** * Test creating a QtiItemPacker */ public function testConstructor() { $itemPacker = new QtiItemPacker(); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPacker', $itemPacker); } /** * Test the exception when a wrong content is given to the parser */ public function testWrongContentToPack() { $this->expectException(common_Exception::class); $itemPacker = new QtiItemPacker(); $itemPacker->packItem(new core_kernel_classes_Resource('foo'), 'en-US', $this->getDirectoryStorage()); } /** * Test packing an item where QTI content isn't valid */ public function testPackingInvalidQtiItem() { $this->expectException(common_Exception::class); $samplePath = dirname(__FILE__) . '/../samples/wrong/'; $sample = 'notvalid_associate.xml'; $this->assertTrue(file_exists($samplePath . $sample)); $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($samplePath . $sample))); $itemPackerMock->packItem(new core_kernel_classes_Resource('foo'), 'en-US', $this->getDirectoryStorage()); } public function testPackingWithoutValidation(): void { $content = file_get_contents(dirname(__FILE__) . '/../samples/xml/qtiv2p1/inline_choice.xml'); $qtiParser = $this ->getMockBuilder(QtiParser::class) ->enableOriginalConstructor() ->setConstructorArgs([$content]) ->onlyMethods(['validate']) ->getMock(); $qtiParser ->expects($this->never()) ->method('validate'); $itemPacker = new QtiItemPackerTestable(); $itemPacker->setSkipValidation(true); $itemPacker->setQtiParser($qtiParser); $itemPacker->packItem(new core_kernel_classes_Resource('foo'), 'en-US', $this->getDirectoryStorage()); } /** * Test packing a simple item that has no assets. */ public function testPackingSimpleItem() { $samplePath = dirname(__FILE__) . '/../samples/xml/qtiv2p1/'; $sample = 'inline_choice.xml'; $this->assertTrue(file_exists($samplePath . $sample)); $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($samplePath . $sample))); $directoryStorage = $this->getMockBuilder(\tao_models_classes_service_StorageDirectory::class) ->disableOriginalConstructor() ->getMock(); $directoryStorage->method('getServiceLocator')->willReturn(ServiceManager::getServiceManager()); $itemPack = $itemPackerMock->packItem(new core_kernel_classes_Resource('foo'), 'en-US', $directoryStorage); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $data = $itemPack->getData(); $this->assertEquals('assessmentItem', $data['qtiClass']); $this->assertEquals('inlineChoice', $data['identifier']); $this->assertEquals([], $itemPack->getAssets('js')); $this->assertEquals([], $itemPack->getAssets('css')); $this->assertEquals([], $itemPack->getAssets('img')); $this->assertEquals([], $itemPack->getAssets('font')); } /** * Assert that response processing is part of the pack */ public function testPackingItemResponseProcessing() { $samplePath = dirname(__FILE__) . '/../samples/xml/qtiv2p1/'; $sample = 'inline_choice.xml'; $this->assertTrue(file_exists($samplePath . $sample)); $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($samplePath . $sample))); $itemPack = $itemPackerMock->packItem( new core_kernel_classes_Resource('foo'), 'en-US', $this->getDirectoryStorage() ); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $data = $itemPack->getData(); $this->assertEquals('assessmentItem', $data['qtiClass']); $this->assertTrue(is_array($data['responseProcessing']['responseRules'])); $this->assertTrue(count($data['responseProcessing']['responseRules']) > 0); } /** * Test packing an item that contain images. */ public function testPackingItemWithImages() { $samplePath = dirname(__FILE__) . '/../samples/xml/qtiv2p1/'; $sample = 'sample-astronomy.xml'; $this->assertTrue(file_exists($samplePath . $sample)); $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($samplePath . $sample))); $itemPack = $itemPackerMock->packItem( new core_kernel_classes_Resource('foo'), 'en-US', $this->getDirectoryStorage() ); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $data = $itemPack->getData(); $this->assertEquals('assessmentItem', $data['qtiClass']); $this->assertEquals('astronomy', $data['identifier']); $this->assertEquals(6, count($itemPack->getAssets('img'))); $this->assertTrue(in_array('earth.png', $itemPack->getAssets('img'))); $this->assertEquals([], $itemPack->getAssets('js')); $this->assertEquals([], $itemPack->getAssets('css')); $this->assertEquals([], $itemPack->getAssets('font')); } /** * Test packing an item that contain a graphic interaction. */ public function testPackingGraphicItem() { $samplePath = dirname(__FILE__) . '/../samples/xml/qtiv2p1/'; $sample = 'hotspot.xml'; $this->assertTrue(file_exists($samplePath . $sample)); $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($samplePath . $sample))); $itemPack = $itemPackerMock->packItem( new core_kernel_classes_Resource('foo'), 'en-US', $this->getDirectoryStorage() ); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $data = $itemPack->getData(); $this->assertEquals('assessmentItem', $data['qtiClass']); $this->assertEquals('hotspot', $data['identifier']); $this->assertEquals(1, count($itemPack->getAssets('img'))); } /** * Test packing an item that contain an object element in a container. */ public function testPackingItemObjectInBody() { $samplePath = dirname(__FILE__) . '/../samples/xml/qtiv2p1/'; $sample = 'svg.xml'; $this->assertTrue(file_exists($samplePath . $sample)); $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($samplePath . $sample))); $itemPack = $itemPackerMock->packItem( new core_kernel_classes_Resource('foo'), 'en-US', $this->getDirectoryStorage() ); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $data = $itemPack->getData(); $this->assertEquals('assessmentItem', $data['qtiClass']); $this->assertEquals('SVG', $data['identifier']); $this->assertEquals(1, count($itemPack->getAssets('img'))); } /** * Test packing an item that contains audio and video */ public function testPackingMultiMediaItem() { $samplePath = dirname(__FILE__) . '/../samples/xml/qtiv2p1/'; $sample = 'audio-video.xml'; $this->assertTrue(file_exists($samplePath . $sample)); $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($samplePath . $sample))); $itemPack = $itemPackerMock->packItem( new core_kernel_classes_Resource('foo'), 'en-US', $this->getDirectoryStorage() ); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $data = $itemPack->getData(); $this->assertEquals('assessmentItem', $data['qtiClass']); $this->assertEquals('mediaInteraction', $data['identifier']); $this->assertEquals(1, count($itemPack->getAssets('audio'))); $this->assertEquals(1, count($itemPack->getAssets('video'))); } /** * Test packing an item that contain a stylesheet. */ public function testPackingItemWithCss() { $sample = dirname(__FILE__) . '/../samples/xml/qtiv2p1/sample-elections.xml'; $path = dirname(__FILE__) . '/../samples/css'; $this->assertTrue(file_exists($sample)); $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem', 'getPath']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($sample))); $publicDirectory = $this->getDirectoryStorage(); $itemPack = $itemPackerMock->packItem(new core_kernel_classes_Resource('foo'), 'en-US', $publicDirectory); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $data = $itemPack->getData(); $this->assertEquals('assessmentItem', $data['qtiClass']); $this->assertEquals('elections-in-the-united-states-2004', $data['identifier']); $this->assertCount(1, $itemPack->getAssets('img')); $this->assertCount(1, $itemPack->getAssets('css')); $this->assertCount(0, $itemPack->getAssets('font')); } public function testPackingItemWithCssBase64() { $this->expectException(common_Exception::class); $sample = __DIR__ . '/../samples/xml/qtiv2p1/sample-elections.xml'; $path = __DIR__ . '/../samples/css'; $this->assertTrue(file_exists($sample)); /** * @var QtiItemPacker $itemPackerMock */ $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($sample))); $itemPackerMock->setAssetEncoders(['js' => 'base64file', 'css' => 'base64file', 'font' => 'base64file', 'img' => 'none', 'audio' => 'none', 'video' => 'none']); $itemPackerMock->setNestedResourcesInclusion(false); $this->assertTrue(file_exists($path . '/style.css')); $itemPack = $itemPackerMock->packItem( new core_kernel_classes_Resource('foo'), '', $this->getDirectoryStorage() ); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $data = $itemPack->getData(); $this->assertEquals('assessmentItem', $data['qtiClass']); $this->assertEquals('elections-in-the-united-states-2004', $data['identifier']); $this->assertCount(1, $itemPack->getAssets('img')); $this->assertCount(1, $itemPack->getAssets('css')); $this->assertCount(0, $itemPack->getAssets('font')); $css = $itemPack->getAssets('css'); $this->assertStringStartsWith('data:text/css;', current($css), 'Have appropriate prefix'); $this->assertRegExp('/icon-checkbox/', base64_decode(str_replace('data:text/css;base64,', '', current($css))), 'Correctly decoded back'); $itemPackerMock->setNestedResourcesInclusion(true); $itemPack = $itemPackerMock->packItem(new core_kernel_classes_Resource('foo'), '', $publicDirectory); } public function testPackingItemWithVideoBase64() { $sample = __DIR__ . '/../samples/xml/packer/qti.xml'; $path = __DIR__ . '/../samples/xml/packer'; /** @var Directory $publicDirectory */ $publicDirectory = $this->getDirectoryStorage(); foreach (glob($path . "/*.*") as $file) { $fileinfo = pathinfo($file); $publicDirectory->getFile($fileinfo['basename'])->write(file_get_contents($file)); } $this->assertTrue(file_exists($sample)); /** * @var QtiItemPacker $itemPackerMock */ $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($sample))); $itemPackerMock->setAssetEncoders(['js' => 'none', 'css' => 'none', 'font' => 'none', 'img' => 'base64file', 'audio' => 'base64file', 'video' => 'base64file']); $this->assertTrue(file_exists($path . '/sample.mp4')); $this->assertTrue(file_exists($path . '/style-custom-tao-user-styles.css')); $this->assertTrue(file_exists($path . '/egyptian-symbol-ouroboros-300x300.png')); $publicDirectory = $this->getDirectoryStorage(); $itemPack = $itemPackerMock->packItem(new core_kernel_classes_Resource('foo'), '', $publicDirectory); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $this->assertEquals(1, count($itemPack->getAssets('img'))); $this->assertEquals(2, count($itemPack->getAssets('video'))); $video = $itemPack->getAssets('video'); $this->assertStringStartsWith('data:video/mp4;', $video['sample.mp4'], 'Encoded as it is local resource'); $this->assertStringStartsWith('https://', $video['https://www.youtube.com/watch?v=J1c2KzJbcGA'], 'Is external resource'); } /** * Test packing a PCI item */ public function testPackingPciItem() { $samplePath = dirname(__FILE__) . '/../samples/xml/qtiv2p1/'; $sample = 'likert.xml'; $this->assertTrue(file_exists($samplePath . $sample)); $itemPackerMock = $this ->getMockBuilder('oat\taoQtiItem\model\pack\QtiItemPacker') ->setMethods(['getXmlByItem']) ->getMock(); $itemPackerMock ->method('getXmlByItem') ->will($this->returnValue(file_get_contents($samplePath . $sample))); $itemPack = $itemPackerMock->packItem( new core_kernel_classes_Resource('foo'), 'en-US', $this->getDirectoryStorage() ); $this->assertInstanceOf('oat\taoItems\model\pack\ItemPack', $itemPack); $this->assertEquals('qti', $itemPack->getType()); $data = $itemPack->getData(); $this->assertEquals('assessmentItem', $data['qtiClass']); $this->assertEquals('pci002', $data['identifier']); $this->assertEquals(3, count($itemPack->getAssets('img'))); $this->assertEquals(2, count($itemPack->getAssets('css'))); } /** * @return MockObject|Directory */ protected function getDirectoryStorage() { return $this->getTempDirectory(); } } class QtiItemPackerTestable extends QtiItemPacker { protected function getXmlByItem(core_kernel_classes_Resource $item, $lang = '') { return dirname(__FILE__) . '/../samples/xml/qtiv2p1/inline_choice.xml'; } }