Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
<?php
namespace Ddeboer\DataImport\Filter;
use Ddeboer\DataImport\Filter\DateTimeThresholdFilter;
use Ddeboer\DataImport\ValueConverter\DateTimeValueConverter;
class DateTimeFilterTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->items = array(
'a' => array('updated_at' => '-3 day'),
'b' => array('updated_at' => '-2 day'),
'c' => array('updated_at' => '-1 day'),
'd' => array('updated_at' => 'today'),
'e' => array('updated_at' => 'now'),
'f' => array('updated_at' => '+1 day'),
);
}
private function applyFilter(DateTimeThresholdFilter $filter, array $items)
{
return array_filter($items, array($filter, '__invoke'));
}
/**
* @expectedException \LogicException
* @expectedExceptionMessage Make sure you set a threshold
*/
public function testDefaultFilter()
{
$this->applyFilter(
new DateTimeThresholdFilter(new DateTimeValueConverter()),
$this->items
);
}
public function testFilter()
{
$resultItems = $this->applyFilter(new DateTimeThresholdFilter(
new DateTimeValueConverter(),
new \DateTime('today')
), $this->items);
$this->assertEquals(
array('d', 'e', 'f'),
array_keys($resultItems)
);
}
public function testSetter()
{
$filter = new DateTimeThresholdFilter(new DateTimeValueConverter());
$filter->setThreshold(new \DateTime('today'));
$resultItems = $this->applyFilter($filter, $this->items);
$this->assertEquals(
array('d', 'e', 'f'),
array_keys($resultItems)
);
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace Ddeboer\DataImport\Filter;
use Ddeboer\DataImport\Filter\OffsetFilter;
/**
* @author Ville Mattila <ville@eventio.fi>
*/
class OffsetFilterTest extends \PHPUnit_Framework_TestCase
{
private function applyFilter(OffsetFilter $filter, array $items) {
$result = array();
foreach ($items as $item) {
if (true === call_user_func($filter, array($item))) {
$result[] = $item;
}
}
return $result;
}
public function testDefaultFilter()
{
$items = array('first','second','third','fourth');
$resultItems = $this->applyFilter(new OffsetFilter(), $items);
$this->assertEquals($resultItems, $items);
}
public function testStartOffset()
{
$items = array('first','second','third','fourth');
$resultItems = $this->applyFilter(new OffsetFilter(1), $items);
$this->assertEquals($resultItems, array('second','third','fourth'));
}
public function testMaxCount()
{
$items = array('first','second','third','fourth');
$resultItems = $this->applyFilter(new OffsetFilter(0, 2), $items);
$this->assertEquals($resultItems, array('first','second'));
}
public function testOffsetWithMaxCount()
{
$items = array('first','second','third','fourth');
$resultItems = $this->applyFilter(new OffsetFilter(1, 1), $items);
$this->assertEquals($resultItems, array('second'));
}
}

View File

@@ -0,0 +1,108 @@
<?php
namespace Ddeboer\DataImport\Tests\Filter;
use Ddeboer\DataImport\Exception\ValidationException;
use Ddeboer\DataImport\Filter\ValidatorFilter;
use Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\ConstraintViolationList;
class ValidationFilterTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
$this->validator = $this->getMock('Symfony\\Component\\Validator\\Validator\\ValidatorInterface');
$this->filter = new ValidatorFilter($this->validator);
}
public function testFilterWithValid()
{
$item = array('foo' => 'bar');
$list = new ConstraintViolationList();
$this->validator->expects($this->once())
->method('validate')
->willReturn($list);
$this->assertTrue(call_user_func($this->filter, $item));
}
public function testFilterWithInvalidItem()
{
$item = array('foo' => 'bar');
$violation = $this->getMock('Symfony\\Component\\Validator\\ConstraintViolationInterface');
$list = new ConstraintViolationList(array($violation));
$this->validator->expects($this->once())
->method('validate')
->willReturn($list);
$this->assertFalse(call_user_func($this->filter, $item));
$this->assertEquals(array(1 => $list), $this->filter->getViolations());
}
public function testStopOnFirstError()
{
$this->filter->throwExceptions();
$item = array('foo' => 'bar');
$violation = $this->getMock('Symfony\\Component\\Validator\\ConstraintViolationInterface');
$list = new ConstraintViolationList(array($violation));
$this->validator->expects($this->once())
->method('validate')
->willReturn($list);
try {
call_user_func($this->filter, $item);
$this->fail('ValidationException should be thrown');
} catch (ValidationException $e) {
$this->assertSame(1, $e->getLineNumber());
$this->assertEquals($list, $e->getViolations());
}
}
public function testFilterNonStrict()
{
$this->filter->setStrict(false);
$item = array('foo' => true, 'bar' => true);
$this->filter->add('foo', new Constraints\IsTrue());
$this->assertTrue(call_user_func($this->filter, $item));
}
public function testFilterLineNumbers()
{
$this->filter->throwExceptions();
$item = array('foo' => 'bar');
$violation = $this->getMock('Symfony\\Component\\Validator\\ConstraintViolationInterface');
$list = new ConstraintViolationList(array($violation));
$this->validator->expects($this->exactly(2))
->method('validate')
->willReturn($list);
try {
$this->assertTrue(call_user_func($this->filter, $item));
$this->fail('ValidationException should be thrown (1)');
} catch (ValidationException $e) {
$this->assertSame(1, $e->getLineNumber());
$this->assertEquals($list, $e->getViolations());
}
try {
$this->assertTrue(call_user_func($this->filter, $item));
$this->fail('ValidationException should be thrown (2)');
} catch (ValidationException $e) {
$this->assertSame(2, $e->getLineNumber());
$this->assertEquals($list, $e->getViolations());
}
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Ddeboer\DataImport\Tests\Fixtures\Entity;
class TestEntity
{
private $firstProperty;
private $secondProperty;
private $firstAssociation;
public function getFirstProperty()
{
return $this->firstProperty;
}
public function setFirstProperty($firstProperty)
{
$this->firstProperty = $firstProperty;
}
public function getSecondProperty()
{
return $this->secondProperty;
}
public function setSecondProperty($secondProperty)
{
$this->secondProperty = $secondProperty;
}
public function getFirstAssociation()
{
return $this->firstAssociation;
}
public function setFirstAssociation($firstAssociation)
{
$this->firstAssociation = $firstAssociation;
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Ddeboer\DataImport\Tests\Fixtures\Entity;
/**
* @Entity()
*/
class User
{
/** @Id @GeneratedValue @Column(type="integer") **/
private $id;
/** @Column(type="string") */
private $username;
public function getId()
{
return $this->id;
}
public function getUsername()
{
return $this->username;
}
public function setUsername($username)
{
$this->username = $username;
}
}

View File

@@ -0,0 +1 @@
50,123,"Description"
Can't render this file because it contains an unexpected character in line 1 and column 20.

View File

@@ -0,0 +1,4 @@
id,number,description
50,123,"Description"
6,456,"Another description"
7,7890,"Some more info"
1 id number description
2 50 123 Description
3 6 456 Another description
4 7 7890 Some more info

Binary file not shown.

View File

@@ -0,0 +1,2 @@
id,description,description,description,details,details,last
50,"First","Second","Third","Details1","Details2","Last one"
1 id description description description details details last
2 50 First Second Third Details1 Details2 Last one

View File

@@ -0,0 +1,5 @@
id,number,description
50,123,"Description"
123,test
7,7890,Some more info,"too many columns"
123,66,Valid
1 id number description
2 50 123 Description
3 123 test
4 7 7890 Some more info too many columns
5 123 66 Valid

View File

@@ -0,0 +1 @@
50,123,"Description"
Can't render this file because it contains an unexpected character in line 1 and column 20.

View File

@@ -0,0 +1,4 @@
id,number,description
50,123,"Description"
6,456
7,7890,"Some more info"
1 id number description
2 50 123 Description
3 6 456
4 7 7890 Some more info

View File

@@ -0,0 +1,4 @@
id,number,description
50,123,"Description"
6,456,"Another description","Some more info"
7,7890,"Yet another description"
1 id number description
2 50 123 Description
3 6 456 Another description Some more info
4 7 7890 Yet another description

Binary file not shown.

View File

@@ -0,0 +1,3 @@
50,123,"Description"
6,456,"Another description"
7,7890,"Some more info"
1 50 123 Description
2 6 456 Another description
3 7 7890 Some more info

View File

@@ -0,0 +1,5 @@
50,123,"Description"
6,"strictly invalid"
7,7890,"Some more info"
3,230,"Yet more info","Even more info"
"strictly invalid"
1 50 123 Description
2 6 strictly invalid
3 7 7890 Some more info
4 3 230 Yet more info Even more info
5 strictly invalid

View File

@@ -0,0 +1,44 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader;
use Ddeboer\DataImport\Reader\CountableIteratorReader;
/**
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
*/
class CountableIteratorReaderTest extends \PHPUnit_Framework_TestCase
{
public function testCount()
{
$iterator = new \ArrayIterator([
[
'id' => 1,
'username' => 'john.doe',
'name' => 'John Doe',
],
]);
$reader = new CountableIteratorReader($iterator);
// We need to rewind the iterator
$reader->rewind();
$this->assertEquals(1, $reader->count());
}
public function testIteratorCount()
{
$reader = new CountableIteratorReader(new CountableIterator);
// We need to rewind the iterator
$reader->rewind();
$this->assertEquals(0, $reader->count());
}
}
class CountableIterator extends \EmptyIterator
{
}

View File

@@ -0,0 +1,281 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader;
use Ddeboer\DataImport\Reader\CsvReader;
class CsvReaderTest extends \PHPUnit_Framework_TestCase
{
public function testReadCsvFileWithColumnHeaders()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_column_headers.csv');
$csvReader = new CsvReader($file);
$csvReader->setHeaderRowNumber(0);
$this->assertEquals(
array(
'id', 'number', 'description'
),
$csvReader->getFields()
);
foreach ($csvReader as $row) {
$this->assertNotNull($row['id']);
$this->assertNotNull($row['number']);
$this->assertNotNull($row['description']);
}
$this->assertEquals(
array(
'id' => 6,
'number' => '456',
'description' => 'Another description'
),
$csvReader->getRow(2)
);
}
public function testReadCsvFileWithoutColumnHeaders()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_no_column_headers.csv');
$csvReader = new CsvReader($file);
$this->assertEmpty($csvReader->getColumnHeaders());
}
public function testReadCsvFileWithManualColumnHeaders()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_no_column_headers.csv');
$csvReader = new CsvReader($file);
$csvReader->setColumnHeaders(array('id', 'number', 'description'));
foreach ($csvReader as $row) {
$this->assertNotNull($row['id']);
$this->assertNotNull($row['number']);
$this->assertNotNull($row['description']);
}
}
public function testReadCsvFileWithTrailingBlankLines()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_blank_lines.csv');
$csvReader = new CsvReader($file);
$csvReader->setColumnHeaders(array('id', 'number', 'description'));
foreach ($csvReader as $row) {
$this->assertNotNull($row['id']);
$this->assertNotNull($row['number']);
$this->assertNotNull($row['description']);
}
}
public function testCountWithoutHeaders()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_no_column_headers.csv');
$csvReader = new CsvReader($file);
$this->assertEquals(3, $csvReader->count());
}
public function testCountWithHeaders()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_column_headers.csv');
$csvReader = new CsvReader($file);
$csvReader->setHeaderRowNumber(0);
$this->assertEquals(3, $csvReader->count(), 'Row count should not include header');
}
public function testCountWithFewerElementsThanColumnHeadersNotStrict()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_fewer_elements_than_column_headers.csv');
$csvReader = new CsvReader($file);
$csvReader->setStrict(false);
$csvReader->setHeaderRowNumber(0);
$this->assertEquals(3, $csvReader->count());
}
public function testCountWithMoreElementsThanColumnHeadersNotStrict()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_more_elements_than_column_headers.csv');
$csvReader = new CsvReader($file);
$csvReader->setStrict(false);
$csvReader->setHeaderRowNumber(0);
$this->assertEquals(3, $csvReader->count());
$this->assertFalse($csvReader->hasErrors());
$this->assertEquals(array(6, 456, 'Another description'), array_values($csvReader->getRow(2)));
}
public function testCountDoesNotMoveFilePointer()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_column_headers.csv');
$csvReader = new CsvReader($file);
$csvReader->setHeaderRowNumber(0);
$key_before_count = $csvReader->key();
$csvReader->count();
$key_after_count = $csvReader->key();
$this->assertEquals($key_after_count, $key_before_count);
}
public function testVaryingElementCountWithColumnHeadersNotStrict()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_column_headers_varying_element_count.csv');
$csvReader = new CsvReader($file);
$csvReader->setStrict(false);
$csvReader->setHeaderRowNumber(0);
$this->assertEquals(4, $csvReader->count());
$this->assertFalse($csvReader->hasErrors());
}
public function testVaryingElementCountWithoutColumnHeadersNotStrict()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_no_column_headers_varying_element_count.csv');
$csvReader = new CsvReader($file);
$csvReader->setStrict(false);
$csvReader->setColumnHeaders(array('id', 'number', 'description'));
$this->assertEquals(5, $csvReader->count());
$this->assertFalse($csvReader->hasErrors());
}
public function testInvalidCsv()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_column_headers_varying_element_count.csv');
$reader = new CsvReader($file);
$reader->setHeaderRowNumber(0);
$this->assertTrue($reader->hasErrors());
$this->assertCount(2, $reader->getErrors());
$errors = $reader->getErrors();
$this->assertEquals(2, key($errors));
$this->assertEquals(array('123', 'test'), current($errors));
next($errors);
$this->assertEquals(3, key($errors));
$this->assertEquals(array('7', '7890', 'Some more info', 'too many columns'), current($errors));
}
public function testLastRowInvalidCsv()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_no_column_headers_varying_element_count.csv');
$reader = new CsvReader($file);
$reader->setColumnHeaders(array('id', 'number', 'description'));
$this->assertTrue($reader->hasErrors());
$this->assertCount(3, $reader->getErrors());
$errors = $reader->getErrors();
$this->assertEquals(1, key($errors));
$this->assertEquals(array('6', 'strictly invalid'), current($errors));
next($errors);
$this->assertEquals(3, key($errors));
$this->assertEquals(array('3','230','Yet more info','Even more info'), current($errors));
next($errors);
$this->assertEquals(4, key($errors));
$this->assertEquals(array('strictly invalid'), current($errors));
}
public function testLineBreaks()
{
$reader = $this->getReader('data_cr_breaks.csv');
$this->assertCount(3, $reader);
}
/**
* @expectedException \Ddeboer\DataImport\Exception\DuplicateHeadersException description
*/
public function testDuplicateHeadersThrowsException()
{
$reader = $this->getReader('data_column_headers_duplicates.csv');
$reader->setHeaderRowNumber(0);
}
public function testDuplicateHeadersIncrement()
{
$reader = $this->getReader('data_column_headers_duplicates.csv');
$reader->setHeaderRowNumber(0, CsvReader::DUPLICATE_HEADERS_INCREMENT);
$reader->rewind();
$current = $reader->current();
$this->assertEquals(
array('id', 'description', 'description1', 'description2', 'details', 'details1', 'last'),
$reader->getColumnHeaders()
);
$this->assertEquals(
array(
'id' => '50',
'description' => 'First',
'description1' => 'Second',
'description2' => 'Third',
'details' => 'Details1',
'details1' => 'Details2',
'last' => 'Last one'
),
$current
);
}
public function testDuplicateHeadersMerge()
{
$reader = $this->getReader('data_column_headers_duplicates.csv');
$reader->setHeaderRowNumber(0, CsvReader::DUPLICATE_HEADERS_MERGE);
$reader->rewind();
$current = $reader->current();
$this->assertCount(4, $reader->getColumnHeaders());
$expected = array(
'id' => '50',
'description' => array('First', 'Second', 'Third'),
'details' => array('Details1', 'Details2'),
'last' => 'Last one'
);
$this->assertEquals($expected, $current);
}
public function testMaximumNesting()
{
if (!function_exists('xdebug_is_enabled')) {
$this->markTestSkipped('xDebug is not installed');
}
$xdebug_start = !xdebug_is_enabled();
if ($xdebug_start) {
xdebug_enable();
}
ini_set('xdebug.max_nesting_level', 200);
$file = new \SplTempFileObject();
for($i = 0; $i < 500; $i++) {
$file->fwrite("1,2,3\n");
}
$reader = new CsvReader($file);
$reader->rewind();
$reader->setStrict(true);
$reader->setColumnHeaders(array('one','two'));
$current = $reader->current();
$this->assertEquals(null, $current);
if ($xdebug_start) {
xdebug_disable();
}
}
protected function getReader($filename)
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/'.$filename);
return new CsvReader($file);
}
}

