tao-test/app/taoQtiTest/test/unit/models/classes/QtiTestServiceTest.php

356 lines
11 KiB
PHP

<?php
namespace oat\taoQtiTest\test\unit\models\classes;
use common_exception_InconsistentData;
use core_kernel_classes_Property as KernelProperty;
use core_kernel_classes_Resource as KernelResource;
use DOMDocument;
use oat\generis\model\data\Ontology;
use oat\generis\model\fileReference\FileReferenceSerializer;
use oat\generis\test\MockObject;
use oat\generis\test\TestCase;
use oat\oatbox\filesystem\Directory;
use oat\oatbox\filesystem\File;
use oat\tao\model\service\ApplicationService;
use oat\taoQtiTest\models\test\AssessmentTestXmlFactory;
use oat\taoQtiTest\models\test\Template\DefaultConfigurationRegistry;
use qtism\common\utils\Format;
use taoQtiTest_models_classes_QtiTestService as QtiTestService;
use Zend\ServiceManager\ServiceLocatorInterface;
class QtiTestServiceTest extends TestCase
{
private const TEST_TEMPLATE = <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<assessmentTest xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" identifier="{testId}" title="{testTitle}" toolName="tao" toolVersion="{taoVersion}" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 http://www.imsglobal.org/xsd/qti/qtiv2p1/imsqti_v2p1.xsd">
<testPart identifier="testPart-1" navigationMode="linear" submissionMode="individual">
<itemSessionControl maxAttempts="0" showFeedback="false" allowReview="true" showSolution="false" allowComment="false" allowSkipping="true" validateResponses="false"/>
<assessmentSection identifier="assessmentSection-1" required="true" fixed="false" title="Section 1" visible="true" keepTogether="true"/>
</testPart>
</assessmentTest>
XML;
private const PLATFORM_VERSION = 'v1-test';
/** @var Directory|MockObject */
private $defaultDirectoryMock;
/** @var FileReferenceSerializer|MockObject */
private $fileReferenceSerializerMock;
/** @var KernelProperty|MockObject */
private $testContentPropertyMock;
/** @var AssessmentTestXmlFactory */
private $xmlFactory;
/** @var DefaultConfigurationRegistry */
private $xmlTemplateOptionsRegistry;
/** @var QtiTestService */
private $sut;
/**
* @before
*/
public function init(): void
{
$this->defaultDirectoryMock = $this->createMock(Directory::class);
$this->fileReferenceSerializerMock = $this->createMock(FileReferenceSerializer::class);
$this->testContentPropertyMock = $this->createMock(KernelProperty::class);
$this->xmlTemplateOptionsRegistry = $this->createPartialMock(DefaultConfigurationRegistry::class, ['getMap']);
$this->xmlFactory = new AssessmentTestXmlFactory(
[
AssessmentTestXmlFactory::OPTION_CONFIGURATION_REGISTRY => $this->xmlTemplateOptionsRegistry
]
);
$this->xmlTemplateOptionsRegistry
->method('getMap')
->willReturn(
[
DefaultConfigurationRegistry::ID => [
'partIdPrefix' => 'testPart',
'sectionIdPrefix' => 'assessmentSection',
'sectionTitlePrefix' => 'Section',
'categories' => [],
'navigationMode' => 0,
'submissionMode' => 0,
'maxAttempts' => 0,
],
]
);
$serviceLocator = $this->creteServiceLocatorMock();
$this->xmlFactory->setServiceLocator($serviceLocator);
$this->xmlTemplateOptionsRegistry->setServiceLocator($serviceLocator);
$this->sut = $this->createPartialMock(
QtiTestService::class,
['getDefaultDir', 'getQtiTestTemplateFileAsString', 'getServiceManager']
);
$this->sut
->method('getDefaultDir')
->willReturn($this->defaultDirectoryMock);
$this->sut
->method('getServiceManager')
->willReturn($serviceLocator);
$this->sut->setServiceLocator($serviceLocator);
$this->sut->setModel(
$this->createModelMock()
);
}
public function testCreateContent(): void
{
$test = $this->createTestMock('https://example.com', '0label-with_sømę-exötïč_charæctêrß');
/** @noinspection PhpUnhandledExceptionInspection */
static::assertSame(
$this->createDirectoryMock(
$test,
$this->createNewFileMock($test)
),
$this->sut->createContent($test)
);
}
public function testOverwriteContent(): void
{
$test = $this->createTestMock('https://example.com', 'label');
/** @noinspection PhpUnhandledExceptionInspection */
static::assertSame(
$this->createDirectoryMock(
$test,
$this->createNewFileMock($test),
true,
false
),
$this->sut->createContent($test, true, false)
);
}
public function testExceptionOnExistingContent(): void
{
$test = $this->createTestMock('https://example.com', 'label');
$this->expectExceptionObject(
new common_exception_InconsistentData("Data directory for test {$test->getUri()} already exists.")
);
$this->createDirectoryMock(
$test,
null,
true
);
/** @noinspection PhpUnhandledExceptionInspection */
$this->sut->createContent($test);
}
public function testExistingContentFile(): void
{
$test = $this->createTestMock('https://example.com', 'label');
/** @noinspection PhpUnhandledExceptionInspection */
static::assertSame(
$this->createDirectoryMock(
$test,
$this->createExistingFileMock($test),
true,
false
),
$this->sut->createContent($test, false, false)
);
}
private function createTemplateDocument(): DOMDocument
{
$document = new DOMDocument('1.0', 'UTF-8');
$document->loadXML(self::TEST_TEMPLATE);
return $document;
}
private function createTestDom(KernelResource $test): DOMDocument
{
$document = $this->createTemplateDocument();
$this
->updateDocumentTitle($document, $test)
->documentElement->setAttribute(
'identifier',
str_replace('_', '-', Format::sanitizeIdentifier($test->getLabel()))
);
$document->documentElement->setAttribute('toolVersion', self::PLATFORM_VERSION);
return $document;
}
private function updateDocumentTitle(DOMDocument $document, KernelResource $test): DOMDocument
{
$document->documentElement->setAttribute('title', $test->getLabel());
return $document;
}
private function createNewFileMock(KernelResource $test): File
{
$fileMock = $this->createMock(File::class);
$fileMock
->expects(static::once())
->method('write')
->with(
$this->createTestDom($test)->saveXML()
)
->willReturn(true);
return $fileMock;
}
private function createExistingFileMock(KernelResource $test): File
{
$documentTemplate = $this->createTemplateDocument();
$fileMock = $this->createMock(File::class);
$fileMock
->expects(static::once())
->method('exists')
->willReturn(true);
$fileMock
->expects(static::once())
->method('read')
->willReturn($documentTemplate->saveXML());
$fileMock
->expects(static::once())
->method('update')
->with(
$this->updateDocumentTitle($documentTemplate, $test)->saveXML()
)
->willReturn(true);
return $fileMock;
}
private function createTestMock(string $uri, string $label): KernelResource
{
$testMock = $this->createMock(KernelResource::class);
$testMock
->method('getUri')
->willReturn($uri);
$testMock
->method('getLabel')
->willReturn($label);
return $testMock;
}
/**
* @param KernelResource|MockObject $test
* @param File|MockObject|null $file
* @param bool $exists
* @param bool $preventOverride
*
* @return Directory
*/
private function createDirectoryMock(
KernelResource $test,
File $file = null,
bool $exists = false,
$preventOverride = true
): Directory {
$mainInvocationRule = !$exists || !$preventOverride ? static::once() : static::never();
$directoryMock = $this->createMock(Directory::class);
$directoryMock
->expects(static::once())
->method('exists')
->willReturn($exists);
$directoryMock
->expects(clone $mainInvocationRule)
->method('getFile')
->with('tao-qtitest-testdefinition.xml')
->willReturn($file);
$this->defaultDirectoryMock
->expects(static::once())
->method('getDirectory')
->with(md5($test->getUri()))
->willReturn($directoryMock);
$serializedDirectoryData = 'serialized_directory_data';
$this->fileReferenceSerializerMock
->expects(clone $mainInvocationRule)
->method('serialize')
->with($directoryMock)
->willReturn($serializedDirectoryData);
$test
->expects(clone $mainInvocationRule)
->method('editPropertyValues')
->with($this->testContentPropertyMock, $serializedDirectoryData);
return $directoryMock;
}
private function creteServiceLocatorMock(): ServiceLocatorInterface
{
$serviceLocatorMock = $this->createMock(ServiceLocatorInterface::class);
$serviceLocatorMock
->method('get')
->willReturnMap(
[
[ApplicationService::SERVICE_ID, $this->createApplicationServiceMock()],
[FileReferenceSerializer::SERVICE_ID, $this->fileReferenceSerializerMock],
[AssessmentTestXmlFactory::class, $this->xmlFactory],
[DefaultConfigurationRegistry::class, $this->xmlTemplateOptionsRegistry],
]
);
return $serviceLocatorMock;
}
private function createModelMock(): Ontology
{
$modelMock = $this->createMock(Ontology::class);
$modelMock
->method('getProperty')
->willReturnMap(
[
['http://www.tao.lu/Ontologies/TAOTest.rdf#TestContent', $this->testContentPropertyMock],
]
);
return $modelMock;
}
private function createApplicationServiceMock(): ApplicationService
{
$applicationServiceMock = $this->createMock(ApplicationService::class);
$applicationServiceMock
->method('getPlatformVersion')
->willReturn(self::PLATFORM_VERSION);
return $applicationServiceMock;
}
}