Chris@0: formatterManager = new FormatterManager(); Chris@0: } Chris@0: Chris@0: function assertFormattedOutputMatches($expected, $format, $data, FormatterOptions $options = null, $userOptions = []) { Chris@0: if (!$options) { Chris@0: $options = new FormatterOptions(); Chris@0: } Chris@0: $options->setOptions($userOptions); Chris@0: $output = new BufferedOutput(); Chris@0: $this->formatterManager->write($output, $format, $data, $options); Chris@0: $actual = preg_replace('#[ \t]*$#sm', '', $output->fetch()); Chris@0: $this->assertEquals(rtrim($expected), rtrim($actual)); Chris@0: } Chris@0: Chris@0: function testSimpleYaml() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'a', Chris@0: 'two' => 'b', Chris@0: 'three' => 'c', Chris@0: ]; Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'yaml', $data); Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'list', $data); Chris@0: Chris@0: $data = new ListDataFromKeys($data); Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'yaml', $data); Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'list', $data); Chris@0: } Chris@0: Chris@0: function testNestedYaml() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => [ Chris@0: 'i' => ['a', 'b', 'c'], Chris@0: ], Chris@0: 'two' => [ Chris@0: 'ii' => ['q', 'r', 's'], Chris@0: ], Chris@0: 'three' => [ Chris@0: 'iii' => ['t', 'u', 'v'], Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'yaml', $data); Chris@0: } Chris@0: Chris@0: function testSimpleJson() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'a', Chris@0: 'two' => 'b', Chris@0: 'three' => 'c', Chris@0: ]; Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'json', $data); Chris@0: } Chris@0: Chris@0: function testSerializeFormat() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'a', Chris@0: 'two' => 'b', Chris@0: 'three' => 'c', Chris@0: ]; Chris@0: Chris@0: $expected = 'a:3:{s:3:"one";s:1:"a";s:3:"two";s:1:"b";s:5:"three";s:1:"c";}'; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'php', $data); Chris@0: } Chris@0: Chris@0: function testNestedJson() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => [ Chris@0: 'i' => ['a', 'b', 'c'], Chris@0: ], Chris@0: 'two' => [ Chris@0: 'ii' => ['q', 'r', 's'], Chris@0: ], Chris@0: 'three' => [ Chris@0: 'iii' => ['t', 'u', 'v'], Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'json', $data); Chris@0: } Chris@0: Chris@0: function testSimplePrintR() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'a', Chris@0: 'two' => 'b', Chris@0: 'three' => 'c', Chris@0: ]; Chris@0: Chris@0: $expected = << a Chris@0: [two] => b Chris@0: [three] => c Chris@0: ) Chris@0: EOT; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'print-r', $data); Chris@0: } Chris@0: Chris@0: function testNestedPrintR() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => [ Chris@0: 'i' => ['a', 'b', 'c'], Chris@0: ], Chris@0: 'two' => [ Chris@0: 'ii' => ['q', 'r', 's'], Chris@0: ], Chris@0: 'three' => [ Chris@0: 'iii' => ['t', 'u', 'v'], Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $expected = << Array Chris@0: ( Chris@0: [i] => Array Chris@0: ( Chris@0: [0] => a Chris@0: [1] => b Chris@0: [2] => c Chris@0: ) Chris@0: Chris@0: ) Chris@0: Chris@0: [two] => Array Chris@0: ( Chris@0: [ii] => Array Chris@0: ( Chris@0: [0] => q Chris@0: [1] => r Chris@0: [2] => s Chris@0: ) Chris@0: Chris@0: ) Chris@0: Chris@0: [three] => Array Chris@0: ( Chris@0: [iii] => Array Chris@0: ( Chris@0: [0] => t Chris@0: [1] => u Chris@0: [2] => v Chris@0: ) Chris@0: Chris@0: ) Chris@0: Chris@0: ) Chris@0: EOT; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'print-r', $data); Chris@0: } Chris@0: Chris@0: function testSimpleVarExport() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'a', Chris@0: 'two' => 'b', Chris@0: 'three' => 'c', Chris@0: ]; Chris@0: Chris@0: $expected = << 'a', Chris@0: 'two' => 'b', Chris@0: 'three' => 'c', Chris@0: ) Chris@0: EOT; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'var_export', $data); Chris@0: } Chris@0: Chris@0: function testNestedVarExport() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => [ Chris@0: 'i' => ['a', 'b', 'c'], Chris@0: ], Chris@0: 'two' => [ Chris@0: 'ii' => ['q', 'r', 's'], Chris@0: ], Chris@0: 'three' => [ Chris@0: 'iii' => ['t', 'u', 'v'], Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $expected = << Chris@0: array ( Chris@0: 'i' => Chris@0: array ( Chris@0: 0 => 'a', Chris@0: 1 => 'b', Chris@0: 2 => 'c', Chris@0: ), Chris@0: ), Chris@0: 'two' => Chris@0: array ( Chris@0: 'ii' => Chris@0: array ( Chris@0: 0 => 'q', Chris@0: 1 => 'r', Chris@0: 2 => 's', Chris@0: ), Chris@0: ), Chris@0: 'three' => Chris@0: array ( Chris@0: 'iii' => Chris@0: array ( Chris@0: 0 => 't', Chris@0: 1 => 'u', Chris@0: 2 => 'v', Chris@0: ), Chris@0: ), Chris@0: ) Chris@0: EOT; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'var_export', $data); Chris@0: } Chris@0: Chris@0: function testList() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'a', Chris@0: 'two' => 'b', Chris@0: 'three' => 'c', Chris@0: ]; Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'list', $data); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @expectedException \Consolidation\OutputFormatters\Exception\UnknownFormatException Chris@0: * @expectedExceptionCode 1 Chris@0: * @expectedExceptionMessage The requested format, 'no-such-format', is not available. Chris@0: */ Chris@0: function testBadFormat() Chris@0: { Chris@0: $this->assertFormattedOutputMatches('Will fail, not return', 'no-such-format', ['a' => 'b']); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @expectedException \Consolidation\OutputFormatters\Exception\IncompatibleDataException Chris@0: * @expectedExceptionCode 1 Chris@0: * @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. Chris@0: */ Chris@0: function testBadDataTypeForCsv() Chris@0: { Chris@0: $this->assertFormattedOutputMatches('Will fail, not return', 'csv', 'String cannot be converted to csv'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @expectedException \Consolidation\OutputFormatters\Exception\IncompatibleDataException Chris@0: * @expectedExceptionCode 1 Chris@0: * @expectedExceptionMessage Data provided to Consolidation\OutputFormatters\Formatters\JsonFormatter must be an array. Instead, a string was provided. Chris@0: */ Chris@0: function testBadDataTypeForJson() Chris@0: { Chris@0: $this->assertFormattedOutputMatches('Will fail, not return', 'json', 'String cannot be converted to json'); Chris@0: } Chris@0: Chris@0: function testNoFormatterSelected() Chris@0: { Chris@0: $data = 'Hello'; Chris@0: $expected = $data; Chris@0: $this->assertFormattedOutputMatches($expected, '', $data); Chris@0: } Chris@0: Chris@0: function testRenderTableAsString() Chris@0: { Chris@0: $data = new RowsOfFields([['f1' => 'A', 'f2' => 'B', 'f3' => 'C'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]); Chris@0: $expected = "A\tB\tC\nx\ty\tz"; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'string', $data); Chris@0: } Chris@0: Chris@0: function testRenderTableAsStringWithSingleField() Chris@0: { Chris@0: $data = new RowsOfFields([['f1' => 'q', 'f2' => 'r', 'f3' => 's'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]); Chris@0: $expected = "q\nx"; Chris@0: Chris@0: $options = new FormatterOptions([FormatterOptions::DEFAULT_STRING_FIELD => 'f1']); Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'string', $data, $options); Chris@0: } Chris@0: Chris@0: function testRenderTableAsStringWithSingleFieldAndUserSelectedField() Chris@0: { Chris@0: $data = new RowsOfFields([['f1' => 'q', 'f2' => 'r', 'f3' => 's'], ['f1' => 'x', 'f2' => 'y', 'f3' => 'z']]); Chris@0: $expected = "r\ny"; Chris@0: Chris@0: $options = new FormatterOptions([FormatterOptions::DEFAULT_STRING_FIELD => 'f1']); Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'string', $data, $options, ['fields' => 'f2']); Chris@0: } Chris@0: Chris@0: function testSimpleCsv() Chris@0: { Chris@0: $data = ['a', 'b', 'c']; Chris@0: $expected = "a,b,c"; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'csv', $data); Chris@0: } Chris@0: Chris@0: function testLinesOfCsv() Chris@0: { Chris@0: $data = [['a', 'b', 'c'], ['x', 'y', 'z']]; Chris@0: $expected = "a,b,c\nx,y,z"; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'csv', $data); Chris@0: } Chris@0: Chris@0: function testCsvWithEscapedValues() Chris@0: { Chris@0: $data = ["Red apple", "Yellow lemon"]; Chris@0: $expected = '"Red apple","Yellow lemon"'; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'csv', $data); Chris@0: } Chris@0: Chris@0: function testCsvWithEmbeddedSingleQuote() Chris@0: { Chris@0: $data = ["John's book", "Mary's laptop"]; Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'csv', $data); Chris@0: } Chris@0: Chris@0: function testCsvWithEmbeddedDoubleQuote() Chris@0: { Chris@0: $data = ['The "best" solution']; Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'csv', $data); Chris@0: } Chris@0: Chris@0: function testCsvBothKindsOfQuotes() Chris@0: { Chris@0: $data = ["John's \"new\" book", "Mary's \"modified\" laptop"]; Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'csv', $data); Chris@0: } Chris@0: Chris@0: function testSimpleTsv() Chris@0: { Chris@0: $data = ['a', 'b', 'c']; Chris@0: $expected = "a\tb\tc"; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'tsv', $data); Chris@0: } Chris@0: Chris@0: function testLinesOfTsv() Chris@0: { Chris@0: $data = [['a', 'b', 'c'], ['x', 'y', 'z']]; Chris@0: $expected = "a\tb\tc\nx\ty\tz"; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'tsv', $data); Chris@0: } Chris@0: Chris@0: function testTsvBothKindsOfQuotes() Chris@0: { Chris@0: $data = ["John's \"new\" book", "Mary's \"modified\" laptop"]; Chris@0: $expected = "John's \"new\" book\tMary's \"modified\" laptop"; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'tsv', $data); Chris@0: } Chris@0: Chris@0: function testTsvWithEscapedValues() Chris@0: { Chris@0: $data = ["Red apple", "Yellow lemon", "Embedded\ttab"]; Chris@0: $expected = "Red apple\tYellow lemon\tEmbedded\\ttab"; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'tsv', $data); Chris@0: } Chris@0: Chris@0: protected function missingCellTableExampleData() Chris@0: { Chris@0: $data = [ Chris@0: [ Chris@0: 'one' => 'a', Chris@0: 'two' => 'b', Chris@0: 'three' => 'c', Chris@0: ], Chris@0: [ Chris@0: 'one' => 'x', Chris@0: 'three' => 'z', Chris@0: ], Chris@0: ]; Chris@0: return new RowsOfFields($data); Chris@0: } Chris@0: Chris@0: function testTableWithMissingCell() Chris@0: { Chris@0: $data = $this->missingCellTableExampleData(); Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'table', $data); Chris@0: Chris@0: $expectedCsv = <<assertFormattedOutputMatches($expectedCsv, 'csv', $data); Chris@0: Chris@0: $expectedTsv = <<assertFormattedOutputMatches($expectedTsv, 'tsv', $data); Chris@0: Chris@0: $expectedTsvWithHeaders = <<assertFormattedOutputMatches($expectedTsvWithHeaders, 'tsv', $data, new FormatterOptions(), ['include-field-labels' => true]); Chris@0: } Chris@0: Chris@0: function testTableWithWordWrapping() Chris@0: { Chris@0: $options = new FormatterOptions(); Chris@0: Chris@0: $data = [ Chris@0: [ Chris@0: 'first' => 'This is a really long cell that contains a lot of data. When it is rendered, it should be wrapped across multiple lines.', Chris@0: '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.', Chris@0: ] Chris@0: ]; Chris@0: $data = new RowsOfFields($data); Chris@0: Chris@0: $expected = <<setWidth(42); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $options); Chris@0: Chris@0: $expected = <<setWidth(78); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $options); Chris@0: } Chris@0: Chris@0: function testWrappingLotsOfColumns() Chris@0: { Chris@0: $options = new FormatterOptions(); Chris@0: Chris@0: $data = [ Chris@0: [ Chris@0: 'id' => '4d87b545-b4c3-4ece-9908-20c5c5e67e81', Chris@0: 'name' => '123456781234567812345678123456781234567812345678', Chris@0: 'service_level' => 'business', Chris@0: 'framework' => 'wordpress-network', Chris@0: 'owner' => '8558a08d-8059-45f6-9c4b-908299a025ee', Chris@0: 'created' => '2017-05-24 19:28:45', Chris@0: 'memberships' => 'b3a42ba5-755d-42ca-9109-21bde32809d0: Team,9bfaaf50-ece3-4460-acb8-dc1b8dd536e8: pantheon-engineering-canary-sites', Chris@0: 'frozen' => 'false', Chris@0: ], Chris@0: [ Chris@0: 'id' => '3d87b545-b4c3-4ece-9908-20c5c5e67e80', Chris@0: 'name' => 'build-tools-136', Chris@0: 'service_level' => 'free', Chris@0: 'framework' => 'drupal8', Chris@0: 'owner' => '7558a08d-8059-45f6-9c4b-908299a025ef', Chris@0: 'created' => '2017-05-24 19:28:45', Chris@0: 'memberships' => '5ae1fa30-8cc4-4894-8ca9-d50628dcba17: ci-for-drupal-8-composer', Chris@0: 'frozen' => 'false', Chris@0: ] Chris@0: ]; Chris@0: $data = new RowsOfFields($data); Chris@0: Chris@0: $expected = <<setWidth(125); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $options); Chris@0: } Chris@0: Chris@0: function testTableWithWordWrapping2() Chris@0: { Chris@0: $options = new FormatterOptions(); Chris@0: Chris@0: $data = [ Chris@0: [ Chris@0: 'id' => 42, Chris@0: 'vid' => 321, Chris@0: 'description' => 'Life, the Universe and Everything.', Chris@0: ], Chris@0: [ Chris@0: 'id' => 13, Chris@0: 'vid' => 789, Chris@0: 'description' => 'Why is six afraid of seven?', Chris@0: ], Chris@0: ]; Chris@0: $data = new RowsOfFields($data); Chris@0: $expected = <<setWidth(42); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $options); Chris@0: } Chris@0: Chris@0: function testTableWithWordWrapping3() Chris@0: { Chris@0: $options = new FormatterOptions(); Chris@0: $data = [ Chris@0: 'name' => 'Rex', Chris@0: 'species' => 'dog', Chris@0: 'food' => 'kibble', Chris@0: 'legs' => '4', Chris@0: 'description' => 'Rex is a very good dog, Brett. He likes kibble, and has four legs.', Chris@0: ]; Chris@0: $data = new PropertyList($data); Chris@0: Chris@0: $expected = <<setWidth(42); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $options); Chris@0: } Chris@0: Chris@0: function testTableWithWordWrapping4() Chris@0: { Chris@0: $options = new FormatterOptions(); Chris@0: Chris@0: $data = [ Chris@0: 'name' => ['label' => 'Name', 'sep' => ':', 'value' => 'Rex', ], Chris@0: 'species' => ['label' => 'Species', 'sep' => ':', 'value' => 'dog', ], Chris@0: 'food' => ['label' => 'Food', 'sep' => ':', 'value' => 'kibble', ], Chris@0: 'legs' => ['label' => 'Legs', 'sep' => ':', 'value' => '4', ], Chris@0: 'description' => ['label' => 'Description', 'sep' => ':', 'value' => 'Rex is a very good dog, Brett. He likes kibble, and has four legs.', ], Chris@0: ]; Chris@0: $data = new RowsOfFields($data); Chris@0: $expected = <<setWidth(78); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $options); Chris@0: } Chris@0: Chris@0: function testTableWithWordWrapping5() Chris@0: { Chris@0: $options = new FormatterOptions(); Chris@0: $data = [ Chris@0: 'name' => ['Name', ':', 'Rex', ], Chris@0: 'species' => ['Species', ':', 'dog', ], Chris@0: 'food' => ['Food', ':', 'kibble', ], Chris@0: 'legs' => ['Legs', ':', '4', ], Chris@0: 'description' => ['Description', ':', 'Rex is a very good dog, Brett. He likes kibble, and has four legs.', ], Chris@0: ]; Chris@0: $data = new RowsOfFields($data); Chris@0: $expected = <<setWidth(78); Chris@0: $options->setIncludeFieldLables(false); Chris@0: $options->setTableStyle('compact'); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $options); Chris@0: } Chris@0: Chris@0: protected function simpleTableExampleData() Chris@0: { Chris@0: $data = [ Chris@0: 'id-123' => Chris@0: [ Chris@0: 'one' => 'a', Chris@0: 'two' => 'b', Chris@0: 'three' => 'c', Chris@0: ], Chris@0: 'id-456' => Chris@0: [ Chris@0: 'one' => 'x', Chris@0: 'two' => 'y', Chris@0: 'three' => 'z', Chris@0: ], Chris@0: ]; Chris@0: return new RowsOfFields($data); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @expectedException \Consolidation\OutputFormatters\Exception\InvalidFormatException Chris@0: * @expectedExceptionCode 1 Chris@0: * @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 Chris@0: */ Chris@0: function testIncompatibleDataForTableFormatter() Chris@0: { Chris@0: $data = $this->simpleTableExampleData()->getArrayCopy(); Chris@0: $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'table', $data); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @expectedException \Consolidation\OutputFormatters\Exception\InvalidFormatException Chris@0: * @expectedExceptionCode 1 Chris@0: * @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 Chris@0: */ Chris@0: function testIncompatibleDataForSectionsFormatter() Chris@0: { Chris@0: $data = $this->simpleTableExampleData()->getArrayCopy(); Chris@0: $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'sections', $data); Chris@0: } Chris@0: Chris@0: function testSimpleTable() Chris@0: { Chris@0: $data = $this->simpleTableExampleData(); Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'table', $data); Chris@0: Chris@0: $expectedBorderless = <<assertFormattedOutputMatches($expectedBorderless, 'table', $data, new FormatterOptions(['table-style' => 'borderless'])); Chris@0: Chris@0: $expectedJson = <<assertFormattedOutputMatches($expectedJson, 'json', $data); Chris@0: Chris@0: $expectedCsv = <<assertFormattedOutputMatches($expectedCsv, 'csv', $data); Chris@0: Chris@0: $expectedList = <<assertFormattedOutputMatches($expectedList, 'list', $data); Chris@0: } Chris@0: Chris@0: protected function tableWithAlternativesExampleData() Chris@0: { Chris@0: $data = [ Chris@0: 'id-123' => Chris@0: [ Chris@0: 'one' => 'a', Chris@0: 'two' => ['this', 'that', 'the other thing'], Chris@0: 'three' => 'c', Chris@0: ], Chris@0: 'id-456' => Chris@0: [ Chris@0: 'one' => 'x', Chris@0: 'two' => 'y', Chris@0: 'three' => ['apples', 'oranges'], Chris@0: ], Chris@0: ]; Chris@0: return new RowsOfFieldsWithAlternatives($data); Chris@0: } Chris@0: Chris@0: function testTableWithAlternatives() Chris@0: { Chris@0: $data = $this->tableWithAlternativesExampleData(); Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'table', $data); Chris@0: Chris@0: $expectedBorderless = <<assertFormattedOutputMatches($expectedBorderless, 'table', $data, new FormatterOptions(['table-style' => 'borderless'])); Chris@0: Chris@0: $expectedJson = <<assertFormattedOutputMatches($expectedJson, 'json', $data); Chris@0: Chris@0: $expectedCsv = <<assertFormattedOutputMatches($expectedCsv, 'csv', $data); Chris@0: Chris@0: $expectedList = <<assertFormattedOutputMatches($expectedList, 'list', $data); Chris@0: } Chris@0: Chris@0: function testSimpleTableWithFieldLabels() Chris@0: { Chris@0: $data = $this->simpleTableExampleData(); Chris@0: $configurationData = new FormatterOptions( Chris@0: [ Chris@0: 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'], Chris@0: 'row-labels' => ['id-123' => 'Walrus', 'id-456' => 'Carpenter'], Chris@0: ] Chris@0: ); Chris@0: $configurationDataAnnotationFormat = new FormatterOptions( Chris@0: [ Chris@0: 'field-labels' => "one: Uno\ntwo: Dos\nthree: Tres", Chris@0: ] Chris@0: ); Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'table', $data, $configurationData); Chris@0: Chris@0: $expectedSidewaysTable = <<assertFormattedOutputMatches($expectedSidewaysTable, 'table', $data, $configurationData->override(['list-orientation' => true])); Chris@0: Chris@0: $expectedAnnotationFormatConfigData = <<assertFormattedOutputMatches($expectedAnnotationFormatConfigData, 'table', $data, $configurationDataAnnotationFormat); Chris@0: Chris@0: $expectedWithNoFields = <<assertFormattedOutputMatches($expectedWithNoFields, 'table', $data, $configurationData, ['include-field-labels' => false]); Chris@0: Chris@0: $expectedWithReorderedFields = <<assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['three', 'one']]); Chris@0: $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['San', 'Ichi']]); Chris@0: $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => 'San,Ichi']); Chris@0: Chris@0: $expectedWithRegexField = <<assertFormattedOutputMatches($expectedWithRegexField, 'table', $data, $configurationData, ['fields' => ['/e$/']]); Chris@0: $this->assertFormattedOutputMatches($expectedWithRegexField, 'table', $data, $configurationData, ['fields' => ['*e']]); Chris@0: $this->assertFormattedOutputMatches($expectedWithRegexField, 'table', $data, $configurationData, ['default-fields' => ['*e']]); Chris@0: Chris@0: $expectedSections = <<assertFormattedOutputMatches($expectedSections, 'sections', $data, $configurationData); Chris@0: Chris@0: $expectedJson = <<assertFormattedOutputMatches($expectedJson, 'json', $data, $configurationData, ['fields' => ['San', 'Ichi']]); Chris@0: Chris@0: $expectedSingleField = <<assertFormattedOutputMatches($expectedSingleField, 'table', $data, $configurationData, ['field' => 'San']); Chris@0: Chris@0: $expectedEmptyColumn = <<assertFormattedOutputMatches($expectedEmptyColumn, 'table', new RowsOfFields([]), $configurationData, ['field' => 'San']); Chris@0: Chris@0: $this->assertFormattedOutputMatches('', '', new RowsOfFields([]), $configurationData, ['field' => 'San']); Chris@0: $this->assertFormattedOutputMatches('[]', 'json', new RowsOfFields([]), $configurationData, ['field' => 'San']); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @expectedException \Consolidation\OutputFormatters\Exception\UnknownFieldException Chris@0: * @expectedExceptionCode 1 Chris@0: * @expectedExceptionMessage The requested field, 'Shi', is not defined. Chris@0: */ Chris@0: function testNoSuchFieldException() Chris@0: { Chris@0: $configurationData = new FormatterOptions( Chris@0: [ Chris@0: 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'], Chris@0: 'row-labels' => ['id-123' => 'Walrus', 'id-456' => 'Carpenter'], Chris@0: ] Chris@0: ); Chris@0: $data = $this->simpleTableExampleData(); Chris@0: $this->assertFormattedOutputMatches('Will throw before comparing', 'table', $data, $configurationData, ['field' => 'Shi']); Chris@0: } Chris@0: Chris@0: protected function simpleListExampleData() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'apple', Chris@0: 'two' => 'banana', Chris@0: 'three' => 'carrot', Chris@0: ]; Chris@0: return new PropertyList($data); Chris@0: } Chris@0: Chris@0: // Test with the deprecated data structure Chris@0: protected function simpleListExampleDataUsingAssociativeList() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'apple', Chris@0: 'two' => 'banana', Chris@0: 'three' => 'carrot', Chris@0: ]; Chris@0: return new AssociativeList($data); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @expectedException \Consolidation\OutputFormatters\Exception\InvalidFormatException Chris@0: * @expectedExceptionCode 1 Chris@0: * @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 Chris@0: */ Chris@0: function testIncompatibleListDataForTableFormatter() Chris@0: { Chris@0: $data = $this->simpleListExampleData(); Chris@0: $this->assertFormattedOutputMatches('Should throw an exception before comparing the table data', 'table', $data->getArrayCopy()); Chris@0: } Chris@0: Chris@0: function testEmptyList() Chris@0: { Chris@0: $data = new RowsOfFields([]); Chris@0: Chris@0: $expected = <<setFieldLabels(['one' => 'I', 'two' => 'II', 'three' => 'III']); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $formatterOptionsWithFieldLables); Chris@0: } Chris@0: Chris@0: function testSimpleList() Chris@0: { Chris@0: Chris@0: $expected = <<simpleListExampleDataUsingAssociativeList(); Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data); Chris@0: Chris@0: $data = $this->simpleListExampleData(); Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data); Chris@0: Chris@0: $expected = <<setFieldLabels(['one' => 'I', 'two' => 'II', 'three' => 'III']); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $formatterOptionsWithFieldLables); Chris@0: Chris@0: $expectedDrushStyleTable = <<setTableStyle('compact') Chris@0: ->setListDelimiter(':'); Chris@0: $this->assertFormattedOutputMatches($expectedDrushStyleTable, 'table', $data, $formatterOptionsWithFieldLables); Chris@0: Chris@0: Chris@0: // Adding an extra field that does not exist in the data set should not change the output Chris@0: $formatterOptionsWithExtraFieldLables = new FormatterOptions(); Chris@0: $formatterOptionsWithExtraFieldLables Chris@0: ->setFieldLabels(['one' => 'I', 'two' => 'II', 'three' => 'III', 'four' => 'IV']); Chris@0: $this->assertFormattedOutputMatches($expected, 'table', $data, $formatterOptionsWithExtraFieldLables); Chris@0: Chris@0: $expectedRotated = <<assertFormattedOutputMatches($expectedRotated, 'table', $data, new FormatterOptions(['list-orientation' => false])); Chris@0: Chris@0: $expectedList = <<< EOT Chris@0: apple Chris@0: banana Chris@0: carrot Chris@0: EOT; Chris@0: $this->assertFormattedOutputMatches($expectedList, 'list', $data); Chris@0: Chris@0: $expectedReorderedList = <<< EOT Chris@0: carrot Chris@0: apple Chris@0: EOT; Chris@0: $options = new FormatterOptions([FormatterOptions::FIELDS => 'three,one']); Chris@0: $this->assertFormattedOutputMatches($expectedReorderedList, 'list', $data, $options); Chris@0: Chris@0: $expectedCsv = <<< EOT Chris@0: One,Two,Three Chris@0: apple,banana,carrot Chris@0: EOT; Chris@0: $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data); Chris@0: Chris@0: $expectedCsvNoHeaders = 'apple,banana,carrot'; Chris@0: $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, new FormatterOptions(), ['include-field-labels' => false]); Chris@0: Chris@0: // Next, configure the formatter options with 'include-field-labels', Chris@0: // but set --include-field-labels to turn the option back on again. Chris@0: $options = new FormatterOptions(['include-field-labels' => false]); Chris@0: $input = new StringInput('test --include-field-labels'); Chris@0: $optionDefinitions = [ Chris@0: new InputArgument('unused', InputArgument::REQUIRED), Chris@0: new InputOption('include-field-labels', null, InputOption::VALUE_NONE), Chris@0: ]; Chris@0: $definition = new InputDefinition($optionDefinitions); Chris@0: $input->bind($definition); Chris@0: $testValue = $input->getOption('include-field-labels'); Chris@0: $this->assertTrue($testValue); Chris@0: $hasFieldLabels = $input->hasOption('include-field-labels'); Chris@0: $this->assertTrue($hasFieldLabels); Chris@0: Chris@0: $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, $options); Chris@0: $options->setInput($input); Chris@0: $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data, $options); Chris@0: } Chris@0: Chris@0: protected function associativeListWithRenderer() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'apple', Chris@0: 'two' => ['banana', 'plantain'], Chris@0: 'three' => 'carrot', Chris@0: 'four' => ['peaches', 'pumpkin pie'], Chris@0: ]; Chris@0: $list = new PropertyList($data); Chris@0: Chris@0: $list->addRendererFunction( Chris@0: function ($key, $cellData, FormatterOptions $options) Chris@0: { Chris@0: if (is_array($cellData)) { Chris@0: return implode(',', $cellData); Chris@0: } Chris@0: return $cellData; Chris@0: } Chris@0: ); Chris@0: Chris@0: return $list; Chris@0: } Chris@0: Chris@0: protected function associativeListWithCsvCells() Chris@0: { Chris@0: $data = [ Chris@0: 'one' => 'apple', Chris@0: 'two' => ['banana', 'plantain'], Chris@0: 'three' => 'carrot', Chris@0: 'four' => ['peaches', 'pumpkin pie'], Chris@0: ]; Chris@0: return new PropertyListWithCsvCells($data); Chris@0: } Chris@0: Chris@0: function testPropertyListWithCsvCells() Chris@0: { Chris@0: $this->doPropertyListWithCsvCells($this->associativeListWithRenderer()); Chris@0: $this->doPropertyListWithCsvCells($this->associativeListWithCsvCells()); Chris@0: } Chris@0: Chris@0: function doPropertyListWithCsvCells($data) Chris@0: { Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'table', $data); Chris@0: Chris@0: $expectedList = <<< EOT Chris@0: apple Chris@0: banana,plantain Chris@0: carrot Chris@0: peaches,pumpkin pie Chris@0: EOT; Chris@0: $this->assertFormattedOutputMatches($expectedList, 'list', $data); Chris@0: Chris@0: $expectedCsv = <<< EOT Chris@0: One,Two,Three,Four Chris@0: apple,"banana,plantain",carrot,"peaches,pumpkin pie" Chris@0: EOT; Chris@0: $this->assertFormattedOutputMatches($expectedCsv, 'csv', $data); Chris@0: Chris@0: $expectedCsvNoHeaders = 'apple,"banana,plantain",carrot,"peaches,pumpkin pie"'; Chris@0: $this->assertFormattedOutputMatches($expectedCsvNoHeaders, 'csv', $data, new FormatterOptions(), ['include-field-labels' => false]); Chris@0: Chris@0: $expectedTsv = <<< EOT Chris@0: apple\tbanana,plantain\tcarrot\tpeaches,pumpkin pie Chris@0: EOT; Chris@0: $this->assertFormattedOutputMatches($expectedTsv, 'tsv', $data); Chris@0: Chris@0: } Chris@0: Chris@0: function testSimpleListWithFieldLabels() Chris@0: { Chris@0: $data = $this->simpleListExampleData(); Chris@0: $configurationData = new FormatterOptions( Chris@0: [ Chris@0: 'field-labels' => ['one' => 'Ichi', 'two' => 'Ni', 'three' => 'San'], Chris@0: ] Chris@0: ); Chris@0: Chris@0: $expected = <<assertFormattedOutputMatches($expected, 'table', $data, $configurationData); Chris@0: Chris@0: $expectedWithReorderedFields = <<assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['three', 'one']]); Chris@0: $this->assertFormattedOutputMatches($expectedWithReorderedFields, 'table', $data, $configurationData, ['fields' => ['San', 'Ichi']]); Chris@0: Chris@0: $expectedJson = <<assertFormattedOutputMatches($expectedJson, 'json', $data, $configurationData, ['fields' => ['San', 'Ichi']]); Chris@0: } Chris@0: Chris@0: function testSimpleXml() Chris@0: { Chris@0: $data = [ Chris@0: 'name' => 'primary', Chris@0: 'description' => 'The primary colors of the color wheel.', Chris@0: 'colors' => Chris@0: [ Chris@0: 'red', Chris@0: 'yellow', Chris@0: 'blue', Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $expected = << Chris@0: Chris@0: The primary colors of the color wheel. Chris@0: Chris@0: red Chris@0: yellow Chris@0: blue Chris@0: Chris@0: Chris@0: EOT; Chris@0: Chris@0: $this->assertFormattedOutputMatches($expected, 'xml', $data); Chris@0: } Chris@0: Chris@0: function domDocumentData() Chris@0: { Chris@0: $dom = new \DOMDocument('1.0', 'UTF-8'); Chris@0: Chris@0: $document = $dom->createElement('document'); Chris@0: $dom->appendChild($document); Chris@0: Chris@0: $document->setAttribute('name', 'primary'); Chris@0: $description = $dom->createElement('description'); Chris@0: $document->appendChild($description); Chris@0: $description->appendChild($dom->createTextNode('The primary colors of the color wheel.')); Chris@0: Chris@0: $this->domCreateElements($dom, $document, 'color', ['red', 'yellow', 'blue']); Chris@0: Chris@0: return $dom; Chris@0: } Chris@0: Chris@0: function domCreateElements($dom, $element, $name, $data) Chris@0: { Chris@0: $container = $dom->createElement("{$name}s"); Chris@0: $element->appendChild($container); Chris@0: foreach ($data as $value) { Chris@0: $child = $dom->createElement($name); Chris@0: $container->appendChild($child); Chris@0: $child->appendChild($dom->createTextNode($value)); Chris@0: } Chris@0: } Chris@0: Chris@0: function complexDomDocumentData() Chris@0: { Chris@0: $dom = new \DOMDocument('1.0', 'UTF-8'); Chris@0: Chris@0: $document = $dom->createElement('document'); Chris@0: $dom->appendChild($document); Chris@0: Chris@0: $document->setAttribute('name', 'widget-collection'); Chris@0: $description = $dom->createElement('description'); Chris@0: $document->appendChild($description); Chris@0: $description->appendChild($dom->createTextNode('A couple of widgets.')); Chris@0: Chris@0: $widgets = $dom->createElement('widgets'); Chris@0: $document->appendChild($widgets); Chris@0: Chris@0: $widget = $dom->createElement('widget'); Chris@0: $widgets->appendChild($widget); Chris@0: $widget->setAttribute('name', 'usual'); Chris@0: $this->domCreateElements($dom, $widget, 'color', ['red', 'yellow', 'blue']); Chris@0: $this->domCreateElements($dom, $widget, 'shape', ['square', 'circle', 'triangle']); Chris@0: Chris@0: $widget = $dom->createElement('widget'); Chris@0: $widgets->appendChild($widget); Chris@0: $widget->setAttribute('name', 'unusual'); Chris@0: $this->domCreateElements($dom, $widget, 'color', ['muave', 'puce', 'umber']); Chris@0: $this->domCreateElements($dom, $widget, 'shape', ['elipse', 'rhombus', 'trapazoid']); Chris@0: Chris@0: return $dom; Chris@0: } Chris@0: Chris@0: function domDocumentTestValues() Chris@0: { Chris@0: Chris@0: $expectedXml = << Chris@0: Chris@0: The primary colors of the color wheel. Chris@0: Chris@0: red Chris@0: yellow Chris@0: blue Chris@0: Chris@0: Chris@0: EOT; Chris@0: Chris@0: $expectedJson = << Chris@0: Chris@0: A couple of widgets. Chris@0: Chris@0: Chris@0: Chris@0: red Chris@0: yellow Chris@0: blue Chris@0: Chris@0: Chris@0: square Chris@0: circle Chris@0: triangle Chris@0: Chris@0: Chris@0: Chris@0: Chris@0: muave Chris@0: puce Chris@0: umber Chris@0: Chris@0: Chris@0: elipse Chris@0: rhombus Chris@0: trapazoid Chris@0: Chris@0: Chris@0: Chris@0: Chris@0: EOT; Chris@0: Chris@0: $expectedComplexJson = <<domDocumentData(), Chris@0: $expectedXml, Chris@0: $expectedJson, Chris@0: ], Chris@0: [ Chris@0: $this->complexDomDocumentData(), Chris@0: $expectedComplexXml, Chris@0: $expectedComplexJson, Chris@0: ], Chris@0: ]; Chris@0: } Chris@0: Chris@0: /** Chris@0: * @dataProvider domDocumentTestValues Chris@0: */ Chris@0: function testDomData($data, $expectedXml, $expectedJson) Chris@0: { Chris@0: $this->assertFormattedOutputMatches($expectedXml, 'xml', $data); Chris@0: $this->assertFormattedOutputMatches($expectedJson, 'json', $data); Chris@0: Chris@0: // Check to see if we get the same xml data if we convert from Chris@0: // DOM -> array -> DOM. Chris@0: $expectedJsonAsArray = (array)json_decode($expectedJson); Chris@0: $this->assertFormattedOutputMatches($expectedXml, 'xml', $expectedJsonAsArray); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @expectedException \Exception Chris@0: * @expectedExceptionCode 1 Chris@0: * @expectedExceptionMessage Data provided to Consolidation\OutputFormatters\Formatters\XmlFormatter must be either an instance of DOMDocument or an array. Instead, a string was provided. Chris@0: */ Chris@0: function testDataTypeForXmlFormatter() Chris@0: { Chris@0: $this->assertFormattedOutputMatches('Will fail, not return', 'xml', 'Strings cannot be converted to XML'); Chris@0: } Chris@0: }