Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Remove callable support for sequence #185

Merged
merged 1 commit into from
Apr 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ For a full diff see [`fa9c564...master`][fa9c564...master].
* Removed `Definition\FakerAwareDefinition` ([#120] and [#123]), by [@localheinz]
* Removed `FixtureFactory::provideWith()` ([#122]), by [@localheinz]
* Removed `FixtureFactory::getAsSingleton()`, `FixtureFactory::setSingleton()`, and `FixtureFactory::unsetSingleton()` ([#124]), by [@localheinz]
* Removed `callable` support for field definitions ([#133]), by [@localheinz]
* Removed `callable` support for field definitions ([#133]) and ([#185]), by [@localheinz]

[fa9c564...master]: https://github.com/ergebnis/factory-bot/compare/fa9c564...master

Expand Down Expand Up @@ -92,5 +92,6 @@ For a full diff see [`fa9c564...master`][fa9c564...master].
[#160]: https://github.com/ergebnis/factory-bot/pull/160
[#161]: https://github.com/ergebnis/factory-bot/pull/161
[#164]: https://github.com/ergebnis/factory-bot/pull/164
[#185]: https://github.com/ergebnis/factory-bot/pull/185

[@localheinz]: https://github.com/localheinz
56 changes: 9 additions & 47 deletions src/FieldDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,66 +13,28 @@

namespace Ergebnis\FactoryBot;

final class FieldDefinition implements FieldDefinition\Resolvable
final class FieldDefinition
{
/**
* @var \Closure
*/
private $closure;

private function __construct(\Closure $closure)
{
$this->closure = $closure;
}

public function resolve(FixtureFactory $fixtureFactory)
{
$closure = $this->closure;

return $closure($fixtureFactory);
}

public static function closure(\Closure $closure): FieldDefinition\Closure
{
return new FieldDefinition\Closure($closure);
}

/**
* Defines a field to be a string based on an incrementing integer.
*
* This is typically used to generate unique names such as usernames.
*
* The parameter may be a function that receives a counter value
* each time the entity is created or it may be a string.
*
* If the parameter is a string string containing "%d" then it will be
* replaced by the counter value. If the string does not contain "%d"
* then the number is simply appended to the parameter.
*
* @param callable|string $funcOrString the function or pattern to generate a value from
* @param int $firstNum the first number to use
* @param string $value
* @param int $initialNumber
*
* @return FieldDefinition\Sequence|self
* @return FieldDefinition\Sequence
*/
public static function sequence($funcOrString, int $firstNum = 1)
public static function sequence($value, int $initialNumber = 1): FieldDefinition\Sequence
{
$n = $firstNum - 1;

if (\is_callable($funcOrString)) {
return new self(static function () use (&$n, $funcOrString) {
++$n;

return \call_user_func($funcOrString, $n);
});
}

if (false === \strpos($funcOrString, '%d')) {
$funcOrString .= '%d';
if (false === \strpos($value, '%d')) {
$value .= '%d';
}

return new FieldDefinition\Sequence(
$funcOrString,
$firstNum
$value,
$initialNumber
);
}

Expand Down
4 changes: 2 additions & 2 deletions src/FixtureFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public function defineEntity(string $className, array $fieldDefinitions = [], ?\
}

if ($fieldDefinition instanceof \Closure) {
return FieldDefinition::sequence($fieldDefinition);
return FieldDefinition::closure($fieldDefinition);
}

return FieldDefinition::value($fieldDefinition);
Expand Down Expand Up @@ -199,7 +199,7 @@ public function get(string $className, array $fieldOverrides = [])
continue;
}

/** @var FieldDefinition $fieldDefinition */
/** @var FieldDefinition\Resolvable $fieldDefinition */
$fieldValues[$fieldName] = $fieldDefinition->resolve($this);
}

Expand Down
3 changes: 2 additions & 1 deletion test/Integration/FixtureFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* @uses \Ergebnis\FactoryBot\EntityDefinition
* @uses \Ergebnis\FactoryBot\FieldDefinition
* @uses \Ergebnis\FactoryBot\FieldDefinition\Reference
* @uses \Ergebnis\FactoryBot\FieldDefinition\Closure
* @uses \Ergebnis\FactoryBot\FieldDefinition\Value
*/
final class FixtureFactoryTest extends AbstractTestCase
Expand Down Expand Up @@ -84,7 +85,7 @@ public function testDoesNotPersistEmbeddableWhenAutomaticPersistingIsTurnedOn():
$fixtureFactory = new FixtureFactory($entityManager);

$fixtureFactory->defineEntity(Fixture\FixtureFactory\Entity\Avatar::class, [
'url' => FieldDefinition::sequence(static function () use ($faker): string {
'url' => FieldDefinition::closure(static function () use ($faker): string {
return $faker->imageUrl();
}),
]);
Expand Down
13 changes: 4 additions & 9 deletions test/Unit/EntityDefinitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*
* @uses \Ergebnis\FactoryBot\Exception\InvalidFieldDefinitions
* @uses \Ergebnis\FactoryBot\FieldDefinition
* @uses \Ergebnis\FactoryBot\FieldDefinition\Value
*/
final class EntityDefinitionTest extends Framework\TestCase
{
Expand All @@ -40,9 +41,7 @@ final class EntityDefinitionTest extends Framework\TestCase
public function testConstructorRejectsFieldDefinitionsWhenValuesAreNotFieldDefinitions($fieldDefinition): void
{
$fieldDefinitions = [
'foo' => FieldDefinition::sequence(static function (): string {
return 'bar';
}),
'foo' => FieldDefinition::value('bar'),
'bar' => $fieldDefinition,
];

Expand All @@ -62,12 +61,8 @@ public function testConstructorSetsValues(): void
$classMetadata = $this->prophesize(ORM\Mapping\ClassMetadata::class);

$fieldDefinitions = [
'foo' => FieldDefinition::sequence(static function (): string {
return 'bar';
}),
'bar' => FieldDefinition::sequence(static function (): string {
return 'baz';
}),
'foo' => FieldDefinition::value('bar'),
'bar' => FieldDefinition::value('baz'),
];

$afterCreate = static function ($entity, array $fieldValues): void {
Expand Down
163 changes: 21 additions & 142 deletions test/Unit/FieldDefinitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,136 +122,15 @@ public function testReferencesResolvesToAnArrayOfCountInstancesOfReferencedClass
self::assertContainsOnly(Fixture\FixtureFactory\Entity\User::class, $resolved);
}

public function testSequenceResolvesToReturnValueOfCallableInvokedWithSequentialNumberWhenSequenceIsCallableAndFirstNumberIsNotSpecified(): void
public function testSequenceResolvesToValueWithPlaceholderReplacedWithSequentialNumberWhenValueContainsPlaceholderAndInitialNumberIsNotSpecified(): void
{
$callable = [
self::class,
'exampleCallable',
];

$fixtureFactory = new FixtureFactory(self::entityManager());

$fixtureFactory->defineEntity(Fixture\FixtureFactory\Entity\User::class);

$fieldDefinition = FieldDefinition::sequence($callable);

$expected = static function (int $number) use ($callable): string {
return \call_user_func(
$callable,
$number
);
};

self::assertSame($expected(1), $fieldDefinition->resolve($fixtureFactory));
self::assertSame($expected(2), $fieldDefinition->resolve($fixtureFactory));
self::assertSame($expected(3), $fieldDefinition->resolve($fixtureFactory));
}

/**
* @dataProvider \Ergebnis\FactoryBot\Test\DataProvider\NumberProvider::intGreaterThanOne()
*
* @param int $firstNumber
*/
public function testSequenceResolvesToReturnValueOfCallableInvokedWithSequentialNumberWhenSequenceIsCallableAndFirstNumberIsSpecified(int $firstNumber): void
{
$callable = [
self::class,
'exampleCallable',
];

$fixtureFactory = new FixtureFactory(self::entityManager());

$fixtureFactory->defineEntity(Fixture\FixtureFactory\Entity\User::class);

$fieldDefinition = FieldDefinition::sequence(
$callable,
$firstNumber
);

$expected = static function (int $number) use ($callable, $firstNumber): string {
return \call_user_func(
$callable,
$number + $firstNumber - 1
);
};

self::assertSame($expected(1), $fieldDefinition->resolve($fixtureFactory));
self::assertSame($expected(2), $fieldDefinition->resolve($fixtureFactory));
self::assertSame($expected(3), $fieldDefinition->resolve($fixtureFactory));
}

public static function exampleCallable(int $number): string
{
return \sprintf(
'number-%d-is-an-integer',
$number
);
}

public function testSequenceResolvesToTheReturnValueOfClosureInvokedWithSequentialNumberWhenSequenceIsClosureAndFirstNumberIsNotSpecified(): void
{
$closure = static function (int $number): string {
return \sprintf(
'number-%d-is-ok',
$number
);
};

$fixtureFactory = new FixtureFactory(self::entityManager());

$fixtureFactory->defineEntity(Fixture\FixtureFactory\Entity\User::class);

$fieldDefinition = FieldDefinition::sequence($closure);

self::assertSame($closure(1), $fieldDefinition->resolve($fixtureFactory));
self::assertSame($closure(2), $fieldDefinition->resolve($fixtureFactory));
self::assertSame($closure(3), $fieldDefinition->resolve($fixtureFactory));
}

/**
* @dataProvider \Ergebnis\FactoryBot\Test\DataProvider\NumberProvider::intGreaterThanOne()
*
* @param int $firstNumber
*/
public function testSequenceResolvesToTheReturnValueOfClosureInvokedWithSequentialNumberWhenSequenceIsClosureAndFirstNumberIsSpecified(int $firstNumber): void
{
$closure = static function (int $number): string {
return \sprintf(
'number-%d-is-ok',
$number
);
};

$fixtureFactory = new FixtureFactory(self::entityManager());

$fixtureFactory->defineEntity(Fixture\FixtureFactory\Entity\User::class);

$fieldDefinition = FieldDefinition::sequence(
$closure,
$firstNumber
);

$expected = static function (int $number) use ($firstNumber): string {
return \sprintf(
'number-%d-is-ok',
$number + $firstNumber - 1
);
};

self::assertSame($expected(1), $fieldDefinition->resolve($fixtureFactory));
self::assertSame($expected(2), $fieldDefinition->resolve($fixtureFactory));
self::assertSame($expected(3), $fieldDefinition->resolve($fixtureFactory));
}

public function testSequenceResolvesToAStringWithPlaceholderReplacedWithSequentialNumberWhenSequenceIsStringThatContainsPlaceholderAndFirstNumberIsNotSpecified(): void
{
$string = 'there-is-no-difference-between-%d-and-%d';
$value = 'there-is-no-difference-between-%d-and-%d';

$fixtureFactory = new FixtureFactory(self::entityManager());

$fixtureFactory->defineEntity(Fixture\FixtureFactory\Entity\User::class);

$fieldDefinition = FieldDefinition::sequence($string);
$fieldDefinition = FieldDefinition::sequence($value);

$expected = static function (int $number): string {
return \sprintf(
Expand All @@ -269,26 +148,26 @@ public function testSequenceResolvesToAStringWithPlaceholderReplacedWithSequenti
/**
* @dataProvider \Ergebnis\FactoryBot\Test\DataProvider\NumberProvider::intGreaterThanOne()
*
* @param int $firstNumber
* @param int $initialNumber
*/
public function testSequenceResolvesToAStringWithPlaceholderReplacedWithSequentialNumberWhenSequenceIsStringThatContainsPlaceholderAndFirstNumberIsSpecified(int $firstNumber): void
public function testSequenceResolvesToValueWithPlaceholderReplacedWithSequentialNumberWhenValueContainsPlaceholderAndInitialNumberIsSpecified(int $initialNumber): void
{
$string = 'there-is-no-difference-between-%d-and-%d';
$value = 'there-is-no-difference-between-%d-and-%d';

$fixtureFactory = new FixtureFactory(self::entityManager());

$fixtureFactory->defineEntity(Fixture\FixtureFactory\Entity\User::class);

$fieldDefinition = FieldDefinition::sequence(
$string,
$firstNumber
$value,
$initialNumber
);

$expected = static function (int $number) use ($firstNumber): string {
$expected = static function (int $number) use ($initialNumber): string {
return \sprintf(
'there-is-no-difference-between-%d-and-%d',
$number + $firstNumber - 1,
$number + $firstNumber - 1
$number + $initialNumber - 1,
$number + $initialNumber - 1
);
};

Expand All @@ -297,15 +176,15 @@ public function testSequenceResolvesToAStringWithPlaceholderReplacedWithSequenti
self::assertSame($expected(3), $fieldDefinition->resolve($fixtureFactory));
}

public function testSequenceResolvesToAStringSuffixedWithSequentialNumberSequenceIsStringThatDoesNotContainPlaceholderWhenFirstNumberIsNotSpecified(): void
public function testSequenceResolvesToValueSuffixedWithSequentialNumberWhenValueDoesNotContainPlaceholderAndInitialNumberIsNotSpecified(): void
{
$string = 'user-';
$value = 'user-';

$fixtureFactory = new FixtureFactory(self::entityManager());

$fixtureFactory->defineEntity(Fixture\FixtureFactory\Entity\User::class);

$fieldDefinition = FieldDefinition::sequence($string);
$fieldDefinition = FieldDefinition::sequence($value);

$expected = static function (int $number): string {
return \sprintf(
Expand All @@ -322,25 +201,25 @@ public function testSequenceResolvesToAStringSuffixedWithSequentialNumberSequenc
/**
* @dataProvider \Ergebnis\FactoryBot\Test\DataProvider\NumberProvider::intGreaterThanOne()
*
* @param int $firstNumber
* @param int $initialNumber
*/
public function testSequenceResolvesToAStringSuffixedWithSequentialNumberSequenceIsStringThatDoesNotContainPlaceholderWhenFirstNumberIsSpecified(int $firstNumber): void
public function testSequenceResolvesToValueSuffixedWithSequentialNumberWhenValueDoesNotContainPlaceholderAndInitialNumberIsSpecified(int $initialNumber): void
{
$string = 'user-';
$value = 'user-';

$fixtureFactory = new FixtureFactory(self::entityManager());

$fixtureFactory->defineEntity(Fixture\FixtureFactory\Entity\User::class);

$fieldDefinition = FieldDefinition::sequence(
$string,
$firstNumber
$value,
$initialNumber
);

$expected = static function (int $number) use ($firstNumber): string {
$expected = static function (int $number) use ($initialNumber): string {
return \sprintf(
'user-%d',
$number + $firstNumber - 1
$number + $initialNumber - 1
);
};

Expand Down