Skip to content

Commit 9e8a042

Browse files
committed
Refactor integer validation to enforce strict integer parsing and enhance exception handling
- Replaced `integerish` with strict `integer` validation in `Assert` to prevent unexpected conversions. - Updated integer type tests (`PositiveInt`, `NonNegativeInt`, `WeekDayInt`, `IntegerBasic`) to verify exceptions for non-strict integer strings. - Refined `IntType` to use strict checks and improved error messaging. - Removed redundant examples from `psalmTest.php` and adjusted invalid input scenarios. - Enhanced documentation and inline comments for clarity.
1 parent 44c73d1 commit 9e8a042

File tree

9 files changed

+27
-33
lines changed

9 files changed

+27
-33
lines changed

src/Code/Assert/Assert.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpTypedValues\Code\Exception\StringTypeException;
99

1010
use function is_numeric;
11+
use function sprintf;
1112

1213
final class Assert
1314
{
@@ -32,16 +33,19 @@ public static function lessThanEq(int|float $value, int|float $max, string $mess
3233
}
3334

3435
/**
35-
* Assert that the given value looks like an integer ("integerish").
36-
* Accepts numeric strings that represent an integer value (e.g., '5', '5.0'),
37-
* but rejects non-numeric strings and floats with a fractional part (e.g., '5.5').
36+
* Assert that the given value looks like an integer.
37+
* Accepts numeric strings that represent an integer value (e.g., '5', '-5'),
38+
* but rejects non-numeric strings and floats with a fractional part (e.g., '5.5', '05').
3839
*
3940
* @throws NumericTypeException
4041
*/
41-
public static function integerish(mixed $value, string $message = ''): void
42+
public static function integer(mixed $value, string $message = ''): void
4243
{
43-
if (!is_numeric($value) || $value != (int) $value) {
44-
throw new NumericTypeException($message !== '' ? $message : 'Expected an "integerish" value');
44+
// Strict check, avoid unexpected string conversion
45+
$value = (string) $value;
46+
$convertedValue = (string) ((int) $value);
47+
if ($value !== $convertedValue) {
48+
throw new NumericTypeException($message !== '' ? $message : sprintf('Unexpected conversions possible, "%s" !== "%s"', $value, $convertedValue));
4549
}
4650
}
4751

src/Code/Integer/IntType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818
protected static function assertNumericString(string $value): void
1919
{
20-
Assert::integerish($value, 'String has no valid integer');
20+
Assert::integer($value, 'String has no valid integer');
2121
}
2222

2323
public function toString(): string

src/psalmTest.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,6 @@
5555
$dt = DateTimeAtom::fromString('2025-01-02T03:04:05+00:00')->value();
5656
echo DateTimeAtom::fromDateTime($dt)->toString() . \PHP_EOL;
5757

58-
try {
59-
$dt = DateTimeAtom::fromString('2025-12-02T03:04:05+ 00:00')->value();
60-
echo DateTimeAtom::fromDateTime($dt)->toString() . \PHP_EOL;
61-
} catch (Throwable $e) {
62-
var_export($e);
63-
}
64-
6558
/**
6659
* Artificial functions.
6760
*/

tests/Unit/Code/Assert/AssertTest.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,20 @@
3838
expect(true)->toBeTrue();
3939
});
4040

41-
it('integerish throws with default message when empty', function (): void {
42-
expect(fn() => Assert::integerish('5.5', ''))
43-
->toThrow(NumericTypeException::class, 'Expected an "integerish" value');
41+
it('integer throws with default message when empty', function (): void {
42+
expect(fn() => Assert::integer('5.5', ''))
43+
->toThrow(NumericTypeException::class, 'Unexpected conversions possible, "5.5" !== "5"');
4444
});
4545

4646
it('integerish throws with custom message when provided', function (): void {
47-
expect(fn() => Assert::integerish('foo', 'custom integerish message'))
47+
expect(fn() => Assert::integer('foo', 'custom integerish message'))
4848
->toThrow(NumericTypeException::class, 'custom integerish message');
4949
});
5050

51-
it('integerish does not throw for integerish values', function (): void {
52-
Assert::integerish('5', '');
53-
Assert::integerish('5.0', '');
54-
Assert::integerish(5, '');
51+
it('integer does not throw for integer values', function (): void {
52+
Assert::integer('5', '');
53+
Assert::integer('-5', '');
54+
Assert::integer(5, '');
5555
expect(true)->toBeTrue();
5656
});
5757

tests/Unit/Code/Integer/IntTypeTest.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,12 @@
1717

1818
it('fromString parses valid integer strings including negatives and leading zeros', function (): void {
1919
expect(IntegerBasic::fromString('-15')->value())->toBe(-15)
20-
->and(IntegerBasic::fromString('0007')->value())->toBe(7)
21-
->and(IntegerBasic::fromString('+5')->value())->toBe(5)
22-
->and(IntegerBasic::fromString(' 5')->value())->toBe(5)
23-
->and(IntegerBasic::fromString('5 ')->value())->toBe(5)
20+
->and(IntegerBasic::fromString('0')->toString())->toBe('0')
2421
->and(IntegerBasic::fromString('42')->toString())->toBe('42');
2522
});
2623

2724
it('fromString rejects non-integer strings', function (): void {
28-
$invalid = ['5a', 'a5', '', 'abc', '--5', '3.14'];
25+
$invalid = ['5a', 'a5', '', 'abc', ' 5', '5 ', '+5', '05', '--5', '3.14'];
2926
foreach ($invalid as $str) {
3027
expect(fn() => IntegerBasic::fromString($str))->toThrow(NumericTypeException::class);
3128
}

tests/Unit/Integer/IntegerTypeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
});
1515

1616
it('fails on "integer-ish" float string', function (): void {
17-
expect(IntegerBasic::fromString('5.0')->value())->toBe(5);
17+
expect(fn() => IntegerBasic::fromString('5.'))->toThrow(NumericTypeException::class);
1818
});
1919

2020
it('fails on float string', function (): void {

tests/Unit/Integer/NonNegativeIntTypeTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
expect(NonNegativeInt::fromString('0')->value())->toBe(0);
1818
});
1919

20-
it('creates NonNegativeInt from integerish string', function (): void {
21-
expect(NonNegativeInt::fromString('5.0')->value())->toBe(5);
20+
it('fails NonNegativeInt from integerish string', function (): void {
21+
expect(fn() => NonNegativeInt::fromString('5.0'))->toThrow(NumericTypeException::class);
2222
});
2323

2424
it('fails creating NonNegativeInt from negative string', function (): void {

tests/Unit/Integer/PositiveIntTypeTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
expect(PositiveInt::fromString('1')->value())->toBe(1);
2222
});
2323

24-
it('creates PositiveInt from integerish string', function (): void {
25-
expect(PositiveInt::fromString('5.0')->value())->toBe(5);
24+
it('fails PositiveInt from integerish string', function (): void {
25+
expect(fn() => PositiveInt::fromString('5.0'))->toThrow(NumericTypeException::class);
2626
});
2727

2828
it('fails creating PositiveInt from string 0', function (): void {

tests/Unit/Integer/WeekDayIntTypeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
});
2828

2929
it('creates WeekDayInt from integerish string', function (): void {
30-
expect(WeekDayInt::fromString('5.0')->value())->toBe(5);
30+
expect(fn() => WeekDayInt::fromString('5.0'))->toThrow(NumericTypeException::class);
3131
});
3232

3333
it('fails creating WeekDayInt from out-of-range strings', function (): void {

0 commit comments

Comments
 (0)