From 046edf2305aa0e4ba62c83e31f027b5c56cc3238 Mon Sep 17 00:00:00 2001 From: Jayan Ratna Date: Sun, 15 Dec 2024 16:03:12 +1300 Subject: [PATCH] feat: Add Broadcasts API --- .github/workflows/tests.yml | 6 +- src/Broadcast.php | 8 +++ src/Client.php | 15 ++--- src/Service/Broadcast.php | 80 ++++++++++++++++++++++++++ src/Service/Service.php | 2 + src/Service/ServiceFactory.php | 1 + tests/Fixtures/Broadcast.php | 41 +++++++++++++ tests/Service/Broadcast.php | 50 ++++++++++++++++ tests/Transporters/HttpTransporter.php | 1 + 9 files changed, 194 insertions(+), 10 deletions(-) create mode 100644 src/Broadcast.php create mode 100644 src/Service/Broadcast.php create mode 100644 tests/Fixtures/Broadcast.php create mode 100644 tests/Service/Broadcast.php diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ad9f814..6ea053b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,12 +10,12 @@ on: jobs: tests: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest strategy: fail-fast: true matrix: - php: [8.1, 8.2, 8.3] + php: [8.1, 8.2, 8.3, 8.4] name: PHP ${{ matrix.php }} @@ -45,4 +45,4 @@ jobs: run: composer update --no-interaction --prefer-dist - name: Execute tests - run: vendor/bin/pest + run: vendor/bin/pest --display-deprecations --fail-on-deprecation diff --git a/src/Broadcast.php b/src/Broadcast.php new file mode 100644 index 0000000..4fbe593 --- /dev/null +++ b/src/Broadcast.php @@ -0,0 +1,8 @@ +transporter->request($payload); + + return $this->createResource('broadcasts', $result); + } + + /** + * Create a new broadcast to send to your audience. + * + * @see https://resend.com/docs/api-reference/broadcasts/create-broadcast + */ + public function create(array $parameters): \Resend\Broadcast + { + $payload = Payload::create('broadcasts', $parameters); + + $result = $this->transporter->request($payload); + + return $this->createResource('broadcasts', $result); + } + + /** + * List all domains. + * + * @return \Resend\Collection<\Resend\Broadcast> + * + * @see https://resend.com/docs/api-reference/broadcasts/list-broadcasts + */ + public function list(): \Resend\Collection + { + $payload = Payload::list('broadcasts'); + + $result = $this->transporter->request($payload); + + return $this->createResource('broadcasts', $result); + } + + /** + * Start sending broadcasts to your audience. + * + * @see https://resend.com/docs/api-reference/broadcasts/send-broadcast + */ + public function send(string $broadcastId, array $parameters): \Resend\Broadcast + { + $payload = Payload::create("broadcasts/{$broadcastId}/send", $parameters); + + $result = $this->transporter->request($payload); + + return $this->createResource('broadcasts', $result); + } + + /** + * Remove an existing broadcast. + * + * @see https://resend.com/docs/api-reference/broadcasts/delete-broadcast + */ + public function remove(string $id): \Resend\Broadcast + { + $payload = Payload::delete('broadcasts', $id); + + $result = $this->transporter->request($payload); + + return $this->createResource('broadcasts', $result); + } +} diff --git a/src/Service/Service.php b/src/Service/Service.php index 83fb2c6..20155ec 100644 --- a/src/Service/Service.php +++ b/src/Service/Service.php @@ -4,6 +4,7 @@ use Resend\ApiKey; use Resend\Audience; +use Resend\Broadcast; use Resend\Collection; use Resend\Contact; use Resend\Contracts\Transporter; @@ -19,6 +20,7 @@ abstract class Service protected $mapping = [ 'api-keys' => ApiKey::class, 'audiences' => Audience::class, + 'broadcasts' => Broadcast::class, 'contacts' => Contact::class, 'domains' => Domain::class, 'emails' => Email::class, diff --git a/src/Service/ServiceFactory.php b/src/Service/ServiceFactory.php index 0e6b4ae..9876dc0 100644 --- a/src/Service/ServiceFactory.php +++ b/src/Service/ServiceFactory.php @@ -15,6 +15,7 @@ class ServiceFactory 'apiKeys' => ApiKey::class, 'audiences' => Audience::class, 'batch' => Batch::class, + 'broadcasts' => Broadcast::class, 'contacts' => Contact::class, 'domains' => Domain::class, 'emails' => Email::class, diff --git a/tests/Fixtures/Broadcast.php b/tests/Fixtures/Broadcast.php new file mode 100644 index 0000000..f94d0ea --- /dev/null +++ b/tests/Fixtures/Broadcast.php @@ -0,0 +1,41 @@ + '559ac32e-9ef5-46fb-82a1-b76b840c0f7b', + 'object' => 'broadcast', + 'name' => 'Announcements', + 'audience_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf', + 'from' => 'Acme ', + 'subject' => 'hello world', + 'reply_to' => null, + 'preview_text' => 'Check out our latest announcements', + 'status' => 'draft', + 'created_at' => '2024-12-01T19:32:22.980Z', + 'scheduled_at' => null, + 'sent_at' => null, + ]; +} + +function broadcasts(): array +{ + return [ + 'data' => [ + [ + 'id' => '559ac32e-9ef5-46fb-82a1-b76b840c0f7b', + 'object' => 'broadcast', + 'name' => 'Announcements', + 'audience_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf', + 'from' => 'Acme ', + 'subject' => 'hello world', + 'reply_to' => null, + 'preview_text' => 'Check out our latest announcements', + 'status' => 'draft', + 'created_at' => '2024-12-01T19:32:22.980Z', + 'scheduled_at' => null, + 'sent_at' => null, + ], + ], + ]; +} diff --git a/tests/Service/Broadcast.php b/tests/Service/Broadcast.php new file mode 100644 index 0000000..c351cca --- /dev/null +++ b/tests/Service/Broadcast.php @@ -0,0 +1,50 @@ +broadcasts->get('559ac32e-9ef5-46fb-82a1-b76b840c0f7b'); + + expect($result)->toBeInstanceOf(Broadcast::class) + ->id->toBe('559ac32e-9ef5-46fb-82a1-b76b840c0f7b'); +}); + +it('can create a broadcast resource', function () { + $client = mockClient('POST', 'broadcasts', [ + 'audience_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf', + 'from' => 'Acme ', + 'subject' => 'hello world', + 'html' => 'Hi {{{FIRST_NAME|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}', + ], broadcast()); + + $result = $client->broadcasts->create([ + 'audience_id' => '78261eea-8f8b-4381-83c6-79fa7120f1cf', + 'from' => 'Acme ', + 'subject' => 'hello world', + 'html' => 'Hi {{{FIRST_NAME|there}}}, you can unsubscribe here: {{{RESEND_UNSUBSCRIBE_URL}}}', + ]); + + expect($result)->toBeInstanceOf(Broadcast::class) + ->id->toBe('559ac32e-9ef5-46fb-82a1-b76b840c0f7b'); +}); + +it('can get a list of broadcast resources', function () { + $client = mockClient('GET', 'broadcasts', [], broadcasts()); + + $result = $client->broadcasts->list(); + + expect($result)->toBeInstanceOf(Collection::class) + ->data->toBeArray(); +}); + +it('can remove a broadcast resource', function () { + $client = mockClient('DELETE', 'broadcasts/559ac32e-9ef5-46fb-82a1-b76b840c0f7b', [], broadcast()); + + $result = $client->broadcasts->remove('559ac32e-9ef5-46fb-82a1-b76b840c0f7b'); + + expect($result)->toBeInstanceOf(Broadcast::class) + ->id->toBe('559ac32e-9ef5-46fb-82a1-b76b840c0f7b'); +}); diff --git a/tests/Transporters/HttpTransporter.php b/tests/Transporters/HttpTransporter.php index bfc268f..5bbcae8 100644 --- a/tests/Transporters/HttpTransporter.php +++ b/tests/Transporters/HttpTransporter.php @@ -15,6 +15,7 @@ use Resend\ValueObjects\Transporter\Payload; beforeEach(function () { + /** @var ClientInterface|Mockery\MockInterface */ $this->client = Mockery::mock(ClientInterface::class); $apiKey = ApiKey::from('foo');