toBe($cents); })->with([ ['799', 79900], ['79,90', 7990], // German keyboard ['79.90', 7990], // copied from somewhere ['0', 0], ['0,05', 5], [' 149 ', 14900], ['79,9', 7990], // one decimal is still a price ['', null], ['neunzehn', null], ['1.000', null], // a thousand, or one euro? refuse rather than guess ['79,999', null], // no fractions of a cent ['-5', null], // Parses fine, then overflows the unsigned column — a typo must come back // as a message beside the field, not as a database error on submit. ['999999999', null], ['42949672,96', null], ['42949672,95', 4294967295], ]); it('does not lose a cent to binary floating point', function () { // (float) '79.90' * 100 is 7989.999… and casting truncates to 7989 — one // cent short, on exactly the prices people charge. foreach (['79,90', '19,90', '0,29', '1234,56'] as $typed) { expect(Money::toCents($typed))->toBe((int) round((float) str_replace(',', '.', $typed) * 100), $typed); } expect(Money::toCents('79,90'))->toBe(7990) ->and(Money::toCents('0,29'))->toBe(29); }); it('round-trips through the form', function () { foreach ([0, 5, 7990, 79900, 958800] as $cents) { expect(Money::toCents(Money::fromCents($cents)))->toBe($cents); } });