API: Added user info and shifts by user and angeltype, simplified neededAngelTypes
This commit is contained in:
parent
4de882ef85
commit
02f998fc38
|
@ -123,10 +123,16 @@ $route->addGroup(
|
|||
$route->get('/openapi', 'Api\IndexController@openApiV0');
|
||||
|
||||
$route->get('/angeltypes', 'Api\AngelTypeController@index');
|
||||
$route->get('/news', 'Api\NewsController@index');
|
||||
$route->get('/angeltypes/{angeltype_id:\d+}/shifts', 'Api\ShiftsController@entriesByAngeltype');
|
||||
|
||||
$route->get('/locations', 'Api\LocationsController@index');
|
||||
$route->get('/locations/{location_id:\d+}/shifts', 'Api\ShiftsController@entriesByLocation');
|
||||
|
||||
$route->get('/news', 'Api\NewsController@index');
|
||||
|
||||
$route->get('/users/self', 'Api\UsersController@self');
|
||||
$route->get('/users/{user_id:\d+}/angeltypes', 'Api\AngelTypeController@ofUser');
|
||||
$route->get('/users/{user_id:\d+}/shifts', 'Api\ShiftsController@entriesByUser');
|
||||
|
||||
$route->addRoute(
|
||||
['POST', 'PUT', 'DELETE', 'PATCH'],
|
||||
|
|
|
@ -21,10 +21,14 @@ servers:
|
|||
description: Your local dev instance
|
||||
|
||||
tags:
|
||||
- name: angeltype
|
||||
description: Angeltypes
|
||||
- name: location
|
||||
description: Event locations
|
||||
- name: news
|
||||
description: News and meeting announcements
|
||||
- name: shift
|
||||
description: Event shifts and location
|
||||
description: Event shifts
|
||||
- name: user
|
||||
description: User information
|
||||
|
||||
|
@ -321,6 +325,55 @@ components:
|
|||
- pronoun
|
||||
- contact
|
||||
- url
|
||||
UserDetail:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/User'
|
||||
- type: object
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
example: user@example.com
|
||||
tshirt:
|
||||
type: string
|
||||
nullable: true
|
||||
example: XL
|
||||
dates:
|
||||
type: object
|
||||
properties:
|
||||
planned_arrival:
|
||||
type: string
|
||||
nullable: true
|
||||
format: date-time
|
||||
description: DateTime in ISO-8601 format
|
||||
example: 2023-05-13T00:00:00.000000Z
|
||||
planned_departure:
|
||||
type: string
|
||||
nullable: true
|
||||
format: date-time
|
||||
description: DateTime in ISO-8601 format
|
||||
example: 2023-05-23T00:00:00.000000Z
|
||||
arrival:
|
||||
type: string
|
||||
nullable: true
|
||||
format: date-time
|
||||
description: Actual arrival date, DateTime in ISO-8601 format
|
||||
example: 2023-05-23T13:37:42.000000Z
|
||||
required:
|
||||
- planned_arrival
|
||||
- planned_departure
|
||||
- arrival
|
||||
language:
|
||||
type: string
|
||||
example: en_US
|
||||
arrived:
|
||||
type: boolean
|
||||
example: true
|
||||
required:
|
||||
- email
|
||||
- tshirt
|
||||
- dates
|
||||
- language
|
||||
- arrived
|
||||
|
||||
security:
|
||||
- bearerAuth: [ ]
|
||||
|
@ -329,7 +382,7 @@ paths:
|
|||
/angeltypes:
|
||||
get:
|
||||
tags:
|
||||
- shift
|
||||
- angeltype
|
||||
summary: Get a list of angeltypes
|
||||
responses:
|
||||
'200':
|
||||
|
@ -348,6 +401,33 @@ paths:
|
|||
'403':
|
||||
$ref: '#/components/responses/ForbiddenError'
|
||||
|
||||
/angeltypes/{id}/shifts:
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The angeltype identifier
|
||||
example: 42
|
||||
schema:
|
||||
type: integer
|
||||
get:
|
||||
tags:
|
||||
- angeltype
|
||||
- shift
|
||||
summary: Get all shifts of the requested angeltype
|
||||
responses:
|
||||
'200':
|
||||
description: Ok
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Shift'
|
||||
|
||||
/news:
|
||||
get:
|
||||
tags:
|
||||
|
@ -373,7 +453,7 @@ paths:
|
|||
/locations:
|
||||
get:
|
||||
tags:
|
||||
- shift
|
||||
- location
|
||||
summary: Get a list of locations
|
||||
responses:
|
||||
'200':
|
||||
|
@ -403,6 +483,7 @@ paths:
|
|||
type: integer
|
||||
get:
|
||||
tags:
|
||||
- location
|
||||
- shift
|
||||
summary: Get all shifts in the requested location
|
||||
responses:
|
||||
|
@ -424,6 +505,28 @@ paths:
|
|||
'404':
|
||||
$ref: '#/components/responses/NotFoundError'
|
||||
|
||||
/users/self:
|
||||
get:
|
||||
tags:
|
||||
- user
|
||||
summary: Get the requesting users information
|
||||
responses:
|
||||
'200':
|
||||
description: Ok
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/UserDetail'
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'403':
|
||||
$ref: '#/components/responses/ForbiddenError'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFoundError'
|
||||
|
||||
/users/{id}/angeltypes:
|
||||
parameters:
|
||||
- name: id
|
||||
|
@ -435,6 +538,7 @@ paths:
|
|||
type: integer
|
||||
get:
|
||||
tags:
|
||||
- angeltype
|
||||
- user
|
||||
summary: Get the users angel types
|
||||
responses:
|
||||
|
@ -456,6 +560,39 @@ paths:
|
|||
'404':
|
||||
$ref: '#/components/responses/NotFoundError'
|
||||
|
||||
/users/{id}/shifts:
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The user identifier
|
||||
example: 42
|
||||
schema:
|
||||
type: integer
|
||||
get:
|
||||
tags:
|
||||
- shift
|
||||
- user
|
||||
summary: Get all shifts of the requested user
|
||||
responses:
|
||||
'200':
|
||||
description: Ok
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Shift'
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'403':
|
||||
$ref: '#/components/responses/ForbiddenError'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFoundError'
|
||||
|
||||
/openapi:
|
||||
get:
|
||||
tags:
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Controllers\Api\Resources;
|
||||
|
||||
class UserDetailResource extends UserResource
|
||||
{
|
||||
public function toArray(): array
|
||||
{
|
||||
return array_merge(parent::toArray(), [
|
||||
'email' => $this->model->contact->email ?: $this->model->email,
|
||||
'tshirt' => $this->model->personalData->shirt_size,
|
||||
'language' => $this->model->settings->language,
|
||||
'arrived' => $this->model->state->arrived,
|
||||
'dates' => [
|
||||
'planned_arrival' => $this->model->personalData->planned_arrival_date,
|
||||
'planned_departure' => $this->model->personalData->planned_departure_date,
|
||||
'arrival' => $this->model->state->arrival_date,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -10,13 +10,44 @@ use Engelsystem\Controllers\Api\Resources\ShiftWithEntriesResource;
|
|||
use Engelsystem\Controllers\Api\Resources\UserResource;
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Models\AngelType;
|
||||
use Engelsystem\Models\Location;
|
||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||
use Engelsystem\Models\Shifts\Shift;
|
||||
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||
use Engelsystem\Models\User\User;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class ShiftsController extends ApiController
|
||||
{
|
||||
public function entriesByAngeltype(Request $request): Response
|
||||
{
|
||||
$id = (int) $request->getAttribute('angeltype_id');
|
||||
/** @var AngelType $angeltype */
|
||||
$angeltype = AngelType::findOrFail($id);
|
||||
/** @var ShiftEntry[]|Collection $shifts */
|
||||
$shiftEntries = $angeltype->shiftEntries()
|
||||
->with([
|
||||
'shift.neededAngelTypes.angelType',
|
||||
'shift.location.neededAngelTypes.angelType',
|
||||
'shift.shiftEntries.angelType',
|
||||
'shift.shiftEntries.user.contact',
|
||||
'shift.shiftEntries.user.personalData',
|
||||
'shift.shiftType',
|
||||
'shift.schedule',
|
||||
])
|
||||
->get();
|
||||
|
||||
/** @var Shift[]|Collection $shifts */
|
||||
$shifts = Collection::make(
|
||||
$shiftEntries
|
||||
->pluck('shift')
|
||||
->sortBy('start')
|
||||
);
|
||||
|
||||
return $this->shiftEntriesResponse($shifts);
|
||||
}
|
||||
|
||||
public function entriesByLocation(Request $request): Response
|
||||
{
|
||||
$locationId = (int) $request->getAttribute('location_id');
|
||||
|
@ -31,10 +62,45 @@ class ShiftsController extends ApiController
|
|||
'shiftEntries.user.contact',
|
||||
'shiftEntries.user.personalData',
|
||||
'shiftType',
|
||||
'schedule',
|
||||
])
|
||||
->orderBy('start')
|
||||
->get();
|
||||
|
||||
return $this->shiftEntriesResponse($shifts);
|
||||
}
|
||||
|
||||
public function entriesByUser(Request $request): Response
|
||||
{
|
||||
$id = (int) $request->getAttribute('user_id');
|
||||
/** @var User $user */
|
||||
$user = User::findOrFail($id);
|
||||
/** @var ShiftEntry[]|Collection $shifts */
|
||||
$shiftEntries = $user->shiftEntries()
|
||||
->with([
|
||||
'shift.neededAngelTypes.angelType',
|
||||
'shift.location.neededAngelTypes.angelType',
|
||||
'shift.shiftEntries.angelType',
|
||||
'shift.shiftEntries.user.contact',
|
||||
'shift.shiftEntries.user.personalData',
|
||||
'shift.shiftType',
|
||||
'shift.schedule',
|
||||
])
|
||||
->get();
|
||||
|
||||
/** @var Shift[]|Collection $shifts */
|
||||
$shifts = Collection::make(
|
||||
$shiftEntries
|
||||
->pluck('shift')
|
||||
->sortBy('start')
|
||||
);
|
||||
|
||||
return $this->shiftEntriesResponse($shifts);
|
||||
}
|
||||
|
||||
protected function shiftEntriesResponse(Collection $shifts): Response
|
||||
{
|
||||
/** @var Collection|Shift[] $shifts */
|
||||
$shiftEntries = [];
|
||||
// Blob of not-optimized mediocre pseudo-serialization
|
||||
foreach ($shifts as $shift) {
|
||||
|
@ -58,7 +124,7 @@ class ShiftsController extends ApiController
|
|||
]);
|
||||
}
|
||||
|
||||
$locationData = new LocationResource($location);
|
||||
$locationData = new LocationResource($shift->location);
|
||||
$shiftEntries[] = (new ShiftWithEntriesResource($shift))->toArray($locationData, $entries);
|
||||
}
|
||||
|
||||
|
@ -72,22 +138,12 @@ class ShiftsController extends ApiController
|
|||
*/
|
||||
protected function getNeededAngelTypes(Shift $shift): Collection
|
||||
{
|
||||
// From shift
|
||||
$neededAngelTypes = $shift->neededAngelTypes;
|
||||
|
||||
// Add from location
|
||||
foreach ($shift->location->neededAngelTypes as $neededAngelType) {
|
||||
/** @var NeededAngelType $existingNeededAngelType */
|
||||
$existingNeededAngelType = $neededAngelTypes
|
||||
->where('angel_type_id', $neededAngelType->angel_type_id)
|
||||
->first();
|
||||
if (!$existingNeededAngelType) {
|
||||
$neededAngelTypes[] = clone $neededAngelType;
|
||||
continue;
|
||||
}
|
||||
|
||||
$existingNeededAngelType->location_id = $shift->location->id;
|
||||
$existingNeededAngelType->count += $neededAngelType->count;
|
||||
if (!$shift->schedule) {
|
||||
// Get from shift
|
||||
$neededAngelTypes = $shift->neededAngelTypes;
|
||||
} else {
|
||||
// Load instead from location
|
||||
$neededAngelTypes = $shift->location->neededAngelTypes;
|
||||
}
|
||||
|
||||
// Add needed angeltypes from additionally added users
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Controllers\Api;
|
||||
|
||||
use Engelsystem\Controllers\Api\Resources\UserDetailResource;
|
||||
use Engelsystem\Helpers\Authenticator;
|
||||
use Engelsystem\Http\Response;
|
||||
|
||||
class UsersController extends ApiController
|
||||
{
|
||||
public function __construct(Response $response, protected Authenticator $auth)
|
||||
{
|
||||
parent::__construct($response);
|
||||
}
|
||||
|
||||
public function self(): Response
|
||||
{
|
||||
$user = $this->auth->user();
|
||||
|
||||
$data = ['data' => (new UserDetailResource($user))->toArray()];
|
||||
return $this->response
|
||||
->withContent(json_encode($data));
|
||||
}
|
||||
}
|
|
@ -10,6 +10,8 @@ use Engelsystem\Http\Request;
|
|||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Models\Location;
|
||||
use Engelsystem\Models\Shifts\NeededAngelType;
|
||||
use Engelsystem\Models\Shifts\Schedule;
|
||||
use Engelsystem\Models\Shifts\ScheduleShift;
|
||||
use Engelsystem\Models\Shifts\Shift;
|
||||
use Engelsystem\Models\Shifts\ShiftEntry;
|
||||
use Engelsystem\Models\User\Contact;
|
||||
|
@ -18,8 +20,13 @@ use Engelsystem\Models\User\User;
|
|||
|
||||
class ShiftsControllerTest extends ApiBaseControllerTest
|
||||
{
|
||||
protected Location $location;
|
||||
protected Shift $shiftA;
|
||||
protected Shift $shiftB;
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Api\ShiftsController::entriesByLocation
|
||||
* @covers \Engelsystem\Controllers\Api\ShiftsController::shiftEntriesResponse
|
||||
* @covers \Engelsystem\Controllers\Api\Resources\ShiftResource::toArray
|
||||
* @covers \Engelsystem\Controllers\Api\Resources\ShiftTypeResource::toArray
|
||||
* @covers \Engelsystem\Controllers\Api\Resources\ShiftWithEntriesResource::toArray
|
||||
|
@ -29,64 +36,8 @@ class ShiftsControllerTest extends ApiBaseControllerTest
|
|||
*/
|
||||
public function testEntriesByLocation(): void
|
||||
{
|
||||
$this->initDatabase();
|
||||
|
||||
/** @var Location $location */
|
||||
$location = Location::factory()->create();
|
||||
|
||||
// Shifts
|
||||
/** @var Shift $shiftA */
|
||||
$shiftA = Shift::factory(1)
|
||||
->create(['location_id' => $location->id, 'start' => Carbon::now()->subHour()])
|
||||
->first();
|
||||
/** @var Shift $shiftB */
|
||||
$shiftB = Shift::factory(1)
|
||||
->create(['location_id' => $location->id, 'start' => Carbon::now()->addHour()])
|
||||
->first();
|
||||
|
||||
// "Empty" entry to be skipped
|
||||
NeededAngelType::factory(1)->create(['location_id' => null, 'shift_id' => $shiftA->id, 'count' => 0]);
|
||||
|
||||
// Needed entry by shift
|
||||
/** @var NeededAngelType $byShift */
|
||||
$byShift = NeededAngelType::factory(2)
|
||||
->create(['location_id' => null, 'shift_id' => $shiftA->id, 'count' => 2])
|
||||
->first();
|
||||
|
||||
// Needed entry by location
|
||||
/** @var NeededAngelType $byLocation */
|
||||
$byLocation = NeededAngelType::factory(1)
|
||||
->create(['location_id' => $location->id, 'shift_id' => null, 'count' => 3])
|
||||
->first();
|
||||
|
||||
// Added by both
|
||||
NeededAngelType::factory(1)
|
||||
->create([
|
||||
'location_id' => $location->id,
|
||||
'shift_id' => null,
|
||||
'angel_type_id' => $byShift->angel_type_id,
|
||||
'count' => 3,
|
||||
])
|
||||
->first();
|
||||
|
||||
// By shift
|
||||
ShiftEntry::factory(2)->create(['shift_id' => $shiftA->id, 'angel_type_id' => $byShift->angel_type_id]);
|
||||
|
||||
// By location
|
||||
ShiftEntry::factory(1)->create(['shift_id' => $shiftA->id, 'angel_type_id' => $byLocation->angel_type_id]);
|
||||
|
||||
// Additional (not required by shift nor location)
|
||||
ShiftEntry::factory(1)->create(['shift_id' => $shiftA->id]);
|
||||
|
||||
foreach (User::all() as $user) {
|
||||
// Generate user data
|
||||
/** @var User $user */
|
||||
PersonalData::factory()->create(['user_id' => $user->id]);
|
||||
Contact::factory()->create(['user_id' => $user->id]);
|
||||
}
|
||||
|
||||
$request = new Request();
|
||||
$request = $request->withAttribute('location_id', $location->id);
|
||||
$request = $request->withAttribute('location_id', $this->location->id);
|
||||
|
||||
$controller = new ShiftsController(new Response());
|
||||
|
||||
|
@ -102,15 +53,15 @@ class ShiftsControllerTest extends ApiBaseControllerTest
|
|||
|
||||
// First shift
|
||||
$shiftAData = $data['data'][0];
|
||||
$this->assertEquals($shiftA->title, $shiftAData['title'], 'Title is equal');
|
||||
$this->assertEquals($location->id, $shiftAData['location']['id'], 'Same location');
|
||||
$this->assertEquals($shiftA->shiftType->id, $shiftAData['shift_type']['id'], 'Shift type equals');
|
||||
$this->assertEquals($this->shiftA->title, $shiftAData['title'], 'Title is equal');
|
||||
$this->assertEquals($this->location->id, $shiftAData['location']['id'], 'Same location');
|
||||
$this->assertEquals($this->shiftA->shiftType->id, $shiftAData['shift_type']['id'], 'Shift type equals');
|
||||
$this->assertCount(4, $shiftAData['entries']);
|
||||
// Has users
|
||||
$entriesA = collect($shiftAData['entries'])->sortBy('type.id');
|
||||
$entry = $entriesA[0];
|
||||
$this->assertCount(2, $entry['users']);
|
||||
$this->assertEquals(5, $entry['needs']);
|
||||
$this->assertEquals(2, $entry['needs']);
|
||||
$user = $entry['users'][0];
|
||||
$this->assertEquals('/users?action=view&user_id=' . $user['id'], $user['url']);
|
||||
$this->assertCount(0, $entriesA[1]['users']);
|
||||
|
@ -119,12 +70,130 @@ class ShiftsControllerTest extends ApiBaseControllerTest
|
|||
|
||||
// Second (empty) shift
|
||||
$shiftBData = $data['data'][1];
|
||||
$this->assertEquals($shiftB->title, $shiftBData['title'], 'Title is equal');
|
||||
$this->assertEquals($location->id, $shiftBData['location']['id'], 'Same location');
|
||||
$this->assertEquals($shiftB->shiftType->id, $shiftBData['shift_type']['id'], 'Shift type equals');
|
||||
$this->assertEquals($this->shiftB->title, $shiftBData['title'], 'Title is equal');
|
||||
$this->assertEquals($this->location->id, $shiftBData['location']['id'], 'Same location');
|
||||
$this->assertEquals($this->shiftB->shiftType->id, $shiftBData['shift_type']['id'], 'Shift type equals');
|
||||
$this->assertCount(2, $shiftBData['entries']);
|
||||
// No users
|
||||
$entriesB = collect($shiftBData['entries'])->sortBy('type.id');
|
||||
$this->assertCount(0, $entriesB[0]['users']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Api\ShiftsController::entriesByAngeltype
|
||||
*/
|
||||
public function testEntriesByAngeltype(): void
|
||||
{
|
||||
/** @var ShiftEntry $firstEntry */
|
||||
$firstEntry = $this->shiftA->shiftEntries->first();
|
||||
|
||||
$request = new Request();
|
||||
$request = $request->withAttribute('angeltype_id', $firstEntry->angelType->id);
|
||||
|
||||
$controller = new ShiftsController(new Response());
|
||||
|
||||
$response = $controller->entriesByAngeltype($request);
|
||||
$this->validateApiResponse('/angeltypes/{id}/shifts', 'get', $response);
|
||||
|
||||
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
|
||||
$this->assertJson($response->getContent());
|
||||
|
||||
$data = json_decode($response->getContent(), true);
|
||||
$this->assertArrayHasKey('data', $data);
|
||||
$this->assertCount(2, $data['data']);
|
||||
|
||||
$shift = $data['data'][0];
|
||||
$this->assertTrue(count($shift['entries']) >= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Api\ShiftsController::entriesByUser
|
||||
*/
|
||||
public function testEntriesByUser(): void
|
||||
{
|
||||
/** @var ShiftEntry $firstEntry */
|
||||
$firstEntry = $this->shiftA->shiftEntries->first();
|
||||
|
||||
$request = new Request();
|
||||
$request = $request->withAttribute('user_id', $firstEntry->user->id);
|
||||
|
||||
$controller = new ShiftsController(new Response());
|
||||
|
||||
$response = $controller->entriesByUser($request);
|
||||
$this->validateApiResponse('/users/{id}/shifts', 'get', $response);
|
||||
|
||||
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
|
||||
$this->assertJson($response->getContent());
|
||||
|
||||
$data = json_decode($response->getContent(), true);
|
||||
$this->assertArrayHasKey('data', $data);
|
||||
$this->assertCount(1, $data['data']);
|
||||
|
||||
$shift = $data['data'][0];
|
||||
$this->assertTrue(count($shift['entries']) >= 1);
|
||||
}
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->location = Location::factory()->create();
|
||||
$schedule = Schedule::factory()->create();
|
||||
|
||||
// Shifts
|
||||
$this->shiftA = Shift::factory(1)
|
||||
->create(['location_id' => $this->location->id, 'start' => Carbon::now()->subHour()])
|
||||
->first();
|
||||
$this->shiftB = Shift::factory(1)
|
||||
->create(['location_id' => $this->location->id, 'start' => Carbon::now()->addHour()])
|
||||
->first();
|
||||
(new ScheduleShift(['shift_id' => $this->shiftB->id, 'schedule_id' => $schedule->id, 'guid' => 'a']))->save();
|
||||
|
||||
// "Empty" entry to be skipped
|
||||
NeededAngelType::factory(1)->create(['location_id' => null, 'shift_id' => $this->shiftA->id, 'count' => 0]);
|
||||
|
||||
// Needed entry by shift
|
||||
/** @var NeededAngelType $byShift */
|
||||
$byShift = NeededAngelType::factory(2)
|
||||
->create(['location_id' => null, 'shift_id' => $this->shiftA->id, 'count' => 2])
|
||||
->first();
|
||||
|
||||
// Needed entry by location
|
||||
/** @var NeededAngelType $byLocation */
|
||||
$byLocation = NeededAngelType::factory(1)
|
||||
->create(['location_id' => $this->location->id, 'shift_id' => null, 'count' => 3])
|
||||
->first();
|
||||
|
||||
// Added by both
|
||||
NeededAngelType::factory(1)
|
||||
->create([
|
||||
'location_id' => $this->location->id,
|
||||
'shift_id' => null,
|
||||
'angel_type_id' => $byShift->angel_type_id,
|
||||
'count' => 3,
|
||||
])
|
||||
->first();
|
||||
|
||||
// By shift
|
||||
ShiftEntry::factory(2)->create([
|
||||
'shift_id' => $this->shiftA->id,
|
||||
'angel_type_id' => $byShift->angel_type_id,
|
||||
]);
|
||||
|
||||
// By location
|
||||
ShiftEntry::factory(1)->create([
|
||||
'shift_id' => $this->shiftA->id,
|
||||
'angel_type_id' => $byLocation->angel_type_id,
|
||||
]);
|
||||
|
||||
// Additional (not required by shift nor location)
|
||||
ShiftEntry::factory(1)->create(['shift_id' => $this->shiftA->id]);
|
||||
|
||||
foreach (User::all() as $user) {
|
||||
// Generate user data
|
||||
/** @var User $user */
|
||||
PersonalData::factory()->create(['user_id' => $user->id]);
|
||||
Contact::factory()->create(['user_id' => $user->id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Engelsystem\Test\Unit\Controllers\Api;
|
||||
|
||||
use Engelsystem\Controllers\Api\UsersController;
|
||||
use Engelsystem\Helpers\Authenticator;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Models\User\Contact;
|
||||
use Engelsystem\Models\User\PersonalData;
|
||||
use Engelsystem\Models\User\Settings;
|
||||
use Engelsystem\Models\User\State;
|
||||
use Engelsystem\Models\User\User;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
class UsersControllerTest extends ApiBaseControllerTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\Api\UsersController::__construct
|
||||
* @covers \Engelsystem\Controllers\Api\UsersController::self
|
||||
* @covers \Engelsystem\Controllers\Api\Resources\UserDetailResource::toArray
|
||||
*/
|
||||
public function testSelf(): void
|
||||
{
|
||||
$user = User::factory()
|
||||
->has(Contact::factory())
|
||||
->has(PersonalData::factory())
|
||||
->has(Settings::factory())
|
||||
->has(State::factory())
|
||||
->create();
|
||||
|
||||
/** @var Authenticator|MockObject $auth */
|
||||
$auth = $this->createMock(Authenticator::class);
|
||||
$this->setExpects($auth, 'user', null, $user);
|
||||
|
||||
$controller = new UsersController(new Response(), $auth);
|
||||
|
||||
$response = $controller->self();
|
||||
$this->validateApiResponse('/users/self', 'get', $response);
|
||||
|
||||
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
|
||||
$this->assertJson($response->getContent());
|
||||
|
||||
$data = json_decode($response->getContent(), true);
|
||||
$this->assertArrayHasKey('data', $data);
|
||||
$this->assertArrayHasKey('id', $data['data']);
|
||||
$this->assertEquals($user->id, $data['data']['id']);
|
||||
$this->assertArrayHasKey('dates', $data['data']);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue