Add toPhpOption; convert both to mostly non-static
This commit is contained in:
@@ -8,7 +8,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Test;
|
||||
|
||||
use BitBadger\InspiredByFSharp\Option;
|
||||
use BitBadger\InspiredByFSharp\Result;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\Attributes\TestDox;
|
||||
@@ -47,11 +46,156 @@ class ResultTest extends TestCase
|
||||
Result::OK('yeah')->getError();
|
||||
}
|
||||
|
||||
#[TestDox('IsOK succeeds for OK result')]
|
||||
public function testIsOKSucceedsForOKResult(): void
|
||||
{
|
||||
$result = Result::OK('ok');
|
||||
$this->assertTrue($result->isOK(), 'The check for "OK" should have returned true');
|
||||
}
|
||||
|
||||
#[TestDox('IsOK succeeds for Error result')]
|
||||
public function testIsOKSucceedsForErrorResult(): void
|
||||
{
|
||||
$result = Result::Error('error');
|
||||
$this->assertFalse($result->isOK(), 'The check for "OK" should have returned false');
|
||||
}
|
||||
|
||||
#[TestDox('IsError succeeds for Error result')]
|
||||
public function testIsErrorSucceedsForErrorResult(): void
|
||||
{
|
||||
$result = Result::Error('not ok');
|
||||
$this->assertTrue($result->isError(), 'The check for "Error" should have returned true');
|
||||
}
|
||||
|
||||
#[TestDox('IsError succeeds for OK result')]
|
||||
public function testIsErrorSucceedsForOKResult(): void
|
||||
{
|
||||
$result = Result::OK('fine');
|
||||
$this->assertFalse($result->isError(), 'The check for "Error" should have returned false');
|
||||
}
|
||||
|
||||
#[TestDox('Map succeeds for OK result')]
|
||||
public function testMapSucceedsForOKResult(): void
|
||||
{
|
||||
$ok = Result::OK('yard');
|
||||
$mapped = $ok->map(fn($it) => strrev($it));
|
||||
$this->assertTrue($mapped->isOK(), 'The mapped result should be "OK"');
|
||||
$this->assertEquals('dray', $mapped->getOK(), 'The mapping function was not called correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Map fails for OK result when mapping is null')]
|
||||
public function testMapFailsForOKResultWhenMappingIsNull(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
Result::OK('not null')->map(fn($it) => null);
|
||||
}
|
||||
|
||||
#[TestDox('Map succeeds for Error result')]
|
||||
public function testMapSucceedsForErrorResult(): void
|
||||
{
|
||||
$tattle = new class { public bool $called = false; };
|
||||
$error = Result::Error('nope');
|
||||
$mapped = $error->map(function () use ($tattle)
|
||||
{
|
||||
$tattle->called = true;
|
||||
return 'hello';
|
||||
});
|
||||
$this->assertTrue($mapped->isError(), 'The mapped result should be "Error"');
|
||||
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
||||
$this->assertSame($error, $mapped, 'The same "Error" instance should have been returned');
|
||||
}
|
||||
|
||||
#[TestDox('MapError succeeds for OK result')]
|
||||
public function testMapErrorSucceedsForOKResult(): void
|
||||
{
|
||||
$tattle = new class { public bool $called = false; };
|
||||
$ok = Result::OK('sure');
|
||||
$mapped = $ok->mapError(function () use ($tattle)
|
||||
{
|
||||
$tattle->called = true;
|
||||
return 'hello';
|
||||
});
|
||||
$this->assertTrue($mapped->isOK(), 'The mapped result should be "OK"');
|
||||
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
||||
$this->assertSame($ok, $mapped, 'The same "OK" instance should have been returned');
|
||||
}
|
||||
|
||||
#[TestDox('MapError succeeds for Error result')]
|
||||
public function testMapErrorSucceedsForErrorResult(): void
|
||||
{
|
||||
$error = Result::Error('taco');
|
||||
$mapped = $error->mapError(fn($it) => str_repeat('*', strlen($it)));
|
||||
$this->assertTrue($mapped->isError(), 'The mapped result should be "Error"');
|
||||
$this->assertEquals('****', $mapped->getError(), 'The mapping function was not called correctly');
|
||||
}
|
||||
|
||||
#[TestDox('MapError fails for Error result when mapping is null')]
|
||||
public function testMapErrorFailsForErrorResultWhenMappingIsNull(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
Result::Error('pizza')->mapError(fn($it) => null);
|
||||
}
|
||||
|
||||
#[TestDox('Iter succeeds for OK result')]
|
||||
public function testIterSucceedsForOKResult(): void
|
||||
{
|
||||
$target = new class { public mixed $called = null; };
|
||||
Result::OK(77)->iter(function ($it) use ($target) { $target->called = $it; });
|
||||
$this->assertEquals(77, $target->called, 'The function should have been called with the "OK" value');
|
||||
}
|
||||
|
||||
#[TestDox('Iter succeeds for Error result')]
|
||||
public function testIterSucceedsForErrorResult(): void
|
||||
{
|
||||
$target = new class { public mixed $called = null; };
|
||||
Result::Error('')->iter(function () use ($target) { $target->called = 'uh oh'; });
|
||||
$this->assertNull($target->called, 'The function should not have been called');
|
||||
}
|
||||
|
||||
#[TestDox('ToOption succeeds for OK result')]
|
||||
public function testToOptionSucceedsForOKResult()
|
||||
{
|
||||
$value = Result::OK(99)->toOption();
|
||||
$this->assertTrue($value->isSome(), 'An "OK" result should map to a "Some" option');
|
||||
$this->assertEquals(99, $value->get(), 'The value is not correct');
|
||||
}
|
||||
|
||||
#[TestDox('ToOption succeeds for Error result')]
|
||||
public function testToOptionSucceedsForErrorResult()
|
||||
{
|
||||
$value = Result::Error('file not found')->toOption();
|
||||
$this->assertTrue($value->isNone(), 'An "Error" result should map to a "None" option');
|
||||
}
|
||||
|
||||
#[TestDox('Tap succeeds for OK result')]
|
||||
public function testTapSucceedsForOKResult(): void
|
||||
{
|
||||
$value = '';
|
||||
$original = Result::OK('working');
|
||||
$tapped = $original->tap(function (Result $it) use (&$value) {
|
||||
$value = $it->isOK() ? 'OK: ' . $it->getOK() : 'Error: ' . $it->getError();
|
||||
});
|
||||
$this->assertEquals('OK: working', $value, 'The tapped function was not called');
|
||||
$this->assertSame($original, $tapped, 'The same result should have been returned');
|
||||
}
|
||||
|
||||
#[TestDox('Tap succeeds for Error result')]
|
||||
public function testTapSucceedsForErrorResult(): void
|
||||
{
|
||||
$value = '';
|
||||
$original = Result::Error('failed');
|
||||
$tapped = $original->tap(function (Result $it) use (&$value) {
|
||||
$value = $it->isOK() ? 'OK: ' . $it->getOK() : 'Error: ' . $it->getError();
|
||||
});
|
||||
$this->assertEquals('Error: failed', $value, 'The tapped function was not called');
|
||||
$this->assertSame($original, $tapped, 'The same result should have been returned');
|
||||
}
|
||||
|
||||
#[TestDox('OK succeeds for non null result')]
|
||||
public function testOKSucceedsForNonNullResult(): void
|
||||
{
|
||||
$result = Result::OK('something');
|
||||
$this->assertTrue(Result::isOK($result), 'The result should have been "OK"');
|
||||
$this->assertTrue($result->isOK(), 'The result should have been "OK"');
|
||||
$this->assertEquals('something', $result->getOK(), 'The "OK" value was incorrect');
|
||||
}
|
||||
|
||||
@@ -66,7 +210,7 @@ class ResultTest extends TestCase
|
||||
public function testErrorSucceedsForNonNullResult(): void
|
||||
{
|
||||
$result = Result::Error('sad trombone');
|
||||
$this->assertTrue(Result::isError($result), 'The result should have been "Error"');
|
||||
$this->assertTrue($result->isError(), 'The result should have been "Error"');
|
||||
$this->assertEquals('sad trombone', $result->getError(), 'The "Error" value was incorrect');
|
||||
}
|
||||
|
||||
@@ -76,149 +220,4 @@ class ResultTest extends TestCase
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
Result::Error(null);
|
||||
}
|
||||
|
||||
#[TestDox('IsOK succeeds for OK result')]
|
||||
public function testIsOKSucceedsForOKResult(): void
|
||||
{
|
||||
$result = Result::OK('ok');
|
||||
$this->assertTrue(Result::isOK($result), 'The check for "OK" should have returned true');
|
||||
}
|
||||
|
||||
#[TestDox('IsOK succeeds for Error result')]
|
||||
public function testIsOKSucceedsForErrorResult(): void
|
||||
{
|
||||
$result = Result::Error('error');
|
||||
$this->assertFalse(Result::isOK($result), 'The check for "OK" should have returned false');
|
||||
}
|
||||
|
||||
#[TestDox('IsError succeeds for Error result')]
|
||||
public function testIsErrorSucceedsForErrorResult(): void
|
||||
{
|
||||
$result = Result::Error('not ok');
|
||||
$this->assertTrue(Result::isError($result), 'The check for "Error" should have returned true');
|
||||
}
|
||||
|
||||
#[TestDox('IsError succeeds for OK result')]
|
||||
public function testIsErrorSucceedsForOKResult(): void
|
||||
{
|
||||
$result = Result::OK('fine');
|
||||
$this->assertFalse(Result::isError($result), 'The check for "Error" should have returned false');
|
||||
}
|
||||
|
||||
#[TestDox('Map succeeds for OK result')]
|
||||
public function testMapSucceedsForOKResult(): void
|
||||
{
|
||||
$ok = Result::OK('yard');
|
||||
$mapped = Result::map(fn($it) => strrev($it), $ok);
|
||||
$this->assertTrue(Result::isOK($mapped), 'The mapped result should be "OK"');
|
||||
$this->assertEquals('dray', $mapped->getOK(), 'The mapping function was not called correctly');
|
||||
}
|
||||
|
||||
#[TestDox('Map fails for OK result when mapping is null')]
|
||||
public function testMapFailsForOKResultWhenMappingIsNull(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
Result::map(fn($it) => null, Result::OK('not null'));
|
||||
}
|
||||
|
||||
#[TestDox('Map succeeds for Error result')]
|
||||
public function testMapSucceedsForErrorResult(): void
|
||||
{
|
||||
$tattle = new class { public bool $called = false; };
|
||||
$error = Result::Error('nope');
|
||||
$mapped = Result::map(function ($ignored) use ($tattle)
|
||||
{
|
||||
$tattle->called = true;
|
||||
return 'hello';
|
||||
}, $error);
|
||||
$this->assertTrue(Result::isError($mapped), 'The mapped result should be "Error"');
|
||||
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
||||
$this->assertNotSame($error, $mapped, 'There should have been a new "Error" instance returned');
|
||||
}
|
||||
|
||||
#[TestDox('MapError succeeds for OK result')]
|
||||
public function testMapErrorSucceedsForOKResult(): void
|
||||
{
|
||||
$tattle = new class { public bool $called = false; };
|
||||
$ok = Result::OK('sure');
|
||||
$mapped = Result::mapError(function ($ignored) use ($tattle)
|
||||
{
|
||||
$tattle->called = true;
|
||||
return 'hello';
|
||||
}, $ok);
|
||||
$this->assertTrue(Result::isOK($mapped), 'The mapped result should be "OK"');
|
||||
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
||||
$this->assertNotSame($ok, $mapped, 'There should have been a new "OK" instance returned');
|
||||
}
|
||||
|
||||
#[TestDox('MapError succeeds for Error result')]
|
||||
public function testMapErrorSucceedsForErrorResult(): void
|
||||
{
|
||||
$error = Result::Error('taco');
|
||||
$mapped = Result::mapError(fn($it) => str_repeat('*', strlen($it)), $error);
|
||||
$this->assertTrue(Result::isError($mapped), 'The mapped result should be "Error"');
|
||||
$this->assertEquals('****', $mapped->getError(), 'The mapping function was not called correctly');
|
||||
}
|
||||
|
||||
#[TestDox('MapError fails for Error result when mapping is null')]
|
||||
public function testMapErrorFailsForErrorResultWhenMappingIsNull(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
Result::mapError(fn($it) => null, Result::Error('pizza'));
|
||||
}
|
||||
|
||||
#[TestDox('Iter succeeds for OK result')]
|
||||
public function testIterSucceedsForOKResult(): void
|
||||
{
|
||||
$target = new class { public mixed $called = null; };
|
||||
Result::iter(function ($it) use ($target) { $target->called = $it; }, Result::OK(77));
|
||||
$this->assertEquals(77, $target->called, 'The function should have been called with the "OK" value');
|
||||
}
|
||||
|
||||
#[TestDox('Iter succeeds for Error result')]
|
||||
public function testIterSucceedsForErrorResult(): void
|
||||
{
|
||||
$target = new class { public mixed $called = null; };
|
||||
Result::iter(function ($ignored) use ($target) { $target->called = 'uh oh'; }, Result::Error(''));
|
||||
$this->assertNull($target->called, 'The function should not have been called');
|
||||
}
|
||||
|
||||
#[TestDox('ToOption succeeds for OK result')]
|
||||
public function testToOptionSucceedsForOKResult()
|
||||
{
|
||||
$value = Result::toOption(Result::OK(99));
|
||||
$this->assertTrue(Option::isSome($value), 'An "OK" result should map to a "Some" option');
|
||||
$this->assertEquals(99, $value->get(), 'The value is not correct');
|
||||
}
|
||||
|
||||
#[TestDox('ToOption succeeds for Error result')]
|
||||
public function testToOptionSucceedsForErrorResult()
|
||||
{
|
||||
$value = Result::toOption(Result::Error('file not found'));
|
||||
$this->assertTrue(Option::isNone($value), 'An "Error" result should map to a "None" option');
|
||||
}
|
||||
|
||||
#[TestDox('Tap succeeds for OK result')]
|
||||
public function testTapSucceedsForOKResult(): void
|
||||
{
|
||||
$value = '';
|
||||
$original = Result::OK('working');
|
||||
$tapped = Result::tap(function (Result $it) use (&$value) {
|
||||
$value = Result::isOK($it) ? 'OK: ' . $it->getOK() : 'Error: ' . $it->getError();
|
||||
}, $original);
|
||||
$this->assertEquals('OK: working', $value, 'The tapped function was not called');
|
||||
$this->assertSame($original, $tapped, 'The same result should have been returned');
|
||||
}
|
||||
|
||||
#[TestDox('Tap succeeds for Error result')]
|
||||
public function testTapSucceedsForErrorResult(): void
|
||||
{
|
||||
$value = '';
|
||||
$original = Result::Error('failed');
|
||||
$tapped = Result::tap(function (Result $it) use (&$value) {
|
||||
$value = Result::isOK($it) ? 'OK: ' . $it->getOK() : 'Error: ' . $it->getError();
|
||||
}, $original);
|
||||
$this->assertEquals('Error: failed', $value, 'The tapped function was not called');
|
||||
$this->assertSame($original, $tapped, 'The same result should have been returned');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user