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

ADD: Faktory::createMany for bulk-creating factories #4

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
36 changes: 34 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ $f = Faktory::create("term", ["name" => "TDD", "taxonomy" => "post_tag"]);
```php
$f = Faktory::create("term", ["name" => "Computer Science", "taxonomy" => "genre"]);
```
#### Using the terms with another Factory
#### Using the terms with another factory
```php
$term = Faktory::create("term", ["name" => "Programming"]);
$page = Faktory::create("page", [
Expand Down Expand Up @@ -136,14 +136,46 @@ $f = Faktory::new("page");
$f->save();
```

## Pass the returned Faktory to a class
## Pass the returned factory to a class
`Faktory::create` or `Faktory::new` will return an object. This object mimics a WordPress post object or term object. You may find yourself frequently passing the created fixture as a paramter to another class. This is where the `as` method can come in useful.
```php
$f = Faktory::create("page")->as("TheClassIWant");
# is equal to
$f = new TheClassIWant(Faktory::create("page"));
```

## Creating multiple factories at once
`Faktory::createMany` or `Faktory::newMany` will return an array of objects in a single line of code.
```php
$factories = Faktory::createMany(5, "post");
```

`createMany` will save the objects to the database.
`newMany` will not save the objects to the database.

They both support the following args:
- `count` (default: `2`): The number of objects to create.
- `type` (default: `page`): See [creating a page factory](https://github.com/substrakt/faktory?tab=readme-ov-file#creating-a-page-factory).
- `args` (default: `[]`): See [creating a page factory and setting attributes](https://github.com/substrakt/faktory?tab=readme-ov-file#creating-a-page-factory-setting-some-attributes).
- `class` (default `null`): The string of a class to instantiate the factories as.

Each Factory is given an incrementing suffix to the `post_title` and `post_name`. See the following example for context.

### Examples

Basic use-case:

```php
$fs = Faktory::createMany(3, 'post', ['post_title' => 'Foo'], 'My\Desired\Class');
```

The above will:
- Create 3 factories.
- Assign them the `post_titles` of `Foo 0`, `Foo 1`, & `Foo 2`.
- Instantiate them as `My\Desired\Class`.
- Save them to the database.
- Return the results as an array.

## Creating your own factories
Add a directory called `factories` in your desired location. In this directory you will put all your custom factory files. If you create a file called, post.php, page.php or term.php it will overwrite the default factories used by Faktory. This is perfectly acceptable.

Expand Down
47 changes: 47 additions & 0 deletions src/Faktory.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ public static function create(string $type = "page", array $args = []): object
return $f;
}

/**
* Returns array of new Faktory objects.
* The objects are saved to the database.
*
* @param int $count The number of objects to create.
* @param string $type The name of the factory to load.
* @param array $args Array of properties and values to override.
* @param ?string $class Set to a class to instantiate the Faktory as.
* @return array<object>
*/
public static function createMany(int $count = 2, string $type = "page", array $args = [], ?string $class = null): array
{
return array_map(function($post) use ($class) {
$post->save();
return $class ? $post->as($class) : $post;
}, static::newMany($count, $type, $args));
}

/**
* Returns are new Faktory object.
* The object is not saved to the database.
Expand All @@ -54,6 +72,35 @@ public static function new(string $type = "page", array $args = []): object
return static::generate($type, $args);
}

/**
* Returns array of new Faktory objects.
* The objects are not saved to the database.
*
* @param int $count The number of objects to create.
* @param string $type The name of the factory to load.
* @param array $args Array of properties and values to override.
* @param ?string $class Set to a class to instantiate the Faktory as.
* @return array<object>
*/
public static function newMany(int $count = 2, string $type = "page", array $args = [], ?string $class = null): array
{
$posts = [];

for ($i = 0; $i < $count; $i++) {
$post = static::generate($type, $args);
$post->post_title .= " {$i}";
$post->post_name .= " {$i}";

if ($class) {
$post = $post->as($class);
}

$posts[] = $post;
}

return $posts;
}

/**
* Load a factory from the available directories and return the containing array.
*
Expand Down
45 changes: 45 additions & 0 deletions tests/faktory-tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,49 @@ public function test_undefined_factory_returns_post_factory_with_post_type_chang
"Faktory::new should return a 'foobar' object when a type is passed"
);
}

public function test_newMany_returns_an_array()
{
$this->assertTrue(
is_array(Faktory::newMany()),
"Faktory::newMany should return an array"
);
}

public function test_newMany_returns_an_array_of_objects()
{
$this->assertIsObject(
Faktory::newMany()[0],
"Faktory::newMany should return an array of objects"
);
}

/**
* @testWith ["post_title"]
* ["post_title"]
*/
public function test_newMany_increments_suffix(string $property)
{
$objects = Faktory::newMany(2, 'post', [$property => "Foo Bar"]);

$this->assertEquals(
"Foo Bar 0", $objects[0]->$property,
"Faktory::newMany should increment the {$property} suffix"
);

$this->assertEquals(
"Foo Bar 1", $objects[1]->$property,
"Faktory::newMany should increment the {$property} suffix"
);
}

public function test_newMany_instantiates_objects_as_specified_class()
{
$objects = Faktory::newMany(2, 'post', ["post_title" => "Foo Bar"], class: "Faktory\Page");

$this->assertEquals(
"Faktory\Page", get_class($objects[0]),
"Faktory::newMany should instantiate objects as the specified class"
);
}
}