'US Dollar',
'code' => 'USD',
'symbol' => '$',
'precision' => 2,
'thousand_separator' => ',',
'decimal_separator' => '.',
'swap_currency_symbol' => false,
], $attributes));
}
function pdfSymbol(string $symbol = '$'): string
{
return ''.$symbol.'';
}
test('a positive amount keeps the symbol against the digits', function () {
expect(format_money_pdf(2473800, pdfCurrency()))
->toBe(pdfSymbol().'24,738.00');
});
test('a negative amount leads with the sign, ahead of the symbol', function () {
// The defect: this used to render "$-24,738.00".
expect(format_money_pdf(-2473800, pdfCurrency()))
->toBe('-'.pdfSymbol().'24,738.00');
});
test('a positive amount keeps the trailing symbol against the digits when swapped', function () {
expect(format_money_pdf(2473800, pdfCurrency(['swap_currency_symbol' => true])))
->toBe('24,738.00'.pdfSymbol());
});
test('a negative amount leads with the sign when the symbol trails', function () {
expect(format_money_pdf(-2473800, pdfCurrency(['swap_currency_symbol' => true])))
->toBe('-24,738.00'.pdfSymbol());
});
test('zero carries no sign', function (bool $swap) {
$currency = pdfCurrency(['swap_currency_symbol' => $swap]);
$expected = $swap ? '0.00'.pdfSymbol() : pdfSymbol().'0.00';
expect(format_money_pdf(0, $currency))->toBe($expected)
->and(format_money_pdf(-0, $currency))->toBe($expected)
->and(format_money_pdf(-0.0, $currency))->toBe($expected);
})->with([true, false]);
test('an amount that rounds away at the currency precision carries no sign', function (bool $swap) {
// Decided on the formatted digits, not on the raw value: a tenth of a cent
// is negative but prints as zero, and "-$0.00" is not a number anyone owes.
$currency = pdfCurrency(['swap_currency_symbol' => $swap]);
$expected = $swap ? '0.00'.pdfSymbol() : pdfSymbol().'0.00';
expect(format_money_pdf(-0.4, $currency))->toBe($expected);
})->with([true, false]);
test('a zero-precision currency drops the decimals and still signs correctly', function () {
$yen = pdfCurrency([
'name' => 'Japanese Yen',
'code' => 'JPY',
'symbol' => '¥',
'precision' => 0,
]);
expect(format_money_pdf(2473800, $yen))->toBe(pdfSymbol('¥').'24,738')
->and(format_money_pdf(-2473800, $yen))->toBe('-'.pdfSymbol('¥').'24,738')
// A single cent is below this currency's precision, so it is not a
// negative amount once formatted.
->and(format_money_pdf(-1, $yen))->toBe(pdfSymbol('¥').'0');
});
test('a comma decimal separator is unaffected by the sign', function () {
$euro = pdfCurrency([
'name' => 'Euro',
'code' => 'EUR',
'symbol' => '€',
'thousand_separator' => '.',
'decimal_separator' => ',',
'swap_currency_symbol' => true,
]);
expect(format_money_pdf(2473800, $euro))->toBe('24.738,00'.pdfSymbol('€'))
->and(format_money_pdf(-2473800, $euro))->toBe('-24.738,00'.pdfSymbol('€'))
->and(format_money_pdf(-40, $euro))->toBe('-0,40'.pdfSymbol('€'))
->and(format_money_pdf(0, $euro))->toBe('0,00'.pdfSymbol('€'));
});
test('the same input types the templates pass are still accepted', function () {
$currency = pdfCurrency();
expect(format_money_pdf(null, $currency))->toBe(pdfSymbol().'0.00')
->and(format_money_pdf('-2473800', $currency))->toBe('-'.pdfSymbol().'24,738.00')
->and(format_money_pdf(-2473800.0, $currency))->toBe('-'.pdfSymbol().'24,738.00')
->and(format_money_pdf(-2473850.5, $currency))->toBe('-'.pdfSymbol().'24,738.51');
});
test('the symbol keeps its DejaVu Sans span so it renders in any font', function () {
expect(format_money_pdf(-2473800, pdfCurrency()))
->toContain('$')
// The sign sits outside the span, in the document font.
->toStartWith('-