129 lines
4.8 KiB
PHP
129 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Saas;
|
|
|
|
use App\Saas\Model\EmployeeDirectory;
|
|
use App\Saas\ResponseParser;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class EmployeeDirectoryTest extends TestCase
|
|
{
|
|
/**
|
|
* The point of the projection: the roster answers with a per-employee api key next to a
|
|
* birthday, a personnel number and an RFID token, and the result of this is cached to the
|
|
* filesystem. None of it may get that far.
|
|
*/
|
|
public function testTheProjectionKeepsNoCredentialsOrPersonalData(): void
|
|
{
|
|
$directory = (new ResponseParser())->parseEmployees($this->roster());
|
|
$serialised = json_encode($directory->toCacheable(), JSON_THROW_ON_ERROR);
|
|
|
|
$this->assertStringNotContainsString('s3cr3t', $serialised, 'The api key must not survive.');
|
|
$this->assertStringNotContainsString('apiKey', $serialised);
|
|
$this->assertStringNotContainsString('1990', $serialised, 'The birthday must not survive.');
|
|
$this->assertStringNotContainsString('RFID', $serialised);
|
|
$this->assertStringNotContainsString('personnelNumber', $serialised);
|
|
}
|
|
|
|
public function testItReadsTheFieldsWeActuallyUse(): void
|
|
{
|
|
$directory = (new ResponseParser())->parseEmployees($this->roster());
|
|
$theo = $directory->find('[email protected]');
|
|
|
|
$this->assertNotNull($theo);
|
|
$this->assertSame('Operations', $theo->getDepartment());
|
|
$this->assertSame('aaaaaaaa-894a-4e63-9c8d-5777e6afdc91', $theo->getUuid());
|
|
$this->assertFalse($theo->hasLeft());
|
|
}
|
|
|
|
public function testADateOfSeparationMarksSomeoneAsGone(): void
|
|
{
|
|
$directory = (new ResponseParser())->parseEmployees($this->roster());
|
|
|
|
$this->assertTrue($directory->find('[email protected]')->hasLeft());
|
|
}
|
|
|
|
/**
|
|
* Both systems have the address typed in by hand, so the one place they have to agree on
|
|
* it cannot be case-sensitive.
|
|
*/
|
|
public function testLookupIgnoresCaseAndSurroundingSpace(): void
|
|
{
|
|
$directory = (new ResponseParser())->parseEmployees($this->roster());
|
|
|
|
$this->assertTrue($directory->has('[email protected]'));
|
|
$this->assertTrue($directory->has(' [email protected] '));
|
|
$this->assertFalse($directory->has('[email protected]'));
|
|
$this->assertFalse($directory->has(null));
|
|
}
|
|
|
|
public function testAnEntryWithoutAnAddressIsDropped(): void
|
|
{
|
|
$directory = (new ResponseParser())->parseEmployees([
|
|
['mainDepartment' => 'Operations', 'email' => ''],
|
|
['mainDepartment' => 'Operations'],
|
|
'not an entry',
|
|
]);
|
|
|
|
$this->assertTrue($directory->isEmpty());
|
|
}
|
|
|
|
public function testItSurvivesTheCacheRoundTrip(): void
|
|
{
|
|
$directory = (new ResponseParser())->parseEmployees($this->roster());
|
|
$restored = EmployeeDirectory::fromCacheable($directory->toCacheable());
|
|
|
|
$this->assertSame($directory->count(), $restored->count());
|
|
$this->assertSame('Operations', $restored->find('[email protected]')->getDepartment());
|
|
$this->assertTrue($restored->find('[email protected]')->hasLeft());
|
|
}
|
|
|
|
/**
|
|
* An unreachable roster produces an empty one, and the importer reads that as "no roster"
|
|
* rather than "nobody is registered".
|
|
*/
|
|
public function testAnEmptyDirectoryIsRecognisable(): void
|
|
{
|
|
$this->assertTrue(EmployeeDirectory::fromEmployees([])->isEmpty());
|
|
}
|
|
|
|
private function roster(): array
|
|
{
|
|
return [
|
|
[
|
|
'personnelNumber' => '4711',
|
|
'mainDepartment' => 'Standard-Abteilung',
|
|
'email' => '[email protected]',
|
|
'givenName' => 'Admin',
|
|
'lastName' => 'Hausmanagement',
|
|
'birthday' => '1990-05-01',
|
|
'joinDate' => '2021-00-01',
|
|
'dateOfSeparation' => null,
|
|
'RFID' => 'abc',
|
|
'uuid' => 'bbbbbbbb-0000-0000-0000-000000000000',
|
|
'apiKey' => 's3cr3t-admin',
|
|
],
|
|
[
|
|
'personnelNumber' => '',
|
|
'mainDepartment' => 'Operations',
|
|
'email' => '[email protected]',
|
|
'givenName' => 'Theo',
|
|
'lastName' => 'Test',
|
|
'birthday' => null,
|
|
'joinDate' => '2021-10-22',
|
|
'dateOfSeparation' => null,
|
|
'RFID' => '',
|
|
'uuid' => 'aaaaaaaa-894a-4e63-9c8d-5777e6afdc91',
|
|
'apiKey' => 's3cr3t-theo',
|
|
],
|
|
[
|
|
'mainDepartment' => 'Operations',
|
|
'email' => '[email protected]',
|
|
'dateOfSeparation' => '2025-05-31',
|
|
'uuid' => 'cccccccc-0000-0000-0000-000000000000',
|
|
'apiKey' => 's3cr3t-ex',
|
|
],
|
|
];
|
|
}
|
|
}
|