PageRenderTime 66ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/api/vendor/guzzle/guzzle/tests/Guzzle/Tests/Service/Command/LocationVisitor/Request/XmlVisitorTest.php

https://gitlab.com/x33n/respond
PHP | 558 lines | 517 code | 23 blank | 18 comment | 2 complexity | a3f52621da9bd542c15f7115e43b1c2d MD5 | raw file
  1. <?php
  2. namespace Guzzle\Tests\Service\Command\LocationVisitor\Request;
  3. use Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor;
  4. use Guzzle\Service\Client;
  5. use Guzzle\Service\Description\Parameter;
  6. use Guzzle\Service\Description\Operation;
  7. use Guzzle\Http\Message\EntityEnclosingRequest;
  8. /**
  9. * @covers Guzzle\Service\Command\LocationVisitor\Request\XmlVisitor
  10. */
  11. class XmlVisitorTest extends AbstractVisitorTestCase
  12. {
  13. public function xmlProvider()
  14. {
  15. return array(
  16. array(
  17. array(
  18. 'data' => array(
  19. 'xmlRoot' => array(
  20. 'name' => 'test',
  21. 'namespaces' => 'http://foo.com'
  22. )
  23. ),
  24. 'parameters' => array(
  25. 'Foo' => array('location' => 'xml', 'type' => 'string'),
  26. 'Baz' => array('location' => 'xml', 'type' => 'string')
  27. )
  28. ),
  29. array('Foo' => 'test', 'Baz' => 'bar'),
  30. '<test xmlns="http://foo.com"><Foo>test</Foo><Baz>bar</Baz></test>'
  31. ),
  32. // Ensure that the content-type is not added
  33. array(array('parameters' => array('Foo' => array('location' => 'xml', 'type' => 'string'))), array(), ''),
  34. // Test with adding attributes and no namespace
  35. array(
  36. array(
  37. 'data' => array(
  38. 'xmlRoot' => array(
  39. 'name' => 'test'
  40. )
  41. ),
  42. 'parameters' => array(
  43. 'Foo' => array('location' => 'xml', 'type' => 'string', 'data' => array('xmlAttribute' => true))
  44. )
  45. ),
  46. array('Foo' => 'test', 'Baz' => 'bar'),
  47. '<test Foo="test"/>'
  48. ),
  49. // Test adding with an array
  50. array(
  51. array(
  52. 'parameters' => array(
  53. 'Foo' => array('location' => 'xml', 'type' => 'string'),
  54. 'Baz' => array(
  55. 'type' => 'array',
  56. 'location' => 'xml',
  57. 'items' => array(
  58. 'type' => 'numeric',
  59. 'sentAs' => 'Bar'
  60. )
  61. )
  62. )
  63. ),
  64. array('Foo' => 'test', 'Baz' => array(1, 2)),
  65. '<Request><Foo>test</Foo><Baz><Bar>1</Bar><Bar>2</Bar></Baz></Request>'
  66. ),
  67. // Test adding an object
  68. array(
  69. array(
  70. 'parameters' => array(
  71. 'Foo' => array('location' => 'xml', 'type' => 'string'),
  72. 'Baz' => array(
  73. 'type' => 'object',
  74. 'location' => 'xml',
  75. 'properties' => array(
  76. 'Bar' => array('type' => 'string'),
  77. 'Bam' => array()
  78. )
  79. )
  80. )
  81. ),
  82. array('Foo' => 'test', 'Baz' => array('Bar' => 'abc', 'Bam' => 'foo')),
  83. '<Request><Foo>test</Foo><Baz><Bar>abc</Bar><Bam>foo</Bam></Baz></Request>'
  84. ),
  85. // Add an array that contains an object
  86. array(
  87. array(
  88. 'parameters' => array(
  89. 'Baz' => array(
  90. 'type' => 'array',
  91. 'location' => 'xml',
  92. 'items' => array(
  93. 'type' => 'object',
  94. 'sentAs' => 'Bar',
  95. 'properties' => array('A' => array(), 'B' => array())
  96. )
  97. )
  98. )
  99. ),
  100. array('Baz' => array(
  101. array('A' => '1', 'B' => '2'),
  102. array('A' => '3', 'B' => '4')
  103. )),
  104. '<Request><Baz><Bar><A>1</A><B>2</B></Bar><Bar><A>3</A><B>4</B></Bar></Baz></Request>'
  105. ),
  106. // Add an object of attributes
  107. array(
  108. array(
  109. 'parameters' => array(
  110. 'Foo' => array('location' => 'xml', 'type' => 'string'),
  111. 'Baz' => array(
  112. 'type' => 'object',
  113. 'location' => 'xml',
  114. 'properties' => array(
  115. 'Bar' => array('type' => 'string', 'data' => array('xmlAttribute' => true)),
  116. 'Bam' => array()
  117. )
  118. )
  119. )
  120. ),
  121. array('Foo' => 'test', 'Baz' => array('Bar' => 'abc', 'Bam' => 'foo')),
  122. '<Request><Foo>test</Foo><Baz Bar="abc"><Bam>foo</Bam></Baz></Request>'
  123. ),
  124. // Check order doesn't matter
  125. array(
  126. array(
  127. 'parameters' => array(
  128. 'Foo' => array('location' => 'xml', 'type' => 'string'),
  129. 'Baz' => array(
  130. 'type' => 'object',
  131. 'location' => 'xml',
  132. 'properties' => array(
  133. 'Bar' => array('type' => 'string', 'data' => array('xmlAttribute' => true)),
  134. 'Bam' => array()
  135. )
  136. )
  137. )
  138. ),
  139. array('Foo' => 'test', 'Baz' => array('Bam' => 'foo', 'Bar' => 'abc')),
  140. '<Request><Foo>test</Foo><Baz Bar="abc"><Bam>foo</Bam></Baz></Request>'
  141. ),
  142. // Add values with custom namespaces
  143. array(
  144. array(
  145. 'parameters' => array(
  146. 'Foo' => array(
  147. 'location' => 'xml',
  148. 'type' => 'string',
  149. 'data' => array(
  150. 'xmlNamespace' => 'http://foo.com'
  151. )
  152. )
  153. )
  154. ),
  155. array('Foo' => 'test'),
  156. '<Request><Foo xmlns="http://foo.com">test</Foo></Request>'
  157. ),
  158. // Add attributes with custom namespace prefix
  159. array(
  160. array(
  161. 'parameters' => array(
  162. 'Wrap' => array(
  163. 'type' => 'object',
  164. 'location' => 'xml',
  165. 'properties' => array(
  166. 'Foo' => array(
  167. 'type' => 'string',
  168. 'sentAs' => 'xsi:baz',
  169. 'data' => array(
  170. 'xmlNamespace' => 'http://foo.com',
  171. 'xmlAttribute' => true
  172. )
  173. )
  174. )
  175. ),
  176. )
  177. ),
  178. array('Wrap' => array(
  179. 'Foo' => 'test'
  180. )),
  181. '<Request><Wrap xsi:baz="test" xmlns:xsi="http://foo.com"/></Request>'
  182. ),
  183. // Add nodes with custom namespace prefix
  184. array(
  185. array(
  186. 'parameters' => array(
  187. 'Wrap' => array(
  188. 'type' => 'object',
  189. 'location' => 'xml',
  190. 'properties' => array(
  191. 'Foo' => array(
  192. 'type' => 'string',
  193. 'sentAs' => 'xsi:Foo',
  194. 'data' => array(
  195. 'xmlNamespace' => 'http://foobar.com'
  196. )
  197. )
  198. )
  199. ),
  200. )
  201. ),
  202. array('Wrap' => array(
  203. 'Foo' => 'test'
  204. )),
  205. '<Request><Wrap><xsi:Foo xmlns:xsi="http://foobar.com">test</xsi:Foo></Wrap></Request>'
  206. ),
  207. array(
  208. array(
  209. 'parameters' => array(
  210. 'Foo' => array(
  211. 'location' => 'xml',
  212. 'type' => 'string',
  213. 'data' => array(
  214. 'xmlNamespace' => 'http://foo.com'
  215. )
  216. )
  217. )
  218. ),
  219. array('Foo' => '<h1>This is a title</h1>'),
  220. '<Request><Foo xmlns="http://foo.com"><![CDATA[<h1>This is a title</h1>]]></Foo></Request>'
  221. ),
  222. // Flat array at top level
  223. array(
  224. array(
  225. 'parameters' => array(
  226. 'Bars' => array(
  227. 'type' => 'array',
  228. 'data' => array('xmlFlattened' => true),
  229. 'location' => 'xml',
  230. 'items' => array(
  231. 'type' => 'object',
  232. 'sentAs' => 'Bar',
  233. 'properties' => array(
  234. 'A' => array(),
  235. 'B' => array()
  236. )
  237. )
  238. ),
  239. 'Boos' => array(
  240. 'type' => 'array',
  241. 'data' => array('xmlFlattened' => true),
  242. 'location' => 'xml',
  243. 'items' => array(
  244. 'sentAs' => 'Boo',
  245. 'type' => 'string'
  246. )
  247. )
  248. )
  249. ),
  250. array(
  251. 'Bars' => array(
  252. array('A' => '1', 'B' => '2'),
  253. array('A' => '3', 'B' => '4')
  254. ),
  255. 'Boos' => array('test', '123')
  256. ),
  257. '<Request><Bar><A>1</A><B>2</B></Bar><Bar><A>3</A><B>4</B></Bar><Boo>test</Boo><Boo>123</Boo></Request>'
  258. ),
  259. // Nested flat arrays
  260. array(
  261. array(
  262. 'parameters' => array(
  263. 'Delete' => array(
  264. 'type' => 'object',
  265. 'location' => 'xml',
  266. 'properties' => array(
  267. 'Items' => array(
  268. 'type' => 'array',
  269. 'data' => array('xmlFlattened' => true),
  270. 'items' => array(
  271. 'type' => 'object',
  272. 'sentAs' => 'Item',
  273. 'properties' => array(
  274. 'A' => array(),
  275. 'B' => array()
  276. )
  277. )
  278. )
  279. )
  280. )
  281. )
  282. ),
  283. array(
  284. 'Delete' => array(
  285. 'Items' => array(
  286. array('A' => '1', 'B' => '2'),
  287. array('A' => '3', 'B' => '4')
  288. )
  289. )
  290. ),
  291. '<Request><Delete><Item><A>1</A><B>2</B></Item><Item><A>3</A><B>4</B></Item></Delete></Request>'
  292. )
  293. );
  294. }
  295. /**
  296. * @dataProvider xmlProvider
  297. */
  298. public function testSerializesXml(array $operation, array $input, $xml)
  299. {
  300. $operation = new Operation($operation);
  301. $command = $this->getMockBuilder('Guzzle\Service\Command\OperationCommand')
  302. ->setConstructorArgs(array($input, $operation))
  303. ->getMockForAbstractClass();
  304. $command->setClient(new Client('http://www.test.com/some/path.php'));
  305. $request = $command->prepare();
  306. if (!empty($input)) {
  307. $this->assertEquals('application/xml', (string) $request->getHeader('Content-Type'));
  308. } else {
  309. $this->assertNull($request->getHeader('Content-Type'));
  310. }
  311. $body = str_replace(array("\n", "<?xml version=\"1.0\"?>"), '', (string) $request->getBody());
  312. $this->assertEquals($xml, $body);
  313. }
  314. public function testAddsContentTypeAndTopLevelValues()
  315. {
  316. $operation = new Operation(array(
  317. 'data' => array(
  318. 'xmlRoot' => array(
  319. 'name' => 'test',
  320. 'namespaces' => array(
  321. 'xsi' => 'http://foo.com'
  322. )
  323. )
  324. ),
  325. 'parameters' => array(
  326. 'Foo' => array('location' => 'xml', 'type' => 'string'),
  327. 'Baz' => array('location' => 'xml', 'type' => 'string')
  328. )
  329. ));
  330. $command = $this->getMockBuilder('Guzzle\Service\Command\OperationCommand')
  331. ->setConstructorArgs(array(array(
  332. 'Foo' => 'test',
  333. 'Baz' => 'bar'
  334. ), $operation))
  335. ->getMockForAbstractClass();
  336. $command->setClient(new Client());
  337. $request = $command->prepare();
  338. $this->assertEquals('application/xml', (string) $request->getHeader('Content-Type'));
  339. $this->assertEquals(
  340. '<?xml version="1.0"?>' . "\n"
  341. . '<test xmlns:xsi="http://foo.com"><Foo>test</Foo><Baz>bar</Baz></test>' . "\n",
  342. (string) $request->getBody()
  343. );
  344. }
  345. public function testCanChangeContentType()
  346. {
  347. $visitor = new XmlVisitor();
  348. $visitor->setContentTypeHeader('application/foo');
  349. $this->assertEquals('application/foo', $this->readAttribute($visitor, 'contentType'));
  350. }
  351. public function testCanAddArrayOfSimpleTypes()
  352. {
  353. $request = new EntityEnclosingRequest('POST', 'http://foo.com');
  354. $visitor = new XmlVisitor();
  355. $param = new Parameter(array(
  356. 'type' => 'object',
  357. 'location' => 'xml',
  358. 'name' => 'Out',
  359. 'properties' => array(
  360. 'Nodes' => array(
  361. 'required' => true,
  362. 'type' => 'array',
  363. 'min' => 1,
  364. 'items' => array('type' => 'string', 'sentAs' => 'Node')
  365. )
  366. )
  367. ));
  368. $param->setParent(new Operation(array(
  369. 'data' => array(
  370. 'xmlRoot' => array(
  371. 'name' => 'Test',
  372. 'namespaces' => array(
  373. 'https://foo/'
  374. )
  375. )
  376. )
  377. )));
  378. $value = array('Nodes' => array('foo', 'baz'));
  379. $this->assertTrue($this->validator->validate($param, $value));
  380. $visitor->visit($this->command, $request, $param, $value);
  381. $visitor->after($this->command, $request);
  382. $this->assertEquals(
  383. "<?xml version=\"1.0\"?>\n"
  384. . "<Test xmlns=\"https://foo/\"><Out><Nodes><Node>foo</Node><Node>baz</Node></Nodes></Out></Test>\n",
  385. (string) $request->getBody()
  386. );
  387. }
  388. public function testCanAddMultipleNamespacesToRoot()
  389. {
  390. $operation = new Operation(array(
  391. 'data' => array(
  392. 'xmlRoot' => array(
  393. 'name' => 'Hi',
  394. 'namespaces' => array(
  395. 'xsi' => 'http://foo.com',
  396. 'foo' => 'http://foobar.com'
  397. )
  398. )
  399. ),
  400. 'parameters' => array(
  401. 'Foo' => array('location' => 'xml', 'type' => 'string')
  402. )
  403. ));
  404. $command = $this->getMockBuilder('Guzzle\Service\Command\OperationCommand')
  405. ->setConstructorArgs(array(array(
  406. 'Foo' => 'test'
  407. ), $operation))
  408. ->getMockForAbstractClass();
  409. $command->setClient(new Client());
  410. $request = $command->prepare();
  411. $this->assertEquals('application/xml', (string) $request->getHeader('Content-Type'));
  412. $this->assertEquals(
  413. '<?xml version="1.0"?>' . "\n"
  414. . '<Hi xmlns:xsi="http://foo.com" xmlns:foo="http://foobar.com"><Foo>test</Foo></Hi>' . "\n",
  415. (string) $request->getBody()
  416. );
  417. }
  418. public function testValuesAreFiltered()
  419. {
  420. $operation = new Operation(array(
  421. 'parameters' => array(
  422. 'Foo' => array(
  423. 'location' => 'xml',
  424. 'type' => 'string',
  425. 'filters' => array('strtoupper')
  426. ),
  427. 'Bar' => array(
  428. 'location' => 'xml',
  429. 'type' => 'object',
  430. 'properties' => array(
  431. 'Baz' => array(
  432. 'filters' => array('strtoupper')
  433. )
  434. )
  435. )
  436. )
  437. ));
  438. $command = $this->getMockBuilder('Guzzle\Service\Command\OperationCommand')
  439. ->setConstructorArgs(array(array(
  440. 'Foo' => 'test',
  441. 'Bar' => array(
  442. 'Baz' => 'abc'
  443. )
  444. ), $operation))
  445. ->getMockForAbstractClass();
  446. $command->setClient(new Client());
  447. $request = $command->prepare();
  448. $this->assertEquals(
  449. '<?xml version="1.0"?>' . "\n"
  450. . '<Request><Foo>TEST</Foo><Bar><Baz>ABC</Baz></Bar></Request>' . "\n",
  451. (string) $request->getBody()
  452. );
  453. }
  454. public function testSkipsNullValues()
  455. {
  456. $operation = new Operation(array(
  457. 'parameters' => array(
  458. 'Foo' => array(
  459. 'location' => 'xml',
  460. 'type' => 'string'
  461. ),
  462. 'Bar' => array(
  463. 'location' => 'xml',
  464. 'type' => 'object',
  465. 'properties' => array(
  466. 'Baz' => array(),
  467. 'Bam' => array(),
  468. )
  469. ),
  470. 'Arr' => array(
  471. 'type' => 'array',
  472. 'items' => array(
  473. 'type' => 'string'
  474. )
  475. )
  476. )
  477. ));
  478. $command = $this->getMockBuilder('Guzzle\Service\Command\OperationCommand')
  479. ->setConstructorArgs(array(array(
  480. 'Foo' => null,
  481. 'Bar' => array(
  482. 'Bar' => null,
  483. 'Bam' => 'test'
  484. ),
  485. 'Arr' => array(null)
  486. ), $operation))
  487. ->getMockForAbstractClass();
  488. $command->setClient(new Client());
  489. $request = $command->prepare();
  490. $this->assertEquals(
  491. '<?xml version="1.0"?>' . "\n"
  492. . '<Request><Bar><Bam>test</Bam></Bar></Request>' . "\n",
  493. (string) $request->getBody()
  494. );
  495. }
  496. public function testAllowsXmlEncoding()
  497. {
  498. $operation = new Operation(array(
  499. 'data' => array(
  500. 'xmlEncoding' => 'UTF-8'
  501. ),
  502. 'parameters' => array(
  503. 'Foo' => array('location' => 'xml')
  504. )
  505. ));
  506. $command = $this->getMockBuilder('Guzzle\Service\Command\OperationCommand')
  507. ->setConstructorArgs(array(array('Foo' => 'test'), $operation))
  508. ->getMockForAbstractClass();
  509. $command->setClient(new Client());
  510. $request = $command->prepare();
  511. $this->assertEquals(
  512. '<?xml version="1.0" encoding="UTF-8"?>' . "\n"
  513. . '<Request><Foo>test</Foo></Request>' . "\n",
  514. (string) $request->getBody()
  515. );
  516. }
  517. public function testAllowsSendingXmlPayloadIfNoXmlParamsWereSet()
  518. {
  519. $operation = new Operation(array(
  520. 'httpMethod' => 'POST',
  521. 'data' => array('xmlAllowEmpty' => true),
  522. 'parameters' => array('Foo' => array('location' => 'xml'))
  523. ));
  524. $command = $this->getMockBuilder('Guzzle\Service\Command\OperationCommand')
  525. ->setConstructorArgs(array(array(), $operation))
  526. ->getMockForAbstractClass();
  527. $command->setClient(new Client('http://foo.com'));
  528. $request = $command->prepare();
  529. $this->assertEquals(
  530. '<?xml version="1.0"?>' . "\n"
  531. . '<Request/>' . "\n",
  532. (string) $request->getBody()
  533. );
  534. }
  535. }