diff --git a/database/factories/FeatureConsumptionFactory.php b/database/factories/FeatureConsumptionFactory.php index ee1930f..3520959 100644 --- a/database/factories/FeatureConsumptionFactory.php +++ b/database/factories/FeatureConsumptionFactory.php @@ -2,13 +2,15 @@ namespace LucasDotVin\Soulbscription\Database\Factories; -use LucasDotVin\Soulbscription\Models\Feature; use Illuminate\Database\Eloquent\Factories\Factory; -use LucasDotVin\Soulbscription\Models\FeatureConsumption; - class FeatureConsumptionFactory extends Factory { - protected $model = FeatureConsumption::class; + protected $model; + + public function __construct() + { + $this->model = config('soulbscription.models.feature_consumption'); + } /** * Define the model's default state. @@ -18,7 +20,7 @@ class FeatureConsumptionFactory extends Factory public function definition() { return [ - 'feature_id' => Feature::factory(), + 'feature_id' => config('soulbscription.models.feature')::factory(), 'consumption' => $this->faker->randomFloat(), 'expired_at' => $this->faker->dateTime(), 'subscriber_id' => $this->faker->randomNumber(), diff --git a/database/factories/FeatureFactory.php b/database/factories/FeatureFactory.php index d6ad559..cadbeac 100644 --- a/database/factories/FeatureFactory.php +++ b/database/factories/FeatureFactory.php @@ -4,11 +4,15 @@ use LucasDotVin\Soulbscription\Enums\PeriodicityType; use Illuminate\Database\Eloquent\Factories\Factory; -use LucasDotVin\Soulbscription\Models\Feature; class FeatureFactory extends Factory { - protected $model = Feature::class; + protected $model; + + public function __construct() + { + $this->model = config('soulbscription.models.feature'); + } /** * Define the model's default state. diff --git a/database/factories/PlanFactory.php b/database/factories/PlanFactory.php index f391db9..5cb0ccd 100644 --- a/database/factories/PlanFactory.php +++ b/database/factories/PlanFactory.php @@ -4,11 +4,15 @@ use LucasDotVin\Soulbscription\Enums\PeriodicityType; use Illuminate\Database\Eloquent\Factories\Factory; -use LucasDotVin\Soulbscription\Models\Plan; class PlanFactory extends Factory { - protected $model = Plan::class; + protected $model; + + public function __construct() + { + $this->model = config('soulbscription.models.plan'); + } /** * Define the model's default state. diff --git a/database/factories/SubscriptionFactory.php b/database/factories/SubscriptionFactory.php index dd3e1a0..c796389 100644 --- a/database/factories/SubscriptionFactory.php +++ b/database/factories/SubscriptionFactory.php @@ -2,13 +2,16 @@ namespace LucasDotVin\Soulbscription\Database\Factories; -use LucasDotVin\Soulbscription\Models\Plan; use Illuminate\Database\Eloquent\Factories\Factory; -use LucasDotVin\Soulbscription\Models\Subscription; class SubscriptionFactory extends Factory { - protected $model = Subscription::class; + protected $model; + + public function __construct() + { + $this->model = config('soulbscription.models.subscription'); + } /** * Define the model's default state. @@ -18,7 +21,7 @@ class SubscriptionFactory extends Factory public function definition() { return [ - 'plan_id' => Plan::factory(), + 'plan_id' => config('soulbscription.models.plan')::factory(), 'canceled_at' => null, 'started_at' => $this->faker->dateTime(), 'suppressed_at' => null, diff --git a/database/factories/SubscriptionRenewalFactory.php b/database/factories/SubscriptionRenewalFactory.php index a54c207..06d4beb 100644 --- a/database/factories/SubscriptionRenewalFactory.php +++ b/database/factories/SubscriptionRenewalFactory.php @@ -2,12 +2,16 @@ namespace LucasDotVin\Soulbscription\Database\Factories; -use LucasDotVin\Soulbscription\Models\{Subscription, SubscriptionRenewal}; use Illuminate\Database\Eloquent\Factories\Factory; class SubscriptionRenewalFactory extends Factory { - protected $model = SubscriptionRenewal::class; + protected $model; + + public function __construct() + { + $this->model = config('soulbscription.models.subscription_renewal'); + } /** * Define the model's default state. @@ -17,7 +21,7 @@ class SubscriptionRenewalFactory extends Factory public function definition() { return [ - 'subscription_id' => Subscription::factory(), + 'subscription_id' => config('soulbscription.models.subscription')::factory(), 'overdue' => $this->faker->boolean(), 'renewal' => $this->faker->boolean(), ]; diff --git a/database/migrations/2022_02_01_235539_create_subscriptions_table.php b/database/migrations/2022_02_01_235539_create_subscriptions_table.php index 5cf7c64..6763b2c 100644 --- a/database/migrations/2022_02_01_235539_create_subscriptions_table.php +++ b/database/migrations/2022_02_01_235539_create_subscriptions_table.php @@ -2,7 +2,6 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; return new class() extends Migration { @@ -15,7 +14,7 @@ public function up() { Schema::create('subscriptions', function (Blueprint $table) { $table->id(); - $table->foreignIdFor(\LucasDotVin\Soulbscription\Models\Plan::class); + $table->foreignIdFor(config('soulbscription.models.plan')::class); $table->timestamp('canceled_at')->nullable(); $table->timestamp('expired_at')->nullable(); $table->timestamp('grace_days_ended_at')->nullable(); diff --git a/database/migrations/2022_02_02_000527_create_feature_consumptions_table.php b/database/migrations/2022_02_02_000527_create_feature_consumptions_table.php index 526eb92..bf5b2d1 100644 --- a/database/migrations/2022_02_02_000527_create_feature_consumptions_table.php +++ b/database/migrations/2022_02_02_000527_create_feature_consumptions_table.php @@ -16,7 +16,7 @@ public function up() $table->id(); $table->decimal('consumption')->unsigned()->nullable(); $table->timestamp('expired_at')->nullable(); - $table->foreignIdFor(\LucasDotVin\Soulbscription\Models\Feature::class)->constrained()->cascadeOnDelete(); + $table->foreignIdFor(config('soulbscription.models.feature')::class)->constrained()->cascadeOnDelete(); $table->timestamps(); if (config('soulbscription.models.subscriber.uses_uuid')) { diff --git a/database/migrations/2022_02_03_001206_create_subscription_renewals_table.php b/database/migrations/2022_02_03_001206_create_subscription_renewals_table.php index beeaa12..dc13026 100644 --- a/database/migrations/2022_02_03_001206_create_subscription_renewals_table.php +++ b/database/migrations/2022_02_03_001206_create_subscription_renewals_table.php @@ -16,7 +16,7 @@ public function up() $table->id(); $table->boolean('overdue'); $table->boolean('renewal'); - $table->foreignIdFor(\LucasDotVin\Soulbscription\Models\Subscription::class); + $table->foreignIdFor(config('soulbscription.models.subscription')::class); $table->timestamps(); }); } diff --git a/database/migrations/2022_02_04_001622_create_feature_plan_table.php b/database/migrations/2022_02_04_001622_create_feature_plan_table.php index c86f672..17c95fd 100644 --- a/database/migrations/2022_02_04_001622_create_feature_plan_table.php +++ b/database/migrations/2022_02_04_001622_create_feature_plan_table.php @@ -15,8 +15,8 @@ public function up() Schema::create('feature_plan', function (Blueprint $table) { $table->id(); $table->decimal('charges')->nullable(); - $table->foreignIdFor(\LucasDotVin\Soulbscription\Models\Feature::class)->constrained()->cascadeOnDelete(); - $table->foreignIdFor(\LucasDotVin\Soulbscription\Models\Plan::class)->constrained()->cascadeOnDelete(); + $table->foreignIdFor(config('soulbscription.models.plan')::class)->constrained()->cascadeOnDelete(); + $table->foreignIdFor(config('soulbscription.models.feature')::class)->constrained()->cascadeOnDelete(); $table->timestamps(); }); } diff --git a/database/migrations/2022_02_25_001622_create_feature_tickets_table.php b/database/migrations/2022_02_25_001622_create_feature_tickets_table.php index f384584..6fac6b1 100644 --- a/database/migrations/2022_02_25_001622_create_feature_tickets_table.php +++ b/database/migrations/2022_02_25_001622_create_feature_tickets_table.php @@ -16,7 +16,7 @@ public function up() $table->id(); $table->decimal('charges')->nullable(); $table->timestamp('expired_at')->nullable(); - $table->foreignIdFor(\LucasDotVin\Soulbscription\Models\Feature::class)->constrained()->cascadeOnDelete(); + $table->foreignIdFor(config('soulbscription.models.feature')::class)->constrained()->cascadeOnDelete(); $table->timestamps(); if (config('soulbscription.models.subscriber.uses_uuid')) { diff --git a/src/Events/FeatureConsumed.php b/src/Events/FeatureConsumed.php index def4b24..374f2e8 100644 --- a/src/Events/FeatureConsumed.php +++ b/src/Events/FeatureConsumed.php @@ -2,23 +2,39 @@ namespace LucasDotVin\Soulbscription\Events; -use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Foundation\Events\Dispatchable; +use InvalidArgumentException; use Illuminate\Queue\SerializesModels; -use LucasDotVin\Soulbscription\Models\Feature; -use LucasDotVin\Soulbscription\Models\FeatureConsumption; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Broadcasting\InteractsWithSockets; class FeatureConsumed { use Dispatchable; - use InteractsWithSockets; use SerializesModels; + use InteractsWithSockets; + + public mixed $feature; + public mixed $subscriber; + public mixed $featureConsumption; public function __construct( - public $subscriber, - public Feature $feature, - public FeatureConsumption $featureConsumption, + $subscriber, + mixed $feature, + mixed $featureConsumption ) { - // + $featureClass = config('soulbscription.models.feature'); + $featureConsumptionClass = config('soulbscription.models.feature_consumption'); + + throw_if(!($feature instanceof $featureClass), new InvalidArgumentException( + "Feature must be an instance of $featureClass." + )); + + throw_if(!($featureConsumption instanceof $featureConsumptionClass), new InvalidArgumentException( + "FeatureConsumption must be an instance of $featureConsumptionClass." + )); + + $this->feature = $feature; + $this->subscriber = $subscriber; + $this->featureConsumption = $featureConsumption; } } diff --git a/src/Events/FeatureTicketCreated.php b/src/Events/FeatureTicketCreated.php index 61fdb61..5124152 100644 --- a/src/Events/FeatureTicketCreated.php +++ b/src/Events/FeatureTicketCreated.php @@ -2,23 +2,39 @@ namespace LucasDotVin\Soulbscription\Events; -use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Foundation\Events\Dispatchable; +use InvalidArgumentException; use Illuminate\Queue\SerializesModels; -use LucasDotVin\Soulbscription\Models\Feature; -use LucasDotVin\Soulbscription\Models\FeatureTicket; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Broadcasting\InteractsWithSockets; class FeatureTicketCreated { use Dispatchable; - use InteractsWithSockets; use SerializesModels; + use InteractsWithSockets; + + public mixed $feature; + public mixed $subscriber; + public mixed $featureTicket; public function __construct( - public $subscriber, - public Feature $feature, - public FeatureTicket $featureTicket, + $subscriber, + mixed $feature, + mixed $featureTicket ) { - // + $featureClass = config('soulbscription.models.feature'); + $featureTicketClass = config('soulbscription.models.feature_ticket'); + + throw_if(!($feature instanceof $featureClass), new InvalidArgumentException( + "Feature must be an instance of $featureClass." + )); + + throw_if(!($featureTicket instanceof $featureTicketClass), new InvalidArgumentException( + "FeatureTicket must be an instance of $featureTicketClass." + )); + + $this->feature = $feature; + $this->subscriber = $subscriber; + $this->featureTicket = $featureTicket; } } diff --git a/src/Events/SubscriptionCanceled.php b/src/Events/SubscriptionCanceled.php index 7ac3348..f1c29a4 100644 --- a/src/Events/SubscriptionCanceled.php +++ b/src/Events/SubscriptionCanceled.php @@ -2,20 +2,27 @@ namespace LucasDotVin\Soulbscription\Events; -use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Foundation\Events\Dispatchable; +use InvalidArgumentException; use Illuminate\Queue\SerializesModels; -use LucasDotVin\Soulbscription\Models\Subscription; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Broadcasting\InteractsWithSockets; class SubscriptionCanceled { use Dispatchable; - use InteractsWithSockets; use SerializesModels; + use InteractsWithSockets; + + public mixed $subscription; + + public function __construct(mixed $subscription) + { + $subscriptionClass = config('soulbscription.models.subscription'); + + throw_if(!($subscription instanceof $subscriptionClass), new InvalidArgumentException( + "Subscription must be an instance of $subscriptionClass." + )); - public function __construct( - public Subscription $subscription, - ) { - // + $this->subscription = $subscription; } } diff --git a/src/Events/SubscriptionRenewed.php b/src/Events/SubscriptionRenewed.php index d0dcd89..5ab9da7 100644 --- a/src/Events/SubscriptionRenewed.php +++ b/src/Events/SubscriptionRenewed.php @@ -2,20 +2,27 @@ namespace LucasDotVin\Soulbscription\Events; -use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Foundation\Events\Dispatchable; +use InvalidArgumentException; use Illuminate\Queue\SerializesModels; -use LucasDotVin\Soulbscription\Models\Subscription; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Broadcasting\InteractsWithSockets; class SubscriptionRenewed { use Dispatchable; - use InteractsWithSockets; use SerializesModels; + use InteractsWithSockets; + + public mixed $subscription; + + public function __construct(mixed $subscription) + { + $subscriptionClass = config('soulbscription.models.subscription'); + + throw_if(!($subscription instanceof $subscriptionClass), new InvalidArgumentException( + "Subscription must be an instance of $subscriptionClass." + )); - public function __construct( - public Subscription $subscription, - ) { - // + $this->subscription = $subscription; } } diff --git a/src/Events/SubscriptionScheduled.php b/src/Events/SubscriptionScheduled.php index 591f329..462231c 100644 --- a/src/Events/SubscriptionScheduled.php +++ b/src/Events/SubscriptionScheduled.php @@ -2,20 +2,27 @@ namespace LucasDotVin\Soulbscription\Events; -use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Foundation\Events\Dispatchable; +use InvalidArgumentException; use Illuminate\Queue\SerializesModels; -use LucasDotVin\Soulbscription\Models\Subscription; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Broadcasting\InteractsWithSockets; class SubscriptionScheduled { use Dispatchable; - use InteractsWithSockets; use SerializesModels; + use InteractsWithSockets; + + public mixed $subscription; + + public function __construct(mixed $subscription) + { + $subscriptionClass = config('soulbscription.models.subscription'); + + throw_if(!($subscription instanceof $subscriptionClass), new InvalidArgumentException( + "Subscription must be an instance of $subscriptionClass." + )); - public function __construct( - public Subscription $subscription, - ) { - // + $this->subscription = $subscription; } } diff --git a/src/Events/SubscriptionStarted.php b/src/Events/SubscriptionStarted.php index 4333315..0b6ae5c 100644 --- a/src/Events/SubscriptionStarted.php +++ b/src/Events/SubscriptionStarted.php @@ -2,20 +2,26 @@ namespace LucasDotVin\Soulbscription\Events; -use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; -use LucasDotVin\Soulbscription\Models\Subscription; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Broadcasting\InteractsWithSockets; class SubscriptionStarted { use Dispatchable; - use InteractsWithSockets; use SerializesModels; + use InteractsWithSockets; + + public mixed $subscription; + + public function __construct(mixed $subscription) + { + $subscriptionClass = config('soulbscription.models.subscription'); + + throw_if(!($subscription instanceof $subscriptionClass), new InvalidArgumentException( + "Subscription must be an instance of $subscriptionClass." + )); - public function __construct( - public Subscription $subscription, - ) { - // + $this->subscription = $subscription; } } diff --git a/src/Events/SubscriptionSuppressed.php b/src/Events/SubscriptionSuppressed.php index bfb93bc..63ed47a 100644 --- a/src/Events/SubscriptionSuppressed.php +++ b/src/Events/SubscriptionSuppressed.php @@ -2,10 +2,10 @@ namespace LucasDotVin\Soulbscription\Events; -use Illuminate\Broadcasting\InteractsWithSockets; -use Illuminate\Foundation\Events\Dispatchable; +use InvalidArgumentException; use Illuminate\Queue\SerializesModels; -use LucasDotVin\Soulbscription\Models\Subscription; +use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Broadcasting\InteractsWithSockets; class SubscriptionSuppressed { @@ -13,9 +13,16 @@ class SubscriptionSuppressed use InteractsWithSockets; use SerializesModels; - public function __construct( - public Subscription $subscription, - ) { - // + public mixed $subscription; + + public function __construct(mixed $subscription) + { + $subscriptionClass = config('soulbscription.models.subscription'); + + throw_if(!($subscription instanceof $subscriptionClass), new InvalidArgumentException( + "Subscription must be an instance of $subscriptionClass." + )); + + $this->subscription = $subscription; } } diff --git a/src/Models/Concerns/HasSubscriptions.php b/src/Models/Concerns/HasSubscriptions.php index 14b3fe1..fe52bf1 100644 --- a/src/Models/Concerns/HasSubscriptions.php +++ b/src/Models/Concerns/HasSubscriptions.php @@ -2,21 +2,17 @@ namespace LucasDotVin\Soulbscription\Models\Concerns; +use LogicException; +use OverflowException; +use OutOfBoundsException; +use InvalidArgumentException; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\Relations\HasMany; -use InvalidArgumentException; -use LogicException; use LucasDotVin\Soulbscription\Events\FeatureConsumed; +use Illuminate\Database\Eloquent\ModelNotFoundException; use LucasDotVin\Soulbscription\Events\FeatureTicketCreated; -use LucasDotVin\Soulbscription\Models\Feature; -use LucasDotVin\Soulbscription\Models\FeatureTicket; -use LucasDotVin\Soulbscription\Models\Plan; -use LucasDotVin\Soulbscription\Models\Subscription; -use OutOfBoundsException; -use OverflowException; trait HasSubscriptions { @@ -117,8 +113,14 @@ public function setConsumedQuota($featureName, float $consumption) event(new FeatureConsumed($this, $feature, $featureConsumption)); } - public function subscribeTo(Plan $plan, $expiration = null, $startDate = null): Subscription + public function subscribeTo(mixed $plan, $expiration = null, $startDate = null): mixed { + $planClass = config('soulbscription.models.plan'); + + throw_if(!($plan instanceof $planClass), new InvalidArgumentException( + "Plan must be an instance of $planClass." + )); + if ($plan->periodicity) { $expiration = $expiration ?? $plan->calculateNextRecurrenceEnd($startDate); @@ -140,30 +142,42 @@ public function subscribeTo(Plan $plan, $expiration = null, $startDate = null): ->start($startDate); } - public function hasSubscriptionTo(Plan $plan): bool + public function hasSubscriptionTo(mixed $plan): bool { + $planClass = config('soulbscription.models.plan'); + + throw_if(!($plan instanceof $planClass), new InvalidArgumentException( + "Plan must be an instance of $planClass." + )); + return $this->subscription() ->where('plan_id', $plan->id) ->exists(); } - public function isSubscribedTo(Plan $plan): bool + public function isSubscribedTo(mixed $plan): bool { return $this->hasSubscriptionTo($plan); } - public function missingSubscriptionTo(Plan $plan): bool + public function missingSubscriptionTo(mixed $plan): bool { return ! $this->hasSubscriptionTo($plan); } - public function isNotSubscribedTo(Plan $plan): bool + public function isNotSubscribedTo(mixed $plan): bool { return ! $this->isSubscribedTo($plan); } - public function switchTo(Plan $plan, $expiration = null, $immediately = true): Subscription + public function switchTo(mixed $plan, $expiration = null, $immediately = true): mixed { + $planClass = config('soulbscription.models.plan'); + + throw_if(!($plan instanceof $planClass), new InvalidArgumentException( + "Plan must be an instance of $planClass." + )); + if ($immediately) { $this->subscription ->markAsSwitched() @@ -178,23 +192,22 @@ public function switchTo(Plan $plan, $expiration = null, $immediately = true): S ->save(); $startDate = $this->subscription->expired_at; - $newSubscription = $this->subscribeTo($plan, startDate: $startDate); - - return $newSubscription; + return $this->subscribeTo($plan, startDate: $startDate); } + /** * @throws LogicException * @throws ModelNotFoundException */ - public function giveTicketFor($featureName, $expiration = null, ?float $charges = null): FeatureTicket + public function giveTicketFor($featureName, $expiration = null, ?float $charges = null): mixed { throw_unless( config('soulbscription.feature_tickets'), new LogicException('The tickets are not enabled in the configs.'), ); - $feature = Feature::whereName($featureName)->firstOrFail(); + $feature = config('soulbscription.models.feature')::whereName($featureName)->firstOrFail(); $featureTicket = $this->featureTickets() ->make([ @@ -286,8 +299,14 @@ public function getTotalCharges($featureName): float return $subscriptionCharges + $ticketCharges; } - protected function consumeNotQuotaFeature(Feature $feature, ?float $consumption = null) + protected function consumeNotQuotaFeature(mixed $feature, ?float $consumption = null) { + $featureClass = config('soulbscription.models.feature'); + + throw_if(!($feature instanceof $featureClass), new InvalidArgumentException( + "Feature must be an instance of $featureClass." + )); + $consumptionExpiration = $feature->consumable ? $feature->calculateNextRecurrenceEnd($this->subscription->started_at) : null; @@ -305,8 +324,15 @@ protected function consumeNotQuotaFeature(Feature $feature, ?float $consumption return $featureConsumption; } - protected function consumeQuotaFeature(Feature $feature, float $consumption) + + protected function consumeQuotaFeature(mixed $feature, float $consumption) { + $featureClass = config('soulbscription.models.feature'); + + throw_if(!($feature instanceof $featureClass), new InvalidArgumentException( + "Feature must be an instance of $featureClass." + )); + $featureConsumption = $this->featureConsumptions() ->whereFeatureId($feature->id) ->firstOrNew(); @@ -346,13 +372,16 @@ protected function getTicketChargesForAFeature(Model $feature): float ->sum('charges'); } - public function getFeature(string $featureName): ?Feature + public function getFeature(string $featureName): mixed { + $featureClass = config('soulbscription.models.feature'); + $feature = $this->features->firstWhere('name', $featureName); - return $feature; + return $feature instanceof $featureClass ? $feature : null; } + public function getFeaturesAttribute(): Collection { if (! is_null($this->loadedFeatures)) { @@ -386,12 +415,12 @@ protected function loadTicketFeatures(): Collection return $this->loadedTicketFeatures; } - return $this->loadedTicketFeatures = Feature::with([ - 'tickets' => fn (HasMany $query) => $query->withoutExpired()->whereMorphedTo('subscriber', $this), - ]) + return $this->loadedTicketFeatures = config('soulbscription.models.feature')::with([ + 'tickets' => fn(HasMany $query) => $query->withoutExpired()->whereMorphedTo('subscriber', $this), + ]) ->whereHas( 'tickets', - fn (Builder $query) => $query->withoutExpired()->whereMorphedTo('subscriber', $this), + fn(Builder $query) => $query->withoutExpired()->whereMorphedTo('subscriber', $this), ) ->get(); } diff --git a/tests/Models/Concerns/ExpiresAndHasGraceDaysTest.php b/tests/Models/Concerns/ExpiresAndHasGraceDaysTest.php index 4e6d17b..1596638 100644 --- a/tests/Models/Concerns/ExpiresAndHasGraceDaysTest.php +++ b/tests/Models/Concerns/ExpiresAndHasGraceDaysTest.php @@ -2,23 +2,36 @@ namespace Tests\Feature\Models\Concerns; -use Illuminate\Foundation\Testing\RefreshDatabase; +use Tests\TestCase; +use InvalidArgumentException; +use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; use LucasDotVin\Soulbscription\Models\Concerns\ExpiresAndHasGraceDays; use LucasDotVin\Soulbscription\Models\Scopes\ExpiringWithGraceDaysScope; -use LucasDotVin\Soulbscription\Models\Subscription; -use Tests\TestCase; class ExpiresAndHasGraceDaysTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; - public const MODEL = Subscription::class; + public const MODEL = 'soulbscription.models.subscription'; + + protected function getModelClass() + { + $modelClass = config(self::MODEL); + + throw_if(!is_a($modelClass, Model::class, true), new InvalidArgumentException( + "Configured subscription model must be a subclass of " . Model::class + )); + + return $modelClass; + } public function testTraitAppliesScope() { - $model = self::MODEL::factory()->create(); + $modelClass = $this->getModelClass(); + $model = $modelClass::factory()->create(); $this->assertArrayHasKey(ExpiresAndHasGraceDays::class, class_uses_recursive($model)); $this->assertArrayHasKey(ExpiringWithGraceDaysScope::class, $model->getGlobalScopes()); @@ -26,25 +39,19 @@ public function testTraitAppliesScope() public function testModelReturnsExpiredStatus() { - $expiredModel = self::MODEL::factory() - ->expired() - ->create(); - - $expiredModelWithFutureGraceDays = self::MODEL::factory() - ->expired() - ->create([ - 'grace_days_ended_at' => now()->addDay(), - ]); - - $expiredModelWithPastGraceDays = self::MODEL::factory() - ->expired() - ->create([ - 'grace_days_ended_at' => now()->subDay(), - ]); - - $notExpiredModel = self::MODEL::factory() - ->notExpired() - ->create(); + $modelClass = $this->getModelClass(); + + $expiredModel = $modelClass::factory()->expired()->create(); + + $expiredModelWithFutureGraceDays = $modelClass::factory()->expired()->create([ + 'grace_days_ended_at' => now()->addDay(), + ]); + + $expiredModelWithPastGraceDays = $modelClass::factory()->expired()->create([ + 'grace_days_ended_at' => now()->subDay(), + ]); + + $notExpiredModel = $modelClass::factory()->notExpired()->create(); $this->assertTrue($expiredModel->expired()); $this->assertFalse($expiredModelWithFutureGraceDays->expired()); @@ -54,31 +61,23 @@ public function testModelReturnsExpiredStatus() public function testModelReturnsNotExpiredStatus() { - $expiredModel = self::MODEL::factory() - ->expired() - ->create(); - - $modelWithNullExpiredAt = self::MODEL::factory() - ->expired() - ->create([ - 'expired_at' => null, - ]); - - $expiredModelWithFutureGraceDays = self::MODEL::factory() - ->expired() - ->create([ - 'grace_days_ended_at' => now()->addDay(), - ]); - - $expiredModelWithPastGraceDays = self::MODEL::factory() - ->expired() - ->create([ - 'grace_days_ended_at' => now()->subDay(), - ]); - - $notExpiredModel = self::MODEL::factory() - ->notExpired() - ->create(); + $modelClass = $this->getModelClass(); + + $expiredModel = $modelClass::factory()->expired()->create(); + + $modelWithNullExpiredAt = $modelClass::factory()->expired()->create([ + 'expired_at' => null, + ]); + + $expiredModelWithFutureGraceDays = $modelClass::factory()->expired()->create([ + 'grace_days_ended_at' => now()->addDay(), + ]); + + $expiredModelWithPastGraceDays = $modelClass::factory()->expired()->create([ + 'grace_days_ended_at' => now()->subDay(), + ]); + + $notExpiredModel = $modelClass::factory()->notExpired()->create(); $this->assertFalse($expiredModel->notExpired()); $this->assertTrue($expiredModelWithFutureGraceDays->notExpired()); @@ -89,31 +88,23 @@ public function testModelReturnsNotExpiredStatus() public function testModelReturnsIfItHasExpired() { - $expiredModel = self::MODEL::factory() - ->expired() - ->create(); - - $modelWithNullExpiredAt = self::MODEL::factory() - ->expired() - ->create([ - 'expired_at' => null, - ]); - - $expiredModelWithFutureGraceDays = self::MODEL::factory() - ->expired() - ->create([ - 'grace_days_ended_at' => now()->addDay(), - ]); - - $expiredModelWithPastGraceDays = self::MODEL::factory() - ->expired() - ->create([ - 'grace_days_ended_at' => now()->subDay(), - ]); - - $notExpiredModel = self::MODEL::factory() - ->notExpired() - ->create(); + $modelClass = $this->getModelClass(); + + $expiredModel = $modelClass::factory()->expired()->create(); + + $modelWithNullExpiredAt = $modelClass::factory()->expired()->create([ + 'expired_at' => null, + ]); + + $expiredModelWithFutureGraceDays = $modelClass::factory()->expired()->create([ + 'grace_days_ended_at' => now()->addDay(), + ]); + + $expiredModelWithPastGraceDays = $modelClass::factory()->expired()->create([ + 'grace_days_ended_at' => now()->subDay(), + ]); + + $notExpiredModel = $modelClass::factory()->notExpired()->create(); $this->assertTrue($expiredModel->hasExpired()); $this->assertFalse($expiredModelWithFutureGraceDays->hasExpired()); @@ -124,31 +115,23 @@ public function testModelReturnsIfItHasExpired() public function testModelReturnsIfItHasNotExpired() { - $expiredModel = self::MODEL::factory() - ->expired() - ->create(); - - $modelWithNullExpiredAt = self::MODEL::factory() - ->expired() - ->create([ - 'expired_at' => null, - ]); - - $expiredModelWithFutureGraceDays = self::MODEL::factory() - ->expired() - ->create([ - 'grace_days_ended_at' => now()->addDay(), - ]); - - $expiredModelWithPastGraceDays = self::MODEL::factory() - ->expired() - ->create([ - 'grace_days_ended_at' => now()->subDay(), - ]); - - $notExpiredModel = self::MODEL::factory() - ->notExpired() - ->create(); + $modelClass = $this->getModelClass(); + + $expiredModel = $modelClass::factory()->expired()->create(); + + $modelWithNullExpiredAt = $modelClass::factory()->expired()->create([ + 'expired_at' => null, + ]); + + $expiredModelWithFutureGraceDays = $modelClass::factory()->expired()->create([ + 'grace_days_ended_at' => now()->addDay(), + ]); + + $expiredModelWithPastGraceDays = $modelClass::factory()->expired()->create([ + 'grace_days_ended_at' => now()->subDay(), + ]); + + $notExpiredModel = $modelClass::factory()->notExpired()->create(); $this->assertFalse($expiredModel->hasNotExpired()); $this->assertTrue($expiredModelWithFutureGraceDays->hasNotExpired()); diff --git a/tests/Models/Concerns/ExpiresTest.php b/tests/Models/Concerns/ExpiresTest.php index 16a6837..29aee5f 100644 --- a/tests/Models/Concerns/ExpiresTest.php +++ b/tests/Models/Concerns/ExpiresTest.php @@ -2,125 +2,120 @@ namespace Tests\Feature\Models\Concerns; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; -use LucasDotVin\Soulbscription\Models\FeatureConsumption; use Tests\TestCase; +use InvalidArgumentException; +use Illuminate\Support\Carbon; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; +use LucasDotVin\Soulbscription\Enums\PeriodicityType; -class ExpiresTest extends TestCase +class HandlesRecurrenceTest extends TestCase { use RefreshDatabase; use WithFaker; - public const MODEL = FeatureConsumption::class; + public const MODEL = 'soulbscription.models.plan'; - public function testExpiredModelsAreNotReturnedByDefault() + protected function getModelClass() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($expiredModelsCount)->create([ - 'expired_at' => now()->subDay(), - ]); + $modelClass = config(self::MODEL); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - $unexpiredModels = self::MODEL::factory()->count($unexpiredModelsCount)->create([ - 'expired_at' => now()->addDay(), - ]); + throw_if(!is_a($modelClass, Model::class, true), new InvalidArgumentException( + "Configured plan model must be a subclass of " . Model::class + )); - $returnedSubscriptions = self::MODEL::all(); - - $this->assertEqualsCanonicalizing( - $unexpiredModels->pluck('id')->toArray(), - $returnedSubscriptions->pluck('id')->toArray(), - ); + return $modelClass; } - public function testExpiredModelsAreReturnedWhenCallingMethodWithExpired() + public function testModelCalculateYearlyExpiration() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - $expiredModels = self::MODEL::factory()->count($expiredModelsCount)->create([ - 'expired_at' => now()->subDay(), - ]); + Carbon::setTestNow(now()); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - $unexpiredModels = self::MODEL::factory()->count($unexpiredModelsCount)->create([ - 'expired_at' => now()->addDay(), + $years = $this->faker->randomDigitNotNull(); + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ + 'periodicity_type' => PeriodicityType::Year, + 'periodicity' => $years, ]); - $expectedSubscriptions = $expiredModels->concat($unexpiredModels); + $this->assertEquals(now()->addYears($years), $plan->calculateNextRecurrenceEnd()); + } - $returnedSubscriptions = self::MODEL::withExpired()->get(); + public function testModelCalculateMonthlyExpiration() + { + Carbon::setTestNow(now()); - $this->assertEqualsCanonicalizing( - $expectedSubscriptions->pluck('id')->toArray(), - $returnedSubscriptions->pluck('id')->toArray(), - ); + $months = $this->faker->randomDigitNotNull(); + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ + 'periodicity_type' => PeriodicityType::Month, + 'periodicity' => $months, + ]); + + $this->assertEquals(now()->addMonths($months), $plan->calculateNextRecurrenceEnd()); } - public function testOnlyExpiredModelsAreReturnedWhenCallingMethodOnlyExpired() + public function testModelCalculateWeeklyExpiration() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - $expiredModels = self::MODEL::factory()->count($expiredModelsCount)->create([ - 'expired_at' => now()->subDay(), - ]); + Carbon::setTestNow(now()); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($unexpiredModelsCount)->create([ - 'expired_at' => now()->addDay(), + $weeks = $this->faker->randomDigitNotNull(); + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ + 'periodicity_type' => PeriodicityType::Week, + 'periodicity' => $weeks, ]); - $returnedSubscriptions = self::MODEL::onlyExpired()->get(); - - $this->assertEqualsCanonicalizing( - $expiredModels->pluck('id')->toArray(), - $returnedSubscriptions->pluck('id')->toArray(), - ); + $this->assertEquals(now()->addWeeks($weeks), $plan->calculateNextRecurrenceEnd()); } - public function testModelReturnsExpiredStatus() + public function testModelCalculateDailyExpiration() { - $expiredModel = self::MODEL::factory() - ->expired() - ->create(); + Carbon::setTestNow(now()); - $notExpiredModel = self::MODEL::factory() - ->notExpired() - ->create(); + $days = $this->faker->randomDigitNotNull(); + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ + 'periodicity_type' => PeriodicityType::Day, + 'periodicity' => $days, + ]); - $this->assertTrue($expiredModel->expired()); - $this->assertFalse($notExpiredModel->expired()); + $this->assertEquals(now()->addDays($days), $plan->calculateNextRecurrenceEnd()); } - public function testModelReturnsNotExpiredStatus() + public function testModelCalculateExpirationWithADifferentStart() { - $expiredModel = self::MODEL::factory() - ->expired() - ->create(); + Carbon::setTestNow(now()); - $notExpiredModel = self::MODEL::factory() - ->notExpired() - ->create(); + $weeks = $this->faker->randomDigitNotNull(); + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ + 'periodicity_type' => PeriodicityType::Week, + 'periodicity' => $weeks, + ]); - $this->assertFalse($expiredModel->notExpired()); - $this->assertTrue($notExpiredModel->notExpired()); + $start = now()->subDay(); + + $this->assertEquals($start->copy()->addWeeks($weeks), $plan->calculateNextRecurrenceEnd($start)); } - public function testModelsWithoutExpirationDateAreReturnedByDefault() + public function testModelCalculateExpirationWithADifferentStartAsString() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($expiredModelsCount)->create([ - 'expired_at' => now()->subDay(), - ]); + Carbon::setTestNow(today()); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - $unexpiredModels = self::MODEL::factory()->count($unexpiredModelsCount)->create([ - 'expired_at' => null, + $weeks = $this->faker->randomDigitNotNull(); + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ + 'periodicity_type' => PeriodicityType::Week, + 'periodicity' => $weeks, ]); - $returnedSubscriptions = self::MODEL::all(); + $start = today()->subDay(); - $this->assertEqualsCanonicalizing( - $unexpiredModels->pluck('id')->toArray(), - $returnedSubscriptions->pluck('id')->toArray(), + $this->assertEquals( + $start->copy()->addWeeks($weeks), + $plan->calculateNextRecurrenceEnd($start->toDateTimeString()), ); } } diff --git a/tests/Models/Concerns/HandlesRecurrenceTest.php b/tests/Models/Concerns/HandlesRecurrenceTest.php index 3c299b9..f3de51a 100644 --- a/tests/Models/Concerns/HandlesRecurrenceTest.php +++ b/tests/Models/Concerns/HandlesRecurrenceTest.php @@ -2,26 +2,39 @@ namespace Tests\Feature\Models\Concerns; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; +use Tests\TestCase; +use InvalidArgumentException; use Illuminate\Support\Carbon; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; use LucasDotVin\Soulbscription\Enums\PeriodicityType; -use LucasDotVin\Soulbscription\Models\Plan; -use Tests\TestCase; class HandlesRecurrenceTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; + + public const MODEL = 'soulbscription.models.plan'; + + protected function getModelClass() + { + $modelClass = config(self::MODEL); + + throw_if(!is_a($modelClass, Model::class, true), new InvalidArgumentException( + "Configured plan model must be a subclass of " . Model::class + )); - public const MODEL = Plan::class; + return $modelClass; + } public function testModelCalculateYearlyExpiration() { Carbon::setTestNow(now()); $years = $this->faker->randomDigitNotNull(); - $plan = self::MODEL::factory()->create([ + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ 'periodicity_type' => PeriodicityType::Year, 'periodicity' => $years, ]); @@ -34,7 +47,8 @@ public function testModelCalculateMonthlyExpiration() Carbon::setTestNow(now()); $months = $this->faker->randomDigitNotNull(); - $plan = self::MODEL::factory()->create([ + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ 'periodicity_type' => PeriodicityType::Month, 'periodicity' => $months, ]); @@ -47,7 +61,8 @@ public function testModelCalculateWeeklyExpiration() Carbon::setTestNow(now()); $weeks = $this->faker->randomDigitNotNull(); - $plan = self::MODEL::factory()->create([ + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ 'periodicity_type' => PeriodicityType::Week, 'periodicity' => $weeks, ]); @@ -60,7 +75,8 @@ public function testModelCalculateDailyExpiration() Carbon::setTestNow(now()); $days = $this->faker->randomDigitNotNull(); - $plan = self::MODEL::factory()->create([ + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ 'periodicity_type' => PeriodicityType::Day, 'periodicity' => $days, ]); @@ -73,7 +89,8 @@ public function testModelCalculateExpirationWithADifferentStart() Carbon::setTestNow(now()); $weeks = $this->faker->randomDigitNotNull(); - $plan = self::MODEL::factory()->create([ + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ 'periodicity_type' => PeriodicityType::Week, 'periodicity' => $weeks, ]); @@ -88,7 +105,8 @@ public function testModelCalculateExpirationWithADifferentStartAsString() Carbon::setTestNow(today()); $weeks = $this->faker->randomDigitNotNull(); - $plan = self::MODEL::factory()->create([ + $modelClass = $this->getModelClass(); + $plan = $modelClass::factory()->create([ 'periodicity_type' => PeriodicityType::Week, 'periodicity' => $weeks, ]); @@ -97,7 +115,7 @@ public function testModelCalculateExpirationWithADifferentStartAsString() $this->assertEquals( $start->copy()->addWeeks($weeks), - $plan->calculateNextRecurrenceEnd($start->toDateTimeString()), + $plan->calculateNextRecurrenceEnd($start->toDateTimeString()) ); } } diff --git a/tests/Models/Concerns/HasSubscriptionsTest.php b/tests/Models/Concerns/HasSubscriptionsTest.php index 29cc427..4b98d50 100644 --- a/tests/Models/Concerns/HasSubscriptionsTest.php +++ b/tests/Models/Concerns/HasSubscriptionsTest.php @@ -2,36 +2,34 @@ namespace Tests\Feature\Models\Concerns; -use Illuminate\Database\Eloquent\ModelNotFoundException; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; +use Tests\TestCase; +use Tests\Mocks\Models\User; + +use LogicException; +use OverflowException; +use OutOfBoundsException; +use InvalidArgumentException; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Event; -use InvalidArgumentException; -use LogicException; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; use LucasDotVin\Soulbscription\Events\FeatureConsumed; +use Illuminate\Database\Eloquent\ModelNotFoundException; +use LucasDotVin\Soulbscription\Events\SubscriptionStarted; use LucasDotVin\Soulbscription\Events\FeatureTicketCreated; use LucasDotVin\Soulbscription\Events\SubscriptionScheduled; -use LucasDotVin\Soulbscription\Events\SubscriptionStarted; use LucasDotVin\Soulbscription\Events\SubscriptionSuppressed; -use LucasDotVin\Soulbscription\Models\Feature; -use LucasDotVin\Soulbscription\Models\FeatureConsumption; -use LucasDotVin\Soulbscription\Models\Plan; -use LucasDotVin\Soulbscription\Models\Subscription; -use LucasDotVin\Soulbscription\Models\SubscriptionRenewal; -use OutOfBoundsException; -use OverflowException; -use Tests\Mocks\Models\User; -use Tests\TestCase; + + class HasSubscriptionsTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; public function testModelCanSubscribeToAPlan() { - $plan = Plan::factory()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); $subscriber = User::factory()->createOne(); Event::fake(); @@ -52,7 +50,7 @@ public function testModelCanSubscribeToAPlan() public function testModelDefinesGraceDaysEnd() { - $plan = Plan::factory() + $plan = config('soulbscription.models.plan')::factory() ->withGraceDays() ->createOne(); @@ -68,8 +66,8 @@ public function testModelCanSwitchToAPlan() { Carbon::setTestNow(now()); - $oldPlan = Plan::factory()->createOne(); - $newPlan = Plan::factory()->createOne(); + $oldPlan = config('soulbscription.models.plan')::factory()->createOne(); + $newPlan = config('soulbscription.models.plan')::factory()->createOne(); $subscriber = User::factory()->createOne(); $oldSubscription = $subscriber->subscribeTo($oldPlan); @@ -100,8 +98,8 @@ public function testModelCanScheduleSwitchToAPlan() { Carbon::setTestNow(now()); - $oldPlan = Plan::factory()->createOne(); - $newPlan = Plan::factory()->createOne(); + $oldPlan = config('soulbscription.models.plan')::factory()->createOne(); + $newPlan = config('soulbscription.models.plan')::factory()->createOne(); $subscriber = User::factory()->createOne(); $oldSubscription = $subscriber->subscribeTo($oldPlan); @@ -128,8 +126,8 @@ public function testModelCanScheduleSwitchToAPlan() public function testModelGetNewSubscriptionAfterSwitching() { - $oldPlan = Plan::factory()->createOne(); - $newPlan = Plan::factory()->createOne(); + $oldPlan = config('soulbscription.models.plan')::factory()->createOne(); + $newPlan = config('soulbscription.models.plan')::factory()->createOne(); $subscriber = User::factory()->createOne(); $subscriber->subscribeTo($oldPlan, startDate: now()->subDay()); @@ -143,8 +141,8 @@ public function testModelGetCurrentSubscriptionAfterScheduleASwitch() { Carbon::setTestNow(now()); - $oldPlan = Plan::factory()->createOne(); - $newPlan = Plan::factory()->createOne(); + $oldPlan = config('soulbscription.models.plan')::factory()->createOne(); + $newPlan = config('soulbscription.models.plan')::factory()->createOne(); $subscriber = User::factory()->createOne(); $oldSubscription = $subscriber->subscribeTo($oldPlan); @@ -159,8 +157,8 @@ public function testModelCanConsumeAFeature() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->consumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -184,8 +182,8 @@ public function testModelCanConsumeAFeature() public function testModelCanConsumeANotConsumableFeatureIfItIsAvailable() { - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->notConsumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->notConsumable()->createOne(); $feature->plans()->attach($plan); $subscriber = User::factory()->createOne(); @@ -205,8 +203,8 @@ public function testModelCantConsumeAnUnavailableFeature() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->consumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -231,8 +229,8 @@ public function testModelCantConsumeAFeatureBeyondItsCharges() $charges = $this->faker->numberBetween(5, 10); $consumption = $charges + 1; - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->consumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -257,8 +255,8 @@ public function testModelCanConsumeSomeAmountOfAConsumableFeature() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->consumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -276,8 +274,8 @@ public function testModelCantConsumeSomeAmountOfAConsumableFeatureFromAnExpiredS $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->consumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -295,8 +293,8 @@ public function testModelCantConsumeSomeAmountOfAConsumableFeature() $charges = $this->faker->numberBetween(5, 10); $consumption = $charges + 1; - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->consumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -314,8 +312,8 @@ public function testModelCanConsumeSomeAmountOfAConsumableFeatureIfItsConsumptio $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->consumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -323,7 +321,7 @@ public function testModelCanConsumeSomeAmountOfAConsumableFeatureIfItsConsumptio $subscriber = User::factory()->createOne(); $subscriber->subscribeTo($plan); - FeatureConsumption::factory() + config('soulbscription.models.feature_consumption')::factory() ->for($feature) ->for($subscriber, 'subscriber') ->createOne([ @@ -339,12 +337,12 @@ public function testModelCanConsumeSomeAmountOfAConsumableFeatureIfItsConsumptio public function testModelHasSubscriptionRenewals() { $subscriber = User::factory()->createOne(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($subscriber, 'subscriber') ->createOne(); $renewalsCount = $this->faker->randomDigitNotNull(); - $renewals = SubscriptionRenewal::factory() + $renewals = config('soulbscription.models.subscription_renewal')::factory() ->times($renewalsCount) ->for($subscription) ->createOne(); @@ -357,7 +355,7 @@ public function testModelHasSubscriptionRenewals() public function testModelHasFeatureTickets() { - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); @@ -375,7 +373,7 @@ public function testModelHasFeatureTickets() public function testModelFeatureTicketsGetsOnlyNotExpired() { - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); @@ -408,7 +406,7 @@ public function testModelFeatureTicketsGetsOnlyNotExpired() public function testModelGetFeaturesFromTickets() { - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); @@ -429,7 +427,7 @@ public function testModelGetFeaturesFromTickets() public function testModelGetFeaturesFromNonExpirableTickets() { - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); @@ -453,7 +451,7 @@ public function testModelCanConsumeSomeAmountOfAConsumableFeatureFromATicket() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges); - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); $ticket = $subscriber->featureTickets()->make([ @@ -476,9 +474,9 @@ public function testModelCanRetrieveTotalChargesForAFeatureConsideringTickets() $subscriptionFeatureCharges = $this->faker->numberBetween(5, 10); $ticketFeatureCharges = $this->faker->numberBetween(5, 10); - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); - $plan = Plan::factory()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $subscriptionFeatureCharges, ]); @@ -503,7 +501,7 @@ public function testModelCanRetrieveTotalChargesForAFeatureConsideringTickets() public function testModelCanConsumeANotConsumableFeatureFromATicket() { - $feature = Feature::factory()->notConsumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->notConsumable()->createOne(); $subscriber = User::factory()->createOne(); $ticket = $subscriber->featureTickets()->make([ @@ -524,8 +522,8 @@ public function testModelCanRetrieveTotalConsumptionsForAFeature() { $consumption = $this->faker->randomDigitNotNull(); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->consumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $feature->plans()->attach($plan); $subscriber = User::factory()->createOne(); @@ -551,8 +549,8 @@ public function testModelCanRetrieveRemainingChargesForAFeature() $charges = $this->faker->numberBetween(6, 10); $consumption = $this->faker->numberBetween(1, 5); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->consumable()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -577,10 +575,10 @@ public function testModelCanRetrieveRemainingChargesForAFeature() public function testModelCantUseChargesFromExpiredTickets() { - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); - $plan = Plan::factory()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); $subscriber->subscribeTo($plan); $subscriptionFeatureCharges = $this->faker->numberBetween(5, 10); @@ -615,10 +613,10 @@ public function testModelCantUseChargesFromExpiredTickets() public function testItIgnoresTicketsWhenItIsDisabled() { - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); - $plan = Plan::factory()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); $plan->features()->attach($feature); $subscriber->subscribeTo($plan); @@ -644,7 +642,7 @@ public function testItCanCreateATicket() $charges = $this->faker->randomDigitNotNull(); $expiration = $this->faker->dateTime(); - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); @@ -663,7 +661,7 @@ public function testItCanCreateANonExpirableTicket() { $charges = $this->faker->randomDigitNotNull(); - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); @@ -683,7 +681,7 @@ public function testItFiresEventWhenCreatingATicket() $charges = $this->faker->randomDigitNotNull(); $expiration = $this->faker->dateTime(); - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); @@ -717,7 +715,7 @@ public function testItRaisesAnExceptionWhenCreatingATicketDespiteItIsDisabled() $charges = $this->faker->randomDigitNotNull(); $expiration = $this->faker->dateTime(); - $feature = Feature::factory()->consumable()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->consumable()->createOne(); $subscriber = User::factory()->createOne(); @@ -734,8 +732,8 @@ public function testItCreateANotExpirableConsumptionForQuotaFeatures() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->quota()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->quota()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -758,8 +756,8 @@ public function testItDoesNotCreateNewConsumptionsForQuoeFeatures() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges / 2); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->quota()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->quota()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -784,8 +782,8 @@ public function testItCanSetQuotaFeatureConsumption() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges / 2); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->quota()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->quota()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -810,8 +808,8 @@ public function testItRaisesAnExceptionWhenSettingConsumedQuotaForANotQuotaFeatu $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges / 2); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->notQuota()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->notQuota()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -827,7 +825,7 @@ public function testItRaisesAnExceptionWhenSettingConsumedQuotaForANotQuotaFeatu public function testItChecksIfTheUserHasSubscriptionToAPlan() { - $plan = Plan::factory()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); $subscriber = User::factory()->createOne(); $subscriber->subscribeTo($plan); @@ -841,7 +839,7 @@ public function testItChecksIfTheUserHasSubscriptionToAPlan() public function testItChecksIfTheUserDoesNotHaveSubscriptionToAPlan() { - $plan = Plan::factory()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); $subscriber = User::factory()->createOne(); $subscriber->subscribeTo($plan); @@ -855,7 +853,7 @@ public function testItChecksIfTheUserDoesNotHaveSubscriptionToAPlan() public function testItReturnsTheLastSubscriptionWhenRetrievingExpired() { - $plan = Plan::factory()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); $subscriber = User::factory()->createOne(); $subscriber->subscribeTo($plan, now()->subDay(), now()->subDay()); @@ -871,8 +869,8 @@ public function testItCanConsumeAFeatureAfterItsChargesIfThisFeatureIsPostpaid() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween(1, $charges * 2); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->postpaid()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->postpaid()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -894,8 +892,8 @@ public function testItDoesNotReturnNegativeChargesForFeatures() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween($charges + 1, $charges * 2); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->postpaid()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->postpaid()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -913,8 +911,8 @@ public function testItReturnsNegativeBalanceForFeatures() $charges = $this->faker->numberBetween(5, 10); $consumption = $this->faker->numberBetween($charges + 1, $charges * 2); - $plan = Plan::factory()->createOne(); - $feature = Feature::factory()->postpaid()->createOne(); + $plan = config('soulbscription.models.plan')::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->postpaid()->createOne(); $feature->plans()->attach($plan, [ 'charges' => $charges, ]); @@ -933,7 +931,7 @@ public function testItReturnsRemainingChargesOnlyForTheGivenUser() $charges = $this->faker->numberBetween(5, 10); - $feature = Feature::factory()->createOne(); + $feature = config('soulbscription.models.feature')::factory()->createOne(); $subscriber = User::factory()->createOne(); $subscriber->giveTicketFor($feature->name, null, $charges); diff --git a/tests/Models/Concerns/StartsTest.php b/tests/Models/Concerns/StartsTest.php index 3f58623..2885dcf 100644 --- a/tests/Models/Concerns/StartsTest.php +++ b/tests/Models/Concerns/StartsTest.php @@ -2,21 +2,34 @@ namespace Tests\Feature\Models\Concerns; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; -use LucasDotVin\Soulbscription\Models\Subscription; use Tests\TestCase; +use InvalidArgumentException; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; class StartsTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; - public const MODEL = Subscription::class; + public const MODEL = 'soulbscription.models.subscription'; + + protected function getModelClass() + { + $modelClass = config(self::MODEL); + + throw_if(!is_a($modelClass, Model::class, true), new InvalidArgumentException( + "Configured subscription model must be a subclass of " . Model::class + )); + + return $modelClass; + } public function testModelReturnsStartedWhenStartedAtIsOnThePast() { - $model = self::MODEL::factory()->make([ + $modelClass = $this->getModelClass(); + $model = $modelClass::factory()->make([ 'started_at' => now()->subDay(), ]); @@ -26,7 +39,8 @@ public function testModelReturnsStartedWhenStartedAtIsOnThePast() public function testModelReturnsNotStartedWhenStartedAtIsOnTheFuture() { - $model = self::MODEL::factory()->make([ + $modelClass = $this->getModelClass(); + $model = $modelClass::factory()->make([ 'started_at' => now()->addDay(), ]); @@ -36,7 +50,8 @@ public function testModelReturnsNotStartedWhenStartedAtIsOnTheFuture() public function testModelReturnsNotStartedWhenStartedAtIsNull() { - $model = self::MODEL::factory()->make(); + $modelClass = $this->getModelClass(); + $model = $modelClass::factory()->make(); $model->started_at = null; $this->assertFalse($model->started()); diff --git a/tests/Models/Concerns/SuppressesTest.php b/tests/Models/Concerns/SuppressesTest.php index 3d19ee4..31a6f3d 100644 --- a/tests/Models/Concerns/SuppressesTest.php +++ b/tests/Models/Concerns/SuppressesTest.php @@ -2,21 +2,34 @@ namespace Tests\Feature\Models\Concerns; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; -use LucasDotVin\Soulbscription\Models\Subscription; use Tests\TestCase; +use InvalidArgumentException; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; class SuppressesTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; - public const MODEL = Subscription::class; + public const MODEL = 'soulbscription.models.subscription'; + + protected function getModelClass() + { + $modelClass = config(self::MODEL); + + throw_if(!is_a($modelClass, Model::class, true), new InvalidArgumentException( + "Configured subscription model must be a subclass of " . Model::class + )); + + return $modelClass; + } public function testModelReturnsSuppressedWhenSuppressedAtIsOnThePast() { - $model = self::MODEL::factory()->make([ + $modelClass = $this->getModelClass(); + $model = $modelClass::factory()->make([ 'suppressed_at' => now()->subDay(), ]); @@ -26,7 +39,8 @@ public function testModelReturnsSuppressedWhenSuppressedAtIsOnThePast() public function testModelReturnsNotSuppressedWhenSuppressedAtIsOnTheFuture() { - $model = self::MODEL::factory()->make([ + $modelClass = $this->getModelClass(); + $model = $modelClass::factory()->make([ 'suppressed_at' => now()->addDay(), ]); @@ -36,7 +50,8 @@ public function testModelReturnsNotSuppressedWhenSuppressedAtIsOnTheFuture() public function testModelReturnsNotSuppressedWhenSuppressedAtIsNull() { - $model = self::MODEL::factory()->make(); + $modelClass = $this->getModelClass(); + $model = $modelClass::factory()->make(); $model->suppressed_at = null; $this->assertFalse($model->suppressed()); diff --git a/tests/Models/FeaturePlanTest.php b/tests/Models/FeaturePlanTest.php index f2c4847..ae7bad8 100644 --- a/tests/Models/FeaturePlanTest.php +++ b/tests/Models/FeaturePlanTest.php @@ -2,40 +2,37 @@ namespace Tests\Feature\Models; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; -use LucasDotVin\Soulbscription\Models\Feature; -use LucasDotVin\Soulbscription\Models\FeaturePlan; -use LucasDotVin\Soulbscription\Models\Plan; use Tests\TestCase; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; class FeaturePlanTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; public function testModelCanRetrievePlan() { - $feature = Feature::factory() + $feature = config('soulbscription.models.feature')::factory() ->create(); - $plan = Plan::factory()->create(); + $plan = config('soulbscription.models.plan')::factory()->create(); $plan->features()->attach($feature); - $featurePlanPivot = FeaturePlan::first(); + $featurePlanPivot = config('soulbscription.models.feature_plan')::first(); $this->assertEquals($plan->id, $featurePlanPivot->plan->id); } public function testModelCanRetrieveFeature() { - $feature = Feature::factory() + $feature = config('soulbscription.models.feature')::factory() ->create(); - $plan = Plan::factory()->create(); + $plan = config('soulbscription.models.plan')::factory()->create(); $plan->features()->attach($feature); - $featurePlanPivot = FeaturePlan::first(); + $featurePlanPivot = config('soulbscription.models.feature_plan')::first(); $this->assertEquals($feature->id, $featurePlanPivot->feature->id); } diff --git a/tests/Models/FeatureTest.php b/tests/Models/FeatureTest.php index 680e1fc..11a30ae 100644 --- a/tests/Models/FeatureTest.php +++ b/tests/Models/FeatureTest.php @@ -2,12 +2,11 @@ namespace Tests\Feature\Models; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; +use Tests\TestCase; use Illuminate\Support\Carbon; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; use LucasDotVin\Soulbscription\Enums\PeriodicityType; -use LucasDotVin\Soulbscription\Models\Feature; -use Tests\TestCase; class FeatureTest extends TestCase { @@ -19,7 +18,7 @@ public function testModelCalculateYearlyExpiration() Carbon::setTestNow(now()); $years = $this->faker->randomDigitNotNull(); - $feature = Feature::factory()->create([ + $feature = config('soulbscription.models.feature')::factory()->create([ 'periodicity_type' => PeriodicityType::Year, 'periodicity' => $years, ]); @@ -32,7 +31,7 @@ public function testModelCalculateMonthlyExpiration() Carbon::setTestNow(now()); $months = $this->faker->randomDigitNotNull(); - $feature = Feature::factory()->create([ + $feature = config('soulbscription.models.feature')::factory()->create([ 'periodicity_type' => PeriodicityType::Month, 'periodicity' => $months, ]); @@ -45,7 +44,7 @@ public function testModelCalculateWeeklyExpiration() Carbon::setTestNow(now()); $weeks = $this->faker->randomDigitNotNull(); - $feature = Feature::factory()->create([ + $feature = config('soulbscription.models.feature')::factory()->create([ 'periodicity_type' => PeriodicityType::Week, 'periodicity' => $weeks, ]); @@ -58,7 +57,7 @@ public function testModelCalculateDailyExpiration() Carbon::setTestNow(now()); $days = $this->faker->randomDigitNotNull(); - $feature = Feature::factory()->create([ + $feature = config('soulbscription.models.feature')::factory()->create([ 'periodicity_type' => PeriodicityType::Day, 'periodicity' => $days, ]); @@ -70,7 +69,7 @@ public function testModelcalculateNextRecurrenceEndConsideringRecurrences() { Carbon::setTestNow(now()); - $feature = Feature::factory()->create([ + $feature = config('soulbscription.models.feature')::factory()->create([ 'periodicity_type' => PeriodicityType::Week, 'periodicity' => 1, ]); @@ -82,11 +81,11 @@ public function testModelcalculateNextRecurrenceEndConsideringRecurrences() public function testModelIsNotQuotaByDefault() { - $creationPayload = Feature::factory()->raw(); + $creationPayload = config('soulbscription.models.feature')::factory()->raw(); unset($creationPayload['quota']); - $feature = Feature::create($creationPayload); + $feature = config('soulbscription.models.feature')::create($creationPayload); $this->assertDatabaseHas('features', [ 'id' => $feature->id, diff --git a/tests/Models/PlanTest.php b/tests/Models/PlanTest.php index ea543f6..2a22743 100644 --- a/tests/Models/PlanTest.php +++ b/tests/Models/PlanTest.php @@ -2,13 +2,11 @@ namespace Tests\Feature\Models; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; +use Tests\TestCase; use Illuminate\Support\Carbon; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; use LucasDotVin\Soulbscription\Enums\PeriodicityType; -use LucasDotVin\Soulbscription\Models\Plan; -use LucasDotVin\Soulbscription\Models\Subscription; -use Tests\TestCase; class PlanTest extends TestCase { @@ -21,7 +19,7 @@ public function testModelCancalculateGraceDaysEnd() $days = $this->faker->randomDigitNotNull(); $graceDays = $this->faker->randomDigitNotNull(); - $plan = Plan::factory()->create([ + $plan = config('soulbscription.models.plan')::factory()->create([ 'grace_days' => $graceDays, 'periodicity_type' => PeriodicityType::Day, 'periodicity' => $days, @@ -35,10 +33,10 @@ public function testModelCancalculateGraceDaysEnd() public function testModelCanRetrieveSubscriptions() { - $plan = Plan::factory() + $plan = config('soulbscription.models.plan')::factory() ->create(); - $subscriptions = Subscription::factory() + $subscriptions = config('soulbscription.models.subscription')::factory() ->for($plan) ->count($subscriptionsCount = $this->faker->randomDigitNotNull()) ->started() @@ -54,7 +52,7 @@ public function testModelCanRetrieveSubscriptions() public function testPlanCanBeCreatedWithoutPeriodicity() { - $plan = Plan::factory() + $plan = config('soulbscription.models.plan')::factory() ->create([ 'periodicity' => null, 'periodicity_type' => null, diff --git a/tests/Models/SubscriptionTest.php b/tests/Models/SubscriptionTest.php index e2cc4bd..4d2b97f 100644 --- a/tests/Models/SubscriptionTest.php +++ b/tests/Models/SubscriptionTest.php @@ -2,31 +2,29 @@ namespace Tests\Feature\Models; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; +use Tests\TestCase; +use Tests\Mocks\Models\User; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Event; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; use LucasDotVin\Soulbscription\Events\SubscriptionCanceled; use LucasDotVin\Soulbscription\Events\SubscriptionRenewed; use LucasDotVin\Soulbscription\Events\SubscriptionStarted; use LucasDotVin\Soulbscription\Events\SubscriptionSuppressed; -use LucasDotVin\Soulbscription\Models\Plan; -use LucasDotVin\Soulbscription\Models\Subscription; -use Tests\Mocks\Models\User; -use Tests\TestCase; class SubscriptionTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; public function testModelRenews() { Carbon::setTestNow(now()); - $plan = Plan::factory()->create(); + $plan = config('soulbscription.models.plan')::factory()->create(); $subscriber = User::factory()->create(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($plan) ->for($subscriber, 'subscriber') ->create([ @@ -53,9 +51,9 @@ public function testModelRenewsBasedOnCurrentDateIfOverdue() { Carbon::setTestNow(now()); - $plan = Plan::factory()->create(); + $plan = config('soulbscription.models.plan')::factory()->create(); $subscriber = User::factory()->create(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($plan) ->for($subscriber, 'subscriber') ->create([ @@ -82,9 +80,9 @@ public function testModelCanCancel() { Carbon::setTestNow(now()); - $plan = Plan::factory()->create(); + $plan = config('soulbscription.models.plan')::factory()->create(); $subscriber = User::factory()->create(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($plan) ->for($subscriber, 'subscriber') ->notStarted() @@ -106,9 +104,9 @@ public function testModelCanStart() { Carbon::setTestNow(now()); - $plan = Plan::factory()->create(); + $plan = config('soulbscription.models.plan')::factory()->create(); $subscriber = User::factory()->create(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($plan) ->for($subscriber, 'subscriber') ->notStarted() @@ -130,9 +128,9 @@ public function testModelCanSuppress() { Carbon::setTestNow(now()); - $plan = Plan::factory()->create(); + $plan = config('soulbscription.models.plan')::factory()->create(); $subscriber = User::factory()->create(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($plan) ->for($subscriber, 'subscriber') ->create(); @@ -151,9 +149,9 @@ public function testModelCanSuppress() public function testModelCanMarkAsSwitched() { - $plan = Plan::factory()->create(); + $plan = config('soulbscription.models.plan')::factory()->create(); $subscriber = User::factory()->create(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($plan) ->for($subscriber, 'subscriber') ->create(); @@ -170,7 +168,7 @@ public function testModelCanMarkAsSwitched() public function testModelRegistersRenewal() { $subscriber = User::factory()->create(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($subscriber, 'subscriber') ->create(); @@ -186,7 +184,7 @@ public function testModelRegistersRenewal() public function testModelRegistersOverdue() { $subscriber = User::factory()->create(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($subscriber, 'subscriber') ->create([ 'expired_at' => now()->subDay(), @@ -204,7 +202,7 @@ public function testModelRegistersOverdue() public function testModelConsidersGraceDaysOnOverdue() { $subscriber = User::factory()->create(); - $subscription = Subscription::factory() + $subscription = config('soulbscription.models.subscription')::factory() ->for($subscriber, 'subscriber') ->create([ 'grace_days_ended_at' => now()->addDay(), @@ -222,21 +220,21 @@ public function testModelConsidersGraceDaysOnOverdue() public function testModelReturnsNotStartedSubscriptionsInNotActiveScope() { - Subscription::factory() + config('soulbscription.models.subscription')::factory() ->count($this->faker()->randomDigitNotNull()) ->started() ->notExpired() ->notSuppressed() ->create(); - $notStartedSubscription = Subscription::factory() + $notStartedSubscription = config('soulbscription.models.subscription')::factory() ->count($notStartedSubscriptionCount = $this->faker()->randomDigitNotNull()) ->notStarted() ->notExpired() ->notSuppressed() ->create(); - $returnedSubscriptions = Subscription::notActive()->get(); + $returnedSubscriptions = config('soulbscription.models.subscription')::notActive()->get(); $this->assertCount($notStartedSubscriptionCount, $returnedSubscriptions); $notStartedSubscription->each( @@ -246,21 +244,21 @@ public function testModelReturnsNotStartedSubscriptionsInNotActiveScope() public function testModelReturnsExpiredSubscriptionsInNotActiveScope() { - Subscription::factory() + config('soulbscription.models.subscription')::factory() ->count($this->faker()->randomDigitNotNull()) ->started() ->notExpired() ->notSuppressed() ->create(); - $expiredSubscription = Subscription::factory() + $expiredSubscription = config('soulbscription.models.subscription')::factory() ->count($expiredSubscriptionCount = $this->faker()->randomDigitNotNull()) ->started() ->expired() ->notSuppressed() ->create(); - $returnedSubscriptions = Subscription::notActive()->get(); + $returnedSubscriptions = config('soulbscription.models.subscription')::notActive()->get(); $this->assertCount($expiredSubscriptionCount, $returnedSubscriptions); $expiredSubscription->each( @@ -270,21 +268,21 @@ public function testModelReturnsExpiredSubscriptionsInNotActiveScope() public function testModelReturnsSuppressedSubscriptionsInNotActiveScope() { - Subscription::factory() + config('soulbscription.models.subscription')::factory() ->count($this->faker()->randomDigitNotNull()) ->started() ->notExpired() ->notSuppressed() ->create(); - $suppressedSubscription = Subscription::factory() + $suppressedSubscription = config('soulbscription.models.subscription')::factory() ->count($suppressedSubscriptionCount = $this->faker()->randomDigitNotNull()) ->started() ->notExpired() ->suppressed() ->create(); - $returnedSubscriptions = Subscription::notActive()->get(); + $returnedSubscriptions = config('soulbscription.models.subscription')::notActive()->get(); $this->assertCount($suppressedSubscriptionCount, $returnedSubscriptions); $suppressedSubscription->each( @@ -294,7 +292,7 @@ public function testModelReturnsSuppressedSubscriptionsInNotActiveScope() public function testModelReturnsOnlyCanceledSubscriptionsWithTheScope() { - Subscription::factory() + config('soulbscription.models.subscription')::factory() ->count($this->faker()->randomDigitNotNull()) ->started() ->notExpired() @@ -302,7 +300,7 @@ public function testModelReturnsOnlyCanceledSubscriptionsWithTheScope() ->notCanceled() ->create(); - $canceledSubscription = Subscription::factory() + $canceledSubscription = config('soulbscription.models.subscription')::factory() ->count($canceledSubscriptionCount = $this->faker()->randomDigitNotNull()) ->started() ->notExpired() @@ -310,7 +308,7 @@ public function testModelReturnsOnlyCanceledSubscriptionsWithTheScope() ->canceled() ->create(); - $returnedSubscriptions = Subscription::canceled()->get(); + $returnedSubscriptions = config('soulbscription.models.subscription')::canceled()->get(); $this->assertCount($canceledSubscriptionCount, $returnedSubscriptions); $canceledSubscription->each( @@ -320,7 +318,7 @@ public function testModelReturnsOnlyCanceledSubscriptionsWithTheScope() public function testModelReturnsOnlyNotCanceledSubscriptionsWithTheScope() { - Subscription::factory() + config('soulbscription.models.subscription')::factory() ->count($this->faker()->randomDigitNotNull()) ->started() ->notExpired() @@ -328,7 +326,7 @@ public function testModelReturnsOnlyNotCanceledSubscriptionsWithTheScope() ->canceled() ->create(); - $notCanceledSubscription = Subscription::factory() + $notCanceledSubscription = config('soulbscription.models.subscription')::factory() ->count($notCanceledSubscriptionCount = $this->faker()->randomDigitNotNull()) ->started() ->notExpired() @@ -336,7 +334,7 @@ public function testModelReturnsOnlyNotCanceledSubscriptionsWithTheScope() ->notCanceled() ->create(); - $returnedSubscriptions = Subscription::notCanceled()->get(); + $returnedSubscriptions = config('soulbscription.models.subscription')::notCanceled()->get(); $this->assertCount($notCanceledSubscriptionCount, $returnedSubscriptions); $notCanceledSubscription->each( diff --git a/tests/Scopes/ExpiringScopeTest.php b/tests/Scopes/ExpiringScopeTest.php index 2b38dc1..e065171 100644 --- a/tests/Scopes/ExpiringScopeTest.php +++ b/tests/Scopes/ExpiringScopeTest.php @@ -2,31 +2,45 @@ namespace Tests\Feature\Models; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; -use LucasDotVin\Soulbscription\Models\FeatureConsumption; use Tests\TestCase; +use InvalidArgumentException; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; class ExpiringScopeTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; + + public const MODEL = 'soulbscription.models.feature_consumption'; + + protected function getModelClass() + { + $modelClass = config(self::MODEL); + + throw_if(!is_a($modelClass, Model::class, true), new InvalidArgumentException( + "Configured feature consumption model must be a subclass of " . Model::class + )); - public const MODEL = FeatureConsumption::class; + return $modelClass; + } public function testExpiredModelsAreNotReturnedByDefault() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($expiredModelsCount)->create([ + $modelClass = $this->getModelClass(); + $expiredModelsCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory()->count($expiredModelsCount)->create([ 'expired_at' => now()->subDay(), ]); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - $unexpiredModels = self::MODEL::factory()->count($unexpiredModelsCount)->create([ + $unexpiredModelsCount = $this->faker->randomDigitNotNull(); + $unexpiredModels = $modelClass::factory()->count($unexpiredModelsCount)->create([ 'expired_at' => now()->addDay(), ]); - $returnedFeatureConsumptions = self::MODEL::all(); + $returnedFeatureConsumptions = $modelClass::all(); $this->assertEqualsCanonicalizing( $unexpiredModels->pluck('id')->toArray(), @@ -36,19 +50,20 @@ public function testExpiredModelsAreNotReturnedByDefault() public function testExpiredModelsAreReturnedWhenCallingMethodWithExpired() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - $expiredModels = self::MODEL::factory()->count($expiredModelsCount)->create([ + $modelClass = $this->getModelClass(); + $expiredModelsCount = $this->faker->randomDigitNotNull(); + + $expiredModels = $modelClass::factory()->count($expiredModelsCount)->create([ 'expired_at' => now()->subDay(), ]); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - $unexpiredModels = self::MODEL::factory()->count($unexpiredModelsCount)->create([ + $unexpiredModelsCount = $this->faker->randomDigitNotNull(); + $unexpiredModels = $modelClass::factory()->count($unexpiredModelsCount)->create([ 'expired_at' => now()->addDay(), ]); $expectedFeatureConsumptions = $expiredModels->concat($unexpiredModels); - - $returnedFeatureConsumptions = self::MODEL::withExpired()->get(); + $returnedFeatureConsumptions = $modelClass::withExpired()->get(); $this->assertEqualsCanonicalizing( $expectedFeatureConsumptions->pluck('id')->toArray(), @@ -58,17 +73,19 @@ public function testExpiredModelsAreReturnedWhenCallingMethodWithExpired() public function testExpiredModelsAreNotReturnedWhenCallingMethodWithExpiredAndPassingFalse() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($expiredModelsCount)->create([ + $modelClass = $this->getModelClass(); + $expiredModelsCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory()->count($expiredModelsCount)->create([ 'expired_at' => now()->subDay(), ]); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - $unexpiredModels = self::MODEL::factory()->count($unexpiredModelsCount)->create([ + $unexpiredModelsCount = $this->faker->randomDigitNotNull(); + $unexpiredModels = $modelClass::factory()->count($unexpiredModelsCount)->create([ 'expired_at' => now()->addDay(), ]); - $returnedFeatureConsumptions = self::MODEL::withExpired(false)->get(); + $returnedFeatureConsumptions = $modelClass::withExpired(false)->get(); $this->assertEqualsCanonicalizing( $unexpiredModels->pluck('id')->toArray(), @@ -78,17 +95,19 @@ public function testExpiredModelsAreNotReturnedWhenCallingMethodWithExpiredAndPa public function testOnlyExpiredModelsAreReturnedWhenCallingMethodOnlyExpired() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - $expiredModels = self::MODEL::factory()->count($expiredModelsCount)->create([ + $modelClass = $this->getModelClass(); + $expiredModelsCount = $this->faker->randomDigitNotNull(); + + $expiredModels = $modelClass::factory()->count($expiredModelsCount)->create([ 'expired_at' => now()->subDay(), ]); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($unexpiredModelsCount)->create([ + $unexpiredModelsCount = $this->faker->randomDigitNotNull(); + $modelClass::factory()->count($unexpiredModelsCount)->create([ 'expired_at' => now()->addDay(), ]); - $returnedFeatureConsumptions = self::MODEL::onlyExpired()->get(); + $returnedFeatureConsumptions = $modelClass::onlyExpired()->get(); $this->assertEqualsCanonicalizing( $expiredModels->pluck('id')->toArray(), diff --git a/tests/Scopes/ExpiringWithGraceDaysScopeTest.php b/tests/Scopes/ExpiringWithGraceDaysScopeTest.php index c49d2ec..bdace9c 100644 --- a/tests/Scopes/ExpiringWithGraceDaysScopeTest.php +++ b/tests/Scopes/ExpiringWithGraceDaysScopeTest.php @@ -2,38 +2,51 @@ namespace Tests\Feature\Models; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; -use LucasDotVin\Soulbscription\Models\Subscription; use Tests\TestCase; +use InvalidArgumentException; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; class ExpiringWithGraceDaysScopeTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; + + public const MODEL = 'soulbscription.models.subscription'; + + protected function getModelClass() + { + $modelClass = config(self::MODEL); - public const MODEL = Subscription::class; + throw_if(!is_a($modelClass, Model::class, true), new InvalidArgumentException( + "Configured subscription model must be a subclass of " . Model::class + )); + + return $modelClass; + } public function testExpiredModelsAreNotReturnedByDefault() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($expiredModelsCount)->create([ + $modelClass = $this->getModelClass(); + $expiredModelsCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory()->count($expiredModelsCount)->create([ 'expired_at' => now()->subDay(), ]); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - $unexpiredModels = self::MODEL::factory()->count($unexpiredModelsCount)->create([ + $unexpiredModelsCount = $this->faker->randomDigitNotNull(); + $unexpiredModels = $modelClass::factory()->count($unexpiredModelsCount)->create([ 'expired_at' => now()->addDay(), ]); - $modelsWithNullExpiredAtCount = $this->faker()->randomDigitNotNull(); - $modelsWithNullExpired = self::MODEL::factory()->count($modelsWithNullExpiredAtCount)->create([ + $modelsWithNullExpiredAtCount = $this->faker->randomDigitNotNull(); + $modelsWithNullExpired = $modelClass::factory()->count($modelsWithNullExpiredAtCount)->create([ 'expired_at' => null, ]); $expectedSubscriptions = $unexpiredModels->concat($modelsWithNullExpired); - - $returnedSubscriptions = self::MODEL::all(); + $returnedSubscriptions = $modelClass::all(); $this->assertEqualsCanonicalizing( $expectedSubscriptions->pluck('id')->toArray(), @@ -43,26 +56,28 @@ public function testExpiredModelsAreNotReturnedByDefault() public function testExpiredModelsWithGraceDaysAreReturnedByDefault() { - $expiredModelsWithoutGraceDaysCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($expiredModelsWithoutGraceDaysCount)->create([ + $modelClass = $this->getModelClass(); + $expiredModelsWithoutGraceDaysCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory()->count($expiredModelsWithoutGraceDaysCount)->create([ 'expired_at' => now()->subDay(), 'grace_days_ended_at' => null, ]); - $expiredModelsWithPastGraceDaysCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($expiredModelsWithPastGraceDaysCount)->create([ + $expiredModelsWithPastGraceDaysCount = $this->faker->randomDigitNotNull(); + $modelClass::factory()->count($expiredModelsWithPastGraceDaysCount)->create([ 'expired_at' => now()->subDay(), 'grace_days_ended_at' => now()->subDay(), ]); - $expiredModelsWithFutureGraceDaysCount = $this->faker()->randomDigitNotNull(); - $expiredModelsWithFutureGraceDays = self::MODEL::factory() + $expiredModelsWithFutureGraceDaysCount = $this->faker->randomDigitNotNull(); + $expiredModelsWithFutureGraceDays = $modelClass::factory() ->count($expiredModelsWithFutureGraceDaysCount)->create([ 'expired_at' => now()->subDay(), 'grace_days_ended_at' => now()->addDay(), ]); - $returnedSubscriptions = self::MODEL::all(); + $returnedSubscriptions = $modelClass::all(); $this->assertEqualsCanonicalizing( $expiredModelsWithFutureGraceDays->pluck('id'), @@ -72,25 +87,27 @@ public function testExpiredModelsWithGraceDaysAreReturnedByDefault() public function testExpiredModelsAreReturnedWhenCallingMethodWithExpired() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - $expiredModels = self::MODEL::factory()->count($expiredModelsCount)->create([ + $modelClass = $this->getModelClass(); + $expiredModelsCount = $this->faker->randomDigitNotNull(); + + $expiredModels = $modelClass::factory()->count($expiredModelsCount)->create([ 'expired_at' => now()->subDay(), ]); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - $unexpiredModels = self::MODEL::factory()->count($unexpiredModelsCount)->create([ + $unexpiredModelsCount = $this->faker->randomDigitNotNull(); + $unexpiredModels = $modelClass::factory()->count($unexpiredModelsCount)->create([ 'expired_at' => now()->addDay(), ]); - $expiredModelsWithFutureGraceDays = self::MODEL::factory() - ->count($this->faker()->randomDigitNotNull()) + $expiredModelsWithFutureGraceDays = $modelClass::factory() + ->count($this->faker->randomDigitNotNull()) ->create([ 'expired_at' => now()->subDay(), 'grace_days_ended_at' => now()->addDay(), ]); - $modelsWithNullExpiredAtCount = $this->faker()->randomDigitNotNull(); - $modelsWithNullExpired = self::MODEL::factory()->count($modelsWithNullExpiredAtCount)->create([ + $modelsWithNullExpiredAtCount = $this->faker->randomDigitNotNull(); + $modelsWithNullExpired = $modelClass::factory()->count($modelsWithNullExpiredAtCount)->create([ 'expired_at' => null, ]); @@ -98,7 +115,7 @@ public function testExpiredModelsAreReturnedWhenCallingMethodWithExpired() ->concat($expiredModelsWithFutureGraceDays) ->concat($modelsWithNullExpired); - $returnedSubscriptions = self::MODEL::withExpired()->get(); + $returnedSubscriptions = $modelClass::withExpired()->get(); $this->assertEqualsCanonicalizing( $expectedSubscriptions->pluck('id')->toArray(), @@ -108,32 +125,34 @@ public function testExpiredModelsAreReturnedWhenCallingMethodWithExpired() public function testExpiredModelsAreNotReturnedWhenCallingMethodWithExpiredAndPassingFalse() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($expiredModelsCount)->create([ + $modelClass = $this->getModelClass(); + $expiredModelsCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory()->count($expiredModelsCount)->create([ 'expired_at' => now()->subDay(), ]); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - $unexpiredModels = self::MODEL::factory()->count($unexpiredModelsCount)->create([ + $unexpiredModelsCount = $this->faker->randomDigitNotNull(); + $unexpiredModels = $modelClass::factory()->count($unexpiredModelsCount)->create([ 'expired_at' => now()->addDay(), ]); - $expiredModelsWithFutureGraceDays = self::MODEL::factory() - ->count($this->faker()->randomDigitNotNull()) + $expiredModelsWithFutureGraceDays = $modelClass::factory() + ->count($this->faker->randomDigitNotNull()) ->create([ 'expired_at' => now()->subDay(), 'grace_days_ended_at' => now()->addDay(), ]); - $modelsWithNullExpiredAtCount = $this->faker()->randomDigitNotNull(); - $modelsWithNullExpired = self::MODEL::factory()->count($modelsWithNullExpiredAtCount)->create([ + $modelsWithNullExpiredAtCount = $this->faker->randomDigitNotNull(); + $modelsWithNullExpired = $modelClass::factory()->count($modelsWithNullExpiredAtCount)->create([ 'expired_at' => null, ]); $expectedSubscriptions = $unexpiredModels->concat($expiredModelsWithFutureGraceDays) ->concat($modelsWithNullExpired); - $returnedSubscriptions = self::MODEL::withExpired(false)->get(); + $returnedSubscriptions = $modelClass::withExpired(false)->get(); $this->assertEqualsCanonicalizing( $expectedSubscriptions->pluck('id')->toArray(), @@ -143,30 +162,32 @@ public function testExpiredModelsAreNotReturnedWhenCallingMethodWithExpiredAndPa public function testOnlyExpiredModelsAreReturnedWhenCallingMethodOnlyExpired() { - $expiredModelsCount = $this->faker()->randomDigitNotNull(); - $expiredModels = self::MODEL::factory()->count($expiredModelsCount)->create([ + $modelClass = $this->getModelClass(); + $expiredModelsCount = $this->faker->randomDigitNotNull(); + + $expiredModels = $modelClass::factory()->count($expiredModelsCount)->create([ 'expired_at' => now()->subDay(), ]); - $unexpiredModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($unexpiredModelsCount)->create([ + $unexpiredModelsCount = $this->faker->randomDigitNotNull(); + $modelClass::factory()->count($unexpiredModelsCount)->create([ 'expired_at' => now()->addDay(), ]); - $modelsWithNullExpiredAtCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($modelsWithNullExpiredAtCount)->create([ + $modelsWithNullExpiredAtCount = $this->faker->randomDigitNotNull(); + $modelClass::factory()->count($modelsWithNullExpiredAtCount)->create([ 'expired_at' => null, ]); - $expiredModelsWithPastGraceDays = self::MODEL::factory() - ->count($this->faker()->randomDigitNotNull()) + $expiredModelsWithPastGraceDays = $modelClass::factory() + ->count($this->faker->randomDigitNotNull()) ->create([ 'expired_at' => now()->subDay(), 'grace_days_ended_at' => now()->subDay(), ]); - $expiredModelsWithNullGraceDays = self::MODEL::factory() - ->count($this->faker()->randomDigitNotNull()) + $expiredModelsWithNullGraceDays = $modelClass::factory() + ->count($this->faker->randomDigitNotNull()) ->create([ 'expired_at' => now()->subDay(), 'grace_days_ended_at' => null, @@ -175,7 +196,7 @@ public function testOnlyExpiredModelsAreReturnedWhenCallingMethodOnlyExpired() $expectedSubscriptions = $expiredModels->concat($expiredModelsWithNullGraceDays) ->concat($expiredModelsWithPastGraceDays); - $returnedSubscriptions = self::MODEL::onlyExpired()->get(); + $returnedSubscriptions = $modelClass::onlyExpired()->get(); $this->assertEqualsCanonicalizing( $expectedSubscriptions->pluck('id')->toArray(), diff --git a/tests/Scopes/StartingScopeTest.php b/tests/Scopes/StartingScopeTest.php index 4d7fe44..98f74d7 100644 --- a/tests/Scopes/StartingScopeTest.php +++ b/tests/Scopes/StartingScopeTest.php @@ -2,33 +2,47 @@ namespace Tests\Feature\Models; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; -use LucasDotVin\Soulbscription\Models\Subscription; use Tests\TestCase; +use InvalidArgumentException; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; class StartingScopeTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; + + public const MODEL = 'soulbscription.models.subscription'; + + protected function getModelClass() + { + $modelClass = config(self::MODEL); - public const MODEL = Subscription::class; + throw_if(!is_a($modelClass, Model::class, true), new InvalidArgumentException( + "Configured subscription model must be a subclass of " . Model::class + )); + + return $modelClass; + } public function testNotStartedModelsAreNotReturnedByDefault() { - $startedModelsCount = $this->faker()->randomDigitNotNull(); - $startedModels = self::MODEL::factory()->count($startedModelsCount)->create([ + $modelClass = $this->getModelClass(); + $startedModelsCount = $this->faker->randomDigitNotNull(); + + $startedModels = $modelClass::factory()->count($startedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->subDay(), ]); - $notStartedModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($notStartedModelsCount)->create([ + $notStartedModelsCount = $this->faker->randomDigitNotNull(); + $modelClass::factory()->count($notStartedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->addDay(), ]); - $returnedSubscriptions = self::MODEL::all(); + $returnedSubscriptions = $modelClass::all(); $this->assertEqualsCanonicalizing( $startedModels->pluck('id')->toArray(), @@ -38,19 +52,21 @@ public function testNotStartedModelsAreNotReturnedByDefault() public function testNotStartedModelsAreNotReturnedWhenCallingWithoutNotStarted() { - $startedModelsCount = $this->faker()->randomDigitNotNull(); - $startedModels = self::MODEL::factory()->count($startedModelsCount)->create([ + $modelClass = $this->getModelClass(); + $startedModelsCount = $this->faker->randomDigitNotNull(); + + $startedModels = $modelClass::factory()->count($startedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->subDay(), ]); - $notStartedModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($notStartedModelsCount)->create([ + $notStartedModelsCount = $this->faker->randomDigitNotNull(); + $modelClass::factory()->count($notStartedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->addDay(), ]); - $returnedSubscriptions = self::MODEL::withoutNotStarted()->get(); + $returnedSubscriptions = $modelClass::withoutNotStarted()->get(); $this->assertEqualsCanonicalizing( $startedModels->pluck('id')->toArray(), @@ -60,21 +76,22 @@ public function testNotStartedModelsAreNotReturnedWhenCallingWithoutNotStarted() public function testStartedModelsAreReturnedWhenCallingMethodWithNotStarted() { - $startedModelsCount = $this->faker()->randomDigitNotNull(); - $startedModels = self::MODEL::factory()->count($startedModelsCount)->create([ + $modelClass = $this->getModelClass(); + $startedModelsCount = $this->faker->randomDigitNotNull(); + + $startedModels = $modelClass::factory()->count($startedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->subDay(), ]); - $notStartedModelsCount = $this->faker()->randomDigitNotNull(); - $notStartedModels = self::MODEL::factory()->count($notStartedModelsCount)->create([ + $notStartedModelsCount = $this->faker->randomDigitNotNull(); + $notStartedModels = $modelClass::factory()->count($notStartedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->addDay(), ]); $expectedSubscriptions = $startedModels->concat($notStartedModels); - - $returnedSubscriptions = self::MODEL::withNotStarted()->get(); + $returnedSubscriptions = $modelClass::withNotStarted()->get(); $this->assertEqualsCanonicalizing( $expectedSubscriptions->pluck('id')->toArray(), @@ -84,19 +101,21 @@ public function testStartedModelsAreReturnedWhenCallingMethodWithNotStarted() public function testNotStartedModelsAreReturnedWhenCallingMethodWithNotStartedAndPassingAFalse() { - $startedModelsCount = $this->faker()->randomDigitNotNull(); - $startedModels = self::MODEL::factory()->count($startedModelsCount)->create([ + $modelClass = $this->getModelClass(); + $startedModelsCount = $this->faker->randomDigitNotNull(); + + $startedModels = $modelClass::factory()->count($startedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->subDay(), ]); - $notStartedModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($notStartedModelsCount)->create([ + $notStartedModelsCount = $this->faker->randomDigitNotNull(); + $modelClass::factory()->count($notStartedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->addDay(), ]); - $returnedSubscriptions = self::MODEL::withNotStarted(false)->get(); + $returnedSubscriptions = $modelClass::withNotStarted(false)->get(); $this->assertEqualsCanonicalizing( $startedModels->pluck('id')->toArray(), @@ -106,19 +125,21 @@ public function testNotStartedModelsAreReturnedWhenCallingMethodWithNotStartedAn public function testOnlyStartedModelsAreReturnedWhenCallingMethodOnlyNotStarted() { - $startedModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory()->count($startedModelsCount)->create([ + $modelClass = $this->getModelClass(); + $startedModelsCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory()->count($startedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->subDay(), ]); - $notStartedModelsCount = $this->faker()->randomDigitNotNull(); - $notStartedModels = self::MODEL::factory()->count($notStartedModelsCount)->create([ + $notStartedModelsCount = $this->faker->randomDigitNotNull(); + $notStartedModels = $modelClass::factory()->count($notStartedModelsCount)->create([ 'expired_at' => now()->addDay(), 'started_at' => now()->addDay(), ]); - $returnedSubscriptions = self::MODEL::onlyNotStarted()->get(); + $returnedSubscriptions = $modelClass::onlyNotStarted()->get(); $this->assertEqualsCanonicalizing( $notStartedModels->pluck('id')->toArray(), diff --git a/tests/Scopes/SuppressingScopeTest.php b/tests/Scopes/SuppressingScopeTest.php index 810c2e1..25c5977 100644 --- a/tests/Scopes/SuppressingScopeTest.php +++ b/tests/Scopes/SuppressingScopeTest.php @@ -2,37 +2,51 @@ namespace Tests\Feature\Models; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Foundation\Testing\WithFaker; -use LucasDotVin\Soulbscription\Models\Subscription; use Tests\TestCase; +use InvalidArgumentException; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Foundation\Testing\RefreshDatabase; class SuppressingScopeTest extends TestCase { - use RefreshDatabase; use WithFaker; + use RefreshDatabase; + + public const MODEL = 'soulbscription.models.subscription'; + + protected function getModelClass() + { + $modelClass = config(self::MODEL); - public const MODEL = Subscription::class; + throw_if(!is_a($modelClass, Model::class, true), new InvalidArgumentException( + "Configured subscription model must be a subclass of " . Model::class + )); + + return $modelClass; + } public function testSuppressedModelsAreNotReturnedByDefault() { - $suppressedModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory() + $modelClass = $this->getModelClass(); + $suppressedModelsCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory() ->count($suppressedModelsCount) ->suppressed() ->notExpired() ->started() ->create(); - $notSuppressedModelsCount = $this->faker()->randomDigitNotNull(); - $notSuppressedModels = self::MODEL::factory() + $notSuppressedModelsCount = $this->faker->randomDigitNotNull(); + $notSuppressedModels = $modelClass::factory() ->count($notSuppressedModelsCount) ->notSuppressed() ->notExpired() ->started() ->create(); - $returnedSubscriptions = self::MODEL::all(); + $returnedSubscriptions = $modelClass::all(); $this->assertEqualsCanonicalizing( $notSuppressedModels->pluck('id')->toArray(), @@ -42,23 +56,25 @@ public function testSuppressedModelsAreNotReturnedByDefault() public function testSuppressedModelsAreNotReturnedWhenCallingWithoutNotSuppressed() { - $suppressedModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory() + $modelClass = $this->getModelClass(); + $suppressedModelsCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory() ->count($suppressedModelsCount) ->suppressed() ->notExpired() ->started() ->create(); - $notSuppressedModelsCount = $this->faker()->randomDigitNotNull(); - $notSuppressedModels = self::MODEL::factory() + $notSuppressedModelsCount = $this->faker->randomDigitNotNull(); + $notSuppressedModels = $modelClass::factory() ->count($notSuppressedModelsCount) ->notSuppressed() ->notExpired() ->started() ->create(); - $returnedSubscriptions = self::MODEL::withoutSuppressed()->get(); + $returnedSubscriptions = $modelClass::withoutSuppressed()->get(); $this->assertEqualsCanonicalizing( $notSuppressedModels->pluck('id')->toArray(), @@ -68,16 +84,18 @@ public function testSuppressedModelsAreNotReturnedWhenCallingWithoutNotSuppresse public function testSuppressedModelsAreReturnedWhenCallingMethodWithNotSuppressed() { - $suppressedModelsCount = $this->faker()->randomDigitNotNull(); - $suppressedModels = self::MODEL::factory() + $modelClass = $this->getModelClass(); + $suppressedModelsCount = $this->faker->randomDigitNotNull(); + + $suppressedModels = $modelClass::factory() ->count($suppressedModelsCount) ->suppressed() ->notExpired() ->started() ->create(); - $notSuppressedModelsCount = $this->faker()->randomDigitNotNull(); - $notSuppressedModels = self::MODEL::factory() + $notSuppressedModelsCount = $this->faker->randomDigitNotNull(); + $notSuppressedModels = $modelClass::factory() ->count($notSuppressedModelsCount) ->notSuppressed() ->notExpired() @@ -85,8 +103,7 @@ public function testSuppressedModelsAreReturnedWhenCallingMethodWithNotSuppresse ->create(); $expectedSubscriptions = $suppressedModels->concat($notSuppressedModels); - - $returnedSubscriptions = self::MODEL::withSuppressed()->get(); + $returnedSubscriptions = $modelClass::withSuppressed()->get(); $this->assertEqualsCanonicalizing( $expectedSubscriptions->pluck('id')->toArray(), @@ -96,23 +113,25 @@ public function testSuppressedModelsAreReturnedWhenCallingMethodWithNotSuppresse public function testSuppressedModelsAreReturnedWhenCallingMethodWithNotSuppressedAndPassingAFalse() { - $suppressedModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory() + $modelClass = $this->getModelClass(); + $suppressedModelsCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory() ->count($suppressedModelsCount) ->suppressed() ->notExpired() ->started() ->create(); - $notSuppressedModelsCount = $this->faker()->randomDigitNotNull(); - $notSuppressedModels = self::MODEL::factory() + $notSuppressedModelsCount = $this->faker->randomDigitNotNull(); + $notSuppressedModels = $modelClass::factory() ->count($notSuppressedModelsCount) ->notSuppressed() ->notExpired() ->started() ->create(); - $returnedSubscriptions = self::MODEL::withSuppressed(false)->get(); + $returnedSubscriptions = $modelClass::withSuppressed(false)->get(); $this->assertEqualsCanonicalizing( $notSuppressedModels->pluck('id')->toArray(), @@ -122,23 +141,26 @@ public function testSuppressedModelsAreReturnedWhenCallingMethodWithNotSuppresse public function testOnlySuppressedModelsAreReturnedWhenCallingMethodOnlyNotSuppressed() { - $suppressedModelsCount = $this->faker()->randomDigitNotNull(); - $suppressedModels = self::MODEL::factory() + $modelClass = $this->getModelClass(); + $suppressedModelsCount = $this->faker->randomDigitNotNull(); + + $suppressedModels = $modelClass::factory() ->count($suppressedModelsCount) ->suppressed() ->notExpired() ->started() ->create(); - $notSuppressedModelsCount = $this->faker()->randomDigitNotNull(); - self::MODEL::factory() + $notSuppressedModelsCount = $this->faker->randomDigitNotNull(); + + $modelClass::factory() ->count($notSuppressedModelsCount) ->notSuppressed() ->notExpired() ->started() ->create(); - $returnedSubscriptions = self::MODEL::onlySuppressed()->get(); + $returnedSubscriptions = $modelClass::onlySuppressed()->get(); $this->assertEqualsCanonicalizing( $suppressedModels->pluck('id')->toArray(),