diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3ba4cf0..6fcd2fd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,26 +1,37 @@ -name: Build +name: Unit Test on: pull_request: branches: - master + - main push: branches: - master + - main jobs: build: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: - php: [7.3, 7.4, 8.0, 8.1] - setup: [basic, stable, lowest] + php: [8.0, 8.1] + laravel: [8.*, 9.*, 10.*] + dependency-version: [prefer-lowest, prefer-stable] + include: + - dbal: ignore + - laravel: 8.* + testbench: ^6.0 + dbal: install + - laravel: 9.* + dbal: install exclude: - - php: 8.0 - setup: lowest - - php: 8.1 - setup: lowest + - laravel: 10.* + php: 8.0 + + name: PHP${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} steps: - name: Checkout @@ -31,11 +42,20 @@ jobs: with: php-version: ${{matrix.php}} + - name: Cache Composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + # Use composer.json for key, if composer.lock is not committed. + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + - name: Install Composer dependencies run: | - if [[ ${{matrix.setup}} = 'basic' ]]; then composer install --prefer-dist --no-interaction --no-suggest; fi - if [[ ${{matrix.setup}} = 'stable' ]]; then composer update --prefer-dist --no-interaction --no-suggest --prefer-stable; fi - if [[ ${{matrix.setup}} = 'lowest' ]]; then composer update --prefer-dist --no-interaction --no-suggest --prefer-lowest --prefer-stable; fi + composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update + if [[ ${{matrix.dbal}} = 'install' ]]; then composer require doctrine/dbal; fi + composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction - name: Run PHPUnit tests run: | diff --git a/.gitignore b/.gitignore index 61aa727..86f5995 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +.DS_Store /composer.lock /.idea/ -/.phpunit.result.cache +/*.cache /vendor/ +phpunit.xml.bak diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000..60b81a2 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,59 @@ +preset: psr12 +version: 8 +enabled: + - alpha_ordered_imports + - binary_operator_spaces + - blank_line_before_return + - cast_spaces + - hash_to_slash_comment + - heredoc_to_nowdoc + - include + - linebreak_after_opening_tag + - method_separation + - native_function_casing + - no_blank_lines_after_phpdoc + - no_blank_lines_after_return + - no_blank_lines_after_throw + - no_blank_lines_between_imports + - no_blank_lines_between_traits + - no_empty_comment + - no_empty_phpdoc + - no_empty_statement + - no_extra_consecutive_blank_lines + - no_short_bool_cast + - no_singleline_whitespace_before_semicolons + - no_spaces_inside_offset + - no_spaces_outside_offset + - no_trailing_comma_in_list_call + - no_trailing_comma_in_singleline_array + - no_unneeded_control_parentheses + - no_unused_imports + - no_useless_return + - no_whitespace_before_comma_in_array + - normalize_index_brace + - object_operator_without_whitespace + - phpdoc_add_missing_param_annotation + - phpdoc_indent + - phpdoc_inline_tag + - phpdoc_link_to_see + - phpdoc_no_access + - phpdoc_no_empty_return + - phpdoc_no_package + - phpdoc_order + - phpdoc_scalar + - phpdoc_separation + - phpdoc_single_line_var_spacing + - phpdoc_trim + - phpdoc_type_to_var + - phpdoc_types + - phpdoc_var_without_name + - print_to_echo + - short_array_syntax + - space_after_semicolon + - standardize_not_equals + - trailing_comma_in_multiline_array + - trim_array_spaces + - unalign_double_arrow + - unalign_equals + - unary_operator_spaces + - whitespace_after_comma_in_array diff --git a/README.md b/README.md index 6a691e9..606b11c 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,17 @@ # Laravel State workflow -Implement [Symfony Workflow](https://symfony.com/doc/current/components/workflow.html) component in Laravel +[![Unit Test](https://github.com/RingierIMU/state-workflow/actions/workflows/main.yml/badge.svg)](https://github.com/RingierIMU/state-workflow/actions/workflows/main.yml) -A workflow consist of state and actions to get from one place to another. -The actions are called transitions which describes how to get from one state to another. +**Laravel State workflow** provide tools for defining and managing workflows and activities with ease. +It offers an object oriented way to define a process or a life cycle that your object goes through. +Each step or stage in the process is called a state. You do also define transitions that describe the action to get from one state to another. + +A workflow consist of **state** and **actions** to get from one state to another. +These **actions** are called **transitions** which describes how to get from one state to another. ## Installation ``` $ composer require ringierimu/state-workflow ``` -For Laravel versions lower than 5.5, this step is important after running above script. -- Open your config/app.php file and add custom service provider: -```php -Ringierimu\StateWorkflow\StateWorkflowServiceProvider::class -``` Publish `config/workflow.php` file ```php $ php artisan vendor:publish --provider="Ringierimu\StateWorkflow\StateWorkflowServiceProvider" @@ -81,6 +80,16 @@ use Ringierimu\StateWorkflow\Traits\HasWorkflowTrait; class Post extends Model { use HasWorkflowTrait; + + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + ..., + 'current_state', // If not using default attribute, update this to match value in workflow.php + ] } ``` @@ -104,6 +113,25 @@ $post->canTransition("activate"); // True //Return Model state history $post->stateHistory(); +``` + +### Authenticated User Resolver +Ability to audit and track who action a specific state change for your object. +The package leverage the default Laravel auth provider to resolve the authenticated user when applying the state changes. + +For a custom authentication mechanism, you should override `authenticatedUserId` in your object class with your own implementation. + +```php +/** + * Return authenticated user id. + * + * @return int|null + */ +public function authenticatedUserId() +{ + // Implement authenticated user resolver +} + ``` ### Fired Event Each step has three events that are fired in order: @@ -252,4 +280,12 @@ You will be required to download `dot` command to make use of this command. ### Usage ```php php artisan workflow:dump workflow_name -``` +``` + +## Run Unit Test +```bash +composer test +``` + +## Credits +- [Symfony Workflow](https://symfony.com/doc/current/components/workflow.html) diff --git a/composer.json b/composer.json index 845735d..07758fa 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,12 @@ { "name": "ringierimu/state-workflow", "type": "library", - "description": "State Management workflow for Laravel", + "description": "Laravel State Workflow provide tools for defining and managing workflows and activities with ease.", "keywords": [ "workflow", "state management", + "state machine", + "state workflow", "laravel" ], "homepage": "https://github.com/RingierIMU/state-workflow", @@ -12,25 +14,23 @@ "authors": [ { "name": "Norby Baruani", - "email": "norbyb@roam.africa", + "email": "norbybaru@gmail.com", "role": "Developer" } ], "require": { - "php": "^7.3|^8.0", - "illuminate/events": "^7|^8|^9|^10.0", - "illuminate/support": "^7|^8|^9|^10.0", + "php": "^8.0", + "illuminate/events": "^8|^9|^10.0", + "illuminate/support": "^8|^9|^10.0", "symfony/event-dispatcher": "^5.1", "symfony/workflow": "^5.1", "symfony/property-access": "^5.1" }, "require-dev": { "funkjedi/composer-include-files": "^1.0", - "laravel/legacy-factories": "^1.1", "mockery/mockery": "^1.3|^1.4.2", - "orchestra/database": "^5|^6|^7", - "orchestra/testbench": "^5|^6|^7|^8.0", - "phpunit/phpunit": "^8|^9" + "orchestra/testbench": "^6.24|^7.0|^8.0", + "phpunit/phpunit": "^9.5|^10.0" }, "extra": { "include_files": [ @@ -50,10 +50,7 @@ "autoload-dev": { "psr-4": { "Ringierimu\\StateWorkflow\\Tests\\": "tests/" - }, - "classmap": [ - "tests/Fixtures/database/factories" - ] + } }, "minimum-stability": "dev", "prefer-stable": true, @@ -61,5 +58,8 @@ "allow-plugins": { "funkjedi/composer-include-files": true } + }, + "scripts": { + "test": "phpunit" } } diff --git a/config/workflow.php b/config/workflow.php index 2b5fffd..e14fdd1 100644 --- a/config/workflow.php +++ b/config/workflow.php @@ -1,23 +1,52 @@ [ + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | This define Authentication user is model of your application. + | Ideally it should match your `providers.users.model` found in `config/auth.php` + | to leverage the default Laravel auth resolver + | + */ 'user_class' => \App\User::class, ], - // this should be your model name in camelcase. eg. PropertyListing::Class => propertyListing + /* + |-------------------------------------------------------------------------- + | Domain entity + |-------------------------------------------------------------------------- + | + | This should be your model name in camelCase. + | + | eg. UserProfile::Class => userProfile + | + | Attributes definition + | + | subscriber: + | Register subscriber for this workflow which contains business rules. + | + | property_path: + | Attribute on your domain entity holding the actual state (default is "current_state") + | + | states: + | Define all possible state your domain entity can transition to + | + | transitions: + | Define all allowed transitions to transit from one state to another + */ 'user' => [ // class of your domain object 'class' => \App\User::class, - // Register subscriber for this workflow which contains business rules. Uncomment line below to register subscriber - //'subscriber' => \App\Listeners\UserEventSubscriber::class, + 'subscriber' => \App\Listeners\UserEventSubscriber::class, - // property of your object holding the actual state (default is "current_state") - //'property_path' => 'current_state', //uncomment this line to override default value + // Uncomment line below to override default attribute + // 'property_path' => 'current_state', - // list of all possible states 'states' => [ 'new', 'pending_activation', @@ -26,23 +55,22 @@ 'blocked', ], - // list of all possible transitions 'transitions' => [ 'create' => [ 'from' => 'new', - 'to' => 'pending_activation', + 'to' => 'pending_activation', ], 'activate' => [ 'from' => 'pending_activation', - 'to' => 'activated', + 'to' => 'activated', ], 'block' => [ 'from' => ['pending_activation', 'activated'], - 'to' => 'blocked', + 'to' => 'blocked', ], 'delete' => [ 'from' => ['pending_activation', 'activated', 'blocked'], - 'to' => 'deleted', + 'to' => 'deleted', ], ], ], diff --git a/database/migrations/2018_12_03_150333_create_state_workflow_histories_table.php b/database/migrations/create_state_workflow_histories_table.php similarity index 88% rename from database/migrations/2018_12_03_150333_create_state_workflow_histories_table.php rename to database/migrations/create_state_workflow_histories_table.php index 99a6acd..1a8efd1 100644 --- a/database/migrations/2018_12_03_150333_create_state_workflow_histories_table.php +++ b/database/migrations/create_state_workflow_histories_table.php @@ -7,12 +7,9 @@ /** * Class CreateStateWorkflowHistoryTable. */ -class CreateStateWorkflowHistoriesTable extends Migration -{ +return new class () extends Migration { /** * Run the migrations. - * - * @return void */ public function up() { @@ -31,11 +28,9 @@ public function up() /** * Reverse the migrations. - * - * @return void */ public function down() { Schema::dropIfExists('state_workflow_histories'); } -} +}; diff --git a/phpunit.xml b/phpunit.xml index caa5580..3cc6b8f 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,26 +1,17 @@ - - - - ./tests - - - - - - - - - - - + + + + ./tests + + + + + + + + + + + diff --git a/src/Interfaces/WorkflowRegistryInterface.php b/src/Interfaces/WorkflowRegistryInterface.php index 0786e35..2be68de 100644 --- a/src/Interfaces/WorkflowRegistryInterface.php +++ b/src/Interfaces/WorkflowRegistryInterface.php @@ -24,8 +24,6 @@ public function get($object, $workflowName = null); * * @param $class * @param $name - * - * @return void */ public function addSubscriber($class, $name); } diff --git a/src/StateWorkflowServiceProvider.php b/src/StateWorkflowServiceProvider.php index ec343f2..933850e 100644 --- a/src/StateWorkflowServiceProvider.php +++ b/src/StateWorkflowServiceProvider.php @@ -17,6 +17,7 @@ class StateWorkflowServiceProvider extends ServiceProvider public function boot() { $this->publishConfig(); + $this->publishDatabase(); $this->loadMigrations(); $this->registerCommands(); } @@ -46,7 +47,7 @@ public function register() */ protected function configPath() { - return __DIR__.'/../config/workflow.php'; + return __DIR__ . '/../config/workflow.php'; } /** @@ -56,7 +57,7 @@ protected function configPath() */ private function migrationPath() { - return __DIR__.'/../database/migrations'; + return __DIR__ . '/../database/migrations'; } /** @@ -68,9 +69,15 @@ protected function publishConfig() $this->publishes([ $this->configPath() => config_path('workflow.php'), ], 'state-workflow-config'); + } + } + protected function publishDatabase() + { + if ($this->app->runningInConsole()) { + $path = 'migrations/' . date('Y_m_d_His', time()); $this->publishes([ - $this->migrationPath() => database_path('migrations'), + $this->migrationPath() . '/create_state_workflow_histories_table.php' => database_path($path . '_create_state_workflow_histories_table.php'), ], 'state-workflow-migrations'); } } diff --git a/src/Subscribers/WorkflowSubscriber.php b/src/Subscribers/WorkflowSubscriber.php index 28a30df..1569c6c 100644 --- a/src/Subscribers/WorkflowSubscriber.php +++ b/src/Subscribers/WorkflowSubscriber.php @@ -108,9 +108,9 @@ public function enteredEvent(Event $event) if (method_exists($model, 'saveStateHistory')) { $model->saveStateHistory([ 'transition' => $event->getTransition()->getName(), - 'from' => $from, - 'to' => $to, - 'context' => method_exists($model, 'getContext') ? $model->getContext() : [], + 'from' => $from, + 'to' => $to, + 'context' => method_exists($model, 'getContext') ? $model->getContext() : [], ]); } @@ -160,12 +160,12 @@ public function completedEvent(Event $event) public static function getSubscribedEvents() { return [ - 'workflow.guard' => ['guardEvent'], - 'workflow.leave' => ['leaveEvent'], + 'workflow.guard' => ['guardEvent'], + 'workflow.leave' => ['leaveEvent'], 'workflow.transition' => ['transitionEvent'], - 'workflow.enter' => ['enterEvent'], - 'workflow.entered' => ['enteredEvent'], - 'workflow.completed' => ['completedEvent'], + 'workflow.enter' => ['enterEvent'], + 'workflow.entered' => ['enteredEvent'], + 'workflow.completed' => ['completedEvent'], ]; } } diff --git a/src/Subscribers/WorkflowSubscriberHandler.php b/src/Subscribers/WorkflowSubscriberHandler.php index 36c78e0..ca0fc34 100644 --- a/src/Subscribers/WorkflowSubscriberHandler.php +++ b/src/Subscribers/WorkflowSubscriberHandler.php @@ -50,7 +50,7 @@ public function subscribe($event) // if the method name starts with 'on' if (preg_match('/^on/', $method)) { // attach the event listener - $event->listen($this->key($method), $class.'@'.$method); + $event->listen($this->key($method), $class . '@' . $method); } } } @@ -118,7 +118,7 @@ protected function key($name) $transition = $segments[0]; unset($segments[0]); $flow = implode('_', $segments); - $name = $transition.'.'.$flow; + $name = $transition . '.' . $flow; } return sprintf('workflow.%s.%s', $this->name, $name); diff --git a/src/Traits/HasWorkflowTrait.php b/src/Traits/HasWorkflowTrait.php index c69e24b..2215db7 100644 --- a/src/Traits/HasWorkflowTrait.php +++ b/src/Traits/HasWorkflowTrait.php @@ -53,7 +53,7 @@ public function state() } /** - * @param $transition + * @param $transition * @param array $context * * @throws \ReflectionException diff --git a/src/WorkflowRegistry.php b/src/WorkflowRegistry.php index f5ae36e..88bf995 100644 --- a/src/WorkflowRegistry.php +++ b/src/WorkflowRegistry.php @@ -93,7 +93,7 @@ public function registerWorkflow(StateWorkflow $workflow, string $className) /** * Add a workflow to the registry from array. * - * @param $name + * @param $name * @param array $workflowData * * @throws \ReflectionException @@ -122,7 +122,7 @@ public function addWorkflows($name, array $workflowData) /** * Return the workflow instance. * - * @param $name + * @param $name * @param array $workflowData * @param Definition $definition * @param MarkingStoreInterface $markingStore @@ -199,15 +199,13 @@ protected function getMarkingStoreInstance(array $workflowData) * * @throws \ReflectionException * @throws Exception - * - * @return void */ public function addSubscriber($class, $name) { $reflection = new ReflectionClass($class); if (!$reflection->implementsInterface(WorkflowEventSubscriberInterface::class)) { - throw new Exception("$class must implements ".WorkflowEventSubscriberInterface::class); + throw new Exception("$class must implements " . WorkflowEventSubscriberInterface::class); } if ($reflection->isInstantiable()) { diff --git a/tests/Fixtures/Models/User.php b/tests/Fixtures/Models/User.php index 87df491..e07d97f 100644 --- a/tests/Fixtures/Models/User.php +++ b/tests/Fixtures/Models/User.php @@ -18,7 +18,7 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'name', 'email', 'password', + 'name', 'email', 'password', 'user_state', ]; /** diff --git a/tests/Fixtures/Subscriber/UserEventSubscriber.php b/tests/Fixtures/Subscriber/UserEventSubscriber.php index 1d4afac..d3af331 100644 --- a/tests/Fixtures/Subscriber/UserEventSubscriber.php +++ b/tests/Fixtures/Subscriber/UserEventSubscriber.php @@ -24,10 +24,10 @@ public function onGuard($event) Log::info(__METHOD__); //$event->getOriginalEvent()->setBlocked(true); - Log::info('workflow name: '.$event->getOriginalEvent()->getWorkflowName()); - Log::info('transition name: '.$event->getOriginalEvent()->getTransition()->getName()); - Log::info('froms: '.implode(',', $event->getOriginalEvent()->getTransition()->getFroms())); - Log::info('tos: '.implode(',', $event->getOriginalEvent()->getTransition()->getTos())); + Log::info('workflow name: ' . $event->getOriginalEvent()->getWorkflowName()); + Log::info('transition name: ' . $event->getOriginalEvent()->getTransition()->getName()); + Log::info('froms: ' . implode(',', $event->getOriginalEvent()->getTransition()->getFroms())); + Log::info('tos: ' . implode(',', $event->getOriginalEvent()->getTransition()->getTos())); } /** @@ -37,10 +37,10 @@ public function onGuardActivate($event) { Log::info(__METHOD__); - Log::info('workflow name: '.$event->getOriginalEvent()->getWorkflowName()); - Log::info('transition name: '.$event->getOriginalEvent()->getTransition()->getName()); - Log::info('froms: '.implode(',', $event->getOriginalEvent()->getTransition()->getFroms())); - Log::info('tos: '.implode(',', $event->getOriginalEvent()->getTransition()->getTos())); + Log::info('workflow name: ' . $event->getOriginalEvent()->getWorkflowName()); + Log::info('transition name: ' . $event->getOriginalEvent()->getTransition()->getName()); + Log::info('froms: ' . implode(',', $event->getOriginalEvent()->getTransition()->getFroms())); + Log::info('tos: ' . implode(',', $event->getOriginalEvent()->getTransition()->getTos())); } /** @@ -95,10 +95,10 @@ public function onCompleted($event) { Log::info(__METHOD__); - Log::info('workflow name: '.$event->getOriginalEvent()->getWorkflowName()); - Log::info('transition name: '.$event->getOriginalEvent()->getTransition()->getName()); - Log::info('froms: '.implode(',', $event->getOriginalEvent()->getTransition()->getFroms())); - Log::info('tos: '.implode(',', $event->getOriginalEvent()->getTransition()->getTos())); + Log::info('workflow name: ' . $event->getOriginalEvent()->getWorkflowName()); + Log::info('transition name: ' . $event->getOriginalEvent()->getTransition()->getName()); + Log::info('froms: ' . implode(',', $event->getOriginalEvent()->getTransition()->getFroms())); + Log::info('tos: ' . implode(',', $event->getOriginalEvent()->getTransition()->getTos())); } /** diff --git a/tests/Fixtures/Traits/ConfigTrait.php b/tests/Fixtures/Traits/ConfigTrait.php index b256632..4624ca0 100644 --- a/tests/Fixtures/Traits/ConfigTrait.php +++ b/tests/Fixtures/Traits/ConfigTrait.php @@ -40,19 +40,19 @@ public function getWorflowConfig() 'transitions' => [ 'create' => [ 'from' => 'new', - 'to' => 'pending_activation', + 'to' => 'pending_activation', ], 'activate' => [ 'from' => 'pending_activation', - 'to' => 'activated', + 'to' => 'activated', ], 'block' => [ 'from' => ['pending_activation', 'activated'], - 'to' => 'blocked', + 'to' => 'blocked', ], 'delete' => [ 'from' => ['activated', 'blocked'], - 'to' => 'deleted', + 'to' => 'deleted', ], ], ], diff --git a/tests/Fixtures/database/factories/UserFactory.php b/tests/Fixtures/database/factories/UserFactory.php deleted file mode 100644 index 1aa2d95..0000000 --- a/tests/Fixtures/database/factories/UserFactory.php +++ /dev/null @@ -1,25 +0,0 @@ -define(Ringierimu\StateWorkflow\Tests\Fixtures\Models\User::class, function (Faker $faker) { - return [ - 'name' => $faker->name, - 'email' => $faker->unique()->safeEmail, - 'email_verified_at' => now(), - 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret - 'remember_token' => Str::random(10), - ]; -}); diff --git a/tests/Fixtures/database/migrations/0000_00_00_000000_create_users_Test_table.php b/tests/Fixtures/database/migrations/0000_00_00_000000_create_users_Test_table.php index d2db955..8879f41 100644 --- a/tests/Fixtures/database/migrations/0000_00_00_000000_create_users_Test_table.php +++ b/tests/Fixtures/database/migrations/0000_00_00_000000_create_users_Test_table.php @@ -4,34 +4,24 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateUsersTestTable extends Migration -{ +return new class () extends Migration { /** * Run the migrations. - * - * @return void */ public function up() { - Schema::create('users', function (Blueprint $table) { - $table->increments('id'); - $table->string('name'); - $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); - $table->string('password'); + Schema::table('users', function (Blueprint $table) { $table->string('user_state'); - $table->rememberToken(); - $table->timestamps(); }); } /** * Reverse the migrations. - * - * @return void */ public function down() { - Schema::dropIfExists('users'); + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('user_state'); + }); } -} +}; diff --git a/tests/Fixtures/database/migrations/0001_00_00_000000_create_state_workflow_histories_Test_table.php b/tests/Fixtures/database/migrations/0001_00_00_000000_create_state_workflow_histories_Test_table.php deleted file mode 100644 index 69bfb8f..0000000 --- a/tests/Fixtures/database/migrations/0001_00_00_000000_create_state_workflow_histories_Test_table.php +++ /dev/null @@ -1,41 +0,0 @@ -increments('id'); - $table->string('model_name')->index(); - $table->integer('model_id')->index(); - $table->string('transition'); - $table->string('from'); - $table->string('to'); - $table->integer('user_id')->index(); - $table->json('context'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('state_workflow_histories'); - } -} diff --git a/tests/TestCase.php b/tests/TestCase.php index d39bebb..54f9f29 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,38 +2,30 @@ namespace Ringierimu\StateWorkflow\Tests; +use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Support\Str; +use Orchestra\Testbench\TestCase as OrchestraTestCase; use Ringierimu\StateWorkflow\StateWorkflowServiceProvider; use Ringierimu\StateWorkflow\Tests\Fixtures\Models\User; use Ringierimu\StateWorkflow\Tests\Fixtures\Traits\ConfigTrait; -/** - * Class TestCase. - */ -abstract class TestCase extends \Orchestra\Testbench\TestCase +abstract class TestCase extends OrchestraTestCase { use ConfigTrait; + use RefreshDatabase; + use WithFaker; /** @var User */ protected $user; public function setUp(): void { - parent::setUp(); // TODO: Change the autogenerated stub - - $this->loadMigrationsFrom(__DIR__.'/Fixtures/database/migrations/'); - $this->withFactories(__DIR__.'/Fixtures/database/factories/'); - - $this->user = factory(User::class)->create( - [ - 'user_state' => 'new', - ] - ); - - auth()->login(factory(User::class)->create( - [ - 'user_state' => 'new', - ] - )); + parent::setUp(); + + $this->user = User::create($this->userFactory()); + + auth()->login(User::create($this->userFactory())); } /** @@ -52,6 +44,28 @@ protected function getPackageProviders($app) protected function getEnvironmentSetUp($app) { $app['config']->set('workflow', $this->getWorflowConfig()); - parent::getEnvironmentSetUp($app); // TODO: Change the autogenerated stub + parent::getEnvironmentSetUp($app); + } + + /** + * Define database migrations. + */ + protected function defineDatabaseMigrations() + { + $this->loadLaravelMigrations(); + $this->loadMigrationsFrom(__DIR__ . '/../database/migrations'); + $this->loadMigrationsFrom(__DIR__ . '/Fixtures/database/migrations/'); + } + + private function userFactory(): array + { + return [ + 'name' => $this->faker->name, + 'email' => $this->faker->unique()->safeEmail, + 'email_verified_at' => now(), + 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret + 'remember_token' => Str::random(10), + 'user_state' => 'new', + ]; } } diff --git a/tests/Unit/UserUnitTest.php b/tests/Unit/UserUnitTest.php index 0b6318f..166fbed 100644 --- a/tests/Unit/UserUnitTest.php +++ b/tests/Unit/UserUnitTest.php @@ -2,7 +2,6 @@ namespace Ringierimu\StateWorkflow\Tests\Unit; -use Ringierimu\StateWorkflow\Tests\Fixtures\Models\User; use Ringierimu\StateWorkflow\Tests\TestCase; use Ringierimu\StateWorkflow\Workflow\StateWorkflow; use Symfony\Component\Workflow\Exception\LogicException; @@ -13,22 +12,6 @@ */ class UserUnitTest extends TestCase { - /** @var User */ - protected $user; - - public function setUp(): void - { - parent::setUp(); // TODO: Change the autogenerated stub - - $this->user = factory(User::class)->create([ - 'user_state' => 'new', - ]); - - auth()->login(factory(User::class)->create([ - 'user_state' => 'new', - ])); - } - /** * @test * diff --git a/tests/WorkflowSubscriberTest.php b/tests/WorkflowSubscriberTest.php index e2cc388..f62e445 100644 --- a/tests/WorkflowSubscriberTest.php +++ b/tests/WorkflowSubscriberTest.php @@ -1,7 +1,6 @@