Skip to content

Commit

Permalink
Add StringEndsWith constraint
Browse files Browse the repository at this point in the history
  • Loading branch information
villfa committed Nov 1, 2020
1 parent 0c71437 commit 185453e
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class ExampleTest extends PHPUnit\Framework\TestCase
* [IsURL](./src/Constraint/IsURL.php): asserts that a string contains only an URL
* [IsEmail](./src/Constraint/IsEmail.php): asserts that a string contains only an email address
* [StringStartsWith](./src/Constraint/StringStartsWith.php): asserts that a string starts with another string
* [StringEndsWith](./src/Constraint/StringEndsWith.php): asserts that a string ends with another string

## Tests

Expand Down
47 changes: 47 additions & 0 deletions src/Constraint/StringEndsWith.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace PHPUnitExtraConstraints\Constraint;

use PHPUnit\Framework\Constraint\Constraint;

use function is_string;
use function strlen;
use function substr_compare;

/**
* Constraint that asserts that a string ends with another string.
*/
final class StringEndsWith extends Constraint
{
/** @var string */
private $needle;

public function __construct(string $needle)
{
$this->needle = $needle;
}

/**
* @inheritDoc
*/
protected function matches($other): bool
{
return is_string($other)
&& self::endsWith($other, $this->needle);
}

private static function endsWith(string $haystack, string $needle): bool
{
return '' === $needle || ('' !== $haystack && 0 === substr_compare($haystack, $needle, -strlen($needle)));
}

/**
* @inheritDoc
*/
public function toString(): string
{
return 'ends with ' . $this->needle;
}
}
66 changes: 66 additions & 0 deletions tests/Constraint/StringEndsWithTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace Tests\PHPUnitExtraConstraints\Constraint;

use PHPUnitExtraConstraints\Constraint\StringEndsWith;
use Tests\PHPUnitExtraConstraints\CustomTestCase;

class StringEndsWithTest extends CustomTestCase
{
/**
* @dataProvider provideValidStrings
* @testdox testWithValidString: $value ends with $needle
*
* @param string $needle
* @param string $value
*/
public function testWithValidString(string $needle, string $value): void
{
$constraint = new StringEndsWith($needle);
self::assertThat($value, $constraint);
}

/**
* @return iterable<array<string>>
*/
public function provideValidStrings(): iterable
{
yield ['c', 'abc'];
yield ['bc', 'abc'];
yield ['abc', 'abc'];
yield ['', 'abc'];
yield ['0', '00'];
}

/**
* @dataProvider provideInvalidStrings
* @testdox testWithInvalidString: $value doesn't end with $needle
*
* @param string $needle
* @param mixed $value
*/
public function testWithInvalidString(string $needle, $value): void
{
$constraint = new StringEndsWith($needle);
$this->expectAssertionFailedError('ends with ' . $needle);
self::assertThat($value, $constraint);
}

/**
* @return iterable<array<mixed>>
*/
public function provideInvalidStrings(): iterable
{
yield ['zzz', null];
yield ['zzz', true];
yield ['zzz', false];
yield ['zzz', 0];
yield ['zzz', 1];
yield ['zzz', []];
yield ['zzz', (object) []];
yield ['zzz', 'abc'];
yield ['zzz', 'z'];
}
}

0 comments on commit 185453e

Please sign in to comment.