2 namespace Consolidation\OutputFormatters;
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 Consolidation\OutputFormatters\StructuredData\ListDataFromKeys;
11 use Symfony\Component\Console\Output\BufferedOutput;
12 use Symfony\Component\Console\Output\OutputInterface;
13 use Symfony\Component\Console\Input\InputInterface;
14 use Symfony\Component\Console\Input\StringInput;
15 use Symfony\Component\Console\Input\InputOption;
16 use Symfony\Component\Console\Input\InputArgument;
17 use Symfony\Component\Console\Input\InputDefinition;
19 class FormattersTests extends \PHPUnit_Framework_TestCase
21 protected $formatterManager;
24 $this->formatterManager = new FormatterManager();
27 function assertFormattedOutputMatches($expected, $format, $data, FormatterOptions $options = null, $userOptions = []) {
29 $options = new FormatterOptions();
31 $options->setOptions($userOptions);
32 $output = new BufferedOutput();
33 $this->formatterManager->write($output, $format, $data, $options);
34 $actual = preg_replace('#[ \t]*$#sm', '', $output->fetch());
35 $this->assertEquals(rtrim($expected), rtrim($actual));
38 function testSimpleYaml()
51 $this->assertFormattedOutputMatches($expected, 'yaml', $data);
58 $this->assertFormattedOutputMatches($expected, 'list', $data);
60 $data = new ListDataFromKeys($data);
67 $this->assertFormattedOutputMatches($expected, 'yaml', $data);
75 $this->assertFormattedOutputMatches($expected, 'list', $data);
78 function testNestedYaml()
82 'i' => ['a', 'b', 'c'],
85 'ii' => ['q', 'r', 's'],
88 'iii' => ['t', 'u', 'v'],
110 $this->assertFormattedOutputMatches($expected, 'yaml', $data);
113 function testSimpleJson()
129 $this->assertFormattedOutputMatches($expected, 'json', $data);
132 function testSerializeFormat()
140 $expected = 'a:3:{s:3:"one";s:1:"a";s:3:"two";s:1:"b";s:5:"three";s:1:"c";}';
142 $this->assertFormattedOutputMatches($expected, 'php', $data);
145 function testNestedJson()
149 'i' => ['a', 'b', 'c'],
152 'ii' => ['q', 'r', 's'],
155 'iii' => ['t', 'u', 'v'],
185 $this->assertFormattedOutputMatches($expected, 'json', $data);
188 function testSimplePrintR()
205 $this->assertFormattedOutputMatches($expected, 'print-r', $data);
208 function testNestedPrintR()
212 'i' => ['a', 'b', 'c'],
215 'ii' => ['q', 'r', 's'],
218 'iii' => ['t', 'u', 'v'],
261 $this->assertFormattedOutputMatches($expected, 'print-r', $data);
264 function testSimpleVarExport()
280 $this->assertFormattedOutputMatches($expected, 'var_export', $data);
283 function testNestedVarExport()
287 'i' => ['a', 'b', 'c'],
290 'ii' => ['q', 'r', 's'],
293 'iii' => ['t', 'u', 'v'],
329 $this->assertFormattedOutputMatches($expected, 'var_export', $data);
346 $this->assertFormattedOutputMatches($expected, 'list', $data);
350 * @expectedException \Consolidation\OutputFormatters\Exception\UnknownFormatException
351 * @expectedExceptionCode 1
352 * @expectedExceptionMessage The requested format, 'no-such-format', is not available.
354 function testBadFormat()
356 $this->assertFormattedOutputMatches('Will fail, not return', 'no-such-format', ['a' => 'b']);
360 * @expectedException \Consolidation\OutputFormatters\Exception\IncompatibleDataException
361 * @expectedExceptionCode 1
362 * @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.
364 function testBadDataTypeForCsv()
366 $this->assertFormattedOutputMatches('Will fail, not return', 'csv', 'String cannot be converted to csv');
370 * @expectedException \Consolidation\OutputFormatters\Exception\IncompatibleDataException
371 * @expectedExceptionCode 1
372 * @expectedExceptionMessage Data provided to Consolidation\OutputFormatters\Formatters\JsonFormatter must be an array. Instead, a string was provided.
374 function testBadDataTypeForJson()
376 $this->assertFormattedOutputMatches('Will fail, not return', 'json', 'String cannot be converted to json');
379 function testNoFormatterSelected()
383 $this->assertFormattedOutputMatches($expected, '', $data);
386 function testRenderTableAsString()
388 $data = new RowsOfFields([['f1' => 'A', 'f2' => 'B', 'f3' => 'C'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]);
389 $expected = "A\tB\tC\nx\ty\tz";
391 $this->assertFormattedOutputMatches($expected, 'string', $data);
394 function testRenderTableAsStringWithSingleField()
396 $data = new RowsOfFields([['f1' => 'q', 'f2' => 'r', 'f3' => 's'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]);
399 $options = new FormatterOptions([FormatterOptions::DEFAULT_STRING_FIELD => 'f1']);
401 $this->assertFormattedOutputMatches($expected, 'string', $data, $options);
404 function testRenderTableAsStringWithSingleFieldAndUserSelectedField()
406 $data = new RowsOfFields([['f1' => 'q', 'f2' => 'r', 'f3' => 's'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]);
409 $options = new FormatterOptions([FormatterOptions::DEFAULT_STRING_FIELD => 'f1']);
411 $this->assertFormattedOutputMatches($expected, 'string', $data, $options, ['fields' => 'f2']);
414 function testSimpleCsv()
416 $data = ['a', 'b', 'c'];
419 $this->assertFormattedOutputMatches($expected, 'csv', $data);
422 function testLinesOfCsv()
424 $data = [['a', 'b', 'c'], ['x', 'y', 'z']];
425 $expected = "a,b,c\nx,y,z";
427 $this->assertFormattedOutputMatches($expected, 'csv', $data);
430 function testCsvWithEscapedValues()
432 $data = ["Red apple", "Yellow lemon"];
433 $expected = '"Red apple","Yellow lemon"';
435 $this->assertFormattedOutputMatches($expected, 'csv', $data);
438 function testCsvWithEmbeddedSingleQuote()
440 $data = ["John's book", "Mary's laptop"];
442 "John's book","Mary's laptop"
445 $this->assertFormattedOutputMatches($expected, 'csv', $data);
448 function testCsvWithEmbeddedDoubleQuote()
450 $data = ['The "best" solution'];
452 "The ""best"" solution"
455 $this->assertFormattedOutputMatches($expected, 'csv', $data);
458 function testCsvBothKindsOfQuotes()
460 $data = ["John's \"new\" book", "Mary's \"modified\" laptop"];
462 "John's ""new"" book","Mary's ""modified"" laptop"
465 $this->assertFormattedOutputMatches($expected, 'csv', $data);
468 function testSimpleTsv()
470 $data = ['a', 'b', 'c'];
471 $expected = "a\tb\tc";
473 $this->assertFormattedOutputMatches($expected, 'tsv', $data);
476 function testLinesOfTsv()
478 $data = [['a', 'b', 'c'], ['x', 'y', 'z']];
479 $expected = "a\tb\tc\nx\ty\tz";
481 $this->assertFormattedOutputMatches($expected, 'tsv', $data);
484 function testTsvBothKindsOfQuotes()
486 $data = ["John's \"new\" book", "Mary's \"modified\" laptop"];
487 $expected = "John's \"new\" book\tMary's \"modified\" laptop";
489 $this->assertFormattedOutputMatches($expected, 'tsv', $data);
492 function testTsvWithEscapedValues()
494 $data = ["Red apple", "Yellow lemon", "Embedded\ttab"];
495 $expected = "Red apple\tYellow lemon\tEmbedded\\ttab";
497 $this->assertFormattedOutputMatches($expected, 'tsv', $data);
500 protected function missingCellTableExampleData()
513 return new RowsOfFields($data);
516 function testTableWithMissingCell()
518 $data = $this->missingCellTableExampleData();
528 $this->assertFormattedOutputMatches($expected, 'table', $data);
530 $expectedCsv = <<<EOT
535 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
537 $expectedTsv = <<<EOT
541 $this->assertFormattedOutputMatches($expectedTsv, 'tsv', $data);
543 $expectedTsvWithHeaders = <<<EOT
548 $this->assertFormattedOutputMatches($expectedTsvWithHeaders, 'tsv', $data, new FormatterOptions(), ['include-field-labels' => true]);
551 function testTableWithWordWrapping()
553 $options = new FormatterOptions();
557 'first' => 'This is a really long cell that contains a lot of data. When it is rendered, it should be wrapped across multiple lines.',
558 '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.',
561 $data = new RowsOfFields($data);
564 ------------------ --------------------
566 ------------------ --------------------
567 This is a really This is the second
568 long cell that column of the same
569 contains a lot table. It is also
570 of data. When it very long, and
571 is rendered, it should be wrapped
572 should be across multiple
573 wrapped across lines, just like
574 multiple lines. the first column.
575 ------------------ --------------------
577 $options->setWidth(42);
578 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
581 ----------------------------------- ---------------------------------------
583 ----------------------------------- ---------------------------------------
584 This is a really long cell that This is the second column of the same
585 contains a lot of data. When it table. It is also very long, and
586 is rendered, it should be wrapped should be wrapped across multiple
587 across multiple lines. lines, just like the first column.
588 ----------------------------------- ---------------------------------------
590 $options->setWidth(78);
591 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
594 function testWrappingLotsOfColumns()
596 $options = new FormatterOptions();
600 'id' => '4d87b545-b4c3-4ece-9908-20c5c5e67e81',
601 'name' => '123456781234567812345678123456781234567812345678',
602 'service_level' => 'business',
603 'framework' => 'wordpress-network',
604 'owner' => '8558a08d-8059-45f6-9c4b-908299a025ee',
605 'created' => '2017-05-24 19:28:45',
606 'memberships' => 'b3a42ba5-755d-42ca-9109-21bde32809d0: Team,9bfaaf50-ece3-4460-acb8-dc1b8dd536e8: pantheon-engineering-canary-sites',
610 'id' => '3d87b545-b4c3-4ece-9908-20c5c5e67e80',
611 'name' => 'build-tools-136',
612 'service_level' => 'free',
613 'framework' => 'drupal8',
614 'owner' => '7558a08d-8059-45f6-9c4b-908299a025ef',
615 'created' => '2017-05-24 19:28:45',
616 'memberships' => '5ae1fa30-8cc4-4894-8ca9-d50628dcba17: ci-for-drupal-8-composer',
620 $data = new RowsOfFields($data);
623 ------------- ---------------- --------------- ----------- ------------- --------- ------------------------------------ --------
624 Id Name Service_level Framework Owner Created Memberships Frozen
625 ------------- ---------------- --------------- ----------- ------------- --------- ------------------------------------ --------
626 4d87b545-b4 12345678123456 business wordp 8558a08d-80 2017-0 b3a42ba5-755d-42ca-9109-21bde32809 false
627 c3-4ece-990 78123456781234 ress- 59-45f6-9c4 5-24 d0:
628 8-20c5c5e67 56781234567812 netwo b-908299a02 19:28: Team,9bfaaf50-ece3-4460-acb8-dc1b8
629 e81 345678 rk 5ee 45 dd536e8:
630 pantheon-engineering-canary-sites
631 3d87b545-b4 build-tools-13 free drupa 7558a08d-80 2017-0 5ae1fa30-8cc4-4894-8ca9-d50628dcba false
632 c3-4ece-990 6 l8 59-45f6-9c4 5-24 17: ci-for-drupal-8-composer
633 8-20c5c5e67 b-908299a02 19:28:
635 ------------- ---------------- --------------- ----------- ------------- --------- ------------------------------------ --------
638 $options->setWidth(125);
639 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
642 function testTableWithWordWrapping2()
644 $options = new FormatterOptions();
650 'description' => 'Life, the Universe and Everything.',
655 'description' => 'Why is six afraid of seven?',
658 $data = new RowsOfFields($data);
660 ---- ----- -----------------------------
662 ---- ----- -----------------------------
663 42 321 Life, the Universe and
665 13 789 Why is six afraid of seven?
666 ---- ----- -----------------------------
668 $options->setWidth(42);
669 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
672 function testTableWithWordWrapping3()
674 $options = new FormatterOptions();
680 'description' => 'Rex is a very good dog, Brett. He likes kibble, and has four legs.',
682 $data = new PropertyList($data);
685 ------------- -------------------------
690 Description Rex is a very good dog,
691 Brett. He likes kibble,
693 ------------- -------------------------
695 $options->setWidth(42);
696 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
699 function testTableWithWordWrapping4()
701 $options = new FormatterOptions();
704 'name' => ['label' => 'Name', 'sep' => ':', 'value' => 'Rex', ],
705 'species' => ['label' => 'Species', 'sep' => ':', 'value' => 'dog', ],
706 'food' => ['label' => 'Food', 'sep' => ':', 'value' => 'kibble', ],
707 'legs' => ['label' => 'Legs', 'sep' => ':', 'value' => '4', ],
708 'description' => ['label' => 'Description', 'sep' => ':', 'value' => 'Rex is a very good dog, Brett. He likes kibble, and has four legs.', ],
710 $data = new RowsOfFields($data);
712 ------------- ----- -----------------------------------------------------
714 ------------- ----- -----------------------------------------------------
719 Description : Rex is a very good dog, Brett. He likes kibble, and
721 ------------- ----- -----------------------------------------------------
723 $options->setWidth(78);
724 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
727 function testTableWithWordWrapping5()
729 $options = new FormatterOptions();
731 'name' => ['Name', ':', 'Rex', ],
732 'species' => ['Species', ':', 'dog', ],
733 'food' => ['Food', ':', 'kibble', ],
734 'legs' => ['Legs', ':', '4', ],
735 'description' => ['Description', ':', 'Rex is a very good dog, Brett. He likes kibble, and has four legs.', ],
737 $data = new RowsOfFields($data);
743 Description : Rex is a very good dog, Brett. He likes kibble, and has
746 $options->setWidth(78);
747 $options->setIncludeFieldLables(false);
748 $options->setTableStyle('compact');
749 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
752 protected function simpleTableExampleData()
768 return new RowsOfFields($data);
772 * @expectedException \Consolidation\OutputFormatters\Exception\InvalidFormatException
773 * @expectedExceptionCode 1
774 * @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
776 function testIncompatibleDataForTableFormatter()
778 $data = $this->simpleTableExampleData()->getArrayCopy();
779 $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'table', $data);
783 * @expectedException \Consolidation\OutputFormatters\Exception\InvalidFormatException
784 * @expectedExceptionCode 1
785 * @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
787 function testIncompatibleDataForSectionsFormatter()
789 $data = $this->simpleTableExampleData()->getArrayCopy();
790 $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'sections', $data);
793 function testSimpleTable()
795 $data = $this->simpleTableExampleData();
805 $this->assertFormattedOutputMatches($expected, 'table', $data);
807 $expectedBorderless = <<<EOT
815 $this->assertFormattedOutputMatches($expectedBorderless, 'table', $data, new FormatterOptions(['table-style' => 'borderless']));
817 $expectedJson = <<<EOT
831 $this->assertFormattedOutputMatches($expectedJson, 'json', $data);
833 $expectedCsv = <<<EOT
838 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
840 $expectedList = <<<EOT
844 $this->assertFormattedOutputMatches($expectedList, 'list', $data);
847 protected function tableWithAlternativesExampleData()
853 'two' => ['this', 'that', 'the other thing'],
860 'three' => ['apples', 'oranges'],
863 return new RowsOfFieldsWithAlternatives($data);
866 function testTableWithAlternatives()
868 $data = $this->tableWithAlternativesExampleData();
871 ----- --------------------------- ----------------
873 ----- --------------------------- ----------------
874 a this|that|the other thing c
876 ----- --------------------------- ----------------
878 $this->assertFormattedOutputMatches($expected, 'table', $data);
880 $expectedBorderless = <<<EOT
881 ===== =========================== ================
883 ===== =========================== ================
884 a this|that|the other thing c
886 ===== =========================== ================
888 $this->assertFormattedOutputMatches($expectedBorderless, 'table', $data, new FormatterOptions(['table-style' => 'borderless']));
890 $expectedJson = <<<EOT
911 $this->assertFormattedOutputMatches($expectedJson, 'json', $data);
913 $expectedCsv = <<<EOT
915 a,"this|that|the other thing",c
918 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
920 $expectedList = <<<EOT
924 $this->assertFormattedOutputMatches($expectedList, 'list', $data);
927 function testSimpleTableWithFieldLabels()
929 $data = $this->simpleTableExampleData();
930 $configurationData = new FormatterOptions(
932 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'],
933 'row-labels' => ['id-123' => 'Walrus', 'id-456' => 'Carpenter'],
936 $configurationDataAnnotationFormat = new FormatterOptions(
938 'field-labels' => "one: Uno\ntwo: Dos\nthree: Tres",
950 $this->assertFormattedOutputMatches($expected, 'table', $data, $configurationData);
952 $expectedSidewaysTable = <<<EOT
959 $this->assertFormattedOutputMatches($expectedSidewaysTable, 'table', $data, $configurationData->override(['list-orientation' => true]));
961 $expectedAnnotationFormatConfigData = <<<EOT
969 $this->assertFormattedOutputMatches($expectedAnnotationFormatConfigData, 'table', $data, $configurationDataAnnotationFormat);
971 $expectedWithNoFields = <<<EOT
977 $this->assertFormattedOutputMatches($expectedWithNoFields, 'table', $data, $configurationData, ['include-field-labels' => false]);
979 $expectedWithReorderedFields = <<<EOT
987 $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['three', 'one']]);
988 $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
989 $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => 'San,Ichi']);
991 $expectedWithRegexField = <<<EOT
999 $this->assertFormattedOutputMatches($expectedWithRegexField, 'table', $data, $configurationData, ['fields' => ['/e$/']]);
1000 $this->assertFormattedOutputMatches($expectedWithRegexField, 'table', $data, $configurationData, ['fields' => ['*e']]);
1001 $this->assertFormattedOutputMatches($expectedWithRegexField, 'table', $data, $configurationData, ['default-fields' => ['*e']]);
1003 $expectedSections = <<<EOT
1015 $this->assertFormattedOutputMatches($expectedSections, 'sections', $data, $configurationData);
1017 $expectedJson = <<<EOT
1029 $this->assertFormattedOutputMatches($expectedJson, 'json', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
1031 $expectedSingleField = <<<EOT
1039 $this->assertFormattedOutputMatches($expectedSingleField, 'table', $data, $configurationData, ['field' => 'San']);
1041 $expectedEmptyColumn = <<<EOT
1047 $this->assertFormattedOutputMatches($expectedEmptyColumn, 'table', new RowsOfFields([]), $configurationData, ['field' => 'San']);
1049 $this->assertFormattedOutputMatches('', '', new RowsOfFields([]), $configurationData, ['field' => 'San']);
1050 $this->assertFormattedOutputMatches('[]', 'json', new RowsOfFields([]), $configurationData, ['field' => 'San']);
1054 * @expectedException \Consolidation\OutputFormatters\Exception\UnknownFieldException
1055 * @expectedExceptionCode 1
1056 * @expectedExceptionMessage The requested field, 'Shi', is not defined.
1058 function testNoSuchFieldException()
1060 $configurationData = new FormatterOptions(
1062 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'],
1063 'row-labels' => ['id-123' => 'Walrus', 'id-456' => 'Carpenter'],
1066 $data = $this->simpleTableExampleData();
1067 $this->assertFormattedOutputMatches('Will throw before comparing', 'table', $data, $configurationData, ['field' => 'Shi']);
1070 protected function simpleListExampleData()
1075 'three' => 'carrot',
1077 return new PropertyList($data);
1080 // Test with the deprecated data structure
1081 protected function simpleListExampleDataUsingAssociativeList()
1086 'three' => 'carrot',
1088 return new AssociativeList($data);
1092 * @expectedException \Consolidation\OutputFormatters\Exception\InvalidFormatException
1093 * @expectedExceptionCode 1
1094 * @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
1096 function testIncompatibleListDataForTableFormatter()
1098 $data = $this->simpleListExampleData();
1099 $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'table', $data->getArrayCopy());
1102 function testEmptyList()
1104 $data = new RowsOfFields([]);
1112 // If we provide field labels, then the output will change to reflect that.
1113 $formatterOptionsWithFieldLables = new FormatterOptions();
1114 $formatterOptionsWithFieldLables
1115 ->setFieldLabels(['one' => 'I', 'two' => 'II', 'three' => 'III']);
1116 $this->assertFormattedOutputMatches($expected, 'table', $data, $formatterOptionsWithFieldLables);
1119 function testSimpleList()
1129 $data = $this->simpleListExampleDataUsingAssociativeList();
1131 $this->assertFormattedOutputMatches($expected, 'table', $data);
1133 $data = $this->simpleListExampleData();
1135 $this->assertFormattedOutputMatches($expected, 'table', $data);
1144 // If we provide field labels, then the output will change to reflect that.
1145 $formatterOptionsWithFieldLables = new FormatterOptions();
1146 $formatterOptionsWithFieldLables
1147 ->setFieldLabels(['one' => 'I', 'two' => 'II', 'three' => 'III']);
1148 $this->assertFormattedOutputMatches($expected, 'table', $data, $formatterOptionsWithFieldLables);
1150 $expectedDrushStyleTable = <<<EOT
1156 // If we provide field labels, then the output will change to reflect that.
1157 $formatterOptionsWithFieldLables = new FormatterOptions();
1158 $formatterOptionsWithFieldLables
1159 ->setTableStyle('compact')
1160 ->setListDelimiter(':');
1161 $this->assertFormattedOutputMatches($expectedDrushStyleTable, 'table', $data, $formatterOptionsWithFieldLables);
1164 // Adding an extra field that does not exist in the data set should not change the output
1165 $formatterOptionsWithExtraFieldLables = new FormatterOptions();
1166 $formatterOptionsWithExtraFieldLables
1167 ->setFieldLabels(['one' => 'I', 'two' => 'II', 'three' => 'III', 'four' => 'IV']);
1168 $this->assertFormattedOutputMatches($expected, 'table', $data, $formatterOptionsWithExtraFieldLables);
1170 $expectedRotated = <<<EOT
1171 ------- -------- --------
1173 ------- -------- --------
1175 ------- -------- --------
1177 $this->assertFormattedOutputMatches($expectedRotated, 'table', $data, new FormatterOptions(['list-orientation' => false]));
1179 $expectedList = <<< EOT
1184 $this->assertFormattedOutputMatches($expectedList, 'list', $data);
1186 $expectedReorderedList = <<< EOT
1190 $options = new FormatterOptions([FormatterOptions::FIELDS => 'three,one']);
1191 $this->assertFormattedOutputMatches($expectedReorderedList, 'list', $data, $options);
1193 $expectedCsv = <<< EOT
1197 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
1199 $expectedCsvNoHeaders = 'apple,banana,carrot';
1200 $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, new FormatterOptions(), ['include-field-labels' => false]);
1202 // Next, configure the formatter options with 'include-field-labels',
1203 // but set --include-field-labels to turn the option back on again.
1204 $options = new FormatterOptions(['include-field-labels' => false]);
1205 $input = new StringInput('test --include-field-labels');
1206 $optionDefinitions = [
1207 new InputArgument('unused', InputArgument::REQUIRED),
1208 new InputOption('include-field-labels', null, InputOption::VALUE_NONE),
1210 $definition = new InputDefinition($optionDefinitions);
1211 $input->bind($definition);
1212 $testValue = $input->getOption('include-field-labels');
1213 $this->assertTrue($testValue);
1214 $hasFieldLabels = $input->hasOption('include-field-labels');
1215 $this->assertTrue($hasFieldLabels);
1217 $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, $options);
1218 $options->setInput($input);
1219 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data, $options);
1222 protected function associativeListWithRenderer()
1226 'two' => ['banana', 'plantain'],
1227 'three' => 'carrot',
1228 'four' => ['peaches', 'pumpkin pie'],
1230 $list = new PropertyList($data);
1232 $list->addRendererFunction(
1233 function ($key, $cellData, FormatterOptions $options)
1235 if (is_array($cellData)) {
1236 return implode(',', $cellData);
1245 protected function associativeListWithCsvCells()
1249 'two' => ['banana', 'plantain'],
1250 'three' => 'carrot',
1251 'four' => ['peaches', 'pumpkin pie'],
1253 return new PropertyListWithCsvCells($data);
1256 function testPropertyListWithCsvCells()
1258 $this->doPropertyListWithCsvCells($this->associativeListWithRenderer());
1259 $this->doPropertyListWithCsvCells($this->associativeListWithCsvCells());
1262 function doPropertyListWithCsvCells($data)
1265 ------- ---------------------
1269 Four peaches,pumpkin pie
1270 ------- ---------------------
1272 $this->assertFormattedOutputMatches($expected, 'table', $data);
1274 $expectedList = <<< EOT
1280 $this->assertFormattedOutputMatches($expectedList, 'list', $data);
1282 $expectedCsv = <<< EOT
1284 apple,"banana,plantain",carrot,"peaches,pumpkin pie"
1286 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
1288 $expectedCsvNoHeaders = 'apple,"banana,plantain",carrot,"peaches,pumpkin pie"';
1289 $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, new FormatterOptions(), ['include-field-labels' => false]);
1291 $expectedTsv = <<< EOT
1292 apple\tbanana,plantain\tcarrot\tpeaches,pumpkin pie
1294 $this->assertFormattedOutputMatches($expectedTsv, 'tsv', $data);
1298 function testSimpleListWithFieldLabels()
1300 $data = $this->simpleListExampleData();
1301 $configurationData = new FormatterOptions(
1303 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'],
1314 $this->assertFormattedOutputMatches($expected, 'table', $data, $configurationData);
1316 $expectedWithReorderedFields = <<<EOT
1322 $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['three', 'one']]);
1323 $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
1325 $expectedJson = <<<EOT
1331 $this->assertFormattedOutputMatches($expectedJson, 'json', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
1334 function testSimpleXml()
1337 'name' => 'primary',
1338 'description' => 'The primary colors of the color wheel.',
1348 <?xml version="1.0" encoding="UTF-8"?>
1349 <document name="primary">
1350 <description>The primary colors of the color wheel.</description>
1353 <color>yellow</color>
1359 $this->assertFormattedOutputMatches($expected, 'xml', $data);
1362 function domDocumentData()
1364 $dom = new \DOMDocument('1.0', 'UTF-8');
1366 $document = $dom->createElement('document');
1367 $dom->appendChild($document);
1369 $document->setAttribute('name', 'primary');
1370 $description = $dom->createElement('description');
1371 $document->appendChild($description);
1372 $description->appendChild($dom->createTextNode('The primary colors of the color wheel.'));
1374 $this->domCreateElements($dom, $document, 'color', ['red', 'yellow', 'blue']);
1379 function domCreateElements($dom, $element, $name, $data)
1381 $container = $dom->createElement("{$name}s");
1382 $element->appendChild($container);
1383 foreach ($data as $value) {
1384 $child = $dom->createElement($name);
1385 $container->appendChild($child);
1386 $child->appendChild($dom->createTextNode($value));
1390 function complexDomDocumentData()
1392 $dom = new \DOMDocument('1.0', 'UTF-8');
1394 $document = $dom->createElement('document');
1395 $dom->appendChild($document);
1397 $document->setAttribute('name', 'widget-collection');
1398 $description = $dom->createElement('description');
1399 $document->appendChild($description);
1400 $description->appendChild($dom->createTextNode('A couple of widgets.'));
1402 $widgets = $dom->createElement('widgets');
1403 $document->appendChild($widgets);
1405 $widget = $dom->createElement('widget');
1406 $widgets->appendChild($widget);
1407 $widget->setAttribute('name', 'usual');
1408 $this->domCreateElements($dom, $widget, 'color', ['red', 'yellow', 'blue']);
1409 $this->domCreateElements($dom, $widget, 'shape', ['square', 'circle', 'triangle']);
1411 $widget = $dom->createElement('widget');
1412 $widgets->appendChild($widget);
1413 $widget->setAttribute('name', 'unusual');
1414 $this->domCreateElements($dom, $widget, 'color', ['muave', 'puce', 'umber']);
1415 $this->domCreateElements($dom, $widget, 'shape', ['elipse', 'rhombus', 'trapazoid']);
1420 function domDocumentTestValues()
1423 $expectedXml = <<<EOT
1424 <?xml version="1.0" encoding="UTF-8"?>
1425 <document name="primary">
1426 <description>The primary colors of the color wheel.</description>
1429 <color>yellow</color>
1435 $expectedJson = <<<EOT
1438 "description": "The primary colors of the color wheel.",
1447 $expectedComplexXml = <<<EOT
1448 <?xml version="1.0" encoding="UTF-8"?>
1449 <document name="widget-collection">
1450 <description>A couple of widgets.</description>
1452 <widget name="usual">
1455 <color>yellow</color>
1459 <shape>square</shape>
1460 <shape>circle</shape>
1461 <shape>triangle</shape>
1464 <widget name="unusual">
1466 <color>muave</color>
1468 <color>umber</color>
1471 <shape>elipse</shape>
1472 <shape>rhombus</shape>
1473 <shape>trapazoid</shape>
1480 $expectedComplexJson = <<<EOT
1482 "name": "widget-collection",
1483 "description": "A couple of widgets.",
1517 $this->domDocumentData(),
1522 $this->complexDomDocumentData(),
1523 $expectedComplexXml,
1524 $expectedComplexJson,
1530 * @dataProvider domDocumentTestValues
1532 function testDomData($data, $expectedXml, $expectedJson)
1534 $this->assertFormattedOutputMatches($expectedXml, 'xml', $data);
1535 $this->assertFormattedOutputMatches($expectedJson, 'json', $data);
1537 // Check to see if we get the same xml data if we convert from
1538 // DOM -> array -> DOM.
1539 $expectedJsonAsArray = (array)json_decode($expectedJson);
1540 $this->assertFormattedOutputMatches($expectedXml, 'xml', $expectedJsonAsArray);
1544 * @expectedException \Exception
1545 * @expectedExceptionCode 1
1546 * @expectedExceptionMessage Data provided to Consolidation\OutputFormatters\Formatters\XmlFormatter must be either an instance of DOMDocument or an array. Instead, a string was provided.
1548 function testDataTypeForXmlFormatter()
1550 $this->assertFormattedOutputMatches('Will fail, not return', 'xml', 'Strings cannot be converted to XML');