From 535c292306c4f2930dd85bf2cedd518fa3ab11f6 Mon Sep 17 00:00:00 2001 From: Jan Henk Hazelaar Date: Wed, 20 May 2026 12:46:41 +0200 Subject: [PATCH] Add UnitResource for project-scoped woningen endpoints Mirror the UnitTypeResource shape for the /projects/:uuid/woningen list and detail endpoints so callers have a typed entry point for individual units (woningen) alongside the existing unit-type resource. Returns raw Saloon responses for now; a DTO layer can follow once the response shape is captured. Changelog: added --- src/NieuwbouwOffice.php | 6 ++ src/Requests/Units/GetUnitRequest.php | 21 ++++++ src/Requests/Units/GetUnitsRequest.php | 18 +++++ src/Resources/UnitResource.php | 29 ++++++++ tests/NieuwbouwOfficeTest.php | 7 ++ tests/Requests/Units/GetUnitRequestTest.php | 20 ++++++ tests/Requests/Units/GetUnitsRequestTest.php | 17 +++++ tests/Resources/UnitResourceTest.php | 70 ++++++++++++++++++++ 8 files changed, 188 insertions(+) create mode 100644 src/Requests/Units/GetUnitRequest.php create mode 100644 src/Requests/Units/GetUnitsRequest.php create mode 100644 src/Resources/UnitResource.php create mode 100644 tests/Requests/Units/GetUnitRequestTest.php create mode 100644 tests/Requests/Units/GetUnitsRequestTest.php create mode 100644 tests/Resources/UnitResourceTest.php diff --git a/src/NieuwbouwOffice.php b/src/NieuwbouwOffice.php index a9664f8..fe2001e 100755 --- a/src/NieuwbouwOffice.php +++ b/src/NieuwbouwOffice.php @@ -3,6 +3,7 @@ namespace NieuwbouwOffice\PhpSdk; use NieuwbouwOffice\PhpSdk\Resources\ProjectResource; +use NieuwbouwOffice\PhpSdk\Resources\UnitResource; use NieuwbouwOffice\PhpSdk\Resources\UnitTypeResource; use Saloon\Http\Auth\TokenAuthenticator; use Saloon\Http\Connector; @@ -38,4 +39,9 @@ public function unitTypes(string $projectUuid): UnitTypeResource { return new UnitTypeResource($this, $projectUuid); } + + public function units(string $projectUuid): UnitResource + { + return new UnitResource($this, $projectUuid); + } } diff --git a/src/Requests/Units/GetUnitRequest.php b/src/Requests/Units/GetUnitRequest.php new file mode 100644 index 0000000..5d6dd82 --- /dev/null +++ b/src/Requests/Units/GetUnitRequest.php @@ -0,0 +1,21 @@ +projectUuid}/woningen/{$this->uuid}/"; + } +} diff --git a/src/Requests/Units/GetUnitsRequest.php b/src/Requests/Units/GetUnitsRequest.php new file mode 100644 index 0000000..e5a18fc --- /dev/null +++ b/src/Requests/Units/GetUnitsRequest.php @@ -0,0 +1,18 @@ +projectUuid}/woningen/"; + } +} diff --git a/src/Resources/UnitResource.php b/src/Resources/UnitResource.php new file mode 100644 index 0000000..dd287e5 --- /dev/null +++ b/src/Resources/UnitResource.php @@ -0,0 +1,29 @@ +connector->send(new GetUnitsRequest($this->projectUuid)); + } + + public function get(string $uuid): Response + { + return $this->connector->send(new GetUnitRequest($this->projectUuid, $uuid)); + } +} diff --git a/tests/NieuwbouwOfficeTest.php b/tests/NieuwbouwOfficeTest.php index 5a8cc9e..84e3239 100644 --- a/tests/NieuwbouwOfficeTest.php +++ b/tests/NieuwbouwOfficeTest.php @@ -2,6 +2,7 @@ use NieuwbouwOffice\PhpSdk\NieuwbouwOffice; use NieuwbouwOffice\PhpSdk\Resources\ProjectResource; +use NieuwbouwOffice\PhpSdk\Resources\UnitResource; use NieuwbouwOffice\PhpSdk\Resources\UnitTypeResource; use Saloon\Enums\Method; use Saloon\Http\Auth\TokenAuthenticator; @@ -85,3 +86,9 @@ public function resolveEndpoint(): string expect($connector->unitTypes('proj-1'))->toBeInstanceOf(UnitTypeResource::class); }); + +it('exposes the units resource for a project', function () { + $connector = new NieuwbouwOffice('test-token'); + + expect($connector->units('proj-1'))->toBeInstanceOf(UnitResource::class); +}); diff --git a/tests/Requests/Units/GetUnitRequestTest.php b/tests/Requests/Units/GetUnitRequestTest.php new file mode 100644 index 0000000..097fa82 --- /dev/null +++ b/tests/Requests/Units/GetUnitRequestTest.php @@ -0,0 +1,20 @@ +getMethod())->toBe(Method::GET); +}); + +it('stores the project uuid and uuid on public properties', function () { + $request = new GetUnitRequest('proj-1', 'unit-9'); + + expect($request->projectUuid)->toBe('proj-1') + ->and($request->uuid)->toBe('unit-9'); +}); + +it('resolves to the project-scoped woningen detail endpoint', function () { + expect((new GetUnitRequest('proj-1', 'unit-9'))->resolveEndpoint()) + ->toBe('/projects/proj-1/woningen/unit-9/'); +}); diff --git a/tests/Requests/Units/GetUnitsRequestTest.php b/tests/Requests/Units/GetUnitsRequestTest.php new file mode 100644 index 0000000..922ac17 --- /dev/null +++ b/tests/Requests/Units/GetUnitsRequestTest.php @@ -0,0 +1,17 @@ +getMethod())->toBe(Method::GET); +}); + +it('stores the project uuid on a public property', function () { + expect((new GetUnitsRequest('proj-1'))->projectUuid)->toBe('proj-1'); +}); + +it('resolves to the project-scoped woningen endpoint', function () { + expect((new GetUnitsRequest('proj-1'))->resolveEndpoint()) + ->toBe('/projects/proj-1/woningen/'); +}); diff --git a/tests/Resources/UnitResourceTest.php b/tests/Resources/UnitResourceTest.php new file mode 100644 index 0000000..4476846 --- /dev/null +++ b/tests/Resources/UnitResourceTest.php @@ -0,0 +1,70 @@ + MockResponse::make([ + 'data' => [ + ['uuid' => 'u1'], + ['uuid' => 'u2'], + ], + ]), + ]); + + $connector = new NieuwbouwOffice('test-token'); + $connector->withMockClient($mockClient); + + $response = $connector->units('proj-1')->list(); + + expect($response)->toBeInstanceOf(Response::class) + ->and($response->json())->toBe([ + 'data' => [ + ['uuid' => 'u1'], + ['uuid' => 'u2'], + ], + ]); + + $mockClient->assertSent(function ($request) { + return $request instanceof GetUnitsRequest + && $request->projectUuid === 'proj-1' + && $request->resolveEndpoint() === '/projects/proj-1/woningen/'; + }); +}); + +it('get() sends a GetUnitRequest with the right project uuid and uuid', function () { + $mockClient = new MockClient([ + GetUnitRequest::class => MockResponse::make([ + 'uuid' => 'unit-9', + ]), + ]); + + $connector = new NieuwbouwOffice('test-token'); + $connector->withMockClient($mockClient); + + $response = $connector->units('proj-1')->get('unit-9'); + + expect($response)->toBeInstanceOf(Response::class) + ->and($response->json())->toBe([ + 'uuid' => 'unit-9', + ]); + + $mockClient->assertSent(function ($request) { + return $request instanceof GetUnitRequest + && $request->projectUuid === 'proj-1' + && $request->uuid === 'unit-9' + && $request->resolveEndpoint() === '/projects/proj-1/woningen/unit-9/'; + }); +}); + +it('can be instantiated directly with a connector and project uuid', function () { + $connector = new NieuwbouwOffice('test-token'); + + expect(new UnitResource($connector, 'proj-1'))->toBeInstanceOf(UnitResource::class); +});