You are here

CsvParserTest.php in Feeds 8.3

File

tests/src/Unit/Component/CsvParserTest.php
View source
<?php

namespace Drupal\Tests\feeds\Unit\Component;

use Drupal\feeds\Component\CsvParser;
use Drupal\Tests\feeds\Unit\FeedsUnitTestCase;
use InvalidArgumentException;

/**
 * @coversDefaultClass \Drupal\feeds\Component\CsvParser
 * @group feeds
 */
class CsvParserTest extends FeedsUnitTestCase {

  /**
   * Tests parsing a CSV source with several line endings.
   *
   * @dataProvider provider
   */
  public function testAlternateLineEnding(array $expected, $ending) {
    $text = file_get_contents(dirname(dirname(dirname(dirname(__DIR__)))) . '/tests/resources/csv/example.csv');
    $text = str_replace("\r\n", $ending, $text);
    $parser = new \LimitIterator(CsvParser::createFromString($text), 0, 4);
    $first = array_slice($expected, 0, 4);
    $this
      ->assertSame(count(iterator_to_array($parser)), 4);
    $this
      ->assertSame(count(iterator_to_array($parser)), 4);
    foreach ($parser as $delta => $row) {
      $this
        ->assertSame($first[$delta], $row);
    }

    // Test second batch.
    $last_pos = $parser
      ->lastLinePos();
    $parser = (new \LimitIterator(CsvParser::createFromString($text), 0, 4))
      ->setStartByte($last_pos);
    $second = array_slice($expected, 4);

    // // Test that rewinding works as expected.
    $this
      ->assertSame(3, count(iterator_to_array($parser)));
    $this
      ->assertSame(3, count(iterator_to_array($parser)));
    foreach ($parser as $delta => $row) {
      $this
        ->assertSame($second[$delta], $row);
    }
  }

  /**
   * Data provider for testAlternateLineEnding().
   */
  public function provider() {
    $expected = [
      [
        'Header A',
        'Header B',
        'Header C',
      ],
      [
        '"1"',
        '"2"',
        '"3"',
      ],
      [
        'qu"ote',
        'qu"ote',
        'qu"ote',
      ],
      [
        "\r\n\r\nline1",
        "\r\n\r\nline2",
        "\r\n\r\nline3",
      ],
      [
        "new\r\nline 1",
        "new\r\nline 2",
        "new\r\nline 3",
      ],
      [
        "\r\n\r\nline1\r\n\r\n",
        "\r\n\r\nline2\r\n\r\n",
        "\r\n\r\nline3\r\n\r\n",
      ],
      [
        'Col A',
        'Col B',
        'Col, C',
      ],
    ];
    $unix = $expected;
    array_walk_recursive($unix, function (&$item, $key) {
      $item = str_replace("\r\n", "\n", $item);
    });
    $mac = $expected;
    array_walk_recursive($mac, function (&$item, $key) {
      $item = str_replace("\r\n", "\r", $item);
    });
    return [
      [
        $expected,
        "\r\n",
      ],
      [
        $unix,
        "\n",
      ],
      [
        $mac,
        "\r",
      ],
    ];
  }

  /**
   * @covers ::setHasHeader
   * @covers ::getHeader
   */
  public function testHasHeader() {
    $file = dirname(dirname(dirname(dirname(__DIR__)))) . '/tests/resources/csv/example.csv';
    $parser = CsvParser::createFromFilePath($file)
      ->setHasHeader();
    $this
      ->assertSame(count(iterator_to_array($parser)), 6);
    $this
      ->assertSame([
      'Header A',
      'Header B',
      'Header C',
    ], $parser
      ->getHeader());
  }

  /**
   * Tests using an asterisk as delimiter.
   */
  public function testAlternateSeparator() {

    // This implicitly tests lines without a newline.
    $parser = CsvParser::createFromString("a*b*c")
      ->setDelimiter('*');
    $this
      ->assertSame([
      'a',
      'b',
      'c',
    ], iterator_to_array($parser)[0]);
  }

  /**
   * Tries to create a CsvParser instance with an invalid file path.
   */
  public function testInvalidFilePath() {
    $this
      ->expectException(InvalidArgumentException::class);
    CsvParser::createFromFilePath('beep boop');
  }

  /**
   * Creates a new CsvParser instance with an invalid CSV source.
   */
  public function testInvalidResourcePath() {
    $this
      ->expectException(InvalidArgumentException::class);
    new CsvParser('beep boop');
  }

  /**
   * Basic test for parsing CSV.
   *
   * @dataProvider csvFileProvider
   */
  public function testCsvParsing($file, $expected) {
    $parser = CsvParser::createFromFilePath($file);
    $parser
      ->setHasHeader();
    $header = $parser
      ->getHeader();
    $output = [];
    $test = [];
    foreach (iterator_to_array($parser) as $row) {
      $new_row = [];
      foreach ($row as $key => $value) {
        if (isset($header[$key])) {
          $new_row[$header[$key]] = $value;
        }
      }
      $output[] = $new_row;
    }
    $this
      ->assertSame($expected, $output);
  }

  /**
   * Data provider for testCsvParsing().
   */
  public function csvFileProvider() {
    $path = dirname(dirname(dirname(dirname(__DIR__)))) . '/tests/resources/csv-parser-component-files';
    $return = [];
    foreach (glob($path . '/csv/*.csv') as $file) {
      $json_file = $path . '/json/' . str_replace('.csv', '.json', basename($file));
      $return[] = [
        $file,
        json_decode(file_get_contents($json_file), TRUE),
      ];
    }
    return $return;
  }

}

Classes

Namesort descending Description
CsvParserTest @coversDefaultClass \Drupal\feeds\Component\CsvParser @group feeds