* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice * * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests * @package cake * @subpackage cake.tests.cases.libs * @since CakePHP(tm) v 1.2.0.5432 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ App::uses('Xml', 'Utility'); App::uses('CakeTestModel', 'TestSuite/Fixture'); /** * Article class * * @package cake * @subpackage cake.tests.cases.libs */ class XmlArticle extends CakeTestModel { /** * name property * * @var string 'Article' */ public $name = 'Article'; /** * belongsTo property * * @var array */ public $belongsTo = array( 'XmlUser' => array( 'className' => 'XmlArticle', 'foreignKey' => 'user_id' ) ); } /** * User class * * @package cake * @subpackage cake.tests.cases.libs */ class XmlUser extends CakeTestModel { /** * name property * * @var string 'User' */ public $name = 'User'; /** * hasMany property * * @var array */ public $hasMany = array('Article'); } /** * XmlTest class * * @package cake * @subpackage cake.tests.cases.libs */ class XmlTest extends CakeTestCase { /** * autoFixtures property * * @var bool false */ public $autoFixtures = false; /** * fixtures property * @var array */ public $fixtures = array( 'core.article', 'core.user' ); /** * setup method * * @access public * @return void */ function setUp() { parent::setup(); $this->_appEncoding = Configure::read('App.encoding'); Configure::write('App.encoding', 'UTF-8'); } /** * tearDown method * * @access public * @return void */ function tearDown() { parent::tearDown(); Configure::write('App.encoding', $this->_appEncoding); } /** * testBuild method * * @return void */ public function testBuild() { $xml = 'value'; $obj = Xml::build($xml); $this->assertTrue($obj instanceof SimpleXMLElement); $this->assertEqual((string)$obj->getName(), 'tag'); $this->assertEqual((string)$obj, 'value'); $xml = 'value'; $this->assertEqual($obj, Xml::build($xml)); $obj = Xml::build($xml, array('return' => 'domdocument')); $this->assertTrue($obj instanceof DOMDocument); $this->assertEqual($obj->firstChild->nodeName, 'tag'); $this->assertEqual($obj->firstChild->nodeValue, 'value'); $xml = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'fixtures' . DS . 'sample.xml'; $obj = Xml::build($xml); $this->assertEqual($obj->getName(), 'tags'); $this->assertEqual(count($obj), 2); $this->assertEqual(Xml::build($xml), Xml::build(file_get_contents($xml))); $obj = Xml::build($xml, array('return' => 'domdocument')); $this->assertEqual($obj->firstChild->nodeName, 'tags'); $this->assertEqual(Xml::build($xml, array('return' => 'domdocument')), Xml::build(file_get_contents($xml), array('return' => 'domdocument'))); $this->assertEqual(Xml::build($xml, array('return' => 'simplexml')), Xml::build($xml, 'simplexml')); $xml = array('tag' => 'value'); $obj = Xml::build($xml); $this->assertEqual($obj->getName(), 'tag'); $this->assertEqual((string)$obj, 'value'); $obj = Xml::build($xml, array('return' => 'domdocument')); $this->assertEqual($obj->firstChild->nodeName, 'tag'); $this->assertEqual($obj->firstChild->nodeValue, 'value'); $obj = Xml::build($xml, array('return' => 'domdocument', 'encoding' => null)); $this->assertNoPattern('/encoding/', $obj->saveXML()); } /** * data provider function for testBuildInvalidData * * @return array */ public static function invalidDataProvider() { return array( array(null), array(false), array(''), array('') ); } /** * testBuildInvalidData * * @dataProvider invalidDataProvider * @expectedException Exception * return void */ public function testBuildInvalidData($value) { Xml::build($value); } /** * testFromArray method * * @return void */ public function testFromArray() { $xml = array('tag' => 'value'); $obj = Xml::fromArray($xml); $this->assertEqual($obj->getName(), 'tag'); $this->assertEqual((string)$obj, 'value'); $xml = array('tag' => null); $obj = Xml::fromArray($xml); $this->assertEqual($obj->getName(), 'tag'); $this->assertEqual((string)$obj, ''); $xml = array('tag' => array('@' => 'value')); $obj = Xml::fromArray($xml); $this->assertEqual($obj->getName(), 'tag'); $this->assertEqual((string)$obj, 'value'); $xml = array( 'tags' => array( 'tag' => array( array( 'id' => '1', 'name' => 'defect' ), array( 'id' => '2', 'name' => 'enhancement' ) ) ) ); $obj = Xml::fromArray($xml, 'attributes'); $this->assertTrue($obj instanceof SimpleXMLElement); $this->assertEqual($obj->getName(), 'tags'); $this->assertEqual(count($obj), 2); $xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?>'; $this->assertEqual(str_replace(array("\r", "\n"), '', $obj->asXML()), $xmlText); $obj = Xml::fromArray($xml); $this->assertTrue($obj instanceof SimpleXMLElement); $this->assertEqual($obj->getName(), 'tags'); $this->assertEqual(count($obj), 2); $xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?>1defect2enhancement'; $this->assertEqual(str_replace(array("\r", "\n"), '', $obj->asXML()), $xmlText); $xml = array( 'tags' => array( ) ); $obj = Xml::fromArray($xml); $this->assertEqual($obj->getName(), 'tags'); $this->assertEqual((string)$obj, ''); $xml = array( 'tags' => array( 'bool' => true, 'int' => 1, 'float' => 10.2, 'string' => 'ok', 'null' => null, 'array' => array() ) ); $obj = Xml::fromArray($xml, 'tags'); $this->assertEqual(count($obj), 6); $this->assertIdentical((string)$obj->bool, '1'); $this->assertIdentical((string)$obj->int, '1'); $this->assertIdentical((string)$obj->float, '10.2'); $this->assertIdentical((string)$obj->string, 'ok'); $this->assertIdentical((string)$obj->null, ''); $this->assertIdentical((string)$obj->array, ''); $xml = array( 'tags' => array( 'tag' => array( array( '@id' => '1', 'name' => 'defect' ), array( '@id' => '2', 'name' => 'enhancement' ) ) ) ); $obj = Xml::fromArray($xml, 'tags'); $xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?>defectenhancement'; $this->assertEqual(str_replace(array("\r", "\n"), '', $obj->asXML()), $xmlText); $xml = array( 'tags' => array( 'tag' => array( array( '@id' => '1', 'name' => 'defect', '@' => 'Tag 1' ), array( '@id' => '2', 'name' => 'enhancement' ), ), '@' => 'All tags' ) ); $obj = Xml::fromArray($xml, 'tags'); $xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?>All tagsTag 1defectenhancement'; $this->assertEqual(str_replace(array("\r", "\n"), '', $obj->asXML()), $xmlText); $xml = array( 'tags' => array( 'tag' => array( 'id' => 1, '@' => 'defect' ) ) ); $obj = Xml::fromArray($xml, 'attributes'); $xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?>defect'; $this->assertEqual(str_replace(array("\r", "\n"), '', $obj->asXML()), $xmlText); } /** * data provider for fromArray() failures * * @return array */ public static function invalidArrayDataProvider() { return array( array(''), array(null), array(false), array(array()), array(array('numeric key as root')), array(array('item1' => '', 'item2' => '')), array(array('items' => array('item1', 'item2'))), array(array( 'tags' => array( 'tag' => array( array( array( 'string' ) ) ) ) )), array(array( 'tags' => array( '@tag' => array( array( '@id' => '1', 'name' => 'defect' ), array( '@id' => '2', 'name' => 'enhancement' ) ) ) )), array(new DateTime()) ); } /** * testFromArrayFail method * * @dataProvider invalidArrayDataProvider * @expectedException Exception */ public function testFromArrayFail($value) { Xml::fromArray($value); } /** * testToArray method * * @return void */ public function testToArray() { $xml = 'name'; $obj = Xml::build($xml); $this->assertEqual(Xml::toArray($obj), array('tag' => 'name')); $xml = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'fixtures' . DS . 'sample.xml'; $obj = Xml::build($xml); $expected = array( 'tags' => array( 'tag' => array( array( '@id' => '1', 'name' => 'defect' ), array( '@id' => '2', 'name' => 'enhancement' ) ) ) ); $this->assertEqual(Xml::toArray($obj), $expected); $array = array( 'tags' => array( 'tag' => array( array( 'id' => '1', 'name' => 'defect' ), array( 'id' => '2', 'name' => 'enhancement' ) ) ) ); $this->assertEqual(Xml::toArray(Xml::fromArray($array, 'tags')), $array); $expected = array( 'tags' => array( 'tag' => array( array( '@id' => '1', '@name' => 'defect' ), array( '@id' => '2', '@name' => 'enhancement' ) ) ) ); $this->assertEqual(Xml::toArray(Xml::fromArray($array, 'attributes')), $expected); $this->assertEqual(Xml::toArray(Xml::fromArray($array, array('return' => 'domdocument', 'format' => 'attributes'))), $expected); $this->assertEqual(Xml::toArray(Xml::fromArray($array)), $array); $this->assertEqual(Xml::toArray(Xml::fromArray($array, array('return' => 'domdocument'))), $array); $array = array( 'tags' => array( 'tag' => array( 'id' => '1', 'posts' => array( array('id' => '1'), array('id' => '2') ) ), 'tagOther' => array( 'subtag' => array( 'id' => '1' ) ) ) ); $expected = array( 'tags' => array( 'tag' => array( '@id' => '1', 'posts' => array( array('@id' => '1'), array('@id' => '2') ) ), 'tagOther' => array( 'subtag' => array( '@id' => '1' ) ) ) ); $this->assertEqual(Xml::toArray(Xml::fromArray($array, 'attributes')), $expected); $this->assertEqual(Xml::toArray(Xml::fromArray($array, array('format' => 'attributes', 'return' => 'domdocument'))), $expected); $xml = ''; $xml .= 'defect'; $xml .= ''; $obj = Xml::build($xml); $expected = array( 'root' => array( 'tag' => array( '@id' => 1, '@' => 'defect' ) ) ); $this->assertEqual(Xml::toArray($obj), $expected); $xml = ''; $xml .= '
ApplesBananas
'; $xml .= 'CakePHPMIT
'; $xml .= 'The book is on the table.
'; $xml .= '
'; $obj = Xml::build($xml); $expected = array( 'root' => array( 'table' => array( array('tr' => array('td' => array('Apples', 'Bananas'))), array('name' => 'CakePHP', 'license' => 'MIT'), 'The book is on the table.' ) ) ); $this->assertEqual(Xml::toArray($obj), $expected); $xml = ''; $xml .= 'defect'; $xml .= '1'; $xml .= ''; $obj = Xml::build($xml); $expected = array( 'root' => array( 'tag' => 'defect', 'cake:bug' => 1 ) ); $this->assertEqual(Xml::toArray($obj), $expected); } /** * testRss * * @return void */ public function testRss() { $rss = file_get_contents(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'fixtures' . DS . 'rss.xml'); $rssAsArray = Xml::toArray(Xml::build($rss)); $this->assertEqual($rssAsArray['rss']['@version'], '2.0'); $this->assertEqual(count($rssAsArray['rss']['channel']['item']), 2); $atomLink = array('@href' => 'http://bakery.cakephp.org/articles/rss', '@rel' => 'self', '@type' => 'application/rss+xml'); $this->assertEqual($rssAsArray['rss']['channel']['atom:link'], $atomLink); $this->assertEqual($rssAsArray['rss']['channel']['link'], 'http://bakery.cakephp.org/'); $expected = array( 'title' => 'Alertpay automated sales via IPN', 'link' => 'http://bakery.cakephp.org/articles/view/alertpay-automated-sales-via-ipn', 'description' => 'I\'m going to show you how I implemented a payment module via the Alertpay payment processor.', 'pubDate' => 'Tue, 31 Aug 2010 01:42:00 -0500', 'guid' => 'http://bakery.cakephp.org/articles/view/alertpay-automated-sales-via-ipn' ); $this->assertIdentical($rssAsArray['rss']['channel']['item'][1], $expected); $rss = array( 'rss' => array( 'xmlns:atom' => 'http://www.w3.org/2005/Atom', '@version' => '2.0', 'channel' => array( 'atom:link' => array( '@href' => 'http://bakery.cakephp.org/articles/rss', '@rel' => 'self', '@type' => 'application/rss+xml' ), 'title' => 'The Bakery: ', 'link' => 'http://bakery.cakephp.org/', 'description' => 'Recent Articles at The Bakery.', 'pubDate' => 'Sun, 12 Sep 2010 04:18:26 -0500', 'item' => array( array( 'title' => 'CakePHP 1.3.4 released', 'link' => 'http://bakery.cakephp.org/articles/view/cakephp-1-3-4-released' ), array( 'title' => 'Wizard Component 1.2 Tutorial', 'link' => 'http://bakery.cakephp.org/articles/view/wizard-component-1-2-tutorial' ) ) ) ) ); $rssAsSimpleXML = Xml::fromArray($rss); $xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?>'; $xmlText .= ''; $xmlText .= ''; $xmlText .= ''; $xmlText .= 'The Bakery: '; $xmlText .= 'http://bakery.cakephp.org/'; $xmlText .= 'Recent Articles at The Bakery.'; $xmlText .= 'Sun, 12 Sep 2010 04:18:26 -0500'; $xmlText .= 'CakePHP 1.3.4 releasedhttp://bakery.cakephp.org/articles/view/cakephp-1-3-4-released'; $xmlText .= 'Wizard Component 1.2 Tutorialhttp://bakery.cakephp.org/articles/view/wizard-component-1-2-tutorial'; $xmlText .= ''; $this->assertEqual(str_replace(array("\r", "\n"), '', $rssAsSimpleXML->asXML()), $xmlText); } /** * testXmlRpc * * @return void */ public function testXmlRpc() { $xml = Xml::build('test'); $expected = array( 'methodCall' => array( 'methodName' => 'test', 'params' => '' ) ); $this->assertIdentical(Xml::toArray($xml), $expected); $xml = Xml::build('test12Egypt0-31'); $expected = array( 'methodCall' => array( 'methodName' => 'test', 'params' => array( 'param' => array( 'value' => array( 'array' => array( 'data' => array( 'value' => array( array('int' => '12'), array('string' => 'Egypt'), array('boolean' => '0'), array('int' => '-31') ) ) ) ) ) ) ) ); $this->assertIdentical(Xml::toArray($xml), $expected); $xmlText = '1testing'; $xml = Xml::build($xmlText); $expected = array( 'methodResponse' => array( 'params' => array( 'param' => array( 'value' => array( 'array' => array( 'data' => array( 'value' => array( array('int' => '1'), array('string' => 'testing') ) ) ) ) ) ) ) ); $this->assertIdentical(Xml::toArray($xml), $expected); $xml = Xml::fromArray($expected, 'tags'); $this->assertEqual(str_replace(array("\r", "\n"), '', $xml->asXML()), $xmlText); } /** * testSoap * * @return void */ public function testSoap() { $xmlRequest = Xml::build(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'fixtures' . DS . 'soap_request.xml'); $expected = array( 'Envelope' => array( '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding', 'soap:Body' => array( 'm:GetStockPrice' => array( 'm:StockName' => 'IBM' ) ) ) ); $this->assertEqual(Xml::toArray($xmlRequest), $expected); $xmlResponse = Xml::build(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'fixtures' . DS . 'soap_response.xml'); $expected = array( 'Envelope' => array( '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding', 'soap:Body' => array( 'm:GetStockPriceResponse' => array( 'm:Price' => '34.5' ) ) ) ); $this->assertEqual(Xml::toArray($xmlResponse), $expected); $xml = array( 'soap:Envelope' => array( 'xmlns:soap' => 'http://www.w3.org/2001/12/soap-envelope', '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding', 'soap:Body' => array( 'xmlns:m' => 'http://www.example.org/stock', 'm:GetStockPrice' => array( 'm:StockName' => 'IBM' ) ) ) ); $xmlRequest = Xml::fromArray($xml, array('encoding' => null)); $xmlText = '<' . '?xml version="1.0"?>'; $xmlText .= ''; $xmlText .= ''; $xmlText .= 'IBM'; $xmlText .= ''; $this->assertEqual(str_replace(array("\r", "\n"), '', $xmlRequest->asXML()), $xmlText); } /** * testNamespace * * @retun void */ public function testNamespace() { $xmlResponse = Xml::build('goodbadTag without ns'); $expected = array( 'root' => array( 'ns:tag' => array( '@id' => '1', 'child' => 'good', 'otherchild' => 'bad' ), 'tag' => 'Tag without ns' ) ); $this->assertEqual(Xml::toArray($xmlResponse), $expected); $xmlResponse = Xml::build('1'); $expected = array( 'root' => array( 'ns:tag' => array( '@id' => '1' ), 'tag' => array( 'id' => '1' ) ) ); $this->assertEqual(Xml::toArray($xmlResponse), $expected); $xmlResponse = Xml::build('1'); $expected = array( 'root' => array( 'ns:attr' => '1' ) ); $this->assertEqual(Xml::toArray($xmlResponse), $expected); $xmlResponse = Xml::build('1'); $this->assertEqual(Xml::toArray($xmlResponse), $expected); $xml = array( 'root' => array( 'ns:attr' => array( 'xmlns:ns' => 'http://cakephp.org', '@' => 1 ) ) ); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>1'; $xmlResponse = Xml::fromArray($xml); $this->assertEqual(str_replace(array("\r", "\n"), '', $xmlResponse->asXML()), $expected); $xml = array( 'root' => array( 'tag' => array( 'xmlns:pref' => 'http://cakephp.org', 'pref:item' => array( 'item 1', 'item 2' ) ) ) ); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>item 1item 2'; $xmlResponse = Xml::fromArray($xml); $this->assertEqual(str_replace(array("\r", "\n"), '', $xmlResponse->asXML()), $expected); $xml = array( 'root' => array( 'tag' => array( 'xmlns:' => 'http://cakephp.org' ) ) ); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>'; $xmlResponse = Xml::fromArray($xml); $this->assertEqual(str_replace(array("\r", "\n"), '', $xmlResponse->asXML()), $expected); $xml = array( 'root' => array( 'xmlns:' => 'http://cakephp.org' ) ); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>'; $xmlResponse = Xml::fromArray($xml); $this->assertEqual(str_replace(array("\r", "\n"), '', $xmlResponse->asXML()), $expected); $xml = array( 'root' => array( 'xmlns:ns' => 'http://cakephp.org' ) ); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>'; $xmlResponse = Xml::fromArray($xml); $this->assertEqual(str_replace(array("\r", "\n"), '', $xmlResponse->asXML()), $expected); } /** * test that CDATA blocks don't get screwed up by SimpleXml * * @return void */ function testCdata() { $xml = '<' . '?xml version="1.0" encoding="UTF-8"?>' . ''; $result = Xml::build($xml); $this->assertEquals(' Mark ', (string)$result->name); } /** * data provider for toArray() failures * * @return array */ public static function invalidToArrayDataProvider() { return array( array(new DateTime()), array(array()) ); } /** * testToArrayFail method * * @dataProvider invalidToArrayDataProvider * @expectedException Exception */ public function testToArrayFail($value) { Xml::toArray($value); } /** * testWithModel method * * @return void */ public function testWithModel() { $this->loadFixtures('User', 'Article'); $user = new XmlUser(); $data = $user->read(null, 1); $obj = Xml::build(compact('data')); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>'; $expected .= '1mariano5f4dcc3b5aa765d61d8327deb882cf99'; $expected .= '2007-03-17 01:16:232007-03-17 01:18:31'; $expected .= '
11First ArticleFirst Article Body'; $expected .= 'Y2007-03-18 10:39:232007-03-18 10:41:31
'; $expected .= '
31Third ArticleThird Article Body'; $expected .= 'Y2007-03-18 10:43:232007-03-18 10:45:31
'; $expected .= '
'; $this->assertEqual(str_replace(array("\r", "\n"), '', $obj->asXML()), $expected); } }