View File

@@ -0,0 +1,200 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader;
use Ddeboer\DataImport\Reader\DbalReader;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Schema;
class DbalReaderTest extends \PHPUnit_Framework_TestCase
{
public function testCalculateRowCount()
{
$reader = $this->getReader();
$reader->setRowCountCalculated();
$this->assertTrue($reader->isRowCountCalculated());
$reader->setRowCountCalculated(false);
$this->assertFalse($reader->isRowCountCalculated());
$reader->setRowCountCalculated(true);
$this->assertTrue($reader->isRowCountCalculated());
}
public function testGetFields()
{
$fields = $this->getReader()->getFields();
$this->assertInternalType('array', $fields);
$this->assertEquals(array('id', 'username', 'name'), $fields);
}
public function testCount()
{
$this->assertEquals(10, $this->getReader()->count());
}
public function testCountInhibited()
{
$reader = $this->getReader();
$reader->setRowCountCalculated(false);
$this->assertEquals(null, $reader->count());
}
public function testSqlAndParamsAreMutable()
{
$reader = $this->getReader();
$reader->setSql('SELECT * FROM groups WHERE id = :id', array('id' => 2));
$this->assertAttributeEquals('SELECT * FROM groups WHERE id = :id', 'sql', $reader);
$this->assertAttributeEquals(array('id' => 2), 'params', $reader);
}
public function testChangeSqlOrParamsClearsNumRowsAndStatement()
{
$reader = $this->getReader();
$reader->count();
$reader->getFields();
$this->assertAttributeNotEmpty('rowCount', $reader);
$this->assertAttributeNotEmpty('stmt', $reader);
$reader->setSql('SELECT * FROM `user` WHERE id IN (:id)', array('id' => array()));
$this->assertAttributeEmpty('rowCount', $reader);
$this->assertAttributeEmpty('stmt', $reader);
}
public function testIterate()
{
$i=31;
foreach ($this->getReader() as $key => $row) {
$this->assertInternalType('array', $row);
$this->assertEquals('user-'.$i, $row['username']);
$this->assertEquals($i - 31, $key);
$i++;
}
$this->assertEquals(41, $i);
}
public function testReaderRewindWorksCorrectly()
{
$reader = $this->getReader();
foreach ($reader as $row) {
if (!isset($row['username'])) {
$this->fail('There should be a username');
}
if ($row['username'] == 'user-35') {
break;
}
}
$reader->rewind();
$this->assertEquals(array(
'id' => 31,
'username' => 'user-31',
'name' => 'name 4',
), $reader->current());
}
public function testCallingCurrentTwiceShouldNotAdvance()
{
$reader = $this->getReader();
$expected = array(
'id' => 31,
'username' => 'user-31',
'name' => 'name 4',
);
$this->assertEquals($expected, $reader->current());
$this->assertEquals($expected, $reader->current());
}
public function testEmptyResultDoesNotThrowException()
{
$reader = $this->getReader();
$reader->setSql(null, array('name' => 'unknown group'));
$this->assertInternalType('array', $reader->getFields());
}
public function testCallValidRewindsIfNeeded()
{
$reader = $this->getReader();
$this->assertTrue($reader->valid());
$this->assertAttributeInternalType('array', 'data', $reader);
}
public function getConnection()
{
$params = array(
'driver' => 'pdo_sqlite',
'memory' => true,
);
$connection = DriverManager::getConnection($params, new Configuration());
$schema = new Schema();
$table = $schema->createTable('groups');
$table->addColumn('id', 'integer', ['autoincrement' => true]);
$table->addColumn('name', 'string', array('length' => 45));
$table->setPrimaryKey(array('id'));
$myTable = $schema->createTable('user');
$myTable->addColumn('id', 'integer', array('unsigned' => true, 'autoincrement' => true));
$myTable->addColumn('username', 'string', array('length' => 32));
$myTable->addColumn('group_id', 'integer');
$myTable->setPrimaryKey(array('id'));
$myTable->addUniqueIndex(array('username'));
$myTable->addForeignKeyConstraint($table, array('group_id'), array('id'));
foreach ($schema->toSql(new SqlitePlatform()) as $query) {
$connection->query($query);
};
return $connection;
}
protected function getReader()
{
$connection = $this->getConnection();
$this->loadFixtures($connection);
return new DbalReader($connection, implode(' ', array(
'SELECT u.id, u.username, g.name',
'FROM `user` u INNER JOIN groups g ON u.group_id = g.id',
'WHERE g.name LIKE :name',
)), array(
'name' => 'name 4',
));
}
/**
* @param Connection $connection
*/
protected function loadFixtures($connection)
{
$counter = 1;
for ($i = 1; $i <= 10; $i++) {
$connection->insert('groups', array('name' => "name {$i}"));
$id = $connection->lastInsertId();
for ($j = 1; $j <= 10; $j++) {
$connection->insert('user', array(
'username' => "user-{$counter}",
'group_id' => $id,
));
$counter++;
}
}
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader;
use Ddeboer\DataImport\Reader\DoctrineReader;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Setup;
use Ddeboer\DataImport\Tests\Fixtures\Entity\User;
class DoctrineReaderTest extends \PHPUnit_Framework_TestCase
{
public function testGetFields()
{
$fields = $this->getReader()->getFields();
$this->assertInternalType('array', $fields);
$this->assertEquals(array('id', 'username'), $fields);
}
public function testCount()
{
$this->assertEquals(100, $this->getReader()->count());
}
public function testIterate()
{
$i = 1;
foreach ($this->getReader() as $data) {
$this->assertInternalType('array', $data);
$this->assertEquals('user' . $i, $data['username']);
$i++;
}
}
protected function getReader()
{
$em = $this->getEntityManager();
for ($i = 1; $i <= 100; $i++) {
$user = new User();
$user->setUsername('user'. $i);
$em->persist($user);
}
$em->flush();
return new DoctrineReader($em, 'Ddeboer\DataImport\Tests\Fixtures\Entity\User');
}
protected function getEntityManager()
{
$dbParams = array(
'driver' => 'pdo_sqlite',
);
$paths = array(
__DIR__.'/../Fixtures/Entity'
);
$config = Setup::createAnnotationMetadataConfiguration($paths, true);
$em = EntityManager::create($dbParams, $config);
$schemaTool = new \Doctrine\ORM\Tools\SchemaTool($em);
$schemaTool->createSchema(
array(
$em->getMetadataFactory()->getMetadataFor('Ddeboer\DataImport\Tests\Fixtures\Entity\User')
)
);
return $em;
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader;
use Ddeboer\DataImport\Reader\ExcelReader;
class ExcelReaderTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
if (!extension_loaded('zip')) {
$this->markTestSkipped();
}
}
public function testGetFields()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_column_headers.xlsx');
$reader = new ExcelReader($file, 0);
$this->assertEquals(array('id', 'number', 'description'), $reader->getFields());
$this->assertEquals(array('id', 'number', 'description'), $reader->getColumnHeaders());
}
public function testCountWithoutHeaders()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_no_column_headers.xls');
$reader = new ExcelReader($file);
$this->assertEquals(3, $reader->count());
}
public function testCountWithHeaders()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_column_headers.xlsx');
$reader = new ExcelReader($file, 0);
$this->assertEquals(3, $reader->count());
}
public function testIterate()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_column_headers.xlsx');
$reader = new ExcelReader($file, 0);
foreach ($reader as $row) {
$this->assertInternalType('array', $row);
$this->assertEquals(array('id', 'number', 'description'), array_keys($row));
}
}
public function testMultiSheet()
{
$file = new \SplFileObject(__DIR__.'/../Fixtures/data_multi_sheet.xls');
$sheet1reader = new ExcelReader($file, null, 0);
$this->assertEquals(3, $sheet1reader->count());
$sheet2reader = new ExcelReader($file, null, 1);
$this->assertEquals(2, $sheet2reader->count());
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader\Factory;
use Ddeboer\DataImport\Reader\Factory\CsvReaderFactory;
class CsvReaderFactoryTest extends \PHPUnit_Framework_TestCase
{
public function testGetReader()
{
$factory = new CsvReaderFactory();
$reader = $factory->getReader(new \SplFileObject(__DIR__.'/../../Fixtures/data_column_headers.csv'));
$this->assertInstanceOf('\Ddeboer\DataImport\Reader\CsvReader', $reader);
$this->assertCount(4, $reader);
$factory = new CsvReaderFactory(0);
$reader = $factory->getReader(new \SplFileObject(__DIR__.'/../../Fixtures/data_column_headers.csv'));
$this->assertCount(3, $reader);
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader\Factory;
use Ddeboer\DataImport\Reader\Factory\ExcelReaderFactory;
class DbalReaderFactoryTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
if (!extension_loaded('zip')) {
$this->markTestSkipped();
}
}
public function testGetReader()
{
$factory = new ExcelReaderFactory();
$reader = $factory->getReader(new \SplFileObject(__DIR__.'/../../Fixtures/data_column_headers.xlsx'));
$this->assertInstanceOf('\Ddeboer\DataImport\Reader\ExcelReader', $reader);
$this->assertCount(4, $reader);
$factory = new ExcelReaderFactory(0);
$reader = $factory->getReader(new \SplFileObject(__DIR__.'/../../Fixtures/data_column_headers.xlsx'));
$this->assertCount(3, $reader);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader\Factory;
use Ddeboer\DataImport\Reader\Factory\DoctrineReaderFactory;
class DoctrineReaderFactoryTest extends \PHPUnit_Framework_TestCase
{
public function testGetReader()
{
$om = $this->getMockBuilder('\Doctrine\Common\Persistence\ObjectManager')->getMock();
$factory = new DoctrineReaderFactory($om);
$reader = $factory->getReader('Some:Object');
$this->assertInstanceOf('\Ddeboer\DataImport\Reader\DoctrineReader', $reader);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader\Factory;
use Ddeboer\DataImport\Reader\Factory\DoctrineReaderFactory;
class ExcelReaderFactoryTest extends \PHPUnit_Framework_TestCase
{
public function testGetReader()
{
$om = $this->getMockBuilder('\Doctrine\Common\Persistence\ObjectManager')->getMock();
$factory = new DoctrineReaderFactory($om);
$reader = $factory->getReader('Some:Object');
$this->assertInstanceOf('\Ddeboer\DataImport\Reader\DoctrineReader', $reader);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader;
use Ddeboer\DataImport\Reader\IteratorReader;
/**
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
*/
class IteratorReaderTest extends \PHPUnit_Framework_TestCase
{
public function testGetFields()
{
$iterator = new \ArrayIterator([
[
'id' => 1,
'username' => 'john.doe',
'name' => 'John Doe',
],
]);
$reader = new IteratorReader($iterator);
// We need to rewind the iterator
$reader->rewind();
$fields = $reader->getFields();
$this->assertInternalType('array', $fields);
$this->assertEquals(['id', 'username', 'name'], $fields);
}
}

View File

@@ -0,0 +1,347 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader;
use Ddeboer\DataImport\Reader\ArrayReader;
use Ddeboer\DataImport\Reader\OneToManyReader;
/**
* Class OneToManyReaderTest
* @package Ddeboer\DataImport\Tests\Reader
* @author Aydin Hassan <aydin@hotmail.co.uk>
*/
class OneToManyReaderTest extends \PHPUnit_Framework_TestCase
{
public function testReaderMergesOneToMany()
{
$leftData = array(
array(
'OrderId' => 1,
'Price' => 30,
),
array(
'OrderId' => 2,
'Price' => 15,
),
);
$rightData = array(
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 1',
),
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 2',
),
array(
'OrderId' => 2,
'Name' => 'Super Cool Item 1',
),
);
$leftReader = new ArrayReader($leftData);
$rightReader = new ArrayReader($rightData);
$oneToManyReader = new OneToManyReader($leftReader, $rightReader, 'items', 'OrderId', 'OrderId');
$expected = array(
array(
'OrderId' => 1,
'Price' => 30,
'items' => array(
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 1',
),
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 2',
),
),
),
array(
'OrderId' => 2,
'Price' => 15,
'items' => array(
array(
'OrderId' => 2,
'Name' => 'Super Cool Item 1',
),
)
),
);
$i = 0;
foreach($oneToManyReader as $row) {
$this->assertEquals($row, $expected[$i++]);
}
}
public function testIfRightReaderIdFieldIsMissingLeftIsUsed()
{
$leftData = array(
array(
'OrderId' => 1,
'Price' => 30,
),
array(
'OrderId' => 2,
'Price' => 15,
),
);
$rightData = array(
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 1',
),
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 2',
),
array(
'OrderId' => 2,
'Name' => 'Super Cool Item 1',
),
);
$leftReader = new ArrayReader($leftData);
$rightReader = new ArrayReader($rightData);
$oneToManyReader = new OneToManyReader($leftReader, $rightReader, 'items', 'OrderId');
$expected = array(
array(
'OrderId' => 1,
'Price' => 30,
'items' => array(
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 1',
),
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 2',
),
),
),
array(
'OrderId' => 2,
'Price' => 15,
'items' => array(
array(
'OrderId' => 2,
'Name' => 'Super Cool Item 1',
),
)
),
);
$i = 0;
foreach($oneToManyReader as $row) {
$this->assertEquals($row, $expected[$i++]);
}
}
public function testReaderThrowsExceptionIfNestKeyExistsInLeftReaderRow()
{
$leftData = array(
array(
'OrderId' => 1,
'Price' => 30,
'items' => null,
),
);
$rightData = array(
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 1',
),
);
$leftReader = new ArrayReader($leftData);
$rightReader = new ArrayReader($rightData);
$oneToManyReader = new OneToManyReader($leftReader, $rightReader, 'items', 'OrderId');
$this->setExpectedException('Ddeboer\DataImport\Exception\ReaderException', 'Left Row: "0" Reader already contains a field named "items". Please choose a different nest key field');
$oneToManyReader->rewind();
$oneToManyReader->current();
}
public function testReaderThrowsExceptionIfIdFieldDoesNotExistInLeftRow()
{
$leftData = array(
array(
'Price' => 30,
),
);
$rightData = array(
array(
'Name' => 'Super Cool Item 1',
),
);
$leftReader = new ArrayReader($leftData);
$rightReader = new ArrayReader($rightData);
$oneToManyReader = new OneToManyReader($leftReader, $rightReader, 'items', 'OrderId');
$this->setExpectedException('Ddeboer\DataImport\Exception\ReaderException', 'Row: "0" has no field named "OrderId"');
$oneToManyReader->rewind();
$oneToManyReader->current();
}
public function testReaderThrowsExceptionIfIdFieldDoesNotExistInRightRow()
{
$leftData = array(
array(
'OrderId' => 1,
'Price' => 30,
),
);
$rightData = array(
array(
'Name' => 'Super Cool Item 1',
),
);
$leftReader = new ArrayReader($leftData);
$rightReader = new ArrayReader($rightData);
$oneToManyReader = new OneToManyReader($leftReader, $rightReader, 'items', 'OrderId');
$this->setExpectedException('Ddeboer\DataImport\Exception\ReaderException', 'Row: "0" has no field named "OrderId"');
$oneToManyReader->rewind();
$oneToManyReader->current();
}
public function testGetKeysReturnsLeftReaderColumnsMergedWithNestKey()
{
$leftReader = new ArrayReader(array(array('col1' => 'data1', 'col2' => 'data2'), array('data3', 'data4')));
$rightReader = new ArrayReader(array());
$oneToManyReader = new OneToManyReader($leftReader, $rightReader, 'items', 'OrderId');
$this->assertSame(array('col1', 'col2', 'items'), $oneToManyReader->getFields());
}
public function testCountReturnsTheCountOfTheLeftReader()
{
$leftReader = new ArrayReader(array());
$rightReader = new ArrayReader(array());
$oneToManyReader = new OneToManyReader($leftReader, $rightReader, 'items', 'OrderId');
$this->assertEquals(0, $oneToManyReader->count());
$leftReader = new ArrayReader(array(array(), array(), array()));
$oneToManyReader = new OneToManyReader($leftReader, $rightReader, 'items', 'OrderId');
$this->assertEquals(3, $oneToManyReader->count());
}
/**
* This is probably a limitation - but it's not need for current implementation
* @dataProvider outOfOrderRowProvider
*/
public function testOutOfOrderRowsInRightReaderAreNotNested($leftData, $rightData, $expected)
{
//var_dump($leftData);
//var_dump($rightData);
$leftReader = new ArrayReader($leftData);
$rightReader = new ArrayReader($rightData);
$oneToManyReader = new OneToManyReader($leftReader, $rightReader, 'items', 'OrderId');
$i = 0;
foreach($oneToManyReader as $row) {
$this->assertEquals($row, $expected[$i++]);
}
}
public function outOfOrderRowProvider()
{
return array(
'skip-first-right-row' => array(
'left' => array(
array(
'OrderId' => 3,
'Price' => 30,
),
array(
'OrderId' => 2,
'Price' => 15,
),
),
'right' => array(
array(
'OrderId' => 2,
'Name' => 'Super Cool Item 1',
),
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 1',
),
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 2',
),
),
'expected' => array(
array(
'OrderId' => 3,
'Price' => 30,
'items' => array()
),
array(
'OrderId' => 2,
'Price' => 15,
'items' => array(
array(
'OrderId' => 2,
'Name' => 'Super Cool Item 1',
),
)
),
),
),
'skip-out-of-order' => array(
'left' => array(
array(
'OrderId' => 1,
'Price' => 30,
),
array(
'OrderId' => 2,
'Price' => 15,
),
),
'right' => array(
array(
'OrderId' => 0,
'Name' => 'Super Cool Item 1',
),
array(
'OrderId' => 2,
'Name' => 'Super Cool Item 2',
),
array(
'OrderId' => 1,
'Name' => 'Super Cool Item 3',
),
),
'expected' => array(
array(
'OrderId' => 1,
'Price' => 30,
'items' => array()
),
array(
'OrderId' => 2,
'Price' => 15,
'items' => array(),
),
),
),
);
}
}

