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 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;
18 class FormattersTests extends \PHPUnit_Framework_TestCase
20 protected $formatterManager;
23 $this->formatterManager = new FormatterManager();
26 function assertFormattedOutputMatches($expected, $format, $data, FormatterOptions $options = null, $userOptions = []) {
28 $options = new FormatterOptions();
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));
37 function testSimpleYaml()
51 $this->assertFormattedOutputMatches($expected, 'yaml', $data);
54 function testNestedYaml()
58 'i' => ['a', 'b', 'c'],
61 'ii' => ['q', 'r', 's'],
64 'iii' => ['t', 'u', 'v'],
86 $this->assertFormattedOutputMatches($expected, 'yaml', $data);
89 function testSimpleJson()
105 $this->assertFormattedOutputMatches($expected, 'json', $data);
108 function testSerializeFormat()
116 $expected = 'a:3:{s:3:"one";s:1:"a";s:3:"two";s:1:"b";s:5:"three";s:1:"c";}';
118 $this->assertFormattedOutputMatches($expected, 'php', $data);
121 function testNestedJson()
125 'i' => ['a', 'b', 'c'],
128 'ii' => ['q', 'r', 's'],
131 'iii' => ['t', 'u', 'v'],
161 $this->assertFormattedOutputMatches($expected, 'json', $data);
164 function testSimplePrintR()
181 $this->assertFormattedOutputMatches($expected, 'print-r', $data);
184 function testNestedPrintR()
188 'i' => ['a', 'b', 'c'],
191 'ii' => ['q', 'r', 's'],
194 'iii' => ['t', 'u', 'v'],
237 $this->assertFormattedOutputMatches($expected, 'print-r', $data);
240 function testSimpleVarExport()
256 $this->assertFormattedOutputMatches($expected, 'var_export', $data);
259 function testNestedVarExport()
263 'i' => ['a', 'b', 'c'],
266 'ii' => ['q', 'r', 's'],
269 'iii' => ['t', 'u', 'v'],
305 $this->assertFormattedOutputMatches($expected, 'var_export', $data);
322 $this->assertFormattedOutputMatches($expected, 'list', $data);
326 * @expectedException \Consolidation\OutputFormatters\Exception\UnknownFormatException
327 * @expectedExceptionCode 1
328 * @expectedExceptionMessage The requested format, 'no-such-format', is not available.
330 function testBadFormat()
332 $this->assertFormattedOutputMatches('Will fail, not return', 'no-such-format', ['a' => 'b']);
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.
340 function testBadDataTypeForCsv()
342 $this->assertFormattedOutputMatches('Will fail, not return', 'csv', 'String cannot be converted to csv');
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.
350 function testBadDataTypeForJson()
352 $this->assertFormattedOutputMatches('Will fail, not return', 'json', 'String cannot be converted to json');
355 function testNoFormatterSelected()
359 $this->assertFormattedOutputMatches($expected, '', $data);
362 function testRenderTableAsString()
364 $data = new RowsOfFields([['f1' => 'A', 'f2' => 'B', 'f3' => 'C'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]);
365 $expected = "A\tB\tC\nx\ty\tz";
367 $this->assertFormattedOutputMatches($expected, 'string', $data);
370 function testRenderTableAsStringWithSingleField()
372 $data = new RowsOfFields([['f1' => 'q', 'f2' => 'r', 'f3' => 's'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]);
375 $options = new FormatterOptions([FormatterOptions::DEFAULT_STRING_FIELD => 'f1']);
377 $this->assertFormattedOutputMatches($expected, 'string', $data, $options);
380 function testRenderTableAsStringWithSingleFieldAndUserSelectedField()
382 $data = new RowsOfFields([['f1' => 'q', 'f2' => 'r', 'f3' => 's'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]);
385 $options = new FormatterOptions([FormatterOptions::DEFAULT_STRING_FIELD => 'f1']);
387 $this->assertFormattedOutputMatches($expected, 'string', $data, $options, ['fields' => 'f2']);
390 function testSimpleCsv()
392 $data = ['a', 'b', 'c'];
395 $this->assertFormattedOutputMatches($expected, 'csv', $data);
398 function testLinesOfCsv()
400 $data = [['a', 'b', 'c'], ['x', 'y', 'z']];
401 $expected = "a,b,c\nx,y,z";
403 $this->assertFormattedOutputMatches($expected, 'csv', $data);
406 function testCsvWithEscapedValues()
408 $data = ["Red apple", "Yellow lemon"];
409 $expected = '"Red apple","Yellow lemon"';
411 $this->assertFormattedOutputMatches($expected, 'csv', $data);
414 function testCsvWithEmbeddedSingleQuote()
416 $data = ["John's book", "Mary's laptop"];
418 "John's book","Mary's laptop"
421 $this->assertFormattedOutputMatches($expected, 'csv', $data);
424 function testCsvWithEmbeddedDoubleQuote()
426 $data = ['The "best" solution'];
428 "The ""best"" solution"
431 $this->assertFormattedOutputMatches($expected, 'csv', $data);
434 function testCsvBothKindsOfQuotes()
436 $data = ["John's \"new\" book", "Mary's \"modified\" laptop"];
438 "John's ""new"" book","Mary's ""modified"" laptop"
441 $this->assertFormattedOutputMatches($expected, 'csv', $data);
444 function testSimpleTsv()
446 $data = ['a', 'b', 'c'];
447 $expected = "a\tb\tc";
449 $this->assertFormattedOutputMatches($expected, 'tsv', $data);
452 function testLinesOfTsv()
454 $data = [['a', 'b', 'c'], ['x', 'y', 'z']];
455 $expected = "a\tb\tc\nx\ty\tz";
457 $this->assertFormattedOutputMatches($expected, 'tsv', $data);
460 function testTsvBothKindsOfQuotes()
462 $data = ["John's \"new\" book", "Mary's \"modified\" laptop"];
463 $expected = "John's \"new\" book\tMary's \"modified\" laptop";
465 $this->assertFormattedOutputMatches($expected, 'tsv', $data);
468 function testTsvWithEscapedValues()
470 $data = ["Red apple", "Yellow lemon", "Embedded\ttab"];
471 $expected = "Red apple\tYellow lemon\tEmbedded\\ttab";
473 $this->assertFormattedOutputMatches($expected, 'tsv', $data);
476 protected function missingCellTableExampleData()
489 return new RowsOfFields($data);
492 function testTableWithMissingCell()
494 $data = $this->missingCellTableExampleData();
504 $this->assertFormattedOutputMatches($expected, 'table', $data);
506 $expectedCsv = <<<EOT
511 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
513 $expectedTsv = <<<EOT
517 $this->assertFormattedOutputMatches($expectedTsv, 'tsv', $data);
519 $expectedTsvWithHeaders = <<<EOT
524 $this->assertFormattedOutputMatches($expectedTsvWithHeaders, 'tsv', $data, new FormatterOptions(), ['include-field-labels' => true]);
527 function testTableWithWordWrapping()
529 $options = new FormatterOptions();
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.',
537 $data = new RowsOfFields($data);
540 ------------------ --------------------
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 ------------------ --------------------
553 $options->setWidth(42);
554 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
557 ----------------------------------- ---------------------------------------
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 ----------------------------------- ---------------------------------------
566 $options->setWidth(78);
567 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
570 function testWrappingLotsOfColumns()
572 $options = new FormatterOptions();
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',
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',
596 $data = new RowsOfFields($data);
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:
611 ------------- ---------------- --------------- ----------- ------------- --------- ------------------------------------ --------
614 $options->setWidth(125);
615 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
618 function testTableWithWordWrapping2()
620 $options = new FormatterOptions();
626 'description' => 'Life, the Universe and Everything.',
631 'description' => 'Why is six afraid of seven?',
634 $data = new RowsOfFields($data);
636 ---- ----- -----------------------------
638 ---- ----- -----------------------------
639 42 321 Life, the Universe and
641 13 789 Why is six afraid of seven?
642 ---- ----- -----------------------------
644 $options->setWidth(42);
645 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
648 function testTableWithWordWrapping3()
650 $options = new FormatterOptions();
656 'description' => 'Rex is a very good dog, Brett. He likes kibble, and has four legs.',
658 $data = new PropertyList($data);
661 ------------- -------------------------
666 Description Rex is a very good dog,
667 Brett. He likes kibble,
669 ------------- -------------------------
671 $options->setWidth(42);
672 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
675 function testTableWithWordWrapping4()
677 $options = new FormatterOptions();
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.', ],
686 $data = new RowsOfFields($data);
688 ------------- ----- -----------------------------------------------------
690 ------------- ----- -----------------------------------------------------
695 Description : Rex is a very good dog, Brett. He likes kibble, and
697 ------------- ----- -----------------------------------------------------
699 $options->setWidth(78);
700 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
703 function testTableWithWordWrapping5()
705 $options = new FormatterOptions();
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.', ],
713 $data = new RowsOfFields($data);
719 Description : Rex is a very good dog, Brett. He likes kibble, and has
722 $options->setWidth(78);
723 $options->setIncludeFieldLables(false);
724 $options->setTableStyle('compact');
725 $this->assertFormattedOutputMatches($expected, 'table', $data, $options);
728 protected function simpleTableExampleData()
744 return new RowsOfFields($data);
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
752 function testIncompatibleDataForTableFormatter()
754 $data = $this->simpleTableExampleData()->getArrayCopy();
755 $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'table', $data);
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
763 function testIncompatibleDataForSectionsFormatter()
765 $data = $this->simpleTableExampleData()->getArrayCopy();
766 $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'sections', $data);
769 function testSimpleTable()
771 $data = $this->simpleTableExampleData();
781 $this->assertFormattedOutputMatches($expected, 'table', $data);
783 $expectedBorderless = <<<EOT
791 $this->assertFormattedOutputMatches($expectedBorderless, 'table', $data, new FormatterOptions(['table-style' => 'borderless']));
793 $expectedJson = <<<EOT
807 $this->assertFormattedOutputMatches($expectedJson, 'json', $data);
809 $expectedCsv = <<<EOT
814 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
816 $expectedList = <<<EOT
820 $this->assertFormattedOutputMatches($expectedList, 'list', $data);
823 protected function tableWithAlternativesExampleData()
829 'two' => ['this', 'that', 'the other thing'],
836 'three' => ['apples', 'oranges'],
839 return new RowsOfFieldsWithAlternatives($data);
842 function testTableWithAlternatives()
844 $data = $this->tableWithAlternativesExampleData();
847 ----- --------------------------- ----------------
849 ----- --------------------------- ----------------
850 a this|that|the other thing c
852 ----- --------------------------- ----------------
854 $this->assertFormattedOutputMatches($expected, 'table', $data);
856 $expectedBorderless = <<<EOT
857 ===== =========================== ================
859 ===== =========================== ================
860 a this|that|the other thing c
862 ===== =========================== ================
864 $this->assertFormattedOutputMatches($expectedBorderless, 'table', $data, new FormatterOptions(['table-style' => 'borderless']));
866 $expectedJson = <<<EOT
887 $this->assertFormattedOutputMatches($expectedJson, 'json', $data);
889 $expectedCsv = <<<EOT
891 a,"this|that|the other thing",c
894 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
896 $expectedList = <<<EOT
900 $this->assertFormattedOutputMatches($expectedList, 'list', $data);
903 function testSimpleTableWithFieldLabels()
905 $data = $this->simpleTableExampleData();
906 $configurationData = new FormatterOptions(
908 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'],
909 'row-labels' => ['id-123' => 'Walrus', 'id-456' => 'Carpenter'],
912 $configurationDataAnnotationFormat = new FormatterOptions(
914 'field-labels' => "one: Uno\ntwo: Dos\nthree: Tres",
926 $this->assertFormattedOutputMatches($expected, 'table', $data, $configurationData);
928 $expectedSidewaysTable = <<<EOT
935 $this->assertFormattedOutputMatches($expectedSidewaysTable, 'table', $data, $configurationData->override(['list-orientation' => true]));
937 $expectedAnnotationFormatConfigData = <<<EOT
945 $this->assertFormattedOutputMatches($expectedAnnotationFormatConfigData, 'table', $data, $configurationDataAnnotationFormat);
947 $expectedWithNoFields = <<<EOT
953 $this->assertFormattedOutputMatches($expectedWithNoFields, 'table', $data, $configurationData, ['include-field-labels' => false]);
955 $expectedWithReorderedFields = <<<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']);
967 $expectedWithRegexField = <<<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']]);
979 $expectedSections = <<<EOT
991 $this->assertFormattedOutputMatches($expectedSections, 'sections', $data, $configurationData);
993 $expectedJson = <<<EOT
1005 $this->assertFormattedOutputMatches($expectedJson, 'json', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
1007 $expectedSingleField = <<<EOT
1015 $this->assertFormattedOutputMatches($expectedSingleField, 'table', $data, $configurationData, ['field' => 'San']);
1017 $expectedEmptyColumn = <<<EOT
1023 $this->assertFormattedOutputMatches($expectedEmptyColumn, 'table', new RowsOfFields([]), $configurationData, ['field' => 'San']);
1025 $this->assertFormattedOutputMatches('', '', new RowsOfFields([]), $configurationData, ['field' => 'San']);
1026 $this->assertFormattedOutputMatches('[]', 'json', new RowsOfFields([]), $configurationData, ['field' => 'San']);
1030 * @expectedException \Consolidation\OutputFormatters\Exception\UnknownFieldException
1031 * @expectedExceptionCode 1
1032 * @expectedExceptionMessage The requested field, 'Shi', is not defined.
1034 function testNoSuchFieldException()
1036 $configurationData = new FormatterOptions(
1038 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'],
1039 'row-labels' => ['id-123' => 'Walrus', 'id-456' => 'Carpenter'],
1042 $data = $this->simpleTableExampleData();
1043 $this->assertFormattedOutputMatches('Will throw before comparing', 'table', $data, $configurationData, ['field' => 'Shi']);
1046 protected function simpleListExampleData()
1051 'three' => 'carrot',
1053 return new PropertyList($data);
1056 // Test with the deprecated data structure
1057 protected function simpleListExampleDataUsingAssociativeList()
1062 'three' => 'carrot',
1064 return new AssociativeList($data);
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
1072 function testIncompatibleListDataForTableFormatter()
1074 $data = $this->simpleListExampleData();
1075 $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'table', $data->getArrayCopy());
1078 function testEmptyList()
1080 $data = new RowsOfFields([]);
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);
1095 function testSimpleList()
1105 $data = $this->simpleListExampleDataUsingAssociativeList();
1107 $this->assertFormattedOutputMatches($expected, 'table', $data);
1109 $data = $this->simpleListExampleData();
1111 $this->assertFormattedOutputMatches($expected, 'table', $data);
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);
1126 $expectedDrushStyleTable = <<<EOT
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);
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);
1146 $expectedRotated = <<<EOT
1147 ------- -------- --------
1149 ------- -------- --------
1151 ------- -------- --------
1153 $this->assertFormattedOutputMatches($expectedRotated, 'table', $data, new FormatterOptions(['list-orientation' => false]));
1155 $expectedList = <<< EOT
1160 $this->assertFormattedOutputMatches($expectedList, 'list', $data);
1162 $expectedReorderedList = <<< EOT
1166 $options = new FormatterOptions([FormatterOptions::FIELDS => 'three,one']);
1167 $this->assertFormattedOutputMatches($expectedReorderedList, 'list', $data, $options);
1169 $expectedCsv = <<< EOT
1173 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
1175 $expectedCsvNoHeaders = 'apple,banana,carrot';
1176 $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, new FormatterOptions(), ['include-field-labels' => false]);
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),
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);
1193 $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, $options);
1194 $options->setInput($input);
1195 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data, $options);
1198 protected function associativeListWithRenderer()
1202 'two' => ['banana', 'plantain'],
1203 'three' => 'carrot',
1204 'four' => ['peaches', 'pumpkin pie'],
1206 $list = new PropertyList($data);
1208 $list->addRendererFunction(
1209 function ($key, $cellData, FormatterOptions $options)
1211 if (is_array($cellData)) {
1212 return implode(',', $cellData);
1221 protected function associativeListWithCsvCells()
1225 'two' => ['banana', 'plantain'],
1226 'three' => 'carrot',
1227 'four' => ['peaches', 'pumpkin pie'],
1229 return new PropertyListWithCsvCells($data);
1232 function testPropertyListWithCsvCells()
1234 $this->doPropertyListWithCsvCells($this->associativeListWithRenderer());
1235 $this->doPropertyListWithCsvCells($this->associativeListWithCsvCells());
1238 function doPropertyListWithCsvCells($data)
1241 ------- ---------------------
1245 Four peaches,pumpkin pie
1246 ------- ---------------------
1248 $this->assertFormattedOutputMatches($expected, 'table', $data);
1250 $expectedList = <<< EOT
1256 $this->assertFormattedOutputMatches($expectedList, 'list', $data);
1258 $expectedCsv = <<< EOT
1260 apple,"banana,plantain",carrot,"peaches,pumpkin pie"
1262 $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data);
1264 $expectedCsvNoHeaders = 'apple,"banana,plantain",carrot,"peaches,pumpkin pie"';
1265 $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, new FormatterOptions(), ['include-field-labels' => false]);
1267 $expectedTsv = <<< EOT
1268 apple\tbanana,plantain\tcarrot\tpeaches,pumpkin pie
1270 $this->assertFormattedOutputMatches($expectedTsv, 'tsv', $data);
1274 function testSimpleListWithFieldLabels()
1276 $data = $this->simpleListExampleData();
1277 $configurationData = new FormatterOptions(
1279 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'],
1290 $this->assertFormattedOutputMatches($expected, 'table', $data, $configurationData);
1292 $expectedWithReorderedFields = <<<EOT
1298 $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['three', 'one']]);
1299 $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
1301 $expectedJson = <<<EOT
1307 $this->assertFormattedOutputMatches($expectedJson, 'json', $data, $configurationData, ['fields' => ['San', 'Ichi']]);
1310 function testSimpleXml()
1313 'name' => 'primary',
1314 'description' => 'The primary colors of the color wheel.',
1324 <?xml version="1.0" encoding="UTF-8"?>
1325 <document name="primary">
1326 <description>The primary colors of the color wheel.</description>
1329 <color>yellow</color>
1335 $this->assertFormattedOutputMatches($expected, 'xml', $data);
1338 function domDocumentData()
1340 $dom = new \DOMDocument('1.0', 'UTF-8');
1342 $document = $dom->createElement('document');
1343 $dom->appendChild($document);
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.'));
1350 $this->domCreateElements($dom, $document, 'color', ['red', 'yellow', 'blue']);
1355 function domCreateElements($dom, $element, $name, $data)
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));
1366 function complexDomDocumentData()
1368 $dom = new \DOMDocument('1.0', 'UTF-8');
1370 $document = $dom->createElement('document');
1371 $dom->appendChild($document);
1373 $document->setAttribute('name', 'widget-collection');
1374 $description = $dom->createElement('description');
1375 $document->appendChild($description);
1376 $description->appendChild($dom->createTextNode('A couple of widgets.'));
1378 $widgets = $dom->createElement('widgets');
1379 $document->appendChild($widgets);
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']);
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']);
1396 function domDocumentTestValues()
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>
1405 <color>yellow</color>
1411 $expectedJson = <<<EOT
1414 "description": "The primary colors of the color wheel.",
1423 $expectedComplexXml = <<<EOT
1424 <?xml version="1.0" encoding="UTF-8"?>
1425 <document name="widget-collection">
1426 <description>A couple of widgets.</description>
1428 <widget name="usual">
1431 <color>yellow</color>
1435 <shape>square</shape>
1436 <shape>circle</shape>
1437 <shape>triangle</shape>
1440 <widget name="unusual">
1442 <color>muave</color>
1444 <color>umber</color>
1447 <shape>elipse</shape>
1448 <shape>rhombus</shape>
1449 <shape>trapazoid</shape>
1456 $expectedComplexJson = <<<EOT
1458 "name": "widget-collection",
1459 "description": "A couple of widgets.",
1493 $this->domDocumentData(),
1498 $this->complexDomDocumentData(),
1499 $expectedComplexXml,
1500 $expectedComplexJson,
1506 * @dataProvider domDocumentTestValues
1508 function testDomData($data, $expectedXml, $expectedJson)
1510 $this->assertFormattedOutputMatches($expectedXml, 'xml', $data);
1511 $this->assertFormattedOutputMatches($expectedJson, 'json', $data);
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);
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.
1524 function testDataTypeForXmlFormatter()
1526 $this->assertFormattedOutputMatches('Will fail, not return', 'xml', 'Strings cannot be converted to XML');