Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@
"autoload": {
"psr-4": {
"Laracasts\\TestDummy\\": "src/"
},
"files": [
"src/functions.php"
]
}
},
"autoload-dev": {
"classmap": [
Expand Down
58 changes: 58 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,3 +318,61 @@ Factory::$databaseProvider = new MyCustomBuilder;
```

And that's it! Now, whenever you generate and save an entity, TestDummy will reference your custom implementation.

#### How can I use the bundle with ex. Doctrine?

To connect DummyTests with ex. Doctrine you need to create an own Adapter class which extends FactoryMethodEloquentModel
class:

```
use Laracasts\TestDummy\PersistableModel\FactoryMethodEloquentModel;
use Doctrine\ORM\EntityManager;

class DoctrineModelAdapter extends FactoryMethodEloquentModel
{

protected $em;

public function __construct(EntityManager $em)
{
$this->em = $em;
}

/**
* Persist the entity.
*
* @param Entity $entity
* @return void
*/
public function save($entity)
{
$this->em->persist($entity);
$this->em->flush();
}
}
```

Then you need to specify a factory method in you Entity class (ex Foo):

```
class Foo extends Entity
{
//...
public static function createFoo($name)
{
$foo = new static();
$foo->setName($name);

return $foo;
}

//...
}
```

Finally, register the Adapter in DummyTests (might be done in AppKernel or bootstrap class).

```
$doctrineModelAdapter = new DoctrineModelAdapter($entityManager);
Factory::$databaseProvider = new Laracasts\TestDummy\Builder($doctrineModelAdapter);
```
30 changes: 27 additions & 3 deletions spec/Laracasts/TestDummy/BuilderSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

namespace spec\Laracasts\TestDummy;

use Illuminate\Database\ConnectionResolver;
use Illuminate\Database\Eloquent\Model;
use Laracasts\TestDummy\FixturesFinder;
use Laracasts\TestDummy\PersistableModel\FactoryMethodEloquentModel;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Laracasts\TestDummy\IsPersistable;
use Laracasts\TestDummy\PersistableModel\IsPersistable;
use Laracasts\TestDummy\Factory;

class BuilderSpec extends ObjectBehavior {

class BuilderSpec extends ObjectBehavior
{
function let(IsPersistable $model)
{
$factories = (new Factory(__DIR__.'/helpers'))->factories();
Expand Down Expand Up @@ -88,6 +91,27 @@ function it_throws_an_exception_if_the_fixture_name_is_not_recognized()
$this->shouldThrow('Laracasts\TestDummy\TestDummyException')->duringAttributesFor('Bar');
}

function it_can_create_entity_using_create_method(IsPersistable $model, ConnectionResolver $resolver)
{
$model = new FactoryMethodEloquentModel();
$factories = (new Factory(__DIR__.'/helpers', $model))->factories();
$this->beConstructedWith($model, $factories);

$overrides = ['name' => 'The Boogaloos'];

$this->build('Foo', $overrides)->name->shouldReturn($overrides['name']);
}

function it_should_not_allow_to_set_name_as_not_string(IsPersistable $model)
{
$model = new FactoryMethodEloquentModel();
$factories = (new Factory(__DIR__.'/helpers', $model))->factories();
$this->beConstructedWith($model, $factories);

$overrides = ['name' => ['it is an array']];

$this->shouldThrow('\InvalidArgumentException')->duringBuild('Foo', $overrides);
}
}

class AlbumStub {
Expand Down
2 changes: 1 addition & 1 deletion spec/Laracasts/TestDummy/FactoriesLoaderSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function it_loads_a_directory_of_user_provided_factories()
$factories = $this->load(__DIR__.'/helpers');

$factories->shouldBeArray();
$factories->shouldHaveCount(2);
$factories->shouldHaveCount(3);
}

public function getMatchers()
Expand Down
6 changes: 6 additions & 0 deletions spec/Laracasts/TestDummy/helpers/all.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@
'name' => $faker->name
];
});

$factory('Foo', function ($faker) {
return [
'name' => $faker->name
];
});
46 changes: 26 additions & 20 deletions src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Support\Collection;
use Faker\Factory as Faker;
use Closure;
use Laracasts\TestDummy\PersistableModel\IsPersistable;

class Builder
{
Expand Down Expand Up @@ -111,7 +112,8 @@ public function build($name, $overrides = [])
*/
public function create($name, array $overrides = [])
{
for ($i = 0; $i < $this->getTimes(); $i++) {
$times = $this->getTimes();
for ($i = 0; $i < $times; $i++) {
$entities[] = $this->persist($name, $overrides);
}

Expand All @@ -134,7 +136,11 @@ protected function persist($name, array $attributes = [])
$entity = $this->build($name, $attributes);

$this->assignRelationships($entity, $attributes);
$this->model->save($entity);
$savedEntity = $this->model->save($entity);

if (null !== $savedEntity) {
return $savedEntity;
}

return $entity;
}
Expand Down Expand Up @@ -166,7 +172,7 @@ protected function getAttributes($name, array $attributes)
*/
protected function filterRelationshipAttributes(array $attributes)
{
return filter_array_keys($attributes, function ($key) {
return $this->filterArrayKeys($attributes, function ($key) {
return ! str_contains($key, '.');
});
}
Expand All @@ -182,7 +188,6 @@ protected function getFixture($name)
{
// The user may provide either a class name or a short
// name identifier. So we'll track it down here.

foreach ($this->fixtures as $fixture) {
if ($fixture->shortName == $name) {
return $fixture;
Expand Down Expand Up @@ -236,20 +241,6 @@ protected function runFaker($attribute)
$attribute = $attribute();
}

// It's possible that the called Faker method returned an array.
// If that is the case, we'll implode it for the user.

if (is_array($attribute)) {

// If we're dealing with an associative array...

if (array_values($attribute) !== $attribute) {
return array_map([$this, 'runFaker'], $attribute);
}

return implode(' ', $attribute);
}

return $attribute;
}

Expand All @@ -260,7 +251,7 @@ protected function runFaker($attribute)
*/
protected function faker()
{
if (! $this->faker) {
if ( ! $this->faker) {
$this->faker = Faker::create();
}

Expand Down Expand Up @@ -331,7 +322,7 @@ protected function fetchRelationId($factoryName, $relationshipName, array $attri
*/
protected function extractRelationshipAttributes($columnName, array $attributes)
{
$attributes = filter_array_keys($attributes, function ($key) use ($columnName) {
$attributes = $this->filterArrayKeys($attributes, function ($key) use ($columnName) {
return starts_with($key, $columnName . '.');
});

Expand All @@ -344,4 +335,19 @@ protected function extractRelationshipAttributes($columnName, array $attributes)

return $extractedAttributes;
}

/**
* Filter an array using keys instead of values.
*
* @param array $array
* @param callable $callback
* @return array
*/
protected function filterArrayKeys(array $array, $callback)
{
$matchedKeys = array_filter(array_keys($array), $callback);

return array_intersect_key($array, array_flip($matchedKeys));
}

}
19 changes: 16 additions & 3 deletions src/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Laracasts\TestDummy;

use Symfony\Component\Process\Exception\LogicException;

class Definition
{

Expand All @@ -10,21 +12,22 @@ class Definition
*
* @var string
*/
public $name;
protected $name;

/**
* The abbreviated short-name.
*
* @var string
*/
public $shortName;
protected $shortName;

/**
* Attributes for the factory.
*
* @var array
*/
public $attributes;
protected $attributes;


/**
* Create a new Definition instance.
Expand All @@ -40,4 +43,14 @@ public function __construct($name, $shortName, $attributes = [])
$this->attributes = $attributes;
}

public function __set($attribute, $value)
{
//We want to keep the object always in the same state
throw new LogicException('You cannot change any value of this object');
}

public function __get($attribute)
{
return $this->{$attribute};
}
}
26 changes: 4 additions & 22 deletions src/FactoriesFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RegexIterator;

class FactoriesFinder
{
Expand Down Expand Up @@ -32,15 +33,10 @@ function __construct($basePath)
*/
public function find()
{
$files = [];
$iterator = $this->getDirectoryIterator();
$iterator = new RegexIterator($iterator, '#^.*\.(php)+$#Di');

foreach ($this->getDirectoryIterator() as $file) {
if ($this->getExtension($file) !== 'php') continue;

$files[] = $file->getPathname();
}

return $files;
return array_keys(iterator_to_array($iterator));
}

/**
Expand All @@ -55,18 +51,4 @@ private function getDirectoryIterator()

return new RecursiveIteratorIterator($directoryIterator);
}

/**
* Get the extension of a file.
*
* @param $file
* @return string|null
*/
private function getExtension($file)
{
$fileInfo = pathinfo($file);

return isset($fileInfo['extension']) ? $fileInfo['extension'] : null;
}

}
2 changes: 1 addition & 1 deletion src/FactoriesLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public function load($basePath)
$designer = new Designer;
$faker = new FakerAdapter;

$factory = function ($name, $shortName, $attributes = []) use ($designer, $faker) {
$factory = function ($name, $shortName, $attributes = []) use ($designer) {
return $designer->define($name, $shortName, $attributes);
};

Expand Down
Loading