More tidying.
[yaffs-website] / vendor / consolidation / output-formatters / tests / testFormatters.php
1 <?php
2 namespace Consolidation\OutputFormatters;
3
4 use Consolidation\TestUtils\PropertyListWithCsvCells;
5 use Consolidation\TestUtils\RowsOfFieldsWithAlternatives;
6 use Consolidation\OutputFormatters\Options\FormatterOptions;
7 use Consolidation\OutputFormatters\StructuredData\AssociativeList;
8 use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
9 use Consolidation\OutputFormatters\StructuredData\PropertyList;
10 use Symfony\Component\Console\Output\BufferedOutput;
11 use Symfony\Component\Console\Output\OutputInterface;
12 use Symfony\Component\Console\Input\InputInterface;
13 use Symfony\Component\Console\Input\StringInput;
14 use Symfony\Component\Console\Input\InputOption;
15 use Symfony\Component\Console\Input\InputArgument;
16 use Symfony\Component\Console\Input\InputDefinition;
17
18 class FormattersTests extends \PHPUnit_Framework_TestCase
19 {
20     protected $formatterManager;
21
22     function setup() {
23         $this->formatterManager = new FormatterManager();
24     }
25
26     function assertFormattedOutputMatches($expected, $format, $data, FormatterOptions $options = null, $userOptions = []) {
27         if (!$options) {
28             $options = new FormatterOptions();
29         }
30         $options->setOptions($userOptions);
31         $output = new BufferedOutput();
32         $this->formatterManager->write($output, $format, $data, $options);
33         $actual = preg_replace('#[ \t]*$#sm', '', $output->fetch());
34         $this->assertEquals(rtrim($expected), rtrim($actual));
35     }
36
37     function testSimpleYaml()
38     {
39         $data = [
40             'one' => 'a',
41             'two' => 'b',
42             'three' => 'c',
43         ];
44
45         $expected = <<<EOT
46 one: a
47 two: b
48 three: c
49 EOT;
50
51         $this->assertFormattedOutputMatches($expected, 'yaml', $data);
52     }
53
54     function testNestedYaml()
55     {
56         $data = [
57             'one' => [
58                 'i' => ['a', 'b', 'c'],
59             ],
60             'two' => [
61                 'ii' => ['q', 'r', 's'],
62             ],
63             'three' => [
64                 'iii' => ['t', 'u', 'v'],
65             ],
66         ];
67
68         $expected = <<<EOT
69 one:
70   i:
71     - a
72     - b
73     - c
74 two:
75   ii:
76     - q
77     - r
78     - s
79 three:
80   iii:
81     - t
82     - u
83     - v
84 EOT;
85
86         $this->assertFormattedOutputMatches($expected, 'yaml', $data);
87     }
88
89     function testSimpleJson()
90     {
91         $data = [
92             'one' => 'a',
93             'two' => 'b',
94             'three' => 'c',
95         ];
96
97         $expected = <<<EOT
98 {
99     "one": "a",
100     "two": "b",
101     "three": "c"
102 }
103 EOT;
104
105         $this->assertFormattedOutputMatches($expected, 'json', $data);
106     }
107
108     function testSerializeFormat()
109     {
110         $data = [
111             'one' => 'a',
112             'two' => 'b',
113             'three' => 'c',
114         ];
115
116         $expected = 'a:3:{s:3:"one";s:1:"a";s:3:"two";s:1:"b";s:5:"three";s:1:"c";}';
117
118         $this->assertFormattedOutputMatches($expected, 'php', $data);
119     }
120
121     function testNestedJson()
122     {
123         $data = [
124             'one' => [
125                 'i' => ['a', 'b', 'c'],
126             ],
127             'two' => [
128                 'ii' => ['q', 'r', 's'],
129             ],
130             'three' => [
131                 'iii' => ['t', 'u', 'v'],
132             ],
133         ];
134
135         $expected = <<<EOT
136 {
137     "one": {
138         "i": [
139             "a",
140             "b",
141             "c"
142         ]
143     },
144     "two": {
145         "ii": [
146             "q",
147             "r",
148             "s"
149         ]
150     },
151     "three": {
152         "iii": [
153             "t",
154             "u",
155             "v"
156         ]
157     }
158 }
159 EOT;
160
161         $this->assertFormattedOutputMatches($expected, 'json', $data);
162     }
163
164     function testSimplePrintR()
165     {
166         $data = [
167             'one' => 'a',
168             'two' => 'b',
169             'three' => 'c',
170         ];
171
172         $expected = <<<EOT
173 Array
174 (
175     [one] => a
176     [two] => b
177     [three] => c
178 )
179 EOT;
180
181         $this->assertFormattedOutputMatches($expected, 'print-r', $data);
182     }
183
184     function testNestedPrintR()
185     {
186         $data = [
187             'one' => [
188                 'i' => ['a', 'b', 'c'],
189             ],
190             'two' => [
191                 'ii' => ['q', 'r', 's'],
192             ],
193             'three' => [
194                 'iii' => ['t', 'u', 'v'],
195             ],
196         ];
197
198         $expected = <<<EOT
199 Array
200 (
201     [one] => Array
202         (
203             [i] => Array
204                 (
205                     [0] => a
206                     [1] => b
207                     [2] => c
208                 )
209
210         )
211
212     [two] => Array
213         (
214             [ii] => Array
215                 (
216                     [0] => q
217                     [1] => r
218                     [2] => s
219                 )
220
221         )
222
223     [three] => Array
224         (
225             [iii] => Array
226                 (
227                     [0] => t
228                     [1] => u
229                     [2] => v
230                 )
231
232         )
233
234 )
235 EOT;
236
237         $this->assertFormattedOutputMatches($expected, 'print-r', $data);
238     }
239
240     function testSimpleVarExport()
241     {
242         $data = [
243             'one' => 'a',
244             'two' => 'b',
245             'three' => 'c',
246         ];
247
248         $expected = <<<EOT
249 array (
250   'one' => 'a',
251   'two' => 'b',
252   'three' => 'c',
253 )
254 EOT;
255
256         $this->assertFormattedOutputMatches($expected, 'var_export', $data);
257     }
258
259     function testNestedVarExport()
260     {
261         $data = [
262             'one' => [
263                 'i' => ['a', 'b', 'c'],
264             ],
265             'two' => [
266                 'ii' => ['q', 'r', 's'],
267             ],
268             'three' => [
269                 'iii' => ['t', 'u', 'v'],
270             ],
271         ];
272
273         $expected = <<<EOT
274 array (
275   'one' =>
276   array (
277     'i' =>
278     array (
279       0 => 'a',
280       1 => 'b',
281       2 => 'c',
282     ),
283   ),
284   'two' =>
285   array (
286     'ii' =>
287     array (
288       0 => 'q',
289       1 => 'r',
290       2 => 's',
291     ),
292   ),
293   'three' =>
294   array (
295     'iii' =>
296     array (
297       0 => 't',
298       1 => 'u',
299       2 => 'v',
300     ),
301   ),
302 )
303 EOT;
304
305         $this->assertFormattedOutputMatches($expected, 'var_export', $data);
306     }
307
308     function testList()
309     {
310         $data = [
311             'one' => 'a',
312             'two' => 'b',
313             'three' => 'c',
314         ];
315
316         $expected = <<<EOT
317 a
318 b
319 c
320 EOT;
321
322         $this->assertFormattedOutputMatches($expected, 'list', $data);
323     }
324
325     /**
326      * @expectedException \Consolidation\OutputFormatters\Exception\UnknownFormatException
327      * @expectedExceptionCode 1
328      * @expectedExceptionMessage The requested format, 'no-such-format', is not available.
329      */
330     function testBadFormat()
331     {
332         $this->assertFormattedOutputMatches('Will fail, not return', 'no-such-format', ['a' => 'b']);
333     }
334
335     /**
336      * @expectedException \Consolidation\OutputFormatters\Exception\IncompatibleDataException
337      * @expectedExceptionCode 1
338      * @expectedExceptionMessage Data provided to Consolidation\OutputFormatters\Formatters\CsvFormatter must be one of an instance of Consolidation\OutputFormatters\StructuredData\RowsOfFields, an instance of Consolidation\OutputFormatters\StructuredData\PropertyList or an array. Instead, a string was provided.
339      */
340     function testBadDataTypeForCsv()
341     {
342         $this->assertFormattedOutputMatches('Will fail, not return', 'csv', 'String cannot be converted to csv');
343     }
344
345     /**
346      * @expectedException \Consolidation\OutputFormatters\Exception\IncompatibleDataException
347      * @expectedExceptionCode 1
348      * @expectedExceptionMessage Data provided to Consolidation\OutputFormatters\Formatters\JsonFormatter must be an array. Instead, a string was provided.
349      */
350     function testBadDataTypeForJson()
351     {
352         $this->assertFormattedOutputMatches('Will fail, not return', 'json', 'String cannot be converted to json');
353     }
354
355     function testNoFormatterSelected()
356     {
357         $data = 'Hello';
358         $expected = $data;
359         $this->assertFormattedOutputMatches($expected, '', $data);
360     }
361
362     function testRenderTableAsString()
363     {
364         $data = new RowsOfFields([['f1' => 'A', 'f2' => 'B', 'f3' => 'C'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]);
365         $expected = "A\tB\tC\nx\ty\tz";
366
367         $this->assertFormattedOutputMatches($expected, 'string', $data);
368     }
369
370     function testRenderTableAsStringWithSingleField()
371     {
372         $data = new RowsOfFields([['f1' => 'q', 'f2' => 'r', 'f3' => 's'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]);
373         $expected = "q\nx";
374
375         $options = new FormatterOptions([FormatterOptions::DEFAULT_STRING_FIELD => 'f1']);
376
377         $this->assertFormattedOutputMatches($expected, 'string', $data, $options);
378     }
379
380     function testRenderTableAsStringWithSingleFieldAndUserSelectedField()
381     {
382         $data = new RowsOfFields([['f1' => 'q', 'f2' => 'r', 'f3' => 's'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]);
383         $expected = "r\ny";
384
385         $options = new FormatterOptions([FormatterOptions::DEFAULT_STRING_FIELD => 'f1']);
386
387         $this->assertFormattedOutputMatches($expected, 'string', $data, $options, ['fields' => 'f2']);
388     }
389
390     function testSimpleCsv()
391     {
392         $data = ['a', 'b', 'c'];
393         $expected = "a,b,c";
394
395         $this->assertFormattedOutputMatches($expected, 'csv', $data);
396     }
397
398     function testLinesOfCsv()
399     {
400         $data = [['a', 'b', 'c'], ['x', 'y', 'z']];
401         $expected = "a,b,c\nx,y,z";
402
403         $this->assertFormattedOutputMatches($expected, 'csv', $data);
404     }
405
406     function testCsvWithEscapedValues()
407     {
408         $data = ["Red apple", "Yellow lemon"];
409         $expected = '"Red apple","Yellow lemon"';
410
411         $this->assertFormattedOutputMatches($expected, 'csv', $data);
412     }
413
414     function testCsvWithEmbeddedSingleQuote()
415     {
416         $data = ["John's book", "Mary's laptop"];
417         $expected = <<<EOT
418 "John's book","Mary's laptop"
419 EOT;
420
421         $this->assertFormattedOutputMatches($expected, 'csv', $data);
422     }
423
424     function testCsvWithEmbeddedDoubleQuote()
425     {
426         $data = ['The "best" solution'];
427         $expected = <<<EOT
428 "The ""best"" solution"
429 EOT;
430
431         $this->assertFormattedOutputMatches($expected, 'csv', $data);
432     }
433
434     function testCsvBothKindsOfQuotes()
435     {
436         $data = ["John's \"new\" book", "Mary's \"modified\" laptop"];
437         $expected = <<<EOT
438 "John's ""new"" book","Mary's ""modified"" laptop"
439 EOT;
440
441         $this->assertFormattedOutputMatches($expected, 'csv', $data);
442     }
443
444     function testSimpleTsv()
445     {
446         $data = ['a', 'b', 'c'];
447         $expected = "a\tb\tc";
448
449         $this->assertFormattedOutputMatches($expected, 'tsv', $data);
450     }
451
452     function testLinesOfTsv()
453     {
454         $data = [['a', 'b', 'c'], ['x', 'y', 'z']];
455         $expected = "a\tb\tc\nx\ty\tz";
456
457         $this->assertFormattedOutputMatches($expected, 'tsv', $data);
458     }
459
460     function testTsvBothKindsOfQuotes()
461     {
462         $data = ["John's \"new\" book", "Mary's \"modified\" laptop"];
463         $expected = "John's \"new\" book\tMary's \"modified\" laptop";
464
465         $this->assertFormattedOutputMatches($expected, 'tsv', $data);
466     }
467
468     function testTsvWithEscapedValues()
469     {
470         $data = ["Red apple", "Yellow lemon", "Embedded\ttab"];
471         $expected = "Red apple\tYellow lemon\tEmbedded\\ttab";
472
473         $this->assertFormattedOutputMatches($expected, 'tsv', $data);
474     }
475
476     protected function missingCellTableExampleData()
477     {
478         $data = [
479             [
480                 'one' => 'a',
481                 'two' => 'b',
482                 'three' => 'c',
483             ],
484             [
485                 'one' => 'x',
486                 'three' => 'z',
487             ],
488         ];
489         return new RowsOfFields($data);
490     }
491
492     function testTableWithMissingCell()
493     {
494         $data = $this->missingCellTableExampleData();
495
496         $expected = <<<EOT
497  ----- ----- -------
498   One   Two   Three
499  ----- ----- -------
500   a     b     c
501   x           z
502  ----- ----- -------
503 EOT;
504         $this->assertFormattedOutputMatches($expected, 'table', $data);
505
506         $expectedCsv = <<<EOT
507 One,Two,Three
508 a,b,c
509 x,,z
510 EOT;
511         $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
512
513         $expectedTsv = <<<EOT
514 a\tb\tc
515 x\t\tz
516 EOT;
517         $this->assertFormattedOutputMatches($expectedTsv, 'tsv', $data);
518
519         $expectedTsvWithHeaders = <<<EOT
520 One\tTwo\tThree
521 a\tb\tc
522 x\t\tz
523 EOT;
524         $this->assertFormattedOutputMatches($expectedTsvWithHeaders, 'tsv', $data, new FormatterOptions(), ['include-field-labels' => true]);
525     }
526
527     function testTableWithWordWrapping()
528     {
529         $options = new FormatterOptions();
530
531         $data = [
532             [
533                 'first' => 'This is a really long cell that contains a lot of data. When it is rendered, it should be wrapped across multiple lines.',
534                 'second' => 'This is the second column of the same table. It is also very long, and should be wrapped across multiple lines, just like the first column.',
535             ]
536         ];
537         $data = new RowsOfFields($data);
538
539         $expected = <<<EOT
540  ------------------ --------------------
541   First              Second
542  ------------------ --------------------
543   This is a really   This is the second
544   long cell that     column of the same
545   contains a lot     table. It is also
546   of data. When it   very long, and
547   is rendered, it    should be wrapped
548   should be          across multiple
549   wrapped across     lines, just like
550   multiple lines.    the first column.
551  ------------------ --------------------
552 EOT;
553         $options->setWidth(42);
554         $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
555
556         $expected = <<<EOT
557  ----------------------------------- ---------------------------------------
558   First                               Second
559  ----------------------------------- ---------------------------------------
560   This is a really long cell that     This is the second column of the same
561   contains a lot of data. When it     table. It is also very long, and
562   is rendered, it should be wrapped   should be wrapped across multiple
563   across multiple lines.              lines, just like the first column.
564  ----------------------------------- ---------------------------------------
565 EOT;
566         $options->setWidth(78);
567         $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
568     }
569
570     function testWrappingLotsOfColumns()
571     {
572         $options = new FormatterOptions();
573
574         $data = [
575             [
576                 'id' => '4d87b545-b4c3-4ece-9908-20c5c5e67e81',
577                 'name' => '123456781234567812345678123456781234567812345678',
578                 'service_level' => 'business',
579                 'framework' => 'wordpress-network',
580                 'owner' => '8558a08d-8059-45f6-9c4b-908299a025ee',
581                 'created' => '2017-05-24 19:28:45',
582                 'memberships' => 'b3a42ba5-755d-42ca-9109-21bde32809d0: Team,9bfaaf50-ece3-4460-acb8-dc1b8dd536e8: pantheon-engineering-canary-sites',
583                 'frozen' => 'false',
584             ],
585             [
586                 'id' => '3d87b545-b4c3-4ece-9908-20c5c5e67e80',
587                 'name' => 'build-tools-136',
588                 'service_level' => 'free',
589                 'framework' => 'drupal8',
590                 'owner' => '7558a08d-8059-45f6-9c4b-908299a025ef',
591                 'created' => '2017-05-24 19:28:45',
592                 'memberships' => '5ae1fa30-8cc4-4894-8ca9-d50628dcba17: ci-for-drupal-8-composer',
593                 'frozen' => 'false',
594             ]
595         ];
596         $data = new RowsOfFields($data);
597
598         $expected = <<<EOT
599  ------------- ---------------- --------------- ----------- ------------- --------- ------------------------------------ --------
600   Id            Name             Service_level   Framework   Owner         Created   Memberships                          Frozen
601  ------------- ---------------- --------------- ----------- ------------- --------- ------------------------------------ --------
602   4d87b545-b4   12345678123456   business        wordp       8558a08d-80   2017-0    b3a42ba5-755d-42ca-9109-21bde32809   false
603   c3-4ece-990   78123456781234                   ress-       59-45f6-9c4   5-24      d0:
604   8-20c5c5e67   56781234567812                   netwo       b-908299a02   19:28:    Team,9bfaaf50-ece3-4460-acb8-dc1b8
605   e81           345678                           rk          5ee           45        dd536e8:
606                                                                                      pantheon-engineering-canary-sites
607   3d87b545-b4   build-tools-13   free            drupa       7558a08d-80   2017-0    5ae1fa30-8cc4-4894-8ca9-d50628dcba   false
608   c3-4ece-990   6                                l8          59-45f6-9c4   5-24      17: ci-for-drupal-8-composer
609   8-20c5c5e67                                                b-908299a02   19:28:
610   e80                                                        5ef           45
611  ------------- ---------------- --------------- ----------- ------------- --------- ------------------------------------ --------
612 EOT;
613
614         $options->setWidth(125);
615         $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
616     }
617
618     function testTableWithWordWrapping2()
619     {
620         $options = new FormatterOptions();
621
622         $data = [
623             [
624                 'id' => 42,
625                 'vid' => 321,
626                 'description' => 'Life, the Universe and Everything.',
627             ],
628             [
629                 'id' => 13,
630                 'vid' => 789,
631                 'description' => 'Why is six afraid of seven?',
632             ],
633         ];
634         $data = new RowsOfFields($data);
635         $expected = <<<EOT
636  ---- ----- -----------------------------
637   Id   Vid   Description
638  ---- ----- -----------------------------
639   42   321   Life, the Universe and
640              Everything.
641   13   789   Why is six afraid of seven?
642  ---- ----- -----------------------------
643 EOT;
644         $options->setWidth(42);
645         $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
646     }
647
648     function testTableWithWordWrapping3()
649     {
650         $options = new FormatterOptions();
651         $data = [
652             'name' => 'Rex',
653             'species' => 'dog',
654             'food' => 'kibble',
655             'legs' => '4',
656             'description' => 'Rex is a very good dog, Brett. He likes kibble, and has four legs.',
657         ];
658         $data = new PropertyList($data);
659
660         $expected = <<<EOT
661  ------------- -------------------------
662   Name          Rex
663   Species       dog
664   Food          kibble
665   Legs          4
666   Description   Rex is a very good dog,
667                 Brett. He likes kibble,
668                 and has four legs.
669  ------------- -------------------------
670 EOT;
671         $options->setWidth(42);
672         $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
673     }
674
675     function testTableWithWordWrapping4()
676     {
677         $options = new FormatterOptions();
678
679         $data = [
680             'name' => ['label' => 'Name', 'sep' => ':', 'value' => 'Rex', ],
681             'species' => ['label' => 'Species', 'sep' => ':', 'value' => 'dog', ],
682             'food' => ['label' => 'Food', 'sep' => ':', 'value' => 'kibble', ],
683             'legs' => ['label' => 'Legs', 'sep' => ':', 'value' => '4', ],
684             'description' => ['label' => 'Description', 'sep' => ':', 'value' => 'Rex is a very good dog, Brett. He likes kibble, and has four legs.', ],
685         ];
686         $data = new RowsOfFields($data);
687         $expected = <<<EOT
688  ------------- ----- -----------------------------------------------------
689   Label         Sep   Value
690  ------------- ----- -----------------------------------------------------
691   Name          :     Rex
692   Species       :     dog
693   Food          :     kibble
694   Legs          :     4
695   Description   :     Rex is a very good dog, Brett. He likes kibble, and
696                       has four legs.
697  ------------- ----- -----------------------------------------------------
698 EOT;
699         $options->setWidth(78);
700         $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
701     }
702
703     function testTableWithWordWrapping5()
704     {
705         $options = new FormatterOptions();
706         $data = [
707             'name' => ['Name', ':', 'Rex', ],
708             'species' => ['Species', ':', 'dog', ],
709             'food' => ['Food', ':', 'kibble', ],
710             'legs' => ['Legs', ':', '4', ],
711             'description' => ['Description', ':', 'Rex is a very good dog, Brett. He likes kibble, and has four legs.', ],
712         ];
713         $data = new RowsOfFields($data);
714         $expected = <<<EOT
715  Name        : Rex
716  Species     : dog
717  Food        : kibble
718  Legs        : 4
719  Description : Rex is a very good dog, Brett. He likes kibble, and has
720                four legs.
721 EOT;
722         $options->setWidth(78);
723         $options->setIncludeFieldLables(false);
724         $options->setTableStyle('compact');
725         $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
726     }
727
728     protected function simpleTableExampleData()
729     {
730         $data = [
731             'id-123' =>
732             [
733                 'one' => 'a',
734                 'two' => 'b',
735                 'three' => 'c',
736             ],
737             'id-456' =>
738             [
739                 'one' => 'x',
740                 'two' => 'y',
741                 'three' => 'z',
742             ],
743         ];
744         return new RowsOfFields($data);
745     }
746
747     /**
748      * @expectedException \Consolidation\OutputFormatters\Exception\InvalidFormatException
749      * @expectedExceptionCode 1
750      * @expectedExceptionMessage The format table cannot be used with the data produced by this command, which was an array.  Valid formats are: csv,json,list,php,print-r,string,tsv,var_export,xml,yaml
751      */
752     function testIncompatibleDataForTableFormatter()
753     {
754         $data = $this->simpleTableExampleData()->getArrayCopy();
755         $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'table', $data);
756     }
757
758     /**
759      * @expectedException \Consolidation\OutputFormatters\Exception\InvalidFormatException
760      * @expectedExceptionCode 1
761      * @expectedExceptionMessage The format sections cannot be used with the data produced by this command, which was an array.  Valid formats are: csv,json,list,php,print-r,string,tsv,var_export,xml,yaml
762      */
763     function testIncompatibleDataForSectionsFormatter()
764     {
765         $data = $this->simpleTableExampleData()->getArrayCopy();
766         $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'sections', $data);
767     }
768
769     function testSimpleTable()
770     {
771         $data = $this->simpleTableExampleData();
772
773         $expected = <<<EOT
774  ----- ----- -------
775   One   Two   Three
776  ----- ----- -------
777   a     b     c
778   x     y     z
779  ----- ----- -------
780 EOT;
781         $this->assertFormattedOutputMatches($expected, 'table', $data);
782
783         $expectedBorderless = <<<EOT
784  ===== ===== =======
785   One   Two   Three
786  ===== ===== =======
787   a     b     c
788   x     y     z
789  ===== ===== =======
790 EOT;
791         $this->assertFormattedOutputMatches($expectedBorderless, 'table', $data, new FormatterOptions(['table-style' => 'borderless']));
792
793         $expectedJson = <<<EOT
794 {
795     "id-123": {
796         "one": "a",
797         "two": "b",
798         "three": "c"
799     },
800     "id-456": {
801         "one": "x",
802         "two": "y",
803         "three": "z"
804     }
805 }
806 EOT;
807         $this->assertFormattedOutputMatches($expectedJson, 'json', $data);
808
809         $expectedCsv = <<<EOT
810 One,Two,Three
811 a,b,c
812 x,y,z
813 EOT;
814         $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
815
816         $expectedList = <<<EOT
817 id-123
818 id-456
819 EOT;
820         $this->assertFormattedOutputMatches($expectedList, 'list', $data);
821     }
822
823     protected function tableWithAlternativesExampleData()
824     {
825         $data = [
826             'id-123' =>
827             [
828                 'one' => 'a',
829                 'two' => ['this', 'that', 'the other thing'],
830                 'three' => 'c',
831             ],
832             'id-456' =>
833             [
834                 'one' => 'x',
835                 'two' => 'y',
836                 'three' => ['apples', 'oranges'],
837             ],
838         ];
839         return new RowsOfFieldsWithAlternatives($data);
840     }
841
842     function testTableWithAlternatives()
843     {
844         $data = $this->tableWithAlternativesExampleData();
845
846         $expected = <<<EOT
847  ----- --------------------------- ----------------
848   One   Two                         Three
849  ----- --------------------------- ----------------
850   a     this|that|the other thing   c
851   x     y                           apples|oranges
852  ----- --------------------------- ----------------
853 EOT;
854         $this->assertFormattedOutputMatches($expected, 'table', $data);
855
856         $expectedBorderless = <<<EOT
857  ===== =========================== ================
858   One   Two                         Three
859  ===== =========================== ================
860   a     this|that|the other thing   c
861   x     y                           apples|oranges
862  ===== =========================== ================
863 EOT;
864         $this->assertFormattedOutputMatches($expectedBorderless, 'table', $data, new FormatterOptions(['table-style' => 'borderless']));
865
866         $expectedJson = <<<EOT
867 {
868     "id-123": {
869         "one": "a",
870         "two": [
871             "this",
872             "that",
873             "the other thing"
874         ],
875         "three": "c"
876     },
877     "id-456": {
878         "one": "x",
879         "two": "y",
880         "three": [
881             "apples",
882             "oranges"
883         ]
884     }
885 }
886 EOT;
887         $this->assertFormattedOutputMatches($expectedJson, 'json', $data);
888
889         $expectedCsv = <<<EOT
890 One,Two,Three
891 a,"this|that|the other thing",c
892 x,y,apples|oranges
893 EOT;
894         $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
895
896         $expectedList = <<<EOT
897 id-123
898 id-456
899 EOT;
900         $this->assertFormattedOutputMatches($expectedList, 'list', $data);
901     }
902
903     function testSimpleTableWithFieldLabels()
904     {
905         $data = $this->simpleTableExampleData();
906         $configurationData = new FormatterOptions(
907             [
908                 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'],
909                 'row-labels' => ['id-123' => 'Walrus', 'id-456' => 'Carpenter'],
910             ]
911         );
912         $configurationDataAnnotationFormat = new FormatterOptions(
913             [
914                 'field-labels' => "one: Uno\ntwo: Dos\nthree: Tres",
915             ]
916         );
917
918         $expected = <<<EOT
919  ------ ---- -----
920   Ichi   Ni   San
921  ------ ---- -----
922   a      b    c
923   x      y    z
924  ------ ---- -----
925 EOT;
926         $this->assertFormattedOutputMatches($expected, 'table', $data, $configurationData);
927
928         $expectedSidewaysTable = <<<EOT
929  ------ --- ---
930   Ichi   a   x
931   Ni     b   y
932   San    c   z
933  ------ --- ---
934 EOT;
935         $this->assertFormattedOutputMatches($expectedSidewaysTable, 'table', $data, $configurationData->override(['list-orientation' => true]));
936
937         $expectedAnnotationFormatConfigData = <<<EOT
938  ----- ----- ------
939   Uno   Dos   Tres
940  ----- ----- ------
941   a     b     c
942   x     y     z
943  ----- ----- ------
944 EOT;
945         $this->assertFormattedOutputMatches($expectedAnnotationFormatConfigData, 'table', $data, $configurationDataAnnotationFormat);
946
947         $expectedWithNoFields = <<<EOT
948  --- --- ---
949   a   b   c
950   x   y   z
951  --- --- ---
952 EOT;
953         $this->assertFormattedOutputMatches($expectedWithNoFields, 'table', $data, $configurationData, ['include-field-labels' => false]);
954
955         $expectedWithReorderedFields = <<<EOT
956  ----- ------
957   San   Ichi
958  ----- ------
959   c     a
960   z     x
961  ----- ------
962 EOT;
963         $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['three', 'one']]);
964         $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
965         $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => 'San,Ichi']);
966
967         $expectedWithRegexField = <<<EOT
968  ------ -----
969   Ichi   San
970  ------ -----
971   a      c
972   x      z
973  ------ -----
974 EOT;
975         $this->assertFormattedOutputMatches($expectedWithRegexField, 'table', $data, $configurationData, ['fields' => ['/e$/']]);
976         $this->assertFormattedOutputMatches($expectedWithRegexField, 'table', $data, $configurationData, ['fields' => ['*e']]);
977         $this->assertFormattedOutputMatches($expectedWithRegexField, 'table', $data, $configurationData, ['default-fields' => ['*e']]);
978
979         $expectedSections = <<<EOT
980
981 Walrus
982  One   a
983  Two   b
984  Three c
985
986 Carpenter
987  One   x
988  Two   y
989  Three z
990 EOT;
991         $this->assertFormattedOutputMatches($expectedSections, 'sections', $data, $configurationData);
992
993         $expectedJson = <<<EOT
994 {
995     "id-123": {
996         "three": "c",
997         "one": "a"
998     },
999     "id-456": {
1000         "three": "z",
1001         "one": "x"
1002     }
1003 }
1004 EOT;
1005         $this->assertFormattedOutputMatches($expectedJson, 'json', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
1006
1007         $expectedSingleField = <<<EOT
1008  -----
1009   San
1010  -----
1011   c
1012   z
1013  -----
1014 EOT;
1015         $this->assertFormattedOutputMatches($expectedSingleField, 'table', $data, $configurationData, ['field' => 'San']);
1016
1017         $expectedEmptyColumn = <<<EOT
1018  -----
1019   San
1020  -----
1021 EOT;
1022
1023         $this->assertFormattedOutputMatches($expectedEmptyColumn, 'table', new RowsOfFields([]), $configurationData, ['field' => 'San']);
1024
1025         $this->assertFormattedOutputMatches('', '', new RowsOfFields([]), $configurationData, ['field' => 'San']);
1026         $this->assertFormattedOutputMatches('[]', 'json', new RowsOfFields([]), $configurationData, ['field' => 'San']);
1027     }
1028
1029     /**
1030      * @expectedException \Consolidation\OutputFormatters\Exception\UnknownFieldException
1031      * @expectedExceptionCode 1
1032      * @expectedExceptionMessage The requested field, 'Shi', is not defined.
1033      */
1034     function testNoSuchFieldException()
1035     {
1036         $configurationData = new FormatterOptions(
1037             [
1038                 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'],
1039                 'row-labels' => ['id-123' => 'Walrus', 'id-456' => 'Carpenter'],
1040             ]
1041         );
1042         $data = $this->simpleTableExampleData();
1043         $this->assertFormattedOutputMatches('Will throw before comparing', 'table', $data, $configurationData, ['field' => 'Shi']);
1044     }
1045
1046     protected function simpleListExampleData()
1047     {
1048         $data = [
1049             'one' => 'apple',
1050             'two' => 'banana',
1051             'three' => 'carrot',
1052         ];
1053         return new PropertyList($data);
1054     }
1055
1056     // Test with the deprecated data structure
1057     protected function simpleListExampleDataUsingAssociativeList()
1058     {
1059         $data = [
1060             'one' => 'apple',
1061             'two' => 'banana',
1062             'three' => 'carrot',
1063         ];
1064         return new AssociativeList($data);
1065     }
1066
1067     /**
1068      * @expectedException \Consolidation\OutputFormatters\Exception\InvalidFormatException
1069      * @expectedExceptionCode 1
1070      * @expectedExceptionMessage The format table cannot be used with the data produced by this command, which was an array.  Valid formats are: csv,json,list,php,print-r,string,tsv,var_export,xml,yaml
1071      */
1072     function testIncompatibleListDataForTableFormatter()
1073     {
1074         $data = $this->simpleListExampleData();
1075         $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'table', $data->getArrayCopy());
1076     }
1077
1078     function testEmptyList()
1079     {
1080         $data = new RowsOfFields([]);
1081
1082         $expected = <<<EOT
1083  --- ---- -----
1084   I   II   III
1085  --- ---- -----
1086 EOT;
1087
1088         // If we provide field labels, then the output will change to reflect that.
1089         $formatterOptionsWithFieldLables = new FormatterOptions();
1090         $formatterOptionsWithFieldLables
1091             ->setFieldLabels(['one' => 'I', 'two' => 'II', 'three' => 'III']);
1092         $this->assertFormattedOutputMatches($expected, 'table', $data, $formatterOptionsWithFieldLables);
1093     }
1094
1095     function testSimpleList()
1096     {
1097
1098         $expected = <<<EOT
1099  ------- --------
1100   One     apple
1101   Two     banana
1102   Three   carrot
1103  ------- --------
1104 EOT;
1105         $data = $this->simpleListExampleDataUsingAssociativeList();
1106
1107         $this->assertFormattedOutputMatches($expected, 'table', $data);
1108
1109         $data = $this->simpleListExampleData();
1110
1111         $this->assertFormattedOutputMatches($expected, 'table', $data);
1112
1113         $expected = <<<EOT
1114  ----- --------
1115   I     apple
1116   II    banana
1117   III   carrot
1118  ----- --------
1119 EOT;
1120         // If we provide field labels, then the output will change to reflect that.
1121         $formatterOptionsWithFieldLables = new FormatterOptions();
1122         $formatterOptionsWithFieldLables
1123             ->setFieldLabels(['one' => 'I', 'two' => 'II', 'three' => 'III']);
1124         $this->assertFormattedOutputMatches($expected, 'table', $data, $formatterOptionsWithFieldLables);
1125
1126         $expectedDrushStyleTable = <<<EOT
1127  One   : apple
1128  Two   : banana
1129  Three : carrot
1130 EOT;
1131
1132         // If we provide field labels, then the output will change to reflect that.
1133         $formatterOptionsWithFieldLables = new FormatterOptions();
1134         $formatterOptionsWithFieldLables
1135             ->setTableStyle('compact')
1136             ->setListDelimiter(':');
1137         $this->assertFormattedOutputMatches($expectedDrushStyleTable, 'table', $data, $formatterOptionsWithFieldLables);
1138
1139
1140         // Adding an extra field that does not exist in the data set should not change the output
1141         $formatterOptionsWithExtraFieldLables = new FormatterOptions();
1142         $formatterOptionsWithExtraFieldLables
1143             ->setFieldLabels(['one' => 'I', 'two' => 'II', 'three' => 'III', 'four' => 'IV']);
1144         $this->assertFormattedOutputMatches($expected, 'table', $data, $formatterOptionsWithExtraFieldLables);
1145
1146         $expectedRotated = <<<EOT
1147  ------- -------- --------
1148   One     Two      Three
1149  ------- -------- --------
1150   apple   banana   carrot
1151  ------- -------- --------
1152 EOT;
1153         $this->assertFormattedOutputMatches($expectedRotated, 'table', $data, new FormatterOptions(['list-orientation' => false]));
1154
1155         $expectedList = <<< EOT
1156 apple
1157 banana
1158 carrot
1159 EOT;
1160         $this->assertFormattedOutputMatches($expectedList, 'list', $data);
1161
1162         $expectedReorderedList = <<< EOT
1163 carrot
1164 apple
1165 EOT;
1166         $options = new FormatterOptions([FormatterOptions::FIELDS => 'three,one']);
1167         $this->assertFormattedOutputMatches($expectedReorderedList, 'list', $data, $options);
1168
1169         $expectedCsv = <<< EOT
1170 One,Two,Three
1171 apple,banana,carrot
1172 EOT;
1173         $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
1174
1175         $expectedCsvNoHeaders = 'apple,banana,carrot';
1176         $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, new FormatterOptions(), ['include-field-labels' => false]);
1177
1178         // Next, configure the formatter options with 'include-field-labels',
1179         // but set --include-field-labels to turn the option back on again.
1180         $options = new FormatterOptions(['include-field-labels' => false]);
1181         $input = new StringInput('test --include-field-labels');
1182         $optionDefinitions = [
1183             new InputArgument('unused', InputArgument::REQUIRED),
1184             new InputOption('include-field-labels', null, InputOption::VALUE_NONE),
1185         ];
1186         $definition = new InputDefinition($optionDefinitions);
1187         $input->bind($definition);
1188         $testValue = $input->getOption('include-field-labels');
1189         $this->assertTrue($testValue);
1190         $hasFieldLabels = $input->hasOption('include-field-labels');
1191         $this->assertTrue($hasFieldLabels);
1192
1193         $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, $options);
1194         $options->setInput($input);
1195         $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data, $options);
1196     }
1197
1198     protected function associativeListWithRenderer()
1199     {
1200         $data = [
1201             'one' => 'apple',
1202             'two' => ['banana', 'plantain'],
1203             'three' => 'carrot',
1204             'four' => ['peaches', 'pumpkin pie'],
1205         ];
1206         $list = new PropertyList($data);
1207
1208         $list->addRendererFunction(
1209             function ($key, $cellData, FormatterOptions $options)
1210             {
1211                 if (is_array($cellData)) {
1212                     return implode(',', $cellData);
1213                 }
1214                 return $cellData;
1215             }
1216         );
1217
1218         return $list;
1219     }
1220
1221     protected function associativeListWithCsvCells()
1222     {
1223         $data = [
1224             'one' => 'apple',
1225             'two' => ['banana', 'plantain'],
1226             'three' => 'carrot',
1227             'four' => ['peaches', 'pumpkin pie'],
1228         ];
1229         return new PropertyListWithCsvCells($data);
1230     }
1231
1232     function testPropertyListWithCsvCells()
1233     {
1234         $this->doPropertyListWithCsvCells($this->associativeListWithRenderer());
1235         $this->doPropertyListWithCsvCells($this->associativeListWithCsvCells());
1236     }
1237
1238     function doPropertyListWithCsvCells($data)
1239     {
1240         $expected = <<<EOT
1241  ------- ---------------------
1242   One     apple
1243   Two     banana,plantain
1244   Three   carrot
1245   Four    peaches,pumpkin pie
1246  ------- ---------------------
1247 EOT;
1248         $this->assertFormattedOutputMatches($expected, 'table', $data);
1249
1250         $expectedList = <<< EOT
1251 apple
1252 banana,plantain
1253 carrot
1254 peaches,pumpkin pie
1255 EOT;
1256         $this->assertFormattedOutputMatches($expectedList, 'list', $data);
1257
1258         $expectedCsv = <<< EOT
1259 One,Two,Three,Four
1260 apple,"banana,plantain",carrot,"peaches,pumpkin pie"
1261 EOT;
1262         $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
1263
1264         $expectedCsvNoHeaders = 'apple,"banana,plantain",carrot,"peaches,pumpkin pie"';
1265         $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, new FormatterOptions(), ['include-field-labels' => false]);
1266
1267         $expectedTsv = <<< EOT
1268 apple\tbanana,plantain\tcarrot\tpeaches,pumpkin pie
1269 EOT;
1270         $this->assertFormattedOutputMatches($expectedTsv, 'tsv', $data);
1271
1272     }
1273
1274     function testSimpleListWithFieldLabels()
1275     {
1276         $data = $this->simpleListExampleData();
1277         $configurationData = new FormatterOptions(
1278             [
1279                 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'],
1280             ]
1281         );
1282
1283         $expected = <<<EOT
1284  ------ --------
1285   Ichi   apple
1286   Ni     banana
1287   San    carrot
1288  ------ --------
1289 EOT;
1290         $this->assertFormattedOutputMatches($expected, 'table', $data, $configurationData);
1291
1292         $expectedWithReorderedFields = <<<EOT
1293  ------ --------
1294   San    carrot
1295   Ichi   apple
1296  ------ --------
1297 EOT;
1298         $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['three', 'one']]);
1299         $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
1300
1301         $expectedJson = <<<EOT
1302 {
1303     "three": "carrot",
1304     "one": "apple"
1305 }
1306 EOT;
1307         $this->assertFormattedOutputMatches($expectedJson, 'json', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
1308     }
1309
1310     function testSimpleXml()
1311     {
1312         $data = [
1313             'name' => 'primary',
1314             'description' => 'The primary colors of the color wheel.',
1315             'colors' =>
1316             [
1317                 'red',
1318                 'yellow',
1319                 'blue',
1320             ],
1321         ];
1322
1323         $expected = <<<EOT
1324 <?xml version="1.0" encoding="UTF-8"?>
1325 <document name="primary">
1326   <description>The primary colors of the color wheel.</description>
1327   <colors>
1328     <color>red</color>
1329     <color>yellow</color>
1330     <color>blue</color>
1331   </colors>
1332 </document>
1333 EOT;
1334
1335         $this->assertFormattedOutputMatches($expected, 'xml', $data);
1336     }
1337
1338     function domDocumentData()
1339     {
1340         $dom = new \DOMDocument('1.0', 'UTF-8');
1341
1342         $document = $dom->createElement('document');
1343         $dom->appendChild($document);
1344
1345         $document->setAttribute('name', 'primary');
1346         $description = $dom->createElement('description');
1347         $document->appendChild($description);
1348         $description->appendChild($dom->createTextNode('The primary colors of the color wheel.'));
1349
1350         $this->domCreateElements($dom, $document, 'color', ['red', 'yellow', 'blue']);
1351
1352         return $dom;
1353     }
1354
1355     function domCreateElements($dom, $element, $name, $data)
1356     {
1357         $container = $dom->createElement("{$name}s");
1358         $element->appendChild($container);
1359         foreach ($data as $value) {
1360             $child = $dom->createElement($name);
1361             $container->appendChild($child);
1362             $child->appendChild($dom->createTextNode($value));
1363         }
1364     }
1365
1366     function complexDomDocumentData()
1367     {
1368         $dom = new \DOMDocument('1.0', 'UTF-8');
1369
1370         $document = $dom->createElement('document');
1371         $dom->appendChild($document);
1372
1373         $document->setAttribute('name', 'widget-collection');
1374         $description = $dom->createElement('description');
1375         $document->appendChild($description);
1376         $description->appendChild($dom->createTextNode('A couple of widgets.'));
1377
1378         $widgets = $dom->createElement('widgets');
1379         $document->appendChild($widgets);
1380
1381         $widget = $dom->createElement('widget');
1382         $widgets->appendChild($widget);
1383         $widget->setAttribute('name', 'usual');
1384         $this->domCreateElements($dom, $widget, 'color', ['red', 'yellow', 'blue']);
1385         $this->domCreateElements($dom, $widget, 'shape', ['square', 'circle', 'triangle']);
1386
1387         $widget = $dom->createElement('widget');
1388         $widgets->appendChild($widget);
1389         $widget->setAttribute('name', 'unusual');
1390         $this->domCreateElements($dom, $widget, 'color', ['muave', 'puce', 'umber']);
1391         $this->domCreateElements($dom, $widget, 'shape', ['elipse', 'rhombus', 'trapazoid']);
1392
1393         return $dom;
1394     }
1395
1396     function domDocumentTestValues()
1397     {
1398
1399         $expectedXml = <<<EOT
1400 <?xml version="1.0" encoding="UTF-8"?>
1401 <document name="primary">
1402   <description>The primary colors of the color wheel.</description>
1403   <colors>
1404     <color>red</color>
1405     <color>yellow</color>
1406     <color>blue</color>
1407   </colors>
1408 </document>
1409 EOT;
1410
1411         $expectedJson = <<<EOT
1412 {
1413     "name": "primary",
1414     "description": "The primary colors of the color wheel.",
1415     "colors": [
1416         "red",
1417         "yellow",
1418         "blue"
1419     ]
1420 }
1421 EOT;
1422
1423         $expectedComplexXml = <<<EOT
1424 <?xml version="1.0" encoding="UTF-8"?>
1425 <document name="widget-collection">
1426   <description>A couple of widgets.</description>
1427   <widgets>
1428     <widget name="usual">
1429       <colors>
1430         <color>red</color>
1431         <color>yellow</color>
1432         <color>blue</color>
1433       </colors>
1434       <shapes>
1435         <shape>square</shape>
1436         <shape>circle</shape>
1437         <shape>triangle</shape>
1438       </shapes>
1439     </widget>
1440     <widget name="unusual">
1441       <colors>
1442         <color>muave</color>
1443         <color>puce</color>
1444         <color>umber</color>
1445       </colors>
1446       <shapes>
1447         <shape>elipse</shape>
1448         <shape>rhombus</shape>
1449         <shape>trapazoid</shape>
1450       </shapes>
1451     </widget>
1452   </widgets>
1453 </document>
1454 EOT;
1455
1456         $expectedComplexJson = <<<EOT
1457 {
1458     "name": "widget-collection",
1459     "description": "A couple of widgets.",
1460     "widgets": {
1461         "usual": {
1462             "name": "usual",
1463             "colors": [
1464                 "red",
1465                 "yellow",
1466                 "blue"
1467             ],
1468             "shapes": [
1469                 "square",
1470                 "circle",
1471                 "triangle"
1472             ]
1473         },
1474         "unusual": {
1475             "name": "unusual",
1476             "colors": [
1477                 "muave",
1478                 "puce",
1479                 "umber"
1480             ],
1481             "shapes": [
1482                 "elipse",
1483                 "rhombus",
1484                 "trapazoid"
1485             ]
1486         }
1487     }
1488 }
1489 EOT;
1490
1491         return [
1492             [
1493                 $this->domDocumentData(),
1494                 $expectedXml,
1495                 $expectedJson,
1496             ],
1497             [
1498                 $this->complexDomDocumentData(),
1499                 $expectedComplexXml,
1500                 $expectedComplexJson,
1501             ],
1502         ];
1503     }
1504
1505     /**
1506      *  @dataProvider domDocumentTestValues
1507      */
1508     function testDomData($data, $expectedXml, $expectedJson)
1509     {
1510         $this->assertFormattedOutputMatches($expectedXml, 'xml', $data);
1511         $this->assertFormattedOutputMatches($expectedJson, 'json', $data);
1512
1513         // Check to see if we get the same xml data if we convert from
1514         // DOM -> array -> DOM.
1515         $expectedJsonAsArray = (array)json_decode($expectedJson);
1516         $this->assertFormattedOutputMatches($expectedXml, 'xml', $expectedJsonAsArray);
1517     }
1518
1519     /**
1520      * @expectedException \Exception
1521      * @expectedExceptionCode 1
1522      * @expectedExceptionMessage Data provided to Consolidation\OutputFormatters\Formatters\XmlFormatter must be either an instance of DOMDocument or an array. Instead, a string was provided.
1523      */
1524     function testDataTypeForXmlFormatter()
1525     {
1526         $this->assertFormattedOutputMatches('Will fail, not return', 'xml', 'Strings cannot be converted to XML');
1527     }
1528 }