Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions backend/phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,33 @@ parameters:
identifier: argument.type
count: 1
path: public/index.php
-
message: '#^Method App\\Normalizer\\Normalizer\:\:toArray\(\) should return array\<string, mixed\> but returns array\|ArrayObject\|bool\|float\|int\|string\|null\.$#'
identifier: return.type
count: 1
path: src/Normalizer/Normalizer.php

-
message: '#^Property App\\Entity\\User\:\:\$id \(int\|null\) is never assigned int so it can be removed from the property type\.$#'
identifier: property.unusedType
count: 1
path: src/Entity/User.php

-
message: '#^Cannot call method getLogging\(\) on App\\Instrumentation\\Instrumentation\|null\.$#'
identifier: method.nonObject
count: 1
path: src/Instrumentation/InstrumentationHolder.php

-
message: '#^Cannot call method getMetrics\(\) on App\\Instrumentation\\Instrumentation\|null\.$#'
identifier: method.nonObject
count: 1
path: src/Instrumentation/InstrumentationHolder.php

-
message: '#^Cannot call method getTracing\(\) on App\\Instrumentation\\Instrumentation\|null\.$#'
identifier: method.nonObject
count: 1
path: src/Instrumentation/InstrumentationHolder.php

-
message: '#^Method App\\Normalizer\\Normalizer\:\:toArray\(\) should return array\<string, mixed\> but returns array\|ArrayObject\|bool\|float\|int\|string\|null\.$#'
identifier: return.type
count: 1
path: src/Normalizer/Normalizer.php
9 changes: 5 additions & 4 deletions backend/src/Instrumentation/InstrumentationHolder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace App\Instrumentation;

use App\Invariant\Ensure;
use Psr\Log\LoggerInterface;

final class InstrumentationHolder
Expand All @@ -12,7 +13,7 @@ final class InstrumentationHolder

public static function initialize(string $telemetry, LoggerInterface $logger): void
{
assert(in_array($telemetry, ['PsrLog', 'Null'], strict: true), 'Either "PsrLog" or "Null" is allowed for parameter $telemetry!');
Ensure::that(in_array($telemetry, ['PsrLog', 'Null'], strict: true), 'Either "PsrLog" or "Null" is allowed for parameter $telemetry!');

if (is_null(self::$instance)) {
self::$instance = new Instrumentation($telemetry, $logger);
Expand All @@ -21,21 +22,21 @@ public static function initialize(string $telemetry, LoggerInterface $logger): v

public static function getLogging(): LoggingInterface
{
assert(!is_null(self::$instance), 'Not yet initialized!');
Ensure::that(!is_null(self::$instance), 'Not yet initialized!');

return self::$instance->getLogging();
}

public static function getMetrics(): MetricsInterface
{
assert(!is_null(self::$instance), 'Not yet initialized!');
Ensure::that(!is_null(self::$instance), 'Not yet initialized!');

return self::$instance->getMetrics();
}

public static function getTracing(): TracingInterface
{
assert(!is_null(self::$instance), 'Not yet initialized!');
Ensure::that(!is_null(self::$instance), 'Not yet initialized!');

return self::$instance->getTracing();
}
Expand Down
5 changes: 3 additions & 2 deletions backend/tests/Unit/Instrumentation/InstrumentationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Instrumentation\LoggingInterface;
use App\Instrumentation\MetricsInterface;
use App\Instrumentation\TracingInterface;
use App\Invariant\InvariantException;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;

Expand Down Expand Up @@ -79,15 +80,15 @@ public function test_provider_provides_tracing_interface(): void

public function test_provider_throws_on_uninitialized_access_logging(): void
{
$this->expectException(\AssertionError::class);
$this->expectException(InvariantException::class);
$this->expectExceptionMessage('Not yet initialized!');

InstrumentationHolder::getLogging();
}

public function test_provider_throws_on_invalid_telemetry_option(): void
{
$this->expectException(\AssertionError::class);
$this->expectException(InvariantException::class);
$this->expectExceptionMessage('Either "PsrLog" or "Null" is allowed');

InstrumentationHolder::initialize('InvalidOption', new NullLogger());
Expand Down
4 changes: 4 additions & 0 deletions backend/tests/Unit/SplitFairly/CompensationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public function test_compensation_when_first_user_spent_more(): void
// User1 spent 50, so owes 25. User2 spent 25, so owes 12.5. Difference: 25 - 12.5 = 12.5
self::assertSame(12.5, $compensation->settlement->value);
self::assertSame('EUR', $compensation->settlement->currency);
self::assertSame(
sprintf('From: "%s" - to: "%s" - price: "%s"', $compensation->from, $compensation->to, (string) $compensation->settlement),
(string) $compensation
);
}

public function test_compensation_when_second_user_spent_more(): void
Expand Down
51 changes: 51 additions & 0 deletions backend/tests/Unit/SplitFairly/EventTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace App\Tests\Unit\SplitFairly;

use App\SplitFairly\Event;
use PHPUnit\Framework\TestCase;

final class EventTest extends TestCase
{
public function test_constructor_sets_properties(): void
{
$createdBy = 'user-1';
$subjectType = 'Expense';
$subjectId = 'exp-1';
$eventType = 'tracked';
$payload = ['price' => 10.0, 'currency' => 'EUR'];
$createdAt = new \DateTimeImmutable('2026-02-12T07:00:00Z');

$event = new Event(
createdBy: $createdBy,
subjectType: $subjectType,
subjectId: $subjectId,
eventType: $eventType,
payload: $payload,
createdAt: $createdAt
);

self::assertSame($createdBy, $event->createdBy);
self::assertSame($subjectType, $event->subjectType);
self::assertSame($subjectId, $event->subjectId);
self::assertSame($eventType, $event->eventType);
self::assertSame($payload, $event->payload);
self::assertSame($createdAt, $event->createdAt);
}

public function test_get_value_returns_payload_value(): void
{
$event = new Event(
createdBy: 'user-1',
subjectType: 'Expense',
subjectId: 'exp-1',
eventType: 'tracked',
payload: ['price' => 10.0, 'currency' => 'EUR'],
);

self::assertSame(10.0, $event->getValue('price'));
self::assertSame('EUR', $event->getValue('currency'));
}
}
43 changes: 43 additions & 0 deletions backend/tests/Unit/SplitFairly/QueryOptionsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace App\Tests\Unit\SplitFairly;

use App\SplitFairly\QueryOptions;
use PHPUnit\Framework\TestCase;

final class QueryOptionsTest extends TestCase
{
public function test_constructor_sets_properties(): void
{
$createdBy = ['user-1', 'user-2'];
$subjectTypes = ['Expense'];
$subjectIds = ['exp-1', 'exp-2'];
$eventTypes = ['tracked'];

$options = new QueryOptions(
createdBy: $createdBy,
subjectTypes: $subjectTypes,
subjectIds: $subjectIds,
eventTypes: $eventTypes
);

self::assertSame($createdBy, $options->createdBy);
self::assertSame($subjectTypes, $options->subjectTypes);
self::assertSame($subjectIds, $options->subjectIds);
self::assertSame($eventTypes, $options->eventTypes);
}

public function test_is_empty_returns_true_for_empty(): void
{
$options = new QueryOptions();
self::assertTrue($options->isEmpty());
}

public function test_is_empty_returns_false_for_non_empty(): void
{
$options = new QueryOptions(createdBy: ['user-1']);
self::assertFalse($options->isEmpty());
}
}