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

Allow factory state to be set #10

Merged
merged 5 commits into from
Oct 4, 2018
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,38 @@ return [
|
| The package will look for the equivalent factory if the
| dependency is an eloquent model. So don't forget to
| create those factories. However, things like the factory
| state & times/count feature aren't supported for the factories.
| create those factories. If you want a specific state to
| be used for your dependency you will have to pass an array
| with 'class' and 'states' keys. The class key will have the
| name of the dependency and states should contain an array of
| factory states you want to apply to the factory, see the
| MailWithDependencyStates example below.
|
| Please note that the factory times/count feature isn't
| supported for the factories.
| Eg:
| What the package supports: factory(Order::class)->create();
| What the package doesn't support: factory(Order::class, 5)->state('pending')->create();
| What the package doesn't support: factory(Order::class, 5)->create();
|
| The package will try to resolve all other non-eloquent objects
| using the Laravel's service container.
|
| Also, don't forget to import these classes at the top :)
|
| eg: 'mailables' => [
| OrderShipped::class => [
| Order::class,
| eg:
| 'mailables' => [
| OrderShipped::class => [
| Order::class,
| 'Personal thank you message',
| ],
| MailWithNoDependency::class => []
| ]
| ],
| MailWithDependencyStates::class => [
| [
| 'class' => Order::class,
| 'states' => ['state1', 'state2']
| ]
| ],
| MailWithNoDependency::class => []
| ]
|
*/

Expand Down
32 changes: 23 additions & 9 deletions config/mailviewer.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,38 @@
|
| The package will look for the equivalent factory if the
| dependency is an eloquent model. So don't forget to
| create those factories. However, things like the factory
| state & times/count feature aren't supported for the factories.
| create those factories. If you want a specific state to
| be used for your dependency you will have to pass an array
| with 'class' and 'states' keys. The class key will have the
| name of the dependency and states should contain an array of
| factory states you want to apply to the factory, see the
| MailWithDependencyStates example below.
|
| Please note that the factory times/count feature isn't
| supported for the factories.
| Eg:
| What the package supports: factory(Order::class)->create();
| What the package doesn't support: factory(Order::class, 5)->state('pending')->create();
| What the package doesn't support: factory(Order::class, 5)->create();
|
| The package will try to resolve all other non-eloquent objects
| using the Laravel's service container.
|
| Also, don't forget to import these classes at the top :)
|
| eg: 'mailables' => [
| OrderShipped::class => [
| Order::class,
| eg:
| 'mailables' => [
| OrderShipped::class => [
| Order::class,
| 'Personal thank you message',
| ],
| MailWithNoDependency::class => []
| ]
| ],
| MailWithDependencyStates::class => [
| [
| 'class' => Order::class,
| 'states' => ['state1', 'state2']
| ]
| ],
| MailWithNoDependency::class => []
| ]
|
*/

Expand Down
19 changes: 17 additions & 2 deletions src/MailViewer.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,18 @@ public static function find(string $mail)
$args = [];

foreach ($dependencies as $dependency) {
$factoryStates = [];

if (is_array($dependency)) {
if (in_array('states', array_keys($dependency))) {
$factoryStates = $dependency['states'];
$dependency = $dependency['class'];
}
}

if (is_string($dependency) && class_exists($dependency)) {
if (isset($eloquentFactory[$dependency])) {
$args[] = factory($dependency)->create();
$args[] = factory($dependency)->states($factoryStates)->make();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious to know why make() over create() 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first reason was the tests, the create function will try to save the Test model in the database as it's a Illuminate model. I can make it some general model that doesn't save to the database to make the test pass too. The other reason is that you probably don't want to save the records to the database when you are just viewing the email via the /mails page, especially on a production environment ;) I actually didn't realise this was happening until I was editing this code.

} else {
$args[] = app($dependency);
}
Expand All @@ -70,6 +79,12 @@ public static function prepareMails(array $mailables): array
$givenParameters = [];

foreach ($dependencies as $dependency) {
if (is_array($dependency)) {
if (in_array('states', array_keys($dependency))) {
$dependency = $dependency['class'];
}
}

$givenParameters[] = is_string($dependency) && class_exists($dependency)
? (new ReflectionClass($dependency))->getName()
: getType($dependency);
Expand All @@ -83,7 +98,7 @@ public static function prepareMails(array $mailables): array

if ($constructorParameters !== $givenParameters) {
throw new Exception(
"The arguments passed for {$mailable} in the config/mailviewer.php file do not match with the constructor
"The arguments passed for {$mailable} in the config/mailviewer.php file do not match with the constructor
params of the {$mailable} class or the constructor params of the {$mailable} class aren't typehinted"
);
}
Expand Down
10 changes: 10 additions & 0 deletions src/MailViewerServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace JoggApp\MailViewer;

use Illuminate\Database\Eloquent\Factory as EloquentFactory;
use Illuminate\Support\ServiceProvider;

class MailViewerServiceProvider extends ServiceProvider
Expand All @@ -15,6 +16,15 @@ public function boot()
$this->loadRoutesFrom(__DIR__ . '/../routes/web.php');

$this->loadViewsFrom(__DIR__ . '/../views', 'mailviewer');

if (app()->environment() === 'testing') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious to know what is the benefit of this container binding since it might effect user's own testing env

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to do this to make sure the TestFactory.php class would be loaded when running the unit tests. Laravel sets the default environment to testing when running unit tests so shouldn't cause a problem for anyone's testing env. See the code on Laravel's repo.

$this->app->singleton(EloquentFactory::class, function ($app) {
$faker = $app->make(\Faker\Generator::class);
$factories_path = __DIR__.'/../tests/Factories';

return EloquentFactory::construct($faker, $factories_path);
});
}
}

public function register()
Expand Down
8 changes: 8 additions & 0 deletions tests/BaseTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use JoggApp\MailViewer\MailViewerServiceProvider;
use JoggApp\MailViewer\Tests\Stubs\Mail\TestEmailForMailViewer;
use JoggApp\MailViewer\Tests\Stubs\Mail\TestEmailWithDependencies;
use JoggApp\MailViewer\Tests\Stubs\Mail\TestEmailWithState;
use JoggApp\MailViewer\Tests\Stubs\Models\Test;
use Orchestra\Testbench\TestCase;

class BaseTestCase extends TestCase
Expand All @@ -27,6 +29,12 @@ protected function getEnvironmentSetUp($app)
\stdClass::class,
'Some name',
7
],
TestEmailWithState::class => [
[
'class' => Test::class,
'states' => ['is-awesome']
]
]
]
);
Expand Down
15 changes: 15 additions & 0 deletions tests/Factories/TestFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

