Three fixes from a fresh code review: 1. SyncUser identify used 'email' / 'name' instead of the PostHog special person properties '\$email' / '\$name'. The frontend already used the correct keys; the backend identify (sole source for users who sign up but never log in) would have populated only custom properties, leaving the built-in person profile email/name blank in the PostHog UI. 2. handleSubscriptionDeleted now short-circuits when plan_id is already null. Stripe re-delivers webhooks on transient failures, and the prior version would dispatch a duplicate 'subscription.cancelled' event and re-flush the (already empty) Pennant cache on each retry. 3. useTracking composable called posthog.capture directly, bypassing the new enabled gate. While posthog-js queues calls before init (so no events leaked over the network in self-hosted mode), the buffer grew unbounded and would fire all queued events in bulk if init was ever called. Replaced with a gated captureEvent helper exported from posthog.ts. Plus: drop the now-trivial 'updating non-plan fields does not flush the pennant cache' test (no observer to test against), refresh stale doc comments referencing the removed SyncUserToPostHog filename, and add a Bus::assertNotDispatched check to the deletion-idempotency test.
41 lines
1.6 KiB
PHP
41 lines
1.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Features\MemberLimit;
|
|
use App\Features\MonthlyCreditsLimit;
|
|
use App\Features\SocialAccountLimit;
|
|
use App\Features\WorkspaceLimit;
|
|
use App\Models\Account;
|
|
use App\Models\Plan;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Laravel\Pennant\Feature;
|
|
|
|
test('forgetPlanFeatureCache drops the cached plan-scoped features', function () {
|
|
$starter = Plan::where('slug', 'starter')->first();
|
|
$plus = Plan::where('slug', 'plus')->first();
|
|
|
|
$account = Account::factory()->create(['plan_id' => $starter->id]);
|
|
|
|
// Prime the Pennant cache against the starter plan.
|
|
Feature::for($account)->value(WorkspaceLimit::class);
|
|
Feature::for($account)->value(SocialAccountLimit::class);
|
|
Feature::for($account)->value(MemberLimit::class);
|
|
Feature::for($account)->value(MonthlyCreditsLimit::class);
|
|
|
|
expect(DB::table('features')->where('scope', 'account|'.$account->id)->count())
|
|
->toBe(4);
|
|
|
|
// Move the account to a plan with different limits and forget the cache.
|
|
$account->update(['plan_id' => $plus->id]);
|
|
$account->forgetPlanFeatureCache();
|
|
$account->load('plan');
|
|
|
|
expect(DB::table('features')->where('scope', 'account|'.$account->id)->count())
|
|
->toBe(0);
|
|
|
|
expect(Feature::for($account)->value(WorkspaceLimit::class))->toBe($plus->workspace_limit);
|
|
expect(Feature::for($account)->value(SocialAccountLimit::class))->toBe($plus->social_account_limit);
|
|
expect(Feature::for($account)->value(MemberLimit::class))->toBe($plus->member_limit);
|
|
expect(Feature::for($account)->value(MonthlyCreditsLimit::class))->toBe($plus->monthly_credits_limit);
|
|
});
|