Step 6: Pest integration tests for webhook ingestion and background job

This commit is contained in:
idevakk
2026-03-05 14:57:40 +05:30
parent ac9e7227e6
commit 4d8f808d97
3 changed files with 185 additions and 9 deletions

View File

@@ -0,0 +1,91 @@
<?php
use App\Events\NewEmailReceived;
use App\Jobs\ProcessIncomingEmail;
use App\Models\Email;
use App\Models\EmailBody;
use Illuminate\Support\Facades\Event;
it('stores incoming email in MariaDB and MongoDB, and broadcasts event', function () {
Event::fake();
$hash = 'test-hash-'.time();
$payload = [
'hash' => $hash,
'metadata' => [
'recipientEmail' => 'test@imail.app',
'recipientName' => 'Test User',
'senderEmail' => 'sender@example.com',
'senderName' => 'Sender Name',
'domain' => 'imail.app',
'subject' => 'Test Subject',
'received_at' => now()->toIso8601String(),
'attachmentSize' => 1024,
'attachments' => [
['filename' => 'test.pdf', 'mimeType' => 'application/pdf', 'size' => 1024],
],
],
'bodyText' => 'This is the plain text body format.',
'bodyHtml' => '<html><body><p>This is the HTML body format.</p></body></html>',
];
$job = new ProcessIncomingEmail($payload);
$job->handle();
// Verify MariaDB storage
$this->assertDatabaseHas('emails', [
'unique_id_hash' => $hash,
'recipient_email' => 'test@imail.app',
'domain' => 'imail.app',
'subject' => 'Test Subject',
'preview' => 'This is the plain text body format.',
'attachment_size' => 1024,
]);
$email = Email::where('unique_id_hash', $hash)->first();
expect($email->attachments_json)->toHaveCount(1)
->and($email->attachments_json[0]['filename'])->toBe('test.pdf');
// Verify MongoDB storage
$body = EmailBody::where('unique_id_hash', $hash)->first();
expect($body)->not->toBeNull()
->and($body->body_text)->toBe('This is the plain text body format.')
->and($body->body_html)->toBe('<html><body><p>This is the HTML body format.</p></body></html>');
// Verify Broadcast Event
Event::assertDispatched(NewEmailReceived::class, function ($event) use ($hash) {
return $event->email->unique_id_hash === $hash;
});
// Cleanup MongoDB (MariaDB is handled by RefreshDatabase if used, but let's be safe)
$body->delete();
});
it('generates preview from stripped HTML if text body is missing', function () {
Event::fake();
$hash = 'test-hash-html-only-'.time();
$payload = [
'hash' => $hash,
'metadata' => [
'recipientEmail' => 'test2@imail.app',
'senderEmail' => 'sender2@example.com',
'domain' => 'imail.app',
'received_at' => now()->toIso8601String(),
],
'bodyText' => null,
'bodyHtml' => '<html><body><h1>Welcome</h1><p>This is a <strong>strong</strong> test.</p> <br> <p>Footer</p></body></html>',
];
$job = new ProcessIncomingEmail($payload);
$job->handle();
// Verify MariaDB storage preview logic
$this->assertDatabaseHas('emails', [
'unique_id_hash' => $hash,
'preview' => 'Welcome This is a strong test. Footer',
]);
// Cleanup MongoDB
EmailBody::where('unique_id_hash', $hash)->delete();
});

View File

@@ -0,0 +1,78 @@
<?php
use App\Jobs\ProcessIncomingEmail;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Queue;
beforeEach(function () {
Config::set('services.mailops.webhook_secret', 'test-secret');
});
it('rejects webhooks without a secret token', function () {
$response = $this->postJson('/api/webhooks/incoming_email', [
'hash' => 'dummy-hash',
]);
$response->assertStatus(401)
->assertJson(['error' => 'Unauthorized']);
});
it('rejects webhooks with an invalid secret token', function () {
$response = $this->postJson('/api/webhooks/incoming_email', [
'hash' => 'dummy-hash',
], [
'Authorization' => 'Bearer wrong-secret',
]);
$response->assertStatus(401);
});
it('accepts valid webhooks and dispatches the processing job', function () {
Queue::fake();
$payload = [
'hash' => 'test-unique-hash-12345',
'metadata' => [
'recipientEmail' => 'test@imail.app',
'recipientName' => 'Test User',
'senderEmail' => 'sender@example.com',
'senderName' => 'Sender Name',
'domain' => 'imail.app',
'subject' => 'Test Subject',
'received_at' => now()->toIso8601String(),
'attachmentSize' => 0,
'attachments' => [],
],
'bodyText' => 'This is a test email body.',
'bodyHtml' => '<p>This is a test email body.</p>',
];
$response = $this->postJson('/api/webhooks/incoming_email', $payload, [
'Authorization' => 'Bearer test-secret',
]);
$response->assertStatus(200)
->assertJson(['status' => 'queued']);
Queue::assertPushed(ProcessIncomingEmail::class, function ($job) use ($payload) {
return $job->payload['hash'] === $payload['hash'];
});
});
it('validates required payload fields', function () {
Queue::fake();
$response = $this->postJson('/api/webhooks/incoming_email', [
// Missing hash and other required fields
'metadata' => [
'recipientEmail' => 'test@imail.app',
],
], [
'Authorization' => 'Bearer test-secret',
]);
$response->assertStatus(422)
->assertJsonValidationErrors(['hash', 'metadata.senderEmail', 'metadata.domain', 'metadata.received_at']);
Queue::assertNothingPushed();
});