createMock(NewsletterManager::class); $manager ->expects(self::once()) ->method('requestApiSubscription') ->with('customer@example.com', [10321569], [10321569, 12345678], 'Mia', 'Muster') ->willReturn(new NewsletterSubscriptionRequestResult( 'customer@example.com', [10321569], NewsletterSubscriptionRequestResult::STATE_CONFIRMATION_REQUESTED, true, )); $manager ->expects(self::once()) ->method('createListIdMapping') ->with([10321569]) ->willReturn([ [ 'id' => 10321569, 'label' => 'E&P Newsletter', ], ]); $controller = new NewsletterSubscriptionController($manager, new NullLogger(), [ 10321569 => 'E&P Newsletter', 12345678 => 'Partner Updates', ]); $response = $controller->subscribe($this->request('customer@example.com', [10321569], 'Mia', 'Muster')); $payload = json_decode((string) $response->getContent(), true, 512, JSON_THROW_ON_ERROR); self::assertSame(Response::HTTP_ACCEPTED, $response->getStatusCode()); self::assertSame([ 'success' => true, 'email' => 'customer@example.com', 'lists' => [ [ 'id' => 10321569, 'label' => 'E&P Newsletter', 'state' => NewsletterSubscriptionRequestResult::LIST_STATE_PENDING, ], ], 'state' => NewsletterSubscriptionRequestResult::STATE_CONFIRMATION_REQUESTED, 'confirmationRequested' => true, ], $payload); } public function testSubscribedRequestReturnsListWiseStates(): void { $manager = $this->createMock(NewsletterManager::class); $manager ->expects(self::once()) ->method('requestApiSubscription') ->with('customer@example.com', [10321569, 12345678], [10321569, 12345678]) ->willReturn(new NewsletterSubscriptionRequestResult( 'customer@example.com', [10321569, 12345678], NewsletterSubscriptionRequestResult::STATE_SUBSCRIBED, false, [ 10321569 => NewsletterSubscriptionRequestResult::LIST_STATE_ALREADY_REGISTERED, 12345678 => NewsletterSubscriptionRequestResult::LIST_STATE_SUCCESS, ], )); $manager ->expects(self::once()) ->method('createListIdMapping') ->with([10321569, 12345678]) ->willReturn([ [ 'id' => 10321569, 'label' => 'E&P Newsletter', ], [ 'id' => 12345678, 'label' => 'Partner Updates', ], ]); $controller = new NewsletterSubscriptionController($manager, new NullLogger(), [ 10321569 => 'E&P Newsletter', 12345678 => 'Partner Updates', ]); $response = $controller->subscribe($this->request('customer@example.com', [10321569, 12345678])); $payload = json_decode((string) $response->getContent(), true, 512, JSON_THROW_ON_ERROR); self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame([ [ 'id' => 10321569, 'label' => 'E&P Newsletter', 'state' => NewsletterSubscriptionRequestResult::LIST_STATE_ALREADY_REGISTERED, ], [ 'id' => 12345678, 'label' => 'Partner Updates', 'state' => NewsletterSubscriptionRequestResult::LIST_STATE_SUCCESS, ], ], $payload['lists']); } public function testNonAllowlistedListIdReturnsBadRequestBeforeSideEffects(): void { $manager = $this->createMock(NewsletterManager::class); $manager ->expects(self::once()) ->method('requestApiSubscription') ->with('customer@example.com', [12345678], [10321569]) ->willThrowException(new NewsletterListNotAllowedException([12345678], [12345678])); $controller = new NewsletterSubscriptionController($manager, new NullLogger(), [ 10321569 => 'E&P Newsletter', ]); $response = $controller->subscribe($this->request('customer@example.com', [12345678])); $payload = json_decode((string) $response->getContent(), true, 512, JSON_THROW_ON_ERROR); self::assertSame(Response::HTTP_BAD_REQUEST, $response->getStatusCode()); self::assertSame([ 'success' => false, 'message' => 'One or more Mailjet list IDs are not allowed.', 'listIds' => [12345678], 'unknownListIds' => [12345678], ], $payload); } public function testProviderFailureReturnsServiceUnavailable(): void { $manager = $this->createMock(NewsletterManager::class); $manager ->expects(self::once()) ->method('requestApiSubscription') ->with('customer@example.com', [10321569], [10321569]) ->willThrowException(new NewsletterProviderException('Mailjet failed')); $controller = new NewsletterSubscriptionController($manager, new NullLogger(), [ 10321569 => 'E&P Newsletter', ]); $response = $controller->subscribe($this->request('customer@example.com', [10321569])); self::assertSame(Response::HTTP_SERVICE_UNAVAILABLE, $response->getStatusCode()); } private function request(string $email, array $listIds, ?string $firstName = null, ?string $lastName = null): NewsletterSubscriptionRequest { $request = new NewsletterSubscriptionRequest(); $request->email = $email; $request->listIds = $listIds; $request->firstName = $firstName; $request->lastName = $lastName; return $request; } }