true, 'license' => [ 'product_id' => 123, 'expires_at' => '2027-01-21', 'version_id' => 5, ], ]; $client = $this->createClientWithResponse($responseData); $result = $client->validate(self::LICENSE_KEY, self::DOMAIN); self::assertInstanceOf(LicenseInfo::class, $result); self::assertSame(123, $result->productId); self::assertSame('2027-01-21', $result->expiresAt->format('Y-m-d')); self::assertSame(5, $result->versionId); } #[Test] public function itThrowsExceptionOnValidationFailure(): void { $responseData = [ 'valid' => false, 'error' => 'license_not_found', 'message' => 'License key not found.', ]; $client = $this->createClientWithResponse($responseData, 403); $this->expectException(LicenseNotFoundException::class); $this->expectExceptionMessage('License key not found.'); $client->validate(self::LICENSE_KEY, self::DOMAIN); } #[Test] public function itRetrievesLicenseStatusSuccessfully(): void { $responseData = [ 'valid' => true, 'status' => 'active', 'domain' => 'example.com', 'expires_at' => '2027-01-21', 'activations_count' => 1, 'max_activations' => 3, ]; $client = $this->createClientWithResponse($responseData); $result = $client->status(self::LICENSE_KEY); self::assertInstanceOf(LicenseStatus::class, $result); self::assertTrue($result->valid); self::assertSame(LicenseState::Active, $result->status); self::assertSame('example.com', $result->domain); self::assertSame(1, $result->activationsCount); self::assertSame(3, $result->maxActivations); } #[Test] public function itActivatesLicenseSuccessfully(): void { $responseData = [ 'success' => true, 'message' => 'License activated successfully.', ]; $client = $this->createClientWithResponse($responseData); $result = $client->activate(self::LICENSE_KEY, self::DOMAIN); self::assertInstanceOf(ActivationResult::class, $result); self::assertTrue($result->success); self::assertSame('License activated successfully.', $result->message); } #[Test] public function itLogsValidationRequests(): void { $responseData = [ 'valid' => true, 'license' => [ 'product_id' => 123, 'expires_at' => null, 'version_id' => null, ], ]; $logger = $this->createMock(LoggerInterface::class); $logger->expects(self::atLeastOnce()) ->method('info') ->with(self::stringContains('License')); $client = $this->createClientWithResponse($responseData, 200, $logger); $client->validate(self::LICENSE_KEY, self::DOMAIN); } #[Test] public function itThrowsExceptionOnHttpError(): void { $httpClient = new MockHttpClient([ new MockResponse('', ['http_code' => 500, 'error' => 'Server error']), ]); $client = new LicenseClient($httpClient, self::BASE_URL); $this->expectException(LicenseException::class); $client->validate(self::LICENSE_KEY, self::DOMAIN); } #[Test] public function itSendsRequestToCorrectEndpoint(): void { $requestHistory = []; $httpClient = new MockHttpClient(function ($method, $url) use (&$requestHistory) { $requestHistory[] = ['method' => $method, 'url' => $url]; return new MockResponse(json_encode([ 'valid' => true, 'license' => ['product_id' => 1, 'expires_at' => null, 'version_id' => null], ])); }); $client = new LicenseClient($httpClient, self::BASE_URL); $client->validate(self::LICENSE_KEY, self::DOMAIN); self::assertCount(1, $requestHistory); self::assertSame('POST', $requestHistory[0]['method']); self::assertStringContainsString('/wp-json/wc-licensed-product/v1/validate', $requestHistory[0]['url']); } private function createClientWithResponse( array $responseData, int $statusCode = 200, ?LoggerInterface $logger = null, ): LicenseClient { $httpClient = new MockHttpClient([ new MockResponse(json_encode($responseData), ['http_code' => $statusCode]), ]); return new LicenseClient($httpClient, self::BASE_URL, $logger); } }