Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add and improve tests #25

Merged
merged 11 commits into from
May 8, 2024
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
1,658 changes: 800 additions & 858 deletions composer.lock

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/Exceptions/UnsupportedCurrency.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
namespace Pelmered\FilamentMoneyField\Exceptions;

class UnsupportedCurrency extends \RuntimeException
{
public function __construct(string $currencyCode)
{
parent::__construct('Currency not supported: ' . $currencyCode);
}
}
5 changes: 4 additions & 1 deletion src/FilamentMoneyFieldServiceProvider.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<?php
namespace Pelmered\FilamentMoneyField;

use Illuminate\Foundation\Application;
use Pelmered\FilamentMoneyField\Forms\Rules\MaxValueRule;
use Pelmered\FilamentMoneyField\Forms\Rules\MaxValueRule2;
use Spatie\LaravelPackageTools\Package;

class FilamentMoneyFieldServiceProvider extends \Spatie\LaravelPackageTools\PackageServiceProvider
Expand All @@ -13,7 +16,7 @@ public function configurePackage(Package $package): void
->hasConfigFile();
}

public function boot()
public function boot(): void
{
$this->publishes([
__DIR__ . '/../config/filament-money-field.php' => config_path('filament-money-field.php'),
Expand Down
48 changes: 8 additions & 40 deletions src/Forms/Components/MoneyInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
use Filament\Forms\Components\TextInput;
use Filament\Support\RawJs;
use Illuminate\Support\Facades\Config;
use Pelmered\FilamentMoneyField\Forms\Rules\MaxValueRule;
use Pelmered\FilamentMoneyField\Forms\Rules\MinValueRule;
use Pelmered\FilamentMoneyField\HasMoneyAttributes;
use Pelmered\FilamentMoneyField\MoneyFormatter;

class MoneyInput extends TextInput
{
use HasMoneyAttributes;


protected function setUp(): void
{
parent::setUp();
Expand Down Expand Up @@ -52,8 +55,7 @@ protected function prepare(): void
$symbolPlacement = Config::get('filament-money-field.form_currency_symbol_placement', 'before');

$getCurrencySymbol = function (MoneyInput $component) {
$formattingRules = MoneyFormatter::getFormattingRules($component->getLocale());
return $formattingRules->currencySymbol;
return MoneyFormatter::getFormattingRules($component->getLocale())->currencySymbol;
};

if ($symbolPlacement === 'before') {
Expand All @@ -70,49 +72,15 @@ protected function prepare(): void
}
}

public function minValue(mixed $min): static
public function minValue(mixed $value): static
{
$this->rule(static function (MoneyInput $component, mixed $state) use ($min) {
return function (string $attribute, mixed $value, \Closure $fail) use ($component, $state, $min) {

$currencyCode = $component->getCurrency();
$locale = $component->getLocale();

$minorValue = MoneyFormatter::parseDecimal(
$state,
$currencyCode,
$locale
);

if ($minorValue < $min) {
$fail('The :attribute must be greater than or equal to ' . MoneyFormatter::formatAsDecimal($min, $currencyCode, $locale) . '.');
}
};
});

$this->rule(new MinValueRule($value, $this));
return $this;
}

public function maxValue(mixed $max): static
public function maxValue(mixed $value): static
{
$this->rule(static function (MoneyInput $component) use ($max) {
return function (string $attribute, mixed $value, \Closure $fail) use ($component, $max) {

$currencyCode = $component->getCurrency();
$locale = $component->getLocale();

$minorValue = MoneyFormatter::parseDecimal(
$value,
$currencyCode,
$locale
);

if ($minorValue > $max) {
$fail('The :attribute must be less than or equal to ' . MoneyFormatter::formatAsDecimal($max, $currencyCode, $locale) . '.');
}
};
});

$this->rule(new MaxValueRule($value, $this));
return $this;
}
}
50 changes: 50 additions & 0 deletions src/Forms/Rules/MaxValueRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
namespace Pelmered\FilamentMoneyField\Forms\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Money\Exception\ParserException;
use Pelmered\FilamentMoneyField\Forms\Components\MoneyInput;
use Pelmered\FilamentMoneyField\MoneyFormatter;

class MaxValueRule implements ValidationRule
{
public function __construct(private int $max, private MoneyInput $component)
{}

public function validate(string $attribute, mixed $value, Closure $fail): void
{
$currencyCode = $this->component->getCurrency();
$locale = $this->component->getLocale();

try {
$minorValue = MoneyFormatter::parseDecimal(
$value,
$currencyCode,
$locale
);

if ($minorValue >= $this->max) {
$fail(
strtr(
'The {attribute} must be less than or equal to {value}.',
[
'{attribute}' => ucwords($this->component->getLabel()),
'{value}' => MoneyFormatter::formatAsDecimal($this->max, $currencyCode, $locale),
]
)
);
}
} catch (ParserException $parserException) {
$fail(
strtr(
'The {attribute} must be a valid numeric value.',
[
'{attribute}' => ucwords($this->component->getLabel()),
]
)
);
}

}
}
49 changes: 49 additions & 0 deletions src/Forms/Rules/MinValueRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
namespace Pelmered\FilamentMoneyField\Forms\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Money\Exception\ParserException;
use Pelmered\FilamentMoneyField\Forms\Components\MoneyInput;
use Pelmered\FilamentMoneyField\MoneyFormatter;

readonly class MinValueRule implements ValidationRule
{
public function __construct(private int $min, private MoneyInput $component)
{}

public function validate(string $attribute, mixed $value, Closure $fail): void
{
$currencyCode = $this->component->getCurrency();
$locale = $this->component->getLocale();

try {
$minorValue = MoneyFormatter::parseDecimal(
$value,
$currencyCode,
$locale
);

if ($minorValue <= $this->min) {
$fail(
strtr(
'The {attribute} must be at least {value}.',
[
'{attribute}' => ucwords($this->component->getLabel()),
'{value}' => MoneyFormatter::formatAsDecimal($this->min, $currencyCode, $locale),
]
)
);
}
} catch (ParserException $parserException) {
$fail(
strtr(
'The {attribute} must be a valid numeric value.',
[
'{attribute}' => ucwords($this->component->getLabel()),
]
)
);
}
}
}
7 changes: 4 additions & 3 deletions src/HasMoneyAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@
use Filament\Infolists\Infolist;
use Money\Currencies\ISOCurrencies;
use Money\Currency;
use Pelmered\FilamentMoneyField\Exceptions\UnsupportedCurrency;

trait HasMoneyAttributes
{
protected Currency $currency;
protected string $locale;
protected ?string $monetarySeparator = null;

protected function getCurrency(): Currency
public function getCurrency(): Currency
{
return $this->currency ?? $this->currency(config('filament-money-field.default_currency') ?? Infolist::$defaultCurrency)->getCurrency();
}

protected function getLocale(): string
public function getLocale(): string
{
return $this->locale ?? config('filament-money-field.default_locale');
}
Expand All @@ -28,7 +29,7 @@ public function currency(string|\Closure|null $currencyCode = null): static
$currencies = new ISOCurrencies();

if (!$currencies->contains($this->currency)) {
throw new \RuntimeException('Currency not supported: ' . $currencyCode);
throw new UnsupportedCurrency($currencyCode);
}

return $this;
Expand Down
2 changes: 1 addition & 1 deletion src/Infolists/Components/MoneyEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ protected function setUp(): void
$this->isMoney = true;
$this->numeric();

$this->formatStateUsing(function (MoneyEntry $component, $state): ?string {
$this->formatStateUsing(function (MoneyEntry $component, $state): string {
$currency = $component->getCurrency();
$locale = $component->getLocale();

Expand Down
9 changes: 8 additions & 1 deletion src/MoneyFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Pelmered\FilamentMoneyField;

use Money\Currencies\ISOCurrencies;
use Money\Exception\ParserException;
use Money\Formatter\IntlMoneyFormatter;
use Money\Parser\IntlLocalizedDecimalParser;
use Money\Money;
Expand Down Expand Up @@ -44,7 +45,11 @@ public static function parseDecimal($moneyString, Currency $currency, string $lo
$formattingRules = self::getFormattingRules($locale);
$moneyString = str_replace($formattingRules->groupingSeparator, '', $moneyString);

return $moneyParser->parse($moneyString, $currency)->getAmount();
try {
return $moneyParser->parse($moneyString, $currency)->getAmount();
} catch (ParserException $parserException) {
throw new ParserException('The value must be a valid numeric value.');
}
}

public static function getFormattingRules($locale): MoneyFormattingRules
Expand All @@ -60,10 +65,12 @@ public static function getFormattingRules($locale): MoneyFormattingRules
);
}

/*
public static function decimalToMoneyString($moneyString, $locale): string
{
return str_replace(',', '.', (string)$moneyString);
}
*/

private static function getNumberFormatter($locale, int $style): NumberFormatter
{
Expand Down
2 changes: 1 addition & 1 deletion src/Tables/Columns/MoneyColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ protected function setUp(): void
$this->isMoney = true;
$this->numeric();

$this->formatStateUsing(function (MoneyColumn $column, $state): ?string {
$this->formatStateUsing(function (MoneyColumn $column, $state): string {
$currency = $column->getCurrency();
$locale = $column->getLocale();

Expand Down
50 changes: 50 additions & 0 deletions tests/Components/FormTestComponent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
namespace Pelmered\FilamentMoneyField\Tests\Components;


use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Livewire\Component;
use Filament\Forms\Form;
use Pelmered\FilamentMoneyField\Forms\Components\MoneyInput;

class FormTestComponent extends Component implements HasForms
{
use InteractsWithForms;

public $data;
public $form;

public static function make(): static
{
return new static();
}


public function form(Form $form): Form
{
return $form
->schema([
MoneyInput::make('price')
->minValue(100)
->maxValue(1000)
]);
}

public function mount(): void
{
//$this->form->fill();
}

public function data($data): static
{
$this->data = $data;

return $this;
}

public function getData()
{
return $this->data;
}
}
43 changes: 43 additions & 0 deletions tests/Components/InfolistTestComponent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
namespace Pelmered\FilamentMoneyField\Tests\Components;


use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Infolists\Concerns\InteractsWithInfolists;
use Filament\Infolists\Contracts\HasInfolists;
use Filament\Infolists\Infolist;
use Livewire\Component;
use Filament\Forms\Form;
use Pelmered\FilamentMoneyField\Forms\Components\MoneyInput;
use Pelmered\FilamentMoneyField\Infolists\Components\MoneyEntry;

class InfolistTestComponent extends Component implements HasForms, HasInfolists
{
use InteractsWithForms;
use InteractsWithInfolists;

public static function make(): static
{
return new static();
}

public function infolist(Infolist $infolist): Infolist
{
return $infolist
->state([])
->schema([
MoneyEntry::make('amount')
->currency('SEK')
->locale('sv_SE')
->label('Amount'),
]);
}

/*
public function render(): View
{
return view('infolists.fixtures.actions');
}
*/
}
Loading