Add Woo Manager email notification milestones with shared mail templates.
Deploy Ladill Woo Manager / deploy (push) Successful in 2m11s
Deploy Ladill Woo Manager / deploy (push) Successful in 2m11s
New order, store connected, Pro expiry, and past-due alerts use the Ladill notification layout with woo branding; expiry reminders dedupe per threshold like hosting. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Woo\ProSubscription;
|
||||
use App\Models\WooOrder;
|
||||
use App\Models\WooStore;
|
||||
use App\Notifications\Woo\WooOrderReceivedNotification;
|
||||
use App\Notifications\Woo\WooProExpiringNotification;
|
||||
use App\Notifications\Woo\WooStoreConnectedNotification;
|
||||
use App\Services\Woo\InstallTokenService;
|
||||
use App\Services\Woo\WooProExpiryAlertService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\TestCase;
|
||||
|
||||
class WooNotificationTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_order_created_webhook_sends_order_received_notification(): void
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$user = User::factory()->create();
|
||||
$store = WooStore::create([
|
||||
'user_id' => $user->id,
|
||||
'site_url' => 'https://shop.example.com',
|
||||
'site_name' => 'Example Shop',
|
||||
'status' => WooStore::STATUS_ACTIVE,
|
||||
'connected_at' => now(),
|
||||
'plugin_token_hash' => hash('sha256', 'test-token'),
|
||||
]);
|
||||
|
||||
$payload = [
|
||||
'id' => 99,
|
||||
'number' => '1099',
|
||||
'status' => 'processing',
|
||||
'currency' => 'GHS',
|
||||
'total' => '75.00',
|
||||
'billing' => ['first_name' => 'Kofi', 'last_name' => 'Annan', 'email' => 'kofi@example.com'],
|
||||
'line_items' => [['name' => 'Cap', 'quantity' => 1, 'total' => '75.00']],
|
||||
'needs_payment' => false,
|
||||
'date_modified_gmt' => now()->utc()->format('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
$body = json_encode($payload, JSON_THROW_ON_ERROR);
|
||||
$signature = base64_encode(hash_hmac('sha256', $body, (string) $store->webhook_secret, true));
|
||||
|
||||
$this->call(
|
||||
'POST',
|
||||
route('woo.webhooks.woocommerce', $store->public_id),
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[
|
||||
'CONTENT_TYPE' => 'application/json',
|
||||
'HTTP_X_WC_WEBHOOK_SIGNATURE' => $signature,
|
||||
'HTTP_X_WC_WEBHOOK_TOPIC' => 'order.created',
|
||||
],
|
||||
$body,
|
||||
)->assertOk();
|
||||
|
||||
Notification::assertSentTo($user, WooOrderReceivedNotification::class);
|
||||
}
|
||||
|
||||
public function test_order_updated_webhook_does_not_send_order_received_notification(): void
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$user = User::factory()->create();
|
||||
$store = WooStore::create([
|
||||
'user_id' => $user->id,
|
||||
'site_url' => 'https://shop.example.com',
|
||||
'status' => WooStore::STATUS_ACTIVE,
|
||||
'connected_at' => now(),
|
||||
'plugin_token_hash' => hash('sha256', 'test-token'),
|
||||
]);
|
||||
|
||||
WooOrder::create([
|
||||
'woo_store_id' => $store->id,
|
||||
'external_order_id' => 42,
|
||||
'order_number' => '1042',
|
||||
'line_items' => [],
|
||||
'currency' => 'GHS',
|
||||
'total_minor' => 5000,
|
||||
]);
|
||||
|
||||
$payload = [
|
||||
'id' => 42,
|
||||
'number' => '1042',
|
||||
'status' => 'completed',
|
||||
'currency' => 'GHS',
|
||||
'total' => '50.00',
|
||||
'billing' => [],
|
||||
'line_items' => [],
|
||||
'needs_payment' => false,
|
||||
'date_modified_gmt' => now()->utc()->format('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
$body = json_encode($payload, JSON_THROW_ON_ERROR);
|
||||
$signature = base64_encode(hash_hmac('sha256', $body, (string) $store->webhook_secret, true));
|
||||
|
||||
$this->call(
|
||||
'POST',
|
||||
route('woo.webhooks.woocommerce', $store->public_id),
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[
|
||||
'CONTENT_TYPE' => 'application/json',
|
||||
'HTTP_X_WC_WEBHOOK_SIGNATURE' => $signature,
|
||||
'HTTP_X_WC_WEBHOOK_TOPIC' => 'order.updated',
|
||||
],
|
||||
$body,
|
||||
)->assertOk();
|
||||
|
||||
Notification::assertNothingSent();
|
||||
}
|
||||
|
||||
public function test_store_activation_sends_store_connected_notification(): void
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$user = User::factory()->create();
|
||||
$store = WooStore::create([
|
||||
'user_id' => $user->id,
|
||||
'site_url' => 'https://shop.example.com',
|
||||
'site_name' => 'Example Shop',
|
||||
'status' => WooStore::STATUS_PENDING,
|
||||
]);
|
||||
|
||||
$token = app(InstallTokenService::class)->issue($store)['token'];
|
||||
|
||||
$this->postJson('/api/v1/stores/activate', [
|
||||
'install_token' => $token,
|
||||
'site_url' => 'https://shop.example.com',
|
||||
])->assertOk();
|
||||
|
||||
Notification::assertSentTo($user, WooStoreConnectedNotification::class);
|
||||
}
|
||||
|
||||
public function test_pro_expiry_alert_sent_once_per_milestone(): void
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$user = User::factory()->create();
|
||||
$subscription = ProSubscription::create([
|
||||
'user_id' => $user->id,
|
||||
'status' => ProSubscription::STATUS_CANCELED,
|
||||
'plan' => ProSubscription::PLAN_PRO,
|
||||
'price_minor' => 4900,
|
||||
'currency' => 'GHS',
|
||||
'auto_renew' => false,
|
||||
'current_period_end' => now()->addDays(7)->startOfDay(),
|
||||
]);
|
||||
|
||||
$service = app(WooProExpiryAlertService::class);
|
||||
$service->checkSubscription($subscription);
|
||||
$service->checkSubscription($subscription->fresh());
|
||||
|
||||
Notification::assertSentTo($user, WooProExpiringNotification::class, 1);
|
||||
$this->assertSame([7], $subscription->fresh()->metadata['expiry_alerts_sent']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user