From 92a7a6b61777ce215895fd0ff1eaaefb465b2a60 Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Sat, 15 Mar 2014 13:25:42 +0700 Subject: [PATCH] More unit tests for Template and Writer --- Classes/PHPWord/Reader/Abstract.php | 2 + Classes/PHPWord/Writer/ODText.php | 1 + Classes/PHPWord/Writer/ODText/Manifest.php | 1 + Tests/PHPWord/TemplateTest.php | 31 ++++++- Tests/PHPWord/Writer/ODTextTest.php | 97 +++++++++++++++++---- Tests/PHPWord/Writer/RTFTest.php | 73 +++++++++++++--- Tests/PHPWord/Writer/Word2007Test.php | 44 ++++++++-- Tests/_files/templates/clone-row.docx | Bin 0 -> 14690 bytes 8 files changed, 214 insertions(+), 35 deletions(-) create mode 100644 Tests/_files/templates/clone-row.docx diff --git a/Classes/PHPWord/Reader/Abstract.php b/Classes/PHPWord/Reader/Abstract.php index 1e7acb51..18392f8b 100644 --- a/Classes/PHPWord/Reader/Abstract.php +++ b/Classes/PHPWord/Reader/Abstract.php @@ -27,6 +27,8 @@ /** * PHPWord_Reader_Abstract + * + * @codeCoverageIgnore Abstract class */ abstract class PHPWord_Reader_Abstract implements PHPWord_Reader_IReader { diff --git a/Classes/PHPWord/Writer/ODText.php b/Classes/PHPWord/Writer/ODText.php index 97e8f29b..6ec25cba 100755 --- a/Classes/PHPWord/Writer/ODText.php +++ b/Classes/PHPWord/Writer/ODText.php @@ -174,6 +174,7 @@ class PHPWord_Writer_ODText implements PHPWord_Writer_IWriter $objZip->addFromString('Pictures/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); } } + // @codeCoverageIgnoreEnd // Close file if ($objZip->close() === false) { diff --git a/Classes/PHPWord/Writer/ODText/Manifest.php b/Classes/PHPWord/Writer/ODText/Manifest.php index 266bf24f..c3c28981 100755 --- a/Classes/PHPWord/Writer/ODText/Manifest.php +++ b/Classes/PHPWord/Writer/ODText/Manifest.php @@ -101,6 +101,7 @@ class PHPWord_Writer_ODText_Manifest extends PHPWord_Writer_ODText_WriterPart $objWriter->endElement(); } } + // @codeCoverageIgnoreEnd $objWriter->endElement(); diff --git a/Tests/PHPWord/TemplateTest.php b/Tests/PHPWord/TemplateTest.php index d7e99e55..872ab182 100644 --- a/Tests/PHPWord/TemplateTest.php +++ b/Tests/PHPWord/TemplateTest.php @@ -2,9 +2,10 @@ namespace PHPWord\Tests; use PHPWord_Template; +use PHPWord; /** - * @coversDefaultClass PHPWord_Template + * @coversDefaultClass PHPWord_Template */ final class TemplateTest extends \PHPUnit_Framework_TestCase { @@ -143,4 +144,32 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase */ @$template->applyXslStyleSheet($xslDOMDocument); } + + /** + * @covers ::setValue + * @covers ::getVariables + * @covers ::cloneRow + * @covers ::saveAs + */ + public function testCloneRow() + { + $template = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'clone-row.docx') + ); + $expectedVar = array('tableHeader', 'userId', 'userName', 'userLocation'); + $docName = 'clone-test-result.docx'; + + $PHPWord = new PHPWord(); + $document = $PHPWord->loadTemplate($template); + $actualVar = $document->getVariables(); + $document->cloneRow('userId', 1); + $document->setValue('userId#1', 'Test'); + $document->saveAs($docName); + $docFound = file_exists($docName); + unlink($docName); + + $this->assertEquals($expectedVar, $actualVar); + $this->assertTrue($docFound); + } } diff --git a/Tests/PHPWord/Writer/ODTextTest.php b/Tests/PHPWord/Writer/ODTextTest.php index 6b162c3a..ef92d249 100644 --- a/Tests/PHPWord/Writer/ODTextTest.php +++ b/Tests/PHPWord/Writer/ODTextTest.php @@ -7,7 +7,8 @@ use PHPWord; /** * Class ODTextTest * - * @package PHPWord\Tests + * @package PHPWord\Tests + * @coversDefaultClass PHPWord_Writer_ODText * @runTestsInSeparateProcesses */ class ODTextTest extends \PHPUnit_Framework_TestCase @@ -37,10 +38,9 @@ class ODTextTest extends \PHPUnit_Framework_TestCase } /** - * Test construct with null value/without PHPWord - * - * @expectedException Exception - * @expectedExceptionMessage No PHPWord assigned. + * @covers ::getPHPWord + * @expectedException Exception + * @expectedExceptionMessage No PHPWord assigned. */ public function testConstructWithNull() { @@ -49,39 +49,106 @@ class ODTextTest extends \PHPUnit_Framework_TestCase } /** - * Test save() + * @covers ::save */ public function testSave() { + $imageSrc = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'PHPWord.png') + ); + $objectSrc = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + ); + $file = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'temp.odt') + ); + $phpWord = new PHPWord(); $phpWord->addFontStyle('Font', array('size' => 11)); $phpWord->addParagraphStyle('Paragraph', array('align' => 'center')); $section = $phpWord->createSection(); - $section->addText('Test 1', 'Font', 'Paragraph'); + $section->addText('Test 1', 'Font'); $section->addTextBreak(); - $section->addText('Test 2'); + $section->addText('Test 2', null, 'Paragraph'); + $section->addLink('http://test.com'); + $section->addTitle('Test', 1); + $section->addPageBreak(); + $section->addTable(); + $section->addListItem('Test'); + $section->addImage($imageSrc); + $section->addObject($objectSrc); + $section->addTOC(); $section = $phpWord->createSection(); $textrun = $section->createTextRun(); $textrun->addText('Test 3'); - $writer = new PHPWord_Writer_ODText($phpWord); - $file = join( - DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'temp.odt') - ); $writer->save($file); + $this->assertTrue(file_exists($file)); + unlink($file); } /** - * Test disk caching parameters + * @covers ::save + * @todo Haven't got any method to test this */ - public function testSetDiskCaching() + public function testSavePhpOutput() + { + $phpWord = new PHPWord(); + $section = $phpWord->createSection(); + $section->addText('Test'); + $writer = new PHPWord_Writer_ODText($phpWord); + $writer->save('php://output'); + } + + /** + * @covers ::save + * @expectedException Exception + * @expectedExceptionMessage PHPWord object unassigned. + */ + public function testSaveException() + { + $writer = new PHPWord_Writer_ODText(); + $writer->save(); + } + + /** + * @covers ::getWriterPart + */ + public function testGetWriterPartNull() + { + $object = new PHPWord_Writer_ODText(); + $this->assertNull($object->getWriterPart('foo')); + } + + /** + * @covers ::setUseDiskCaching + * @covers ::getUseDiskCaching + */ + public function testSetGetUseDiskCaching() { $object = new PHPWord_Writer_ODText(); $object->setUseDiskCaching(true, PHPWORD_TESTS_DIR_ROOT); $this->assertTrue($object->getUseDiskCaching()); $this->assertEquals(PHPWORD_TESTS_DIR_ROOT, $object->getDiskCachingDirectory()); } + + /** + * @covers ::setUseDiskCaching + * @expectedException Exception + */ + public function testSetUseDiskCachingException() + { + $dir = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, 'foo') + ); + + $object = new PHPWord_Writer_ODText($phpWord); + $object->setUseDiskCaching(true, $dir); + } } diff --git a/Tests/PHPWord/Writer/RTFTest.php b/Tests/PHPWord/Writer/RTFTest.php index d232854b..d071def7 100644 --- a/Tests/PHPWord/Writer/RTFTest.php +++ b/Tests/PHPWord/Writer/RTFTest.php @@ -6,13 +6,15 @@ use PHPWord; /** * Class RTFTest - * @package PHPWord\Tests + * + * @package PHPWord\Tests + * @coversDefaultClass PHPWord_Writer_RTF * @runTestsInSeparateProcesses */ class RTFTest extends \PHPUnit_Framework_TestCase { /** - * Test construct + * covers ::construct */ public function testConstruct() { @@ -23,10 +25,9 @@ class RTFTest extends \PHPUnit_Framework_TestCase } /** - * Test construct with null value/without PHPWord - * - * @expectedException Exception - * @expectedExceptionMessage No PHPWord assigned. + * covers ::__construct + * @expectedException Exception + * @expectedExceptionMessage No PHPWord assigned. */ public function testConstructWithNull() { @@ -35,28 +36,72 @@ class RTFTest extends \PHPUnit_Framework_TestCase } /** - * Test save() + * @covers ::save + * @todo Haven't got any method to test this + */ + public function testSavePhpOutput() + { + $phpWord = new PHPWord(); + $section = $phpWord->createSection(); + $section->addText('Test'); + $writer = new PHPWord_Writer_RTF($phpWord); + $writer->save('php://output'); + } + + /** + * @covers ::save + * @expectedException Exception + * @expectedExceptionMessage PHPWord object unassigned. + */ + public function testSaveException() + { + $writer = new PHPWord_Writer_RTF(); + $writer->save(); + } + + /** + * @covers ::save + * @covers :: */ public function testSave() { + $imageSrc = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'PHPWord.png') + ); + $objectSrc = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + ); + $file = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'temp.rtf') + ); + $phpWord = new PHPWord(); $phpWord->addFontStyle('Font', array('size' => 11)); $phpWord->addParagraphStyle('Paragraph', array('align' => 'center')); $section = $phpWord->createSection(); - $section->addText('Test 1', 'Font', 'Paragraph'); + $section->addText('Test 1', 'Font'); $section->addTextBreak(); - $section->addText('Test 2'); + $section->addText('Test 2', null, 'Paragraph'); + $section->addLink('http://test.com'); + $section->addTitle('Test', 1); + $section->addPageBreak(); + $section->addTable(); + $section->addListItem('Test'); + $section->addImage($imageSrc); + $section->addObject($objectSrc); + $section->addTOC(); $section = $phpWord->createSection(); $textrun = $section->createTextRun(); $textrun->addText('Test 3'); - + $textrun->addTextBreak(); $writer = new PHPWord_Writer_RTF($phpWord); - $file = join( - DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'temp.rtf') - ); $writer->save($file); + $this->assertTrue(file_exists($file)); + unlink($file); } } diff --git a/Tests/PHPWord/Writer/Word2007Test.php b/Tests/PHPWord/Writer/Word2007Test.php index ac66af2a..df58d737 100644 --- a/Tests/PHPWord/Writer/Word2007Test.php +++ b/Tests/PHPWord/Writer/Word2007Test.php @@ -8,7 +8,8 @@ use PHPWord\Tests\TestHelperDOCX; /** * Class Word2007Test * - * @package PHPWord\Tests + * @package PHPWord\Tests + * @coversDefaultClass PHPWord_Writer_Word2007 * @runTestsInSeparateProcesses */ class Word2007Test extends \PHPUnit_Framework_TestCase @@ -18,6 +19,9 @@ class Word2007Test extends \PHPUnit_Framework_TestCase TestHelperDOCX::clear(); } + /** + * covers ::__construct + */ public function testConstruct() { $object = new PHPWord_Writer_Word2007(new PHPWord()); @@ -37,6 +41,9 @@ class Word2007Test extends \PHPUnit_Framework_TestCase } } + /** + * @covers ::save + */ public function testSave() { $phpWord = new PHPWord(); @@ -51,9 +58,9 @@ class Word2007Test extends \PHPUnit_Framework_TestCase $textrun->addText('Test 3'); $writer = new PHPWord_Writer_Word2007($phpWord); - $file = join( - DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'temp.docx') + $file = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'temp.docx') ); $writer->save($file); $this->assertTrue(file_exists($file)); @@ -61,7 +68,7 @@ class Word2007Test extends \PHPUnit_Framework_TestCase } /** - * @covers PHPWord_Writer_Word2007::checkContentTypes + * @covers ::checkContentTypes */ public function testCheckContentTypes() { @@ -89,4 +96,31 @@ class Word2007Test extends \PHPUnit_Framework_TestCase ); } } + + /** + * @covers ::setUseDiskCaching + * @covers ::getUseDiskCaching + */ + public function testSetGetUseDiskCaching() + { + $object = new PHPWord_Writer_Word2007($phpWord); + $object->setUseDiskCaching(true, PHPWORD_TESTS_DIR_ROOT); + + $this->assertTrue($object->getUseDiskCaching()); + } + + /** + * @covers ::setUseDiskCaching + * @expectedException Exception + */ + public function testSetUseDiskCachingException() + { + $dir = \join( + \DIRECTORY_SEPARATOR, + array(\PHPWORD_TESTS_DIR_ROOT, 'foo') + ); + + $object = new PHPWord_Writer_Word2007($phpWord); + $object->setUseDiskCaching(true, $dir); + } } diff --git a/Tests/_files/templates/clone-row.docx b/Tests/_files/templates/clone-row.docx new file mode 100644 index 0000000000000000000000000000000000000000..eb944367f035ea2a39f4ea0fa3ab7e7cc3939bef GIT binary patch literal 14690 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 literal 0 HcmV?d00001