use JoggApp\MailViewer\Tests\Stubs\Models\Test;

/** @var \Illuminate\Database\Eloquent\Factory $factory */

$factory->define(Test::class, function () {
return [
'is_awesome' => 'no'
];
});

$factory->state(Test::class, 'is-awesome', [
'is_awesome' => 'yes'
]);
8 changes: 8 additions & 0 deletions tests/MailViewerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,12 @@ public function it_renders_the_mailable_with_dependencies_on_its_dedicated_route
$this->get(route('mv-mailviewer', 'TestEmailWithDependencies'))
->assertSee('The test email view');
}

/** @test */
public function it_renders_the_mailable_with_state_on_its_dedicated_route()
{
$this->get(route('mv-mailviewer', 'TestEmailWithState'))
->assertSee('The test email view')
->assertSee('Is awesome: yes');
}
}
35 changes: 35 additions & 0 deletions tests/Stubs/Mail/TestEmailWithState.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace JoggApp\MailViewer\Tests\Stubs\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use JoggApp\MailViewer\Tests\Stubs\Models\Test;

class TestEmailWithState extends Mailable
{
use Queueable, SerializesModels;

public $object;

/**
* Create a new message instance.
*
* @return void
*/
public function __construct(Test $object)
{
$this->object = $object;
}

/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('mailviewer::stubs.emailtestview_withstate');
}
}
9 changes: 9 additions & 0 deletions tests/Stubs/Models/Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace JoggApp\MailViewer\Tests\Stubs\Models;

use Illuminate\Database\Eloquent\Model;

class Test extends Model
{
}
3 changes: 3 additions & 0 deletions views/stubs/emailtestview_withstate.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The test email view

Is awesome: {{ $object->is_awesome }}