feat: create ClickUp task after confirming accommodation booking

This commit is contained in:
Björn Fromme
2026-08-20 17:56:29 +02:00
parent 0a1683667f
commit 7c5f6dd5ef
18 changed files with 535 additions and 48 deletions
+99
View File
@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
namespace App\Tests\ClickUp;
use App\ClickUp\ApiClient;
use App\ClickUp\Exception\ClickUpException;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
class ApiClientTest extends TestCase
{
public function testCreateTaskFromTemplatePostsTheNameAndReturnsTheTaskId(): void
{
$requests = [];
$http = new MockHttpClient(function (string $method, string $url, array $options) use (&$requests): MockResponse {
$requests[] = [$method, $url, $options];
return new MockResponse(json_encode(['id' => 'abc123'], JSON_THROW_ON_ERROR), [
'response_headers' => ['content-type' => 'application/json'],
]);
});
$taskId = $this->client($http)->createTaskFromTemplate('WIEN01 2026-08-20 Müller');
self::assertSame('abc123', $taskId);
self::assertSame('POST', $requests[0][0]);
self::assertSame('https://clickup.test/list/555/taskTemplate/tpl-7', $requests[0][1]);
self::assertSame(['name' => 'WIEN01 2026-08-20 Müller'], json_decode((string) $requests[0][2]['body'], true, 512, JSON_THROW_ON_ERROR));
self::assertContains('Authorization: pk_secret', $requests[0][2]['headers']);
}
public function testUpdateTaskStatusPutsTheStatus(): void
{
$requests = [];
$http = new MockHttpClient(function (string $method, string $url, array $options) use (&$requests): MockResponse {
$requests[] = [$method, $url, $options];
return new MockResponse(json_encode(['id' => 'abc123'], JSON_THROW_ON_ERROR), [
'response_headers' => ['content-type' => 'application/json'],
]);
});
$this->client($http)->updateTaskStatus('abc123', 'GRO');
self::assertSame('PUT', $requests[0][0]);
self::assertSame('https://clickup.test/task/abc123', $requests[0][1]);
self::assertSame(['status' => 'GRO'], json_decode((string) $requests[0][2]['body'], true, 512, JSON_THROW_ON_ERROR));
}
public function testAResponseWithoutATaskIdIsAnError(): void
{
$http = new MockHttpClient(new MockResponse(json_encode(['err' => 'nope'], JSON_THROW_ON_ERROR), [
'response_headers' => ['content-type' => 'application/json'],
]));
$this->expectException(ClickUpException::class);
$this->client($http)->createTaskFromTemplate('WIEN01 2026-08-20 Müller');
}
public function testAnHttpErrorIsWrappedInADomainException(): void
{
$http = new MockHttpClient(new MockResponse('rate limited', ['http_code' => 429]));
$this->expectException(ClickUpException::class);
$this->client($http)->createTaskFromTemplate('WIEN01 2026-08-20 Müller');
}
public function testAnUnconfiguredClientReportsItselfAndRefusesToRequest(): void
{
$http = new MockHttpClient(function (): MockResponse {
self::fail('No request must be made when the client is unconfigured.');
});
$client = new ApiClient($http, new NullLogger(), 'pk_secret', '', 'tpl-7', 'https://clickup.test');
self::assertFalse($client->isConfigured());
$this->expectException(ClickUpException::class);
$client->createTaskFromTemplate('WIEN01 2026-08-20 Müller');
}
public function testAFullyConfiguredClientReportsItself(): void
{
self::assertTrue($this->client(new MockHttpClient())->isConfigured());
self::assertFalse((new ApiClient(new MockHttpClient(), new NullLogger()))->isConfigured());
}
private function client(MockHttpClient $http): ApiClient
{
return new ApiClient($http, new NullLogger(), 'pk_secret', '555', 'tpl-7', 'https://clickup.test');
}
}