Add localization settings

This commit is contained in:
Constantin Graf
2025-04-13 16:26:31 +02:00
committed by Gregor Vostrak
parent 3c9160a08a
commit ae00fdb0e9
33 changed files with 1526 additions and 89 deletions

View File

@@ -110,7 +110,7 @@ class OrganizationEndpointTest extends ApiEndpointTestAbstract
$response->assertForbidden();
}
public function test_update_endpoint_updates_project(): void
public function test_update_endpoint_can_update_the_organization_name(): void
{
// Arrange
$data = $this->createUserWithPermission([
@@ -123,14 +123,55 @@ class OrganizationEndpointTest extends ApiEndpointTestAbstract
// Act
$response = $this->putJson(route('api.v1.organizations.update', [$data->organization->getKey()]), [
'name' => $organizationFake->name,
'billable_rate' => $organizationFake->billable_rate,
'billable_rate' => null,
]);
// Assert
$response->assertStatus(200);
$this->assertDatabaseHas(Organization::class, [
'name' => $organizationFake->name,
'billable_rate' => $organizationFake->billable_rate,
]);
}
public function test_update_endpoint_can_update_formats(): void
{
// Arrange
$data = $this->createUserWithPermission([
'organizations:update',
]);
$this->assertBillableRateServiceIsUnused();
$organizationFake = Organization::factory()->make();
Passport::actingAs($data->user);
// Act
$response = $this->putJson(route('api.v1.organizations.update', [$data->organization->getKey()]), [
'name' => $organizationFake->name,
'number_format' => $organizationFake->number_format->value,
'currency_format' => $organizationFake->currency_format->value,
'date_format' => $organizationFake->date_format->value,
'interval_format' => $organizationFake->interval_format->value,
'time_format' => $organizationFake->time_format->value,
]);
// Assert
$response->assertStatus(200);
$response->assertJson([
'data' => [
'id' => $data->organization->getKey(),
'number_format' => $organizationFake->number_format->value,
'currency_format' => $organizationFake->currency_format->value,
'date_format' => $organizationFake->date_format->value,
'interval_format' => $organizationFake->interval_format->value,
'time_format' => $organizationFake->time_format->value,
],
]);
$this->assertDatabaseHas(Organization::class, [
'name' => $organizationFake->name,
'number_format' => $organizationFake->number_format,
'currency_format' => $organizationFake->currency_format,
'date_format' => $organizationFake->date_format,
'interval_format' => $organizationFake->interval_format,
'time_format' => $organizationFake->time_format,
]);
}
@@ -146,14 +187,21 @@ class OrganizationEndpointTest extends ApiEndpointTestAbstract
// Act
$response = $this->putJson(route('api.v1.organizations.update', [$data->organization->getKey()]), [
'name' => $organizationFake->name,
'billable_rate' => $organizationFake->billable_rate,
]);
// Assert
$response->assertStatus(200);
$response->assertJson([
'data' => [
'id' => $data->organization->getKey(),
'name' => $data->organization->name,
'billable_rate' => $organizationFake->billable_rate,
],
]);
$this->assertDatabaseHas(Organization::class, [
'name' => $organizationFake->name,
'id' => $data->organization->getKey(),
'name' => $data->organization->name,
'billable_rate' => $organizationFake->billable_rate,
]);
}

View File

@@ -0,0 +1,97 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Service;
use App\Service\CurrencyService;
use Brick\Money\Currency;
use Brick\Money\Money;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
use Tests\TestCaseWithDatabase;
#[CoversClass(CurrencyService::class)]
#[UsesClass(CurrencyService::class)]
class CurrencyServiceTest extends TestCaseWithDatabase
{
private CurrencyService $currencyService;
protected function setUp(): void
{
parent::setUp();
$this->currencyService = new CurrencyService;
}
public function test_get_currency_symbol_for_currency_eur(): void
{
// Arrange
$money = Money::of(1, Currency::of('EUR'));
// Act
$symbol = $this->currencyService->getCurrencySymbolForMoney($money);
// Assert
$this->assertSame('€', $symbol);
}
public function test_get_currency_symbol_for_currency_usd(): void
{
// Arrange
$money = Money::of(1, Currency::of('USD'));
// Act
$symbol = $this->currencyService->getCurrencySymbolForMoney($money);
// Assert
$this->assertSame('$', $symbol);
}
public function test_get_currency_symbol_for_currency_gbp(): void
{
// Arrange
$money = Money::of(1, Currency::of('GBP'));
// Act
$symbol = $this->currencyService->getCurrencySymbolForMoney($money);
// Assert
$this->assertSame('£', $symbol);
}
public function test_get_currency_symbol_for_currency_cad(): void
{
// Arrange
$money = Money::of(1, Currency::of('CAD'));
// Act
$symbol = $this->currencyService->getCurrencySymbolForMoney($money);
// Assert
$this->assertSame('$', $symbol);
}
public function test_get_currency_symbol_for_currency_cop(): void
{
// Arrange
$money = Money::of(1, Currency::of('COP'));
// Act
$symbol = $this->currencyService->getCurrencySymbolForMoney($money);
// Assert
$this->assertSame('$', $symbol);
}
public function test_get_currency_symbol_for_currency_without_known_symbol(): void
{
// Arrange
$currency = 'XXX';
// Act
$symbol = $this->currencyService->getCurrencySymbol($currency);
// Assert
$this->assertSame('XXX', $symbol);
}
}

View File

@@ -0,0 +1,256 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Service;
use App\Enums\CurrencyFormat;
use App\Enums\DateFormat;
use App\Enums\IntervalFormat;
use App\Enums\NumberFormat;
use App\Enums\TimeFormat;
use App\Service\LocalizationService;
use Brick\Money\Currency;
use Brick\Money\Money;
use Carbon\CarbonInterval;
use Illuminate\Support\Carbon;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
use Tests\TestCaseWithDatabase;
#[CoversClass(LocalizationService::class)]
#[UsesClass(LocalizationService::class)]
class LocalizationServiceTest extends TestCaseWithDatabase
{
private LocalizationService $localizationService;
protected function setUp(): void
{
parent::setUp();
$this->localizationService = new LocalizationService(
CurrencyFormat::SymbolAfterWithSpace,
DateFormat::PointSeperatedDMYYYY,
TimeFormat::TwelveHours,
NumberFormat::ThousandsPointDecimalComma,
IntervalFormat::Decimal,
);
}
public function test_format_interval_with_type_decimal_and_number_format_thousands_comma_decimal_point(): void
{
// Arrange
$interval = CarbonInterval::seconds(4 + (60 * 3) + (60 * 60 * 30001));
$this->localizationService->setIntervalFormat(IntervalFormat::Decimal);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsCommaDecimalPoint);
// Act
$formatted = $this->localizationService->formatInterval($interval);
// Assert
$this->assertSame('30,001.05', $formatted);
}
public function test_format_interval_with_type_decimal_and_number_format_thousands_space_decimal_point(): void
{
// Arrange
$interval = CarbonInterval::seconds(4 + (60 * 3) + (60 * 60 * 30001));
$this->localizationService->setIntervalFormat(IntervalFormat::Decimal);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsSpaceDecimalPoint);
// Act
$formatted = $this->localizationService->formatInterval($interval);
// Assert
$this->assertSame('30 001.05', $formatted);
}
public function test_format_interval_with_type_decimal_and_number_format_thousands_point_decimal_comma(): void
{
// Arrange
$interval = CarbonInterval::seconds(4 + (60 * 3) + (60 * 60 * 30001));
$this->localizationService->setIntervalFormat(IntervalFormat::Decimal);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsPointDecimalComma);
// Act
$formatted = $this->localizationService->formatInterval($interval);
// Assert
$this->assertSame('30.001,05', $formatted);
}
public function test_format_interval_with_type_decimal_and_number_format_thousands_apostrophe_decimal_point(): void
{
// Arrange
$interval = CarbonInterval::seconds(4 + (60 * 3) + (60 * 60 * 30001));
$this->localizationService->setIntervalFormat(IntervalFormat::Decimal);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsApostropheDecimalPoint);
// Act
$formatted = $this->localizationService->formatInterval($interval);
// Assert
$this->assertSame('30\'001.05', $formatted);
}
public function test_format_interval_with_type_hours_minutes(): void
{
// Arrange
$interval = CarbonInterval::seconds(4 + (60 * 3) + (60 * 60 * 30001));
$this->localizationService->setIntervalFormat(IntervalFormat::HoursMinutes);
// Act
$formatted = $this->localizationService->formatInterval($interval);
// Assert
$this->assertSame('30001h 03m', $formatted);
}
public function test_format_interval_with_type_hours_minutes_colon_seperated(): void
{
// Arrange
$interval = CarbonInterval::seconds(4 + (60 * 3) + (60 * 60 * 30001));
$this->localizationService->setIntervalFormat(IntervalFormat::HoursMinutesColonSeperated);
// Act
$formatted = $this->localizationService->formatInterval($interval);
// Assert
$this->assertSame('30001:03', $formatted);
}
public function test_format_interval_with_type_hours_minutes_seconds_colon_seperated(): void
{
// Arrange
$interval = CarbonInterval::seconds(4 + (60 * 3) + (60 * 60 * 30001));
$this->localizationService->setIntervalFormat(IntervalFormat::HoursMinutesSecondsColonSeperated);
// Act
$formatted = $this->localizationService->formatInterval($interval);
// Assert
$this->assertSame('30001:03:04', $formatted);
}
public function test_format_currency_with_type_symbol_after_with_space_and_number_format_thousands_space_decimal_comma(): void
{
// Arrange
$this->localizationService->setCurrencyFormat(CurrencyFormat::SymbolAfterWithSpace);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsSpaceDecimalComma);
$money = Money::of(1234567.89, Currency::of('EUR'));
// Act
$formatted = $this->localizationService->formatCurrency($money);
// Assert
$this->assertSame('1 234 567,89 €', $formatted);
}
public function test_format_currency_with_type_symbol_before_with_space_and_number_format_thousands_space_decimal_comma(): void
{
// Arrange
$this->localizationService->setCurrencyFormat(CurrencyFormat::SymbolBeforeWithSpace);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsSpaceDecimalComma);
$money = Money::of(1234567.89, Currency::of('EUR'));
// Act
$formatted = $this->localizationService->formatCurrency($money);
// Assert
$this->assertSame('€ 1 234 567,89', $formatted);
}
public function test_format_currency_with_type_symbol_before_and_number_format_thousands_space_decimal_comma(): void
{
// Arrange
$this->localizationService->setCurrencyFormat(CurrencyFormat::SymbolBefore);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsSpaceDecimalComma);
$money = Money::of(1234567.89, Currency::of('EUR'));
// Act
$formatted = $this->localizationService->formatCurrency($money);
// Assert
$this->assertSame('€1 234 567,89', $formatted);
}
public function test_format_currency_with_type_symbol_after_and_number_format_thousands_space_decimal_comma(): void
{
// Arrange
$this->localizationService->setCurrencyFormat(CurrencyFormat::SymbolAfter);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsSpaceDecimalComma);
$money = Money::of(1234567.89, Currency::of('EUR'));
// Act
$formatted = $this->localizationService->formatCurrency($money);
// Assert
$this->assertSame('1 234 567,89€', $formatted);
}
public function test_format_currency_with_type_iso_code_after_with_space_and_number_format_thousands_space_decimal_comma(): void
{
// Arrange
$this->localizationService->setCurrencyFormat(CurrencyFormat::ISOCodeAfterWithSpace);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsSpaceDecimalComma);
$money = Money::of(1234567.89, Currency::of('EUR'));
// Act
$formatted = $this->localizationService->formatCurrency($money);
// Assert
$this->assertSame('1 234 567,89 EUR', $formatted);
}
public function test_format_currency_with_type_iso_code_before_with_space_and_number_format_thousands_space_decimal_comma(): void
{
// Arrange
$this->localizationService->setCurrencyFormat(CurrencyFormat::ISOCodeBeforeWithSpace);
$this->localizationService->setNumberFormat(NumberFormat::ThousandsSpaceDecimalComma);
$money = Money::of(1234567.89, Currency::of('EUR'));
// Act
$formatted = $this->localizationService->formatCurrency($money);
// Assert
$this->assertSame('EUR 1 234 567,89', $formatted);
}
public function test_format_date_with_type_slash_seperated_ddmmy(): void
{
// Arrange
$this->localizationService->setDateFormat(DateFormat::SlashSeperatedDDMMYYYY);
$date = Carbon::createFromDate(2001, 2, 3);
// Act
$formatted = $this->localizationService->formatDate($date);
// Assert
$this->assertSame('03/02/2001', $formatted);
}
public function test_format_time_with_type_twelve_hours(): void
{
// Arrange
$this->localizationService->setTimeFormat(TimeFormat::TwelveHours);
$time = Carbon::createFromTime(19, 9, 8);
// Act
$formatted = $this->localizationService->formatTime($time);
// Assert
$this->assertSame('07:09 pm', $formatted);
}
public function test_format_time_with_type_twenty_four_hours(): void
{
// Arrange
$this->localizationService->setTimeFormat(TimeFormat::TwentyFourHours);
$time = Carbon::createFromTime(14, 9, 8);
// Act
$formatted = $this->localizationService->formatTime($time);
// Assert
$this->assertSame('14:09', $formatted);
}
}