View File

@@ -0,0 +1,91 @@
<?php
namespace Ddeboer\DataImport\Tests\Reader;
use Ddeboer\DataImport\Reader\PdoReader;
// use Doctrine\DBAL\Configuration;
// use Doctrine\DBAL\DriverManager;
// use Doctrine\DBAL\Platforms\SqlitePlatform;
class PdoReaderTest extends \PHPUnit_Framework_TestCase
{
public function testGetFields()
{
$fields = $this->getReader()->getFields();
$this->assertInternalType('array', $fields);
$this->assertEquals(array('id', 'username', 'name'), $fields);
}
public function testCount()
{
$this->assertEquals(100, $this->getReader()->count());
}
public function testIterate()
{
$i=1;
foreach ($this->getReader() as $row) {
$this->assertInternalType('array', $row);
$this->assertEquals('user-'.$i, $row['username']);
$i++;
}
}
public function testReaderRewindWorksCorrectly()
{
$reader = $this->getReader();
foreach ($reader as $row) {
}
foreach ($reader as $row) {
}
}
public function getConnection()
{
$connection = new \PDO('sqlite::memory:');
// Set error mode = exception for easy debugging
$connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
// Build schema
$connection->query('CREATE TABLE pdo_group (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(45)
)');
$connection->query('CREATE TABLE pdo_user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username VARCHAR(32),
group_id INTEGER,
FOREIGN KEY(group_id) REFERENCES pdo_group(id)
)');
$connection->query('CREATE UNIQUE INDEX user_username ON pdo_user(username)');
return $connection;
}
protected function getReader()
{
$connection = $this->getConnection();
$group_insert = $connection->prepare('INSERT INTO pdo_group (name) VALUES (:name)');
$user_insert = $connection->prepare('INSERT INTO pdo_user (username, group_id) VALUES (:username, :group)');
$counter = 1;
for ($i = 1; $i <= 10; $i++) {
$group_insert->execute(array(':name' => "name {$i}"));
$id = $connection->lastInsertId();
for ($j = 1; $j <= 10; $j++) {
$user_insert->execute(array(
':username' => "user-{$counter}",
':group' => $id
));
$counter++;
}
}
return new PdoReader($connection, 'SELECT u.id, u.username, g.name FROM `pdo_user` u INNER JOIN `pdo_group` g ON u.group_id = g.id');
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace Ddeboer\DataImport\Tests;
use Ddeboer\DataImport\Result;
/**
* Tests For Workflow Result
*
* @author Aydin Hassan <aydin@hotmail.co.uk>
*/
class ResultTest extends \PHPUnit_Framework_TestCase
{
public function testResultName()
{
$result = new Result('export', new \DateTime, new \DateTime, 10, new \SplObjectStorage());
$this->assertSame('export', $result->getName());
}
public function testResultCounts()
{
$result = new Result('export', new \DateTime, new \DateTime, 10, new \SplObjectStorage());
$this->assertSame(10, $result->getTotalProcessedCount());
$this->assertSame(10, $result->getSuccessCount());
$this->assertSame(0, $result->getErrorCount());
$exceptions = new \SplObjectStorage();
$exceptions->attach(new \Exception());
$exceptions->attach(new \Exception());
$result = new Result('export', new \DateTime, new \DateTime, 10, $exceptions);
$this->assertSame(10, $result->getTotalProcessedCount());
$this->assertSame(8, $result->getSuccessCount());
$this->assertSame(2, $result->getErrorCount());
}
public function testDates()
{
$startDate = new \DateTime("22-07-2014 22:00");
$endDate = new \DateTime("22-07-2014 23:30");
$result = new Result('export', $startDate, $endDate, 10, new \SplObjectStorage());
$this->assertSame($startDate, $result->getStartTime());
$this->assertSame($endDate, $result->getEndTime());
$this->assertInstanceOf('DateInterval', $result->getElapsed());
}
public function testHasErrorsReturnsTrueIfAnyExceptions()
{
$exceptions = new \SplObjectStorage();
$exceptions->attach(new \Exception());
$exceptions->attach(new \Exception());
$result = new Result('export', new \DateTime, new \DateTime, 10, $exceptions);
$this->assertTrue($result->hasErrors());
}
public function testHasErrorsReturnsFalseIfNoExceptions()
{
$result = new Result('export', new \DateTime, new \DateTime, 10, new \SplObjectStorage());
$this->assertFalse($result->hasErrors());
}
public function testGetExceptions()
{
$exceptions = new \SplObjectStorage();
$exceptions->attach(new \Exception());
$exceptions->attach(new \Exception());
$result = new Result('export', new \DateTime, new \DateTime, 10, $exceptions);
$this->assertSame($exceptions, $result->getExceptions());
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Ddeboer\DataImport\Tests\Step;
use Ddeboer\DataImport\Step\ConverterStep;
class ConverterStepTest extends \PHPUnit_Framework_TestCase
{
private $step;
protected function setUp()
{
$this->step = new ConverterStep();
}
public function testProcess()
{
$this->step->add(function() { return ['bar']; });
$data = ['foo'];
$this->step->process($data);
$this->assertEquals(['bar'], $data);
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Ddeboer\DataImport\Tests\Step;
use Ddeboer\DataImport\Step\FilterStep;
class FilterStepTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
$this->filter = new FilterStep();
}
public function testProcess()
{
$this->filter->add(function ($v) { return in_array('bar', $v); });
$d = ['foo'];
$this->assertFalse($this->filter->process($d));
$d = ['bar'];
$this->assertTrue($this->filter->process($d));
}
public function testClone()
{
$reflection = new \ReflectionObject($this->filter);
$property = $reflection->getProperty('filters');
$property->setAccessible(true);
$this->filter->add(function ($v) { return in_array('bar', $v); });
$d = ['foo'];
$this->filter->process($d);
$this->assertCount(1, $property->getValue($this->filter));
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Ddeboer\DataImport\Tests\Step;
use Ddeboer\DataImport\Step\MappingStep;
class MappingStepTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
$this->filter = new MappingStep();
}
public function testProcess()
{
$this->filter->map('[foo]', '[bar]');
$data = [
'foo' => '1',
];
$this->filter->process($data);
$this->assertEquals(['bar' => '1'], $data);
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Ddeboer\DataImport\Tests\Step;
use Ddeboer\DataImport\Step\ValidatorStep;
use Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
class ValidatorStepTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
$this->validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface');
$this->filter = new ValidatorStep($this->validator);
}
public function testProcess()
{
$data = ['title' => null];
$this->filter->add('title', $constraint = new Constraints\NotNull());
$list = new ConstraintViolationList();
$list->add($this->buildConstraintViolation());
$this->validator->expects($this->once())
->method('validate')
->willReturn($list);
$this->assertFalse($this->filter->process($data));
$this->assertEquals([1 => $list], $this->filter->getViolations());
}
/**
* @expectedException Ddeboer\DataImport\Exception\ValidationException
*/
public function testProcessWithExceptions()
{
$data = ['title' => null];
$this->filter->add('title', $constraint = new Constraints\NotNull());
$this->filter->throwExceptions();
$list = new ConstraintViolationList();
$list->add($this->buildConstraintViolation());
$this->validator->expects($this->once())
->method('validate')
->willReturn($list);
$this->assertFalse($this->filter->process($data));
}
public function testPriority()
{
$this->assertEquals(128, $this->filter->getPriority());
}
private function buildConstraintViolation()
{
return $this->getMockBuilder('Symfony\Component\Validator\ConstraintViolation')
->disableOriginalConstructor()
->getMock();
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Ddeboer\DataImport\Tests\Step;
use Ddeboer\DataImport\Step\ValueConverterStep;
class ValueConverterStepTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
$this->filter = new ValueConverterStep();
}
public function testProcess()
{
$this->filter->add('[foo]', function($v) { return 'barfoo'; });
$data = ['foo' => 'foobar'];
$this->filter->process($data);
$this->assertEquals(['foo' => 'barfoo'], $data);
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace Ddeboer\DataImport\Tests\ValueConverter;
use Ddeboer\DataImport\ValueConverter\ArrayValueConverterMap;
use Ddeboer\DataImport\ValueConverter\CallbackValueConverter;
/**
* @author Christoph Rosse <christoph@rosse.at>
*/
class ArrayValueConverterMapTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testConvertWithNoArrayArgument()
{
$converter = new ArrayValueConverterMap(array('foo' => function($input) {return $input;}));
call_user_func($converter, 'foo');
}
public function testConvertWithMultipleFields()
{
$data = array(
array(
'foo' => 'test',
'bar' => 'test'
),
array(
'foo' => 'test2',
'bar' => 'test2'
),
);
$addBarConverter = function($input) { return 'bar'.$input; };
$addBazConverter = function($input) { return 'baz'.$input; };
$converter = new ArrayValueConverterMap(
array(
'foo' => array($addBarConverter),
'bar' => array($addBazConverter, $addBarConverter),
)
);
$data = call_user_func($converter, $data);
$this->assertEquals('bartest', $data[0]['foo']);
$this->assertEquals('barbaztest', $data[0]['bar']);
$this->assertEquals('bartest2', $data[1]['foo']);
$this->assertEquals('barbaztest2', $data[1]['bar']);
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Ddeboer\DataImport\Tests\ValueConverter;
use Ddeboer\DataImport\ValueConverter\CharsetValueConverter;
/**
* @author Markus Bachmann <markus.bachmann@bachi.biz>
*/
class CharsetValueConverterTest extends \PHPUnit_Framework_TestCase
{
public function testConvert()
{
$utf8 = utf8_encode('test');
$converter = new CharsetValueConverter('UTF-8');
$this->assertEquals($utf8, call_user_func($converter, $utf8));
$value = iconv('UTF-8', 'UTF-16', $utf8);
$converter = new CharsetValueConverter('UTF-8', 'UTF-16');
$this->assertEquals($utf8, call_user_func($converter, $value));
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Ddeboer\DataImport\Tests\ValueConverter;
use Ddeboer\DataImport\ValueConverter\DateTimeToStringValueConverter;
class DateTimeToStringValueConverterTest extends \PHPUnit_Framework_TestCase
{
public function testConvertWithoutOutputFormatReturnsString()
{
$value = new \DateTime('2010-01-01 01:00:00');
$converter = new DateTimeToStringValueConverter;
$output = $converter->convert($value);
$this->assertEquals('2010-01-01 01:00:00', $output);
}
/**
* @expectedException \Ddeboer\DataImport\Exception\UnexpectedValueException
* @expectedExceptionMessage Input must be DateTime object
*/
public function testInvalidInputFormatThrowsException()
{
$value = '14/10/2008 09:40:20';
$converter = new DateTimeToStringValueConverter;
$converter->convert($value);
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Ddeboer\DataImport\Tests\ValueConverter;
use Ddeboer\DataImport\ValueConverter\DateTimeValueConverter;
class DateTimeValueConverterTest extends \PHPUnit_Framework_TestCase
{
public function testConvertWithoutInputOrOutputFormatReturnsDateTimeInstance()
{
$value = '2011-10-20 13:05';
$converter = new DateTimeValueConverter;
$output = call_user_func($converter, $value);
$this->assertInstanceOf('\DateTime', $output);
$this->assertEquals('13', $output->format('H'));
}
public function testConvertWithFormatReturnsDateTimeInstance()
{
$value = '14/10/2008 09:40:20';
$converter = new DateTimeValueConverter('d/m/Y H:i:s');
$output = call_user_func($converter, $value);
$this->assertInstanceOf('\DateTime', $output);
$this->assertEquals('20', $output->format('s'));
}
public function testConvertWithInputAndOutputFormatReturnsString()
{
$value = '14/10/2008 09:40:20';
$converter = new DateTimeValueConverter('d/m/Y H:i:s', 'd-M-Y');
$output = call_user_func($converter, $value);
$this->assertEquals('14-Oct-2008', $output);
}
public function testConvertWithNoInputStringWithOutputFormatReturnsString()
{
$value = '2011-10-20 13:05';
$converter = new DateTimeValueConverter(null, 'd-M-Y');
$output = call_user_func($converter, $value);
$this->assertEquals('20-Oct-2011', $output);
}
public function testInvalidInputFormatThrowsException()
{
$value = '14/10/2008 09:40:20';
$converter = new DateTimeValueConverter('d-m-y', 'd-M-Y');
$this->setExpectedException("UnexpectedValueException", "14/10/2008 09:40:20 is not a valid date/time according to format d-m-y");
call_user_func($converter, $value);
}
public function testNullIsReturnedIfNullPassed()
{
$converter = new DateTimeValueConverter('d-m-y', 'd-M-Y');
$this->assertNull(call_user_func($converter, null));
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Ddeboer\DataImport\Tests\ValueConverter;
use Ddeboer\DataImport\ValueConverter\MappingValueConverter;
class MappingValueConverterTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException Ddeboer\DataImport\Exception\UnexpectedValueException
* @expectedExceptionMessage Cannot find mapping for value "unexpected value"
*/
public function testConvert()
{
$converter = new MappingValueConverter(array(
'source' => 'destination'
));
$this->assertSame('destination', call_user_func($converter, 'source'));
call_user_func($converter, 'unexpected value');
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Ddeboer\DataImport\Tests\ValueConverter;
use Ddeboer\DataImport\ValueConverter\ObjectConverter;
/**
* @author Markus Bachmann <markus.bachmann@bachi.biz
*/
class ObjectConverterTest extends \PHPUnit_Framework_TestCase
{
public function testGetAndSetPropertyPath()
{
$converter = new ObjectConverter();
$this->assertNull($converter->getPropertyPath());
$converter->setPropertyPath('foo.bar');
$this->assertEquals('foo.bar', $converter->getPropertyPath());
}
public function testConvertWithToString()
{
$converter = new ObjectConverter();
$object = new ToStringDummy();
$this->assertEquals('foo', call_user_func($converter, $object));
}
public function testConvertWithPropertyPath()
{
$converter = new ObjectConverter('foo');
$object = new Dummy();
$this->assertEquals('bar', call_user_func($converter, $object));
}
/**
* @expectedException RuntimeException
*/
public function testConvertAObjectWithoutToString()
{
$converter = new ObjectConverter;
call_user_func($converter, new Dummy());
}
/**
* @expectedException Ddeboer\DataImport\Exception\UnexpectedTypeException
*/
public function testConvetANonObject()
{
$converter = new ObjectConverter();
call_user_func($converter, 'foo');
}
}
class Dummy
{
public $foo = 'bar';
}
class ToStringDummy
{
public function __toString()
{
return 'foo';
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Ddeboer\DataImport\ValueConverter;
use Ddeboer\DataImport\ValueConverter\StringToObjectConverter;
/**
* @author Markus Bachmann <markus.bachmann@bachi.biz>
*/
class StringToObjectConverterTest extends \PHPUnit_Framework_TestCase
{
public function testConvert()
{
$repository = $this->getMock(
'Doctrine\\Common\\Persistence\\ObjectRepository',
array('find', 'findAll', 'findBy', 'findOneBy', 'getClassName', 'findOneByName')
);
$converter = new StringToObjectConverter($repository, 'name');
$class = new \stdClass();
$repository->expects($this->once())
->method('findOneByName')
->with('bar')
->will($this->returnValue($class));
$this->assertEquals($class, call_user_func($converter, 'bar'));
}
}

View File

@@ -0,0 +1,312 @@
<?php
namespace Ddeboer\DataImport\Tests;
use Ddeboer\DataImport\Exception\WriterException;
use Ddeboer\DataImport\Reader\ArrayReader;
use Ddeboer\DataImport\Step\ConverterStep;
use Ddeboer\DataImport\Step\FilterStep;
use Ddeboer\DataImport\Step\MappingStep;
use Ddeboer\DataImport\Step\ValueConverterStep;
use Ddeboer\DataImport\Writer\ArrayWriter;
use Ddeboer\DataImport\Workflow\StepAggregator;
use Ddeboer\DataImport\Filter\CallbackFilter;
use Ddeboer\DataImport\ValueConverter\CallbackValueConverter;
use Ddeboer\DataImport\ItemConverter\CallbackItemConverter;
use Ddeboer\DataImport\Writer\CallbackWriter;
use Ddeboer\DataImport\Exception\SourceNotFoundException;
class WorkflowTest extends \PHPUnit_Framework_TestCase
{
public function testAddStep()
{
$step = $this->getMock('Ddeboer\DataImport\Step');
$this->getWorkflow()->addStep($step);
}
public function testAddCallbackWriter()
{
$this->getWorkflow()->addWriter(new CallbackWriter(function($item) {
// var_dump($item);
}));
}
public function testWriterIsPreparedAndFinished()
{
$writer = $this->getMockBuilder('\Ddeboer\DataImport\Writer\CallbackWriter')
->disableOriginalConstructor()
->getMock();
$writer->expects($this->once())
->method('prepare');
$writer->expects($this->once())
->method('finish');
$this->getWorkflow()->addWriter($writer)
->process();
}
public function testWorkflowWithObjects()
{
$reader = new ArrayReader(array(
new Dummy('foo'),
new Dummy('bar'),
new Dummy('foobar'),
));
$data = array();
$writer = new ArrayWriter($data);
$workflow = new StepAggregator($reader);
$workflow->addWriter($writer);
$converterStep = new ConverterStep([
function($item) { return array('name' => $item->name); }
]);
$valueStep = new ValueConverterStep();
$valueStep->add('[name]', function($name) { return strrev($name); });
$workflow->addStep($converterStep)->addStep($valueStep);
$workflow->process();
$this->assertEquals(array(
array('name' => 'oof'),
array('name' => 'rab'),
array('name' => 'raboof')
), $data);
}
/**
* @expectedException \Ddeboer\DataImport\Exception\UnexpectedTypeException
*/
public function testItemConverterWhichReturnObjects()
{
$reader = new ArrayReader(array(
new Dummy('foo'),
new Dummy('bar'),
new Dummy('foobar'),
));
$data = array();
$writer = new ArrayWriter($data);
$workflow = new StepAggregator($reader);
$workflow->addWriter($writer);
$converterStep = new ConverterStep();
$converterStep->add(function($item) { return $item; });
$workflow->addStep($converterStep)->process();
}
/**
* @expectedException \Ddeboer\DataImport\Exception\UnexpectedTypeException
*/
public function testItemConverterWithObjectsAndNoItemConverters()
{
$reader = new ArrayReader(array(
new Dummy('foo'),
new Dummy('bar'),
new Dummy('foobar'),
));
$data = array();
$writer = new ArrayWriter($data);
$workflow = new StepAggregator($reader);
$workflow->addWriter($writer);
$workflow->process();
}
public function testFilterPriority()
{
$offsetFilter = $this->getMockBuilder('\Ddeboer\DataImport\Filter\OffsetFilter')
->disableOriginalConstructor()
->setMethods(array('__invoke'))
->getMock();
$offsetFilter->expects($this->never())->method('filter');
$validatorFilter = $this->getMockBuilder('\Ddeboer\DataImport\Filter\ValidatorFilter')
->disableOriginalConstructor()
->setMethods(array('__invoke'))
->getMock();
$validatorFilter->expects($this->exactly(3))
->method('__invoke')
->will($this->returnValue(false));
$filterStep = (new FilterStep())
->add($offsetFilter)
->add($validatorFilter);
$this->getWorkflow()
->addStep($filterStep)
->process();
}
public function testFilterPriorityOverride()
{
$offsetFilter = $this->getMockBuilder('\Ddeboer\DataImport\Filter\OffsetFilter')
->disableOriginalConstructor()
->setMethods(array('__invoke'))
->getMock();
$offsetFilter->expects($this->exactly(3))
->method('__invoke')
->will($this->returnValue(false));
$validatorFilter = $this->getMockBuilder('\Ddeboer\DataImport\Filter\ValidatorFilter')
->disableOriginalConstructor()
->setMethods(array('__invoke'))
->getMock();
$validatorFilter->expects($this->never())->method('filter');
$filterStep = (new FilterStep())
->add($offsetFilter, 257)
->add($validatorFilter);
$this->getWorkflow()
->addStep($filterStep)
->process();
}
public function testExceptionInterfaceThrownFromWriterIsCaught()
{
$originalData = array(array('foo' => 'bar'));
$reader = new ArrayReader($originalData);
$array = array();
$writer = $this->getMock('Ddeboer\DataImport\Writer\ArrayWriter', array(), array(&$array));
$exception = new SourceNotFoundException("Log me!");
$writer->expects($this->once())
->method('writeItem')
->with($originalData[0])
->will($this->throwException($exception));
$logger = $this->getMock('Psr\Log\LoggerInterface');
$logger->expects($this->once())
->method('error')
->with($exception->getMessage());
$workflow = new StepAggregator($reader);
$workflow->setLogger($logger);
$workflow->setSkipItemOnFailure(true);
$workflow->addWriter($writer);
$workflow->process();
}
public function testWorkflowResultWhenAllSuccessful()
{
$workflow = $this->getWorkflow();
$result = $workflow->process();
$this->assertInstanceOf('Ddeboer\DataImport\Result', $result);
$this->assertInstanceOf('DateTime', $result->getStartTime());
$this->assertInstanceOf('DateTime', $result->getEndTime());
$this->assertInstanceOf('DateInterval', $result->getElapsed());
$this->assertInstanceOf('Ddeboer\DataImport\Result', $result);
$this->assertSame(3, $result->getTotalProcessedCount());
$this->assertSame(3, $result->getSuccessCount());
$this->assertSame(0, $result->getErrorCount());
$this->assertFalse($result->hasErrors());
$this->assertEmpty($result->getExceptions());
$this->assertSame(null, $result->getName());
}
public function testMultipleMappingsForAnItemAfterAnotherItemConverterwasAdded()
{
$originalData = array(array('foo' => 'bar', 'baz' => 'value'));
$outputTestData = array();
$writer = new ArrayWriter($outputTestData);
$reader = new ArrayReader($originalData);
$workflow = new StepAggregator($reader);
$converterStep = new ConverterStep();
// add a dummy item converter
$converterStep->add(function($item) { return $item; });
$mappingStep = (new MappingStep())
->map('[foo]', '[bar]')
->map('[baz]', '[bazzoo]');
// add multiple mappings
$workflow
->addStep($converterStep)
->addStep($mappingStep)
->addWriter($writer)
->process()
;
$this->assertArrayHasKey('bar', $outputTestData[0]);
$this->assertArrayHasKey('bazzoo', $outputTestData[0]);
}
public function _testWorkflowResultWithExceptionThrowFromWriter()
{
$workflow = $this->getWorkflow();
$workflow->setSkipItemOnFailure(true);
$writer = $this->getMock('Ddeboer\DataImport\Writer\WriterInterface');
$e = new WriterException();
$writer
->expects($this->at(1))
->method('writeItem')
->with(array('first' => 'James', 'last' => 'Bond'))
->will($this->throwException($e));
$workflow->addWriter($writer);
$result = $workflow->process();
$this->assertInstanceOf('Ddeboer\DataImport\Result', $result);
$this->assertInstanceOf('DateTime', $result->getStartTime());
$this->assertInstanceOf('DateTime', $result->getEndTime());
$this->assertInstanceOf('DateInterval', $result->getElapsed());
$this->assertInstanceOf('Ddeboer\DataImport\Result', $result);
$this->assertSame(3, $result->getTotalProcessedCount());
$this->assertSame(2, $result->getSuccessCount());
$this->assertSame(1, $result->getErrorCount());
$this->assertTrue($result->hasErrors());
$this->assertSame(array($e), iterator_to_array($result->getExceptions()));
$this->assertSame(null, $result->getName());
}
protected function getWorkflow()
{
$reader = new ArrayReader(array(
array(
'first' => 'James',
'last' => 'Bond'
),
array(
'first' => 'Miss',
'last' => 'Moneypenny'
),
array(
'first' => null,
'last' => 'Doe'
)
));
return new StepAggregator($reader);
}
}
class Dummy
{
public $name;
public function __construct($name)
{
$this->name = $name;
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
class AbstractStreamWriterTest extends StreamWriterTest
{
protected function setUp()
{
$this->writer = $this->getMockForAbstractClass('Ddeboer\\DataImport\\Writer\\AbstractStreamWriter');
}
public function testItImplementsWriterInterface()
{
$this->assertInstanceOf('Ddeboer\\DataImport\\Writer', $this->writer);
}
public function testItThrowsInvalidArgumentExceptionOnInvalidStream()
{
$invalidStreams = array(0, 1, null, 'stream', new \stdClass());
foreach ($invalidStreams as $invalidStream) {
try {
$this->writer->setStream($invalidStream);
$this->fail('Above call should throw exception');
} catch (\InvalidArgumentException $exception) {
$this->assertContains('Expects argument to be a stream resource', $exception->getMessage());
}
}
}
public function testGetStreamReturnsAStreamResource()
{
$this->assertTrue('resource' == gettype($stream = $this->writer->getStream()), 'getStream should return a resource');
$this->assertEquals('stream', get_resource_type($stream));
}
public function testSetStream()
{
$this->assertSame($this->writer, $this->writer->setStream($this->getStream()));
$this->assertSame($this->getStream(), $this->writer->getStream());
}
public function testCloseOnFinishIsInhibitable()
{
$this->assertTrue($this->writer->getCloseStreamOnFinish());
$this->assertSame($this->writer, $this->writer->setCloseStreamOnFinish(false));
$this->assertFalse($this->writer->getCloseStreamOnFinish());
$this->assertSame($this->writer, $this->writer->setCloseStreamOnFinish(true));
$this->assertTrue($this->writer->getCloseStreamOnFinish());
}
public function testCloseOnFinishIsFalseForAutoOpenedStreams()
{
$this->writer->setCloseStreamOnFinish(true);
$this->writer->getStream();
$this->assertFalse($this->writer->getCloseStreamOnFinish());
}
public function testFinishCloseStreamAccordingToCloseOnFinishState()
{
$stream = $this->getStream();
$this->writer->setStream($stream);
$this->writer->prepare();
$this->writer->setCloseStreamOnFinish(false);
$this->writer->finish();
$this->assertTrue(is_resource($stream));
$this->writer->setCloseStreamOnFinish(true);
$this->writer->finish();
$this->assertFalse(is_resource($stream));
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Ddeboer\DataImport\Writer\BatchWriter;
class BatchWriterTest extends \PHPUnit_Framework_TestCase
{
public function testWriteItem()
{
$delegate = $this->getMock('Ddeboer\DataImport\Writer');
$writer = new BatchWriter($delegate);
$delegate->expects($this->once())
->method('prepare');
$delegate->expects($this->never())
->method('writeItem');
$writer->prepare();
$writer->writeItem(['Test']);
}
public function testFlush()
{
$delegate = $this->getMock('Ddeboer\DataImport\Writer');
$writer = new BatchWriter($delegate);
$delegate->expects($this->exactly(20))
->method('writeItem');
$writer->prepare();
for ($i = 0; $i < 20; $i++) {
$writer->writeItem(['Test']);
}
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Ddeboer\DataImport\Writer\CallbackWriter;
/**
* @author Markus Bachmann <markus.bachmann@bachi.biz>
*/
class CallbackWriterTest extends \PHPUnit_Framework_TestCase
{
public function testPrepare()
{
$callable = function(array $item) {
return '';
};
$writer = new CallbackWriter($callable);
$writer->prepare();
}
public function testWriteItem()
{
$string = '';
$callable = function(array $item) use (&$string) {
$string = implode(',', array_values($item));
};
$writer = new CallbackWriter($callable);
$writer->writeItem(array('foo' => 'bar', 'bar' => 'foo'));
$this->assertEquals('bar,foo', $string);
}
public function testFinish()
{
$callable = function(array $item) {
return '';
};
$writer = new CallbackWriter($callable);
$writer->finish();
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Ddeboer\DataImport\Writer\ConsoleProgressWriter;
use Ddeboer\DataImport\Workflow\StepAggregator;
use Ddeboer\DataImport\Reader\ArrayReader;
use Symfony\Component\Console\Output\NullOutput;
class ConsoleProgressWriterTest extends \PHPUnit_Framework_TestCase
{
public function testWrite()
{
$data = array(
array(
'first' => 'The first',
'second' => 'Second property'
), array(
'first' => 'Another first',
'second' => 'Last second'
)
);
$reader = new ArrayReader($data);
$output = $this->getMockBuilder('Symfony\Component\Console\Output\OutputInterface')
->getMock();
$outputFormatter = $this->getMock('Symfony\Component\Console\Formatter\OutputFormatterInterface');
$output->expects($this->once())
->method('isDecorated')
->will($this->returnValue(true));
$output->expects($this->atLeastOnce())
->method('getFormatter')
->will($this->returnValue($outputFormatter));
$output->expects($this->atLeastOnce())
->method('write');
$writer = new ConsoleProgressWriter($output, $reader);
$workflow = new StepAggregator($reader);
$workflow->addWriter($writer)
->process();
$this->assertEquals('debug', $writer->getVerbosity());
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Helper\Table;
use Ddeboer\DataImport\Workflow\StepAggregator;
use Ddeboer\DataImport\Reader\ArrayReader;
use Ddeboer\DataImport\ItemConverter\MappingItemConverter;
use Ddeboer\DataImport\Writer\ConsoleTableWriter;
/**
* @author Igor Mukhin <igor.mukhin@gmail.com>
*/
class ConsoleTableWriterTest extends \PHPUnit_Framework_TestCase
{
public function testRightColumnsHeadersNamesAfterItemConverter()
{
$data = array(
array(
'firstname' => 'John',
'lastname' => 'Doe'
),
array(
'firstname' => 'Ivan',
'lastname' => 'Sidorov'
)
);
$reader = new ArrayReader($data);
$output = new BufferedOutput();
$table = $this->getMockBuilder('Symfony\Component\Console\Helper\Table')
->disableOriginalConstructor()
->getMock();
$table->expects($this->at(2))
->method('addRow');
$workflow = new StepAggregator($reader);
$workflow
->addWriter(new ConsoleTableWriter($output, $table))
->process()
;
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Ddeboer\DataImport\Writer\CsvWriter;
class CsvWriterTest extends StreamWriterTest
{
public function testWriteItem()
{
$writer = new CsvWriter(';', '"', $this->getStream());
$writer->prepare();
$writer->writeItem(array('first', 'last'));
$writer->writeItem(array(
'first' => 'James',
'last' => 'Bond'
));
$writer->writeItem(array(
'first' => '',
'last' => 'Dr. No'
));
$this->assertContentsEquals(
"first;last\nJames;Bond\n;\"Dr. No\"\n",
$writer
);
$writer->finish();
}
public function testWriteUtf8Item()
{
$writer = new CsvWriter(';', '"', $this->getStream(), true);
$writer->prepare();
$writer->writeItem(array('Précédent', 'Suivant'));
$this->assertContentsEquals(
chr(0xEF) . chr(0xBB) . chr(0xBF) . "Précédent;Suivant\n",
$writer
);
$writer->finish();
}
/**
* Test that column names not prepended to first row
* if CsvWriter's 5-th parameter not given
*
* @author Igor Mukhin <igor.mukhin@gmail.com>
*/
public function testHeaderNotPrependedByDefault()
{
$writer = new CsvWriter(';', '"', $this->getStream(), false);
$writer->prepare();
$writer->writeItem(array(
'col 1 name'=>'col 1 value',
'col 2 name'=>'col 2 value',
'col 3 name'=>'col 3 value'
));
# Values should be at first line
$this->assertContentsEquals(
"\"col 1 value\";\"col 2 value\";\"col 3 value\"\n",
$writer
);
$writer->finish();
}
/**
* Test that column names prepended at first row
* and values have been written at second line
* if CsvWriter's 5-th parameter set to true
*
* @author Igor Mukhin <igor.mukhin@gmail.com>
*/
public function testHeaderPrependedWhenOptionSetToTrue()
{
$writer = new CsvWriter(';', '"', $this->getStream(), false, true);
$writer->prepare();
$writer->writeItem(array(
'col 1 name'=>'col 1 value',
'col 2 name'=>'col 2 value',
'col 3 name'=>'col 3 value'
));
# Column names should be at second line
# Values should be at second line
$this->assertContentsEquals(
"\"col 1 name\";\"col 2 name\";\"col 3 name\"\n" .
"\"col 1 value\";\"col 2 value\";\"col 3 value\"\n",
$writer
);
$writer->finish();
}
}

View File

@@ -0,0 +1,166 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Ddeboer\DataImport\Writer\DoctrineWriter;
use Ddeboer\DataImport\Tests\Fixtures\Entity\TestEntity;
class DoctrineWriterTest extends \PHPUnit_Framework_TestCase
{
public function testWriteItem()
{
$em = $this->getEntityManager();
$em->expects($this->once())
->method('persist');
$writer = new DoctrineWriter($em, 'DdeboerDataImport:TestEntity');
$association = new TestEntity();
$item = array(
'firstProperty' => 'some value',
'secondProperty' => 'some other value',
'firstAssociation'=> $association
);
$writer->writeItem($item);
}
protected function getEntityManager()
{
$em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
->setMethods(array('getRepository', 'getClassMetadata', 'persist', 'flush', 'clear', 'getConnection', 'getReference'))
->disableOriginalConstructor()
->getMock();
$repo = $this->getMockBuilder('Doctrine\ORM\EntityRepository')
->disableOriginalConstructor()
->getMock();
$metadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')
->setMethods(array('getName', 'getFieldNames', 'getAssociationNames', 'setFieldValue', 'getAssociationMappings'))
->disableOriginalConstructor()
->getMock();
$metadata->expects($this->any())
->method('getName')
->will($this->returnValue('Ddeboer\DataImport\Tests\Fixtures\Entity\TestEntity'));
$metadata->expects($this->any())
->method('getFieldNames')
->will($this->returnValue(array('firstProperty', 'secondProperty')));
$metadata->expects($this->any())
->method('getAssociationNames')
->will($this->returnValue(array('firstAssociation')));
$metadata->expects($this->any())
->method('getAssociationMappings')
->will($this->returnValue(array(array('fieldName' => 'firstAssociation','targetEntity' => 'Ddeboer\DataImport\Tests\Fixtures\Entity\TestEntity'))));
$configuration = $this->getMockBuilder('Doctrine\DBAL\Configuration')
->setMethods(array('getConnection'))
->disableOriginalConstructor()
->getMock();
$connection = $this->getMockBuilder('Doctrine\DBAL\Connection')
->setMethods(array('getConfiguration', 'getDatabasePlatform', 'getTruncateTableSQL', 'executeQuery'))
->disableOriginalConstructor()
->getMock();
$connection->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$connection->expects($this->any())
->method('getDatabasePlatform')
->will($this->returnSelf());
$connection->expects($this->any())
->method('getTruncateTableSQL')
->will($this->returnValue('TRUNCATE SQL'));
$connection->expects($this->any())
->method('executeQuery')
->with('TRUNCATE SQL');
$em->expects($this->once())
->method('getRepository')
->will($this->returnValue($repo));
$em->expects($this->once())
->method('getClassMetadata')
->will($this->returnValue($metadata));
$em->expects($this->any())
->method('getConnection')
->will($this->returnValue($connection));
$self = $this;
$em->expects($this->any())
->method('persist')
->will($this->returnCallback(function ($argument) use ($self) {
$self->assertNotNull($argument->getFirstAssociation());
return true;
}));
return $em;
}
public function testLoadAssociationWithoutObject()
{
$em = $this->getEntityManager();
$em->expects($this->once())
->method('persist');
$em->expects($this->once())
->method('getReference');
$writer = new DoctrineWriter($em, 'DdeboerDataImport:TestEntity');
$item = array(
'firstProperty' => 'some value',
'secondProperty' => 'some other value',
'firstAssociation' => 'firstAssociationId'
);
$writer->writeItem($item);
}
public function testLoadAssociationWithPresetObject()
{
$em = $this->getEntityManager();
$em->expects($this->once())
->method('persist');
$em->expects($this->never())
->method('getReference');
$writer = new DoctrineWriter($em, 'DdeboerDataImport:TestEntity');
$association = new TestEntity();
$item = array(
'firstProperty' => 'some value',
'secondProperty' => 'some other value',
'firstAssociation' => $association,
);
$writer->writeItem($item);
}
/**
* Test to make sure that we are clearing the write entity
*/
public function testFlushAndClear()
{
$em = $this->getEntityManager();
$em->expects($this->once())
->method('clear')
->with($this->equalTo('Ddeboer\DataImport\Tests\Fixtures\Entity\TestEntity'));
$writer = new DoctrineWriter($em, 'DdeboerDataImport:TestEntity');
$writer->finish();
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Ddeboer\DataImport\Writer\ExcelWriter;
class ExcelWriterTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
if (!extension_loaded('zip')) {
$this->markTestSkipped();
}
}
public function testWriteItemAppendWithSheetTitle()
{
$file = tempnam(sys_get_temp_dir(), null);
$writer = new ExcelWriter(new \SplFileObject($file, 'w'), 'Sheet 1');
$writer->prepare();
$writer->writeItem(array('first', 'last'));
$writer->writeItem(array(
'first' => 'James',
'last' => 'Bond'
));
$writer->writeItem(array(
'first' => '',
'last' => 'Dr. No'
));
$writer->finish();
// Open file with append mode ('a') to add a sheet
$writer = new ExcelWriter(new \SplFileObject($file, 'a'), 'Sheet 2');
$writer->prepare();
$writer->writeItem(array('first', 'last'));
$writer->writeItem(array(
'first' => 'Miss',
'last' => 'Moneypenny'
));
$writer->finish();
$excel = \PHPExcel_IOFactory::load($file);
$this->assertTrue($excel->sheetNameExists('Sheet 1'));
$this->assertEquals(3, $excel->getSheetByName('Sheet 1')->getHighestRow());
$this->assertTrue($excel->sheetNameExists('Sheet 2'));
$this->assertEquals(2, $excel->getSheetByName('Sheet 2')->getHighestRow());
}
public function testWriteItemWithoutSheetTitle()
{
$outputFile = new \SplFileObject(tempnam(sys_get_temp_dir(), null));
$writer = new ExcelWriter($outputFile);
$writer->prepare();
$writer->writeItem(array('first', 'last'));
$writer->finish();
}
/**
* Test that column names not prepended to first row if ExcelWriter's 4-th
* parameter not given
*
* @author Igor Mukhin <igor.mukhin@gmail.com>
*/
public function testHeaderNotPrependedByDefault()
{
$file = tempnam(sys_get_temp_dir(), null);
$writer = new ExcelWriter(new \SplFileObject($file, 'w'), null, 'Excel2007');
$writer->prepare();
$writer->writeItem(array(
'col 1 name'=>'col 1 value',
'col 2 name'=>'col 2 value',
'col 3 name'=>'col 3 value'
));
$writer->finish();
$excel = \PHPExcel_IOFactory::load($file);
$sheet = $excel->getActiveSheet()->toArray();
# Values should be at first line
$this->assertEquals(array('col 1 value', 'col 2 value', 'col 3 value'), $sheet[0]);
}
/**
* Test that column names prepended at first row
* and values have been written at second line
* if ExcelWriter's 4-th parameter set to true
*
* @author Igor Mukhin <igor.mukhin@gmail.com>
*/
public function testHeaderPrependedWhenOptionSetToTrue()
{
$file = tempnam(sys_get_temp_dir(), null);
$writer = new ExcelWriter(new \SplFileObject($file, 'w'), null, 'Excel2007', true);
$writer->prepare();
$writer->writeItem(array(
'col 1 name'=>'col 1 value',
'col 2 name'=>'col 2 value',
'col 3 name'=>'col 3 value'
));
$writer->finish();
$excel = \PHPExcel_IOFactory::load($file);
$sheet = $excel->getActiveSheet()->toArray();
# Check column names at first line
$this->assertEquals(array('col 1 name', 'col 2 name', 'col 3 name'), $sheet[0]);
# Check values at second line
$this->assertEquals(array('col 1 value', 'col 2 value', 'col 3 value'), $sheet[1]);
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Ddeboer\DataImport\Writer\PdoWriter;
class PdoWriterTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \PDO
*/
private $pdo;
public function setUp()
{
$this->pdo = new \PDO('sqlite::memory:');
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); //important
$this->pdo->exec('DROP TABLE IF EXISTS `example`');
$this->pdo->exec('CREATE TABLE `example` (a TEXT, b TEXT)');
}
public function testValidWriteItem()
{
$writer = new PdoWriter($this->pdo, 'example');
$writer->prepare();
$writer->writeItem(array('a' => 'foo', 'b' => 'bar'));
$writer->finish();
$stmnt = $this->pdo->query('SELECT * FROM `example`');
$this->assertEquals(
array(array('a'=>'foo', 'b'=>'bar')),
$stmnt->fetchAll(\PDO::FETCH_ASSOC),
'database does not contain expected row'
);
}
public function testValidWriteMultiple()
{
$writer = new PdoWriter($this->pdo, 'example');
$writer->prepare();
$writer->writeItem(array('a' => 'foo', 'b' => 'bar'));
$writer->writeItem(array('a' => 'cat', 'b' => 'dog'));
$writer->writeItem(array('a' => 'ac', 'b' => 'dc'));
$writer->finish();
$stmnt = $this->pdo->query('SELECT * FROM `example`');
$this->assertEquals(
array(array('a'=>'foo', 'b'=>'bar'), array('a'=>'cat', 'b'=>'dog'), array('a'=>'ac', 'b'=>'dc')),
$stmnt->fetchAll(\PDO::FETCH_ASSOC),
'database does not contain all expected rows'
);
}
/**
* @expectedException \Ddeboer\DataImport\Exception\WriterException
*/
public function testWriteTooManyValues()
{
$writer = new PdoWriter($this->pdo, 'example');
$writer->prepare();
$writer->writeItem(array('foo', 'bar', 'baz')); //expects two
$writer->finish();
}
/**
* @expectedException \Ddeboer\DataImport\Exception\WriterException
*/
public function testWriteToNonexistentTable()
{
$writer = new PdoWriter($this->pdo, 'foobar');
$writer->prepare();
$writer->writeItem(array('foo', 'bar'));
$writer->finish();
}
/**
* Tests PDO instance with silent errors.
*
* @expectedException \Ddeboer\DataImport\Exception\WriterException
*/
public function testStatementCreateFailureWithNoException()
{
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_SILENT);
$writer = new PdoWriter($this->pdo, 'foob`ar');
$writer->prepare();
$writer->writeItem(array('foo', 'bar'));
$writer->finish();
}
/**
* Tests PDO instance with silent errors. First inert prepares the statement, second creates an exception.
*
* @expectedException \Ddeboer\DataImport\Exception\WriterException
*/
public function testWriteFailureWithNoException()
{
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_SILENT);
$writer = new PdoWriter($this->pdo, 'example');
$writer->prepare();
$writer->writeItem(array('foo', 'bar'));
$writer->writeItem(array('foo', 'bar', 'baz'));
$writer->finish();
}
}

View File

@@ -0,0 +1,141 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Ddeboer\DataImport\Writer\StreamMergeWriter;
class StreamMergeWriterTest extends AbstractStreamWriterTest
{
/** @var StreamMergeWriter */
protected $writer;
protected function setUp()
{
parent::setUp();
$this->writer = new StreamMergeWriter();
}
public function testItIsInstantiable()
{
$this->assertInstanceOf('Ddeboer\DataImport\Writer\StreamMergeWriter', $this->writer);
}
public function testItIsAStreamWriter()
{
$this->assertInstanceOf('Ddeboer\DataImport\Writer\AbstractStreamWriter', $this->writer);
}
public function testDiscriminantField()
{
$this->assertSame($this->writer, $this->writer->setDiscriminantField('foo'));
$this->assertSame('foo', $this->writer->getDiscriminantField());
}
public function testDiscriminantFieldDefaultsToDiscr()
{
$this->assertSame('discr', $this->writer->getDiscriminantField());
}
public function testSetStreamWriterForSpecificDiscrValue()
{
$fooWriter = $this->getMockBuilder('Ddeboer\DataImport\Writer\AbstractStreamWriter')
->setMethods(array('setStream'))
->getMockForAbstractClass();
$this->writer->setStream($stream = $this->getStream());
$fooWriter
->expects($this->once())
->method('setStream')
->with($stream)
->will($this->returnSelf());
$this->assertSame($this->writer, $this->writer->setStreamWriter('foo', $fooWriter));
$this->assertSame($fooWriter, $this->writer->getStreamWriter('foo'));
}
public function testHasStreamWriter()
{
$fooWriter = $this->getMockBuilder('Ddeboer\DataImport\Writer\AbstractStreamWriter')
->getMockForAbstractClass();
$this->assertFalse($this->writer->hasStreamWriter('foo'), 'no foo stream writer should be registered');
$this->writer->setStreamWriter('foo', $fooWriter);
$this->assertTrue($this->writer->hasStreamWriter('foo'), 'foo stream writer should be registered');
}
public function testStreamWriters()
{
$fooWriter = $this->getMockBuilder('Ddeboer\DataImport\Writer\AbstractStreamWriter')
->getMockForAbstractClass();
$barWriter = $this->getMockBuilder('Ddeboer\DataImport\Writer\AbstractStreamWriter')
->getMockForAbstractClass();
$writers = array(
'foo' => $fooWriter,
'bar' => $barWriter,
);
$this->assertSame($this->writer, $this->writer->setStreamWriters($writers));
$this->assertSame($writers, $this->writer->getStreamWriters());
}
public function testWriteItem()
{
$fooWriter = $this->getMockBuilder('Ddeboer\DataImport\Writer\AbstractStreamWriter')
->getMockForAbstractClass();
$barWriter = $this->getMockBuilder('Ddeboer\DataImport\Writer\AbstractStreamWriter')
->getMockForAbstractClass();
$writers = array(
'foo' => $fooWriter,
'bar' => $barWriter,
);
$this->writer->setStreamWriters($writers);
$this->writer->setDiscriminantField('foo');
$barItem = array('foo' => 'bar');
$fooWriter->expects($this->never())
->method('writeItem');
$barWriter->expects($this->once())
->method('writeItem')
->with($barItem)
->will($this->returnSelf());
$this->writer->writeItem($barItem);
}
public function testSetStream()
{
$fooWriter = $this->getMockBuilder('Ddeboer\DataImport\Writer\AbstractStreamWriter')
->getMockForAbstractClass();
$barWriter = $this->getMockBuilder('Ddeboer\DataImport\Writer\AbstractStreamWriter')
->getMockForAbstractClass();
$writers = array(
'foo' => $fooWriter,
'bar' => $barWriter,
);
$stream = $this->writer->getStream();
$this->writer->setStreamWriters($writers);
$this->assertSame($stream, $fooWriter->getStream());
$this->assertSame($stream, $barWriter->getStream());
$this->assertSame($this->writer, $this->writer->setStream($stream = $this->getStream()));
$this->assertSame($stream, $fooWriter->getStream());
$this->assertSame($stream, $barWriter->getStream());
}
public function testSetWriterShouldInhibitStreamClose()
{
$fooWriter = $this->getMockBuilder('Ddeboer\DataImport\Writer\AbstractStreamWriter')
->setMethods(array('setCloseStreamOnFinish'))
->getMockForAbstractClass();
$fooWriter
->expects($this->once())
->method('setCloseStreamOnFinish')->with(false)
->will($this->returnArgument(0));
$this->writer->setStreamWriter('foo', $fooWriter);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace Ddeboer\DataImport\Tests\Writer;
use Ddeboer\DataImport\Writer\AbstractStreamWriter;
abstract class StreamWriterTest extends \PHPUnit_Framework_TestCase
{
protected $stream;
/** @var AbstractStreamWriter */
protected $writer;
protected function tearDown()
{
if (is_resource($this->stream)) {
fclose($this->stream);
$this->stream = null;
}
}
protected function getStream()
{
if (!is_resource($this->stream)) {
$this->stream = fopen('php://temp', 'r+');
}
return $this->stream;
}
/**
* @param string $expected
* @param AbstractStreamWriter $actual
* @param string $message
*/
public static function assertContentsEquals($expected, $actual, $message = '')
{
$stream = $actual->getStream();
rewind($stream);
$actual = stream_get_contents($stream);
self::assertEquals($expected, $actual, $message);
}
}