diff --git a/.gitattributes b/.gitattributes index 4160131..05f17e3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ /.gitattributes export-ignore /.gitignore export-ignore -/phpunit.xml.dist export-ignore /tests export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index feba0f6..2f3eecb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,68 +3,12 @@ name: CI on: [push, pull_request] jobs: - phpunit: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macOS-latest] - php-version: ['8.2', '8.3'] - dependencies: ['lowest', 'highest'] - name: 'PHPUnit' - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: mbstring, intl - coverage: xdebug - - name: Composer - uses: "ramsey/composer-install@v2" - with: - dependency-versions: ${{ matrix.dependencies }} - - name: PHPUnit - run: vendor/bin/phpunit --coverage-clover=coverage.clover - - uses: codecov/codecov-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} + blackbox: + uses: innmind/github-workflows/.github/workflows/black-box-matrix.yml@main + coverage: + uses: innmind/github-workflows/.github/workflows/coverage-matrix.yml@main + secrets: inherit psalm: - runs-on: ubuntu-latest - strategy: - matrix: - php-version: ['8.2', '8.3'] - dependencies: ['lowest', 'highest'] - name: 'Psalm' - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: mbstring, intl - - name: Composer - uses: "ramsey/composer-install@v2" - with: - dependency-versions: ${{ matrix.dependencies }} - - name: Psalm - run: vendor/bin/psalm --shepherd + uses: innmind/github-workflows/.github/workflows/psalm-matrix.yml@main cs: - runs-on: ubuntu-latest - strategy: - matrix: - php-version: ['8.2'] - name: 'CS' - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: mbstring, intl - - name: Composer - uses: "ramsey/composer-install@v2" - - name: CS - run: vendor/bin/php-cs-fixer fix --diff --dry-run + uses: innmind/github-workflows/.github/workflows/cs.yml@main diff --git a/.github/workflows/extensive.yml b/.github/workflows/extensive.yml new file mode 100644 index 0000000..257f139 --- /dev/null +++ b/.github/workflows/extensive.yml @@ -0,0 +1,12 @@ +name: Extensive CI + +on: + push: + tags: + - '*' + paths: + - '.github/workflows/extensive.yml' + +jobs: + blackbox: + uses: innmind/github-workflows/.github/workflows/extensive.yml@main diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b25ad8a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,11 @@ +name: Create release + +on: + push: + tags: + - '*' + +jobs: + release: + uses: innmind/github-workflows/.github/workflows/release.yml@main + secrets: inherit diff --git a/.gitignore b/.gitignore index e96516b..987e2a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ composer.lock vendor -.phpunit.result.cache diff --git a/CHANGELOG.md b/CHANGELOG.md index 25a6531..6ffd95e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,44 @@ # Changelog +## [Unreleased] + +### Added + +- `Innmind\Colour\CMYKA::attempt()` +- `Innmind\Colour\Colour::attempt()` +- `Innmind\Colour\HSLA::attempt()` +- `Innmind\Colour\RGBA::attempt()` + +### Changed + +- Requires PHP `8.4` +- Named constructors `::of()`, `::fromHexadecimal()` and `::fromIntensity()` now return instances of `Innmind\Immutable\Attempt` +- `Innmind\Colour\Alpha` constructor is now private, use `::of()` instead +- `Innmind\Colour\Back` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Blue` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Cyan` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Green` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Hue` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Intensity` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Lightness` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Magenta` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Red` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Saturation` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\Yellow` constructor is now private, use `::of()` or `::at()` instead +- `Innmind\Colour\CMYKA` constructor is now private, use `::from()` instead +- `Innmind\Colour\HSLA` constructor is now private, use `::from()` instead +- `Innmind\Colour\RGBA` constructor is now private, use `::from()` instead + +### Removed + +- `Innmind\Colour\Exception\Exception` +- `Innmind\Colour\Exception\DomainException` +- `Innmind\Colour\Exception\InvalidValueRangeException` + +### Fixed + +- PHP `8.4` deprecations + ## 4.3.0 - 2025-03-20 ### Added diff --git a/blackbox.php b/blackbox.php new file mode 100644 index 0000000..d6f7152 --- /dev/null +++ b/blackbox.php @@ -0,0 +1,32 @@ +when( + \getenv('BLACKBOX_SET_SIZE') !== false, + static fn(Application $app) => $app->scenariiPerProof((int) \getenv('BLACKBOX_SET_SIZE')), + ) + ->when( + \getenv('ENABLE_COVERAGE') !== false, + static fn(Application $app) => $app + ->codeCoverage( + CodeCoverage::of( + __DIR__.'/src/', + __DIR__.'/tests/', + __DIR__.'/fixtures/', + ) + ->dumpTo('coverage.clover') + ->enableWhen(true), + ) + ->scenariiPerProof(50), + ) + ->tryToProve(Load::directory(__DIR__.'/tests/')) + ->exit(); diff --git a/composer.json b/composer.json index f2580cf..7ab0468 100644 --- a/composer.json +++ b/composer.json @@ -15,8 +15,8 @@ "issues": "http://github.com/Innmind/Colour/issues" }, "require": { - "php": "~8.2", - "innmind/immutable": "~4.0|~5.0" + "php": "~8.4", + "innmind/immutable": "~6.0" }, "autoload": { "psr-4": { @@ -30,18 +30,17 @@ } }, "require-dev": { - "phpunit/phpunit": "~10.2|~11.0|~12.0", - "vimeo/psalm": "~5.0", - "innmind/black-box": "~5.0|^6.0.1", + "innmind/static-analysis": "~1.3", + "innmind/black-box": "~6.5", "innmind/coding-standard": "~2.0" }, "conflict": { - "innmind/black-box": "<5.0|~7.0" + "innmind/black-box": "<6.0|~7.0" }, "suggest": { "innmind/black-box": "For property based testing" }, "provide": { - "innmind/black-box-sets": "5.0" + "innmind/black-box-sets": "6.0" } } diff --git a/fixtures/Colour.php b/fixtures/Colour.php index 3318c9b..dc38d38 100644 --- a/fixtures/Colour.php +++ b/fixtures/Colour.php @@ -16,9 +16,6 @@ final class Colour */ public static function any(): Set { - return Set\Decorate::immutable( - static fn($case) => $case->toRGBA(), - Set\Elements::of(...Colours::cases()), - ); + return Set::of(...Colours::cases())->map(static fn($case) => $case->toRGBA()); } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 01eb7ae..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - ./tests - - - - - . - - - ./tests - ./vendor - - - diff --git a/psalm.xml b/psalm.xml index 5d768ff..a4a4d73 100644 --- a/psalm.xml +++ b/psalm.xml @@ -14,4 +14,7 @@ + + + diff --git a/src/Alpha.php b/src/Alpha.php index 51206ca..2fae613 100644 --- a/src/Alpha.php +++ b/src/Alpha.php @@ -3,8 +3,7 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable @@ -13,39 +12,39 @@ final class Alpha { private float $value; - /** - * @throws InvalidValueRangeException - */ - public function __construct(float $value) + private function __construct(float $value) { if ($value < 0 || $value > 1) { - throw new InvalidValueRangeException((string) $value); + throw new \OutOfBoundsException((string) $value); } $this->value = $value; } + /** + * @psalm-pure + */ + public static function max(): self + { + return new self(1); + } + /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(float $value): Maybe + public static function of(float $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); - } + return Attempt::of(static fn() => new self($value)); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function fromHexadecimal(string $hex): Maybe + public static function fromHexadecimal(string $hex): Attempt { if (\mb_strlen($hex) === 1) { $hex .= $hex; diff --git a/src/Black.php b/src/Black.php index 69fbafa..66ac6f6 100644 --- a/src/Black.php +++ b/src/Black.php @@ -3,41 +3,43 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Black { - private int $value; + /** + * @param int<0, 100> $value + */ + private function __construct( + private int $value, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 100> $value */ - public function __construct(int $value) + public static function at(int $value): self { - if ($value < 0 || $value > 100) { - throw new InvalidValueRangeException((string) $value); - } - - $this->value = $value; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 100) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } public function add(self $black): self @@ -75,6 +77,9 @@ public function atMinimum(): bool return $this->value === 0; } + /** + * @return int<0, 100> + */ public function toInt(): int { return $this->value; diff --git a/src/Blue.php b/src/Blue.php index 848db4e..69e4231 100644 --- a/src/Blue.php +++ b/src/Blue.php @@ -3,49 +3,51 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Blue { - private int $integer; + /** + * @param int<0, 255> $integer + */ + private function __construct( + private int $integer, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 255> $value */ - public function __construct(int $integer) + public static function at(int $value): self { - if ($integer < 0 || $integer > 255) { - throw new InvalidValueRangeException((string) $integer); - } - - $this->integer = $integer; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 255) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function fromHexadecimal(string $hex): Maybe + public static function fromHexadecimal(string $hex): Attempt { if (\mb_strlen($hex) === 1) { $hex .= $hex; @@ -55,9 +57,9 @@ public static function fromHexadecimal(string $hex): Maybe } /** - * @return Maybe + * @return Attempt */ - public static function fromIntensity(Intensity $intensity): Maybe + public static function fromIntensity(Intensity $intensity): Attempt { return self::of( (int) \round((255 * $intensity->toInt()) / 100), @@ -99,6 +101,9 @@ public function atMinimum(): bool return $this->integer === 0; } + /** + * @return int<0, 255> + */ public function toInt(): int { return $this->integer; diff --git a/src/CMYKA.php b/src/CMYKA.php index 831e513..472ad54 100644 --- a/src/CMYKA.php +++ b/src/CMYKA.php @@ -3,10 +3,10 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\DomainException; use Innmind\Immutable\{ Str, Maybe, + Attempt, }; /** @@ -17,37 +17,36 @@ final class CMYKA private const PATTERN_WITH_ALPHA = '~^device-cmyk\((?\d{1,3})%, ?(?\d{1,3})%, ?(?\d{1,3})%, ?(?\d{1,3})%, ?(?[01]|0?\.\d+|1\.0)\)$~'; private const PATTERN_WITHOUT_ALPHA = '~^device-cmyk\((?\d{1,3})%, ?(?\d{1,3})%, ?(?\d{1,3})%, ?(?\d{1,3})%\)$~'; - private Cyan $cyan; - private Magenta $magenta; - private Yellow $yellow; - private Black $black; - private Alpha $alpha; + private function __construct( + private Cyan $cyan, + private Magenta $magenta, + private Yellow $yellow, + private Black $black, + private Alpha $alpha, + ) { + } - public function __construct( + /** + * @psalm-pure + */ + public static function from( Cyan $cyan, Magenta $magenta, Yellow $yellow, Black $black, - Alpha $alpha = null, - ) { - $this->cyan = $cyan; - $this->magenta = $magenta; - $this->yellow = $yellow; - $this->black = $black; - $this->alpha = $alpha ?? new Alpha(1); + ?Alpha $alpha = null, + ): self { + return new self($cyan, $magenta, $yellow, $black, $alpha ?? Alpha::max()); } /** * @psalm-pure * - * @throws DomainException + * @throws \Exception */ public static function of(string $colour): self { - return self::maybe($colour)->match( - static fn($self) => $self, - static fn() => throw new DomainException($colour), - ); + return self::attempt($colour)->unwrap(); } /** @@ -56,10 +55,20 @@ public static function of(string $colour): self * @return Maybe */ public static function maybe(string $colour): Maybe + { + return self::attempt($colour)->maybe(); + } + + /** + * @psalm-pure + * + * @return Attempt + */ + public static function attempt(string $colour): Attempt { $colour = Str::of($colour)->trim(); - return self::withAlpha($colour)->otherwise( + return self::withAlpha($colour)->recover( static fn() => self::withoutAlpha($colour), ); } @@ -219,10 +228,10 @@ public function toRGBA(): RGBA $green = 1 - \min(1, $magenta * (1 - $black) + $black); $blue = 1 - \min(1, $yellow * (1 - $black) + $black); - return new RGBA( - new Red((int) \round($red * 255)), - new Green((int) \round($green * 255)), - new Blue((int) \round($blue * 255)), + return RGBA::from( + Red::of((int) \round($red * 255))->unwrap(), + Green::of((int) \round($green * 255))->unwrap(), + Blue::of((int) \round($blue * 255))->unwrap(), $this->alpha, ); } @@ -262,46 +271,59 @@ public function toString(): string /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function withAlpha(Str $colour): Maybe + private static function withAlpha(Str $colour): Attempt { $matches = $colour ->capture(self::PATTERN_WITH_ALPHA) ->map(static fn($_, $match) => $match->toString()); $cyan = $matches ->get('cyan') - ->filter(static fn($cyan) => \is_numeric($cyan)) + ->filter(\is_numeric(...)) ->map(static fn($cyan) => (int) $cyan) - ->flatMap(static fn($cyan) => Cyan::of($cyan)); + ->attempt(static fn() => new \DomainException("Cyan not found in '{$colour->toString()}'")) + ->flatMap(Cyan::of(...)); $magenta = $matches ->get('magenta') - ->filter(static fn($magenta) => \is_numeric($magenta)) + ->filter(\is_numeric(...)) ->map(static fn($magenta) => (int) $magenta) - ->flatMap(static fn($magenta) => Magenta::of($magenta)); + ->attempt(static fn() => new \DomainException("Magenta not found in '{$colour->toString()}'")) + ->flatMap(Magenta::of(...)); $yellow = $matches ->get('yellow') - ->filter(static fn($yellow) => \is_numeric($yellow)) + ->filter(\is_numeric(...)) ->map(static fn($yellow) => (int) $yellow) - ->flatMap(static fn($yellow) => Yellow::of($yellow)); + ->attempt(static fn() => new \DomainException("Yellow not found in '{$colour->toString()}'")) + ->flatMap(Yellow::of(...)); $black = $matches ->get('black') - ->filter(static fn($black) => \is_numeric($black)) + ->filter(\is_numeric(...)) ->map(static fn($black) => (int) $black) - ->flatMap(static fn($black) => Black::of($black)); + ->attempt(static fn() => new \DomainException("Black not found in '{$colour->toString()}'")) + ->flatMap(Black::of(...)); $alpha = $matches ->get('alpha') - ->filter(static fn($alpha) => \is_numeric($alpha)) + ->filter(\is_numeric(...)) ->map(static fn($alpha) => (float) $alpha) - ->flatMap(static fn($alpha) => Alpha::of($alpha)); - - return Maybe::all($cyan, $magenta, $yellow, $black, $alpha)->map( - static fn(Cyan $cyan, Magenta $magenta, Yellow $yellow, Black $black, Alpha $alpha) => new self( - $cyan, - $magenta, - $yellow, - $black, - $alpha, + ->attempt(static fn() => new \DomainException("Alpha not found in '{$colour->toString()}'")) + ->flatMap(Alpha::of(...)); + + return $cyan->flatMap( + static fn($cyan) => $magenta->flatMap( + static fn($magenta) => $yellow->flatMap( + static fn($yellow) => $black->flatMap( + static fn($black) => $alpha->map( + static fn($alpha) => self::from( + $cyan, + $magenta, + $yellow, + $black, + $alpha, + ), + ), + ), + ), ), ); } @@ -309,40 +331,50 @@ private static function withAlpha(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function withoutAlpha(Str $colour): Maybe + private static function withoutAlpha(Str $colour): Attempt { $matches = $colour ->capture(self::PATTERN_WITHOUT_ALPHA) ->map(static fn($_, $match) => $match->toString()); $cyan = $matches ->get('cyan') - ->filter(static fn($cyan) => \is_numeric($cyan)) + ->filter(\is_numeric(...)) ->map(static fn($cyan) => (int) $cyan) - ->flatMap(static fn($cyan) => Cyan::of($cyan)); + ->attempt(static fn() => new \DomainException("Cyan not found in '{$colour->toString()}'")) + ->flatMap(Cyan::of(...)); $magenta = $matches ->get('magenta') - ->filter(static fn($magenta) => \is_numeric($magenta)) + ->filter(\is_numeric(...)) ->map(static fn($magenta) => (int) $magenta) - ->flatMap(static fn($magenta) => Magenta::of($magenta)); + ->attempt(static fn() => new \DomainException("Magenta not found in '{$colour->toString()}'")) + ->flatMap(Magenta::of(...)); $yellow = $matches ->get('yellow') - ->filter(static fn($yellow) => \is_numeric($yellow)) + ->filter(\is_numeric(...)) ->map(static fn($yellow) => (int) $yellow) - ->flatMap(static fn($yellow) => Yellow::of($yellow)); + ->attempt(static fn() => new \DomainException("Yellow not found in '{$colour->toString()}'")) + ->flatMap(Yellow::of(...)); $black = $matches ->get('black') - ->filter(static fn($black) => \is_numeric($black)) + ->filter(\is_numeric(...)) ->map(static fn($black) => (int) $black) - ->flatMap(static fn($black) => Black::of($black)); - - return Maybe::all($cyan, $magenta, $yellow, $black)->map( - static fn(Cyan $cyan, Magenta $magenta, Yellow $yellow, Black $black) => new self( - $cyan, - $magenta, - $yellow, - $black, + ->attempt(static fn() => new \DomainException("Black not found in '{$colour->toString()}'")) + ->flatMap(Black::of(...)); + + return $cyan->flatMap( + static fn($cyan) => $magenta->flatMap( + static fn($magenta) => $yellow->flatMap( + static fn($yellow) => $black->map( + static fn($black) => self::from( + $cyan, + $magenta, + $yellow, + $black, + ), + ), + ), ), ); } diff --git a/src/Colour.php b/src/Colour.php index 141b3bd..1e79f79 100644 --- a/src/Colour.php +++ b/src/Colour.php @@ -3,9 +3,9 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\DomainException; use Innmind\Immutable\{ Maybe, + Attempt, }; /** @@ -117,14 +117,11 @@ enum Colour /** * @psalm-pure * - * @throws DomainException + * @throws \Exception */ public static function of(string $colour): RGBA|HSLA|CMYKA { - return self::maybe($colour)->match( - static fn($colour) => $colour, - static fn() => throw new DomainException($colour), - ); + return self::attempt($colour)->unwrap(); } /** @@ -134,9 +131,19 @@ public static function of(string $colour): RGBA|HSLA|CMYKA */ public static function maybe(string $colour): Maybe { - return RGBA::maybe($colour) - ->otherwise(static fn() => HSLA::maybe($colour)) - ->otherwise(static fn() => CMYKA::maybe($colour)); + return self::attempt($colour)->maybe(); + } + + /** + * @psalm-pure + * + * @return Attempt + */ + public static function attempt(string $colour): Attempt + { + return RGBA::attempt($colour) + ->recover(static fn() => HSLA::attempt($colour)) + ->recover(static fn() => CMYKA::attempt($colour)); } /** diff --git a/src/Cyan.php b/src/Cyan.php index a9654b9..3c1402c 100644 --- a/src/Cyan.php +++ b/src/Cyan.php @@ -3,41 +3,43 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Cyan { - private int $value; + /** + * @param int<0, 100> $value + */ + private function __construct( + private int $value, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 100> $value */ - public function __construct(int $value) + public static function at(int $value): self { - if ($value < 0 || $value > 100) { - throw new InvalidValueRangeException((string) $value); - } - - $this->value = $value; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 100) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } public function add(self $cyan): self @@ -75,6 +77,9 @@ public function atMinimum(): bool return $this->value === 0; } + /** + * @return int<0, 100> + */ public function toInt(): int { return $this->value; diff --git a/src/Exception/DomainException.php b/src/Exception/DomainException.php deleted file mode 100644 index ef1da27..0000000 --- a/src/Exception/DomainException.php +++ /dev/null @@ -1,8 +0,0 @@ - $integer + */ + private function __construct( + private int $integer, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 255> $value */ - public function __construct(int $integer) + public static function at(int $value): self { - if ($integer < 0 || $integer > 255) { - throw new InvalidValueRangeException((string) $integer); - } - - $this->integer = $integer; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 255) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function fromHexadecimal(string $hex): Maybe + public static function fromHexadecimal(string $hex): Attempt { if (\mb_strlen($hex) === 1) { $hex .= $hex; @@ -57,9 +59,9 @@ public static function fromHexadecimal(string $hex): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function fromIntensity(Intensity $intensity): Maybe + public static function fromIntensity(Intensity $intensity): Attempt { return self::of( (int) \round((255 * $intensity->toInt()) / 100), @@ -101,6 +103,9 @@ public function atMinimum(): bool return $this->integer === 0; } + /** + * @return int<0, 255> + */ public function toInt(): int { return $this->integer; diff --git a/src/HSLA.php b/src/HSLA.php index b7895e7..94e507b 100644 --- a/src/HSLA.php +++ b/src/HSLA.php @@ -3,10 +3,10 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\DomainException; use Innmind\Immutable\{ Str, Maybe, + Attempt, }; /** @@ -17,34 +17,34 @@ final class HSLA private const PATTERN_WITH_ALPHA = '~^hsla\((?\d{1,3}), ?(?\d{1,3})%, ?(?\d{1,3})%, ?(?[01]|0?\.\d+|1\.0)\)$~'; private const PATTERN_WITHOUT_ALPHA = '~^hsl\((?\d{1,3}), ?(?\d{1,3})%, ?(?\d{1,3})%\)$~'; - private Hue $hue; - private Saturation $saturation; - private Lightness $lightness; - private Alpha $alpha; + private function __construct( + private Hue $hue, + private Saturation $saturation, + private Lightness $lightness, + private Alpha $alpha, + ) { + } - public function __construct( + /** + * @psalm-pure + */ + public static function from( Hue $hue, Saturation $saturation, Lightness $lightness, - Alpha $alpha = null, - ) { - $this->hue = $hue; - $this->saturation = $saturation; - $this->lightness = $lightness; - $this->alpha = $alpha ?? new Alpha(1); + ?Alpha $alpha = null, + ): self { + return new self($hue, $saturation, $lightness, $alpha ?? Alpha::max()); } /** * @psalm-pure * - * @throws DomainException + * @throws \Exception */ public static function of(string $colour): self { - return self::maybe($colour)->match( - static fn($self) => $self, - static fn() => throw new DomainException($colour), - ); + return self::attempt($colour)->unwrap(); } /** @@ -53,10 +53,20 @@ public static function of(string $colour): self * @return Maybe */ public static function maybe(string $colour): Maybe + { + return self::attempt($colour)->maybe(); + } + + /** + * @psalm-pure + * + * @return Attempt + */ + public static function attempt(string $colour): Attempt { $colour = Str::of($colour)->trim(); - return self::withAlpha($colour)->otherwise( + return self::withAlpha($colour)->recover( static fn() => self::withoutAlpha($colour), ); } @@ -164,10 +174,10 @@ public function toRGBA(): RGBA $lightness = $this->lightness->toInt() / 100; if ($this->saturation->atMinimum()) { - return new RGBA( - new Red((int) \round($lightness * 255)), - new Green((int) \round($lightness * 255)), - new Blue((int) \round($lightness * 255)), + return RGBA::from( + Red::of((int) \round($lightness * 255))->unwrap(), + Green::of((int) \round($lightness * 255))->unwrap(), + Blue::of((int) \round($lightness * 255))->unwrap(), $this->alpha, ); } @@ -179,10 +189,10 @@ public function toRGBA(): RGBA $q = $lightness < 0.5 ? $lightness * (1 + $saturation) : $lightness + $saturation - $lightness * $saturation; $p = 2 * $lightness - $q; - return new RGBA( - new Red((int) \round($this->hueToPoint($p, $q, $hue + 1 / 3) * 255)), - new Green((int) \round($this->hueToPoint($p, $q, $hue) * 255)), - new Blue((int) \round($this->hueToPoint($p, $q, $hue - 1 / 3) * 255)), + return RGBA::from( + Red::of((int) \round($this->hueToPoint($p, $q, $hue + 1 / 3) * 255))->unwrap(), + Green::of((int) \round($this->hueToPoint($p, $q, $hue) * 255))->unwrap(), + Blue::of((int) \round($this->hueToPoint($p, $q, $hue - 1 / 3) * 255))->unwrap(), $this->alpha, ); } @@ -251,40 +261,50 @@ private function hueToPoint(float $p, float $q, float $t): float /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function withAlpha(Str $colour): Maybe + private static function withAlpha(Str $colour): Attempt { $matches = $colour ->capture(self::PATTERN_WITH_ALPHA) ->map(static fn($_, $match) => $match->toString()); $hue = $matches ->get('hue') - ->filter(static fn($hue) => \is_numeric($hue)) + ->filter(\is_numeric(...)) ->map(static fn($hue) => (int) $hue) - ->flatMap(static fn($hue) => Hue::of($hue)); + ->attempt(static fn() => new \DomainException("Hue not found in '{$colour->toString()}'")) + ->flatMap(Hue::of(...)); $saturation = $matches ->get('saturation') - ->filter(static fn($saturation) => \is_numeric($saturation)) + ->filter(\is_numeric(...)) ->map(static fn($saturation) => (int) $saturation) - ->flatMap(static fn($saturation) => Saturation::of($saturation)); + ->attempt(static fn() => new \DomainException("Saturation not found in '{$colour->toString()}'")) + ->flatMap(Saturation::of(...)); $lightness = $matches ->get('lightness') - ->filter(static fn($lightness) => \is_numeric($lightness)) + ->filter(\is_numeric(...)) ->map(static fn($lightness) => (int) $lightness) - ->flatMap(static fn($lightness) => Lightness::of($lightness)); + ->attempt(static fn() => new \DomainException("Lightness not found in '{$colour->toString()}'")) + ->flatMap(Lightness::of(...)); $alpha = $matches ->get('alpha') - ->filter(static fn($alpha) => \is_numeric($alpha)) + ->filter(\is_numeric(...)) ->map(static fn($alpha) => (float) $alpha) - ->flatMap(static fn($alpha) => Alpha::of($alpha)); - - return Maybe::all($hue, $saturation, $lightness, $alpha)->map( - static fn(Hue $hue, Saturation $saturation, Lightness $lightness, Alpha $alpha) => new self( - $hue, - $saturation, - $lightness, - $alpha, + ->attempt(static fn() => new \DomainException("Alpha not found in '{$colour->toString()}'")) + ->flatMap(Alpha::of(...)); + + return $hue->flatMap( + static fn($hue) => $saturation->flatMap( + static fn($saturation) => $lightness->flatMap( + static fn($lightness) => $alpha->map( + static fn($alpha) => self::from( + $hue, + $saturation, + $lightness, + $alpha, + ), + ), + ), ), ); } @@ -292,34 +312,41 @@ private static function withAlpha(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function withoutAlpha(Str $colour): Maybe + private static function withoutAlpha(Str $colour): Attempt { $matches = $colour ->capture(self::PATTERN_WITHOUT_ALPHA) ->map(static fn($_, $match) => $match->toString()); $hue = $matches ->get('hue') - ->filter(static fn($hue) => \is_numeric($hue)) + ->filter(\is_numeric(...)) ->map(static fn($hue) => (int) $hue) - ->flatMap(static fn($hue) => Hue::of($hue)); + ->attempt(static fn() => new \DomainException("Hue not found in '{$colour->toString()}'")) + ->flatMap(Hue::of(...)); $saturation = $matches ->get('saturation') - ->filter(static fn($saturation) => \is_numeric($saturation)) + ->filter(\is_numeric(...)) ->map(static fn($saturation) => (int) $saturation) - ->flatMap(static fn($saturation) => Saturation::of($saturation)); + ->attempt(static fn() => new \DomainException("Saturation not found in '{$colour->toString()}'")) + ->flatMap(Saturation::of(...)); $lightness = $matches ->get('lightness') - ->filter(static fn($lightness) => \is_numeric($lightness)) + ->filter(\is_numeric(...)) ->map(static fn($lightness) => (int) $lightness) - ->flatMap(static fn($lightness) => Lightness::of($lightness)); - - return Maybe::all($hue, $saturation, $lightness)->map( - static fn(Hue $hue, Saturation $saturation, Lightness $lightness) => new self( - $hue, - $saturation, - $lightness, + ->attempt(static fn() => new \DomainException("Lightness not found in '{$colour->toString()}'")) + ->flatMap(Lightness::of(...)); + + return $hue->flatMap( + static fn($hue) => $saturation->flatMap( + static fn($saturation) => $lightness->map( + static fn($lightness) => self::from( + $hue, + $saturation, + $lightness, + ), + ), ), ); } diff --git a/src/Hue.php b/src/Hue.php index d253dc7..bbd9bd0 100644 --- a/src/Hue.php +++ b/src/Hue.php @@ -3,55 +3,53 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Hue { - private int $value; + /** + * @param int<0, 359> $value + */ + private function __construct( + private int $value, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 359> $value */ - public function __construct(int $value) + public static function at(int $value): self { - if ($value < 0 || $value > 359) { - throw new InvalidValueRangeException((string) $value); - } - - $this->value = $value; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 359) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } public function rotateBy(int $degrees): self { - $degrees = $this->value + $degrees; + $degrees = ($this->value + $degrees) % 360; if ($degrees < 0) { return new self(360 + $degrees); } - if ($degrees > 359) { - return new self($degrees - 360); - } - return new self($degrees); } @@ -75,6 +73,9 @@ public function atMinimum(): bool return $this->value === 0; } + /** + * @return int<0, 359> + */ public function toInt(): int { return $this->value; diff --git a/src/Intensity.php b/src/Intensity.php index 5235d22..4a2e340 100644 --- a/src/Intensity.php +++ b/src/Intensity.php @@ -3,43 +3,48 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Intensity { - private int $value; + /** + * @param int<0, 100> $value + */ + private function __construct( + private int $value, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 100> $value */ - public function __construct(int $value) + public static function at(int $value): self { - if ($value < 0 || $value > 100) { - throw new InvalidValueRangeException((string) $value); - } - - $this->value = $value; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 100) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } + /** + * @return int<0, 100> + */ public function toInt(): int { return $this->value; diff --git a/src/Lightness.php b/src/Lightness.php index 2a1d781..667460e 100644 --- a/src/Lightness.php +++ b/src/Lightness.php @@ -3,41 +3,43 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Lightness { - private int $value; + /** + * @param int<0, 100> $value + */ + private function __construct( + private int $value, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 100> $value */ - public function __construct(int $value) + public static function at(int $value): self { - if ($value < 0 || $value > 100) { - throw new InvalidValueRangeException((string) $value); - } - - $this->value = $value; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 100) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } public function add(self $lightness): self @@ -75,6 +77,9 @@ public function atMinimum(): bool return $this->value === 0; } + /** + * @return int<0, 100> + */ public function toInt(): int { return $this->value; diff --git a/src/Magenta.php b/src/Magenta.php index 63fbfc3..ab02abc 100644 --- a/src/Magenta.php +++ b/src/Magenta.php @@ -3,41 +3,43 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Magenta { - private int $value; + /** + * @param int<0, 100> $value + */ + private function __construct( + private int $value, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 100> $value */ - public function __construct(int $value) + public static function at(int $value): self { - if ($value < 0 || $value > 100) { - throw new InvalidValueRangeException((string) $value); - } - - $this->value = $value; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 100) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } public function add(self $magenta): self @@ -75,6 +77,9 @@ public function atMinimum(): bool return $this->value === 0; } + /** + * @return int<0, 100> + */ public function toInt(): int { return $this->value; diff --git a/src/RGBA.php b/src/RGBA.php index fbdfd0f..c8a2763 100644 --- a/src/RGBA.php +++ b/src/RGBA.php @@ -3,10 +3,10 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\DomainException; use Innmind\Immutable\{ Str, Maybe, + Attempt, }; /** @@ -21,34 +21,34 @@ final class RGBA private const RGBA_FUNCTION_PATTERN = '~^rgba\((?\d{1,3}), ?(?\d{1,3}), ?(?\d{1,3}), ?(?[01]|0?\.\d+|1\.0)\)$~'; private const PERCENTED_RGBA_FUNCTION_PATTERN = '~^rgba\((?\d{1,3})%, ?(?\d{1,3})%, ?(?\d{1,3})%, ?(?[01]|0?\.\d+|1\.0)\)$~'; - private Red $red; - private Blue $blue; - private Green $green; - private Alpha $alpha; + private function __construct( + private Red $red, + private Green $green, + private Blue $blue, + private Alpha $alpha, + ) { + } - public function __construct( + /** + * @psalm-pure + */ + public static function from( Red $red, Green $green, Blue $blue, - Alpha $alpha = null, - ) { - $this->red = $red; - $this->blue = $blue; - $this->green = $green; - $this->alpha = $alpha ?? new Alpha(1); + ?Alpha $alpha = null, + ): self { + return new self($red, $green, $blue, $alpha ?? Alpha::max()); } /** * @psalm-pure * - * @throws DomainException + * @throws \Exception */ public static function of(string $colour): self { - return self::maybe($colour)->match( - static fn($self) => $self, - static fn() => throw new DomainException($colour), - ); + return self::attempt($colour)->unwrap(); } /** @@ -57,12 +57,22 @@ public static function of(string $colour): self * @return Maybe */ public static function maybe(string $colour): Maybe + { + return self::attempt($colour)->maybe(); + } + + /** + * @psalm-pure + * + * @return Attempt + */ + public static function attempt(string $colour): Attempt { $colour = Str::of($colour)->trim(); return self::fromHexadecimal($colour) - ->otherwise(static fn() => self::fromRGBFunction($colour)) - ->otherwise(static fn() => self::fromRGBAFunction($colour)); + ->recover(static fn() => self::fromRGBFunction($colour)) + ->recover(static fn() => self::fromRGBAFunction($colour)); } public function red(): Red @@ -195,10 +205,10 @@ public function toHSLA(): HSLA $lightness = ($max + $min) / 2; if ($max === $min) { - return new HSLA( - new Hue(0), - new Saturation(0), - new Lightness((int) \round($lightness * 100)), + return HSLA::from( + Hue::at(0), + Saturation::at(0), + Lightness::of((int) \round($lightness * 100))->unwrap(), $this->alpha, ); } @@ -221,10 +231,10 @@ public function toHSLA(): HSLA $hue *= 60; - return new HSLA( - new Hue((int) \round($hue)), - new Saturation((int) \round($saturation * 100)), - new Lightness((int) \round($lightness * 100)), + return HSLA::from( + Hue::of((int) \round($hue))->unwrap(), + Saturation::of((int) \round($saturation * 100))->unwrap(), + Lightness::of((int) \round($lightness * 100))->unwrap(), $this->alpha, ); } @@ -240,11 +250,11 @@ public function toCMYKA(): CMYKA $this->green->atMinimum() && $this->blue->atMinimum() ) { - return new CMYKA( - new Cyan(0), - new Magenta(0), - new Yellow(0), - new Black(100), + return CMYKA::from( + Cyan::at(0), + Magenta::at(0), + Yellow::at(0), + Black::at(100), $this->alpha, ); } @@ -254,11 +264,11 @@ public function toCMYKA(): CMYKA $magenta = (1 - $green - $black) / (1 - $black); $yellow = (1 - $blue - $black) / (1 - $black); - return new CMYKA( - new Cyan((int) \round($cyan * 100)), - new Magenta((int) \round($magenta * 100)), - new Yellow((int) \round($yellow * 100)), - new Black((int) \round($black * 100)), + return CMYKA::from( + Cyan::of((int) \round($cyan * 100))->unwrap(), + Magenta::of((int) \round($magenta * 100))->unwrap(), + Yellow::of((int) \round($yellow * 100))->unwrap(), + Black::of((int) \round($black * 100))->unwrap(), $this->alpha, ); } @@ -286,11 +296,11 @@ public function toString(): string /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function fromHexadecimal(Str $colour): Maybe + private static function fromHexadecimal(Str $colour): Attempt { - return self::fromHexadecimalWithAlpha($colour)->otherwise( + return self::fromHexadecimalWithAlpha($colour)->recover( static fn() => self::fromHexadecimalWithoutAlpha($colour), ); } @@ -298,9 +308,9 @@ private static function fromHexadecimal(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function fromHexadecimalWithAlpha(Str $colour): Maybe + private static function fromHexadecimalWithAlpha(Str $colour): Attempt { if ($colour->startsWith('#')) { $colour = $colour->drop(1); @@ -310,8 +320,8 @@ private static function fromHexadecimalWithAlpha(Str $colour): Maybe $colour->length() !== 4 && $colour->length() !== 8 ) { - /** @var Maybe */ - return Maybe::nothing(); + /** @var Attempt */ + return Attempt::error(new \DomainException('Invalid length')); } $matches = $colour @@ -319,23 +329,33 @@ private static function fromHexadecimalWithAlpha(Str $colour): Maybe ->map(static fn($_, $match) => $match->toString()); $red = $matches ->get('red') - ->flatMap(static fn($red) => Red::fromHexadecimal($red)); + ->attempt(static fn() => new \DomainException("Red not found in '{$colour->toString()}'")) + ->flatMap(Red::fromHexadecimal(...)); $green = $matches ->get('green') - ->flatMap(static fn($green) => Green::fromHexadecimal($green)); + ->attempt(static fn() => new \DomainException("Green not found in '{$colour->toString()}'")) + ->flatMap(Green::fromHexadecimal(...)); $blue = $matches ->get('blue') - ->flatMap(static fn($blue) => Blue::fromHexadecimal($blue)); + ->attempt(static fn() => new \DomainException("Blue not found in '{$colour->toString()}'")) + ->flatMap(Blue::fromHexadecimal(...)); $alpha = $matches ->get('alpha') - ->flatMap(static fn($alpha) => Alpha::fromHexadecimal($alpha)); - - return Maybe::all($red, $green, $blue, $alpha)->map( - static fn(Red $red, Green $green, Blue $blue, Alpha $alpha) => new self( - $red, - $green, - $blue, - $alpha, + ->attempt(static fn() => new \DomainException("Alpha not found in '{$colour->toString()}'")) + ->flatMap(Alpha::fromHexadecimal(...)); + + return $red->flatMap( + static fn($red) => $green->flatMap( + static fn($green) => $blue->flatMap( + static fn($blue) => $alpha->map( + static fn($alpha) => self::from( + $red, + $green, + $blue, + $alpha, + ), + ), + ), ), ); } @@ -343,9 +363,9 @@ private static function fromHexadecimalWithAlpha(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function fromHexadecimalWithoutAlpha(Str $colour): Maybe + private static function fromHexadecimalWithoutAlpha(Str $colour): Attempt { if ($colour->startsWith('#')) { $colour = $colour->drop(1); @@ -355,8 +375,8 @@ private static function fromHexadecimalWithoutAlpha(Str $colour): Maybe $colour->length() !== 3 && $colour->length() !== 6 ) { - /** @var Maybe */ - return Maybe::nothing(); + /** @var Attempt */ + return Attempt::error(new \DomainException('Invalid length')); } $matches = $colour @@ -364,19 +384,26 @@ private static function fromHexadecimalWithoutAlpha(Str $colour): Maybe ->map(static fn($_, $match) => $match->toString()); $red = $matches ->get('red') - ->flatMap(static fn($red) => Red::fromHexadecimal($red)); + ->attempt(static fn() => new \DomainException("Red not found in '{$colour->toString()}'")) + ->flatMap(Red::fromHexadecimal(...)); $green = $matches ->get('green') - ->flatMap(static fn($green) => Green::fromHexadecimal($green)); + ->attempt(static fn() => new \DomainException("Green not found in '{$colour->toString()}'")) + ->flatMap(Green::fromHexadecimal(...)); $blue = $matches ->get('blue') - ->flatMap(static fn($blue) => Blue::fromHexadecimal($blue)); - - return Maybe::all($red, $green, $blue)->map( - static fn(Red $red, Green $green, Blue $blue) => new self( - $red, - $green, - $blue, + ->attempt(static fn() => new \DomainException("Blue not found in '{$colour->toString()}'")) + ->flatMap(Blue::fromHexadecimal(...)); + + return $red->flatMap( + static fn($red) => $green->flatMap( + static fn($green) => $blue->map( + static fn($blue) => self::from( + $red, + $green, + $blue, + ), + ), ), ); } @@ -384,11 +411,11 @@ private static function fromHexadecimalWithoutAlpha(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function fromRGBFunction(Str $colour): Maybe + private static function fromRGBFunction(Str $colour): Attempt { - return self::fromRGBFunctionWithPoints($colour)->otherwise( + return self::fromRGBFunctionWithPoints($colour)->recover( static fn() => self::fromRGBFunctionWithPercents($colour), ); } @@ -396,34 +423,41 @@ private static function fromRGBFunction(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function fromRGBFunctionWithPoints(Str $colour): Maybe + private static function fromRGBFunctionWithPoints(Str $colour): Attempt { $matches = $colour ->capture(self::RGB_FUNCTION_PATTERN) ->map(static fn($_, $match) => $match->toString()); $red = $matches ->get('red') - ->filter(static fn($red) => \is_numeric($red)) + ->filter(\is_numeric(...)) ->map(static fn($red) => (int) $red) - ->flatMap(static fn($red) => Red::of($red)); + ->attempt(static fn() => new \DomainException("Red not found in '{$colour->toString()}'")) + ->flatMap(Red::of(...)); $green = $matches ->get('green') - ->filter(static fn($green) => \is_numeric($green)) + ->filter(\is_numeric(...)) ->map(static fn($green) => (int) $green) - ->flatMap(static fn($green) => Green::of($green)); + ->attempt(static fn() => new \DomainException("Grren not found in '{$colour->toString()}'")) + ->flatMap(Green::of(...)); $blue = $matches ->get('blue') - ->filter(static fn($blue) => \is_numeric($blue)) + ->filter(\is_numeric(...)) ->map(static fn($blue) => (int) $blue) - ->flatMap(static fn($blue) => Blue::of($blue)); - - return Maybe::all($red, $green, $blue)->map( - static fn(Red $red, Green $green, Blue $blue) => new self( - $red, - $green, - $blue, + ->attempt(static fn() => new \DomainException("Blue not found in '{$colour->toString()}'")) + ->flatMap(Blue::of(...)); + + return $red->flatMap( + static fn($red) => $green->flatMap( + static fn($green) => $blue->map( + static fn($blue) => self::from( + $red, + $green, + $blue, + ), + ), ), ); } @@ -431,37 +465,44 @@ private static function fromRGBFunctionWithPoints(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function fromRGBFunctionWithPercents(Str $colour): Maybe + private static function fromRGBFunctionWithPercents(Str $colour): Attempt { $matches = $colour ->capture(self::PERCENTED_RGB_FUNCTION_PATTERN) ->map(static fn($_, $match) => $match->toString()); $red = $matches ->get('red') - ->filter(static fn($red) => \is_numeric($red)) + ->filter(\is_numeric(...)) ->map(static fn($red) => (int) $red) - ->flatMap(static fn($red) => Intensity::of($red)) - ->flatMap(static fn($red) => Red::fromIntensity($red)); + ->attempt(static fn() => new \DomainException("Red not found in '{$colour->toString()}'")) + ->flatMap(Intensity::of(...)) + ->flatMap(Red::fromIntensity(...)); $green = $matches ->get('green') - ->filter(static fn($green) => \is_numeric($green)) + ->filter(\is_numeric(...)) ->map(static fn($green) => (int) $green) - ->flatMap(static fn($green) => Intensity::of($green)) - ->flatMap(static fn($green) => Green::fromIntensity($green)); + ->attempt(static fn() => new \DomainException("Green not found in '{$colour->toString()}'")) + ->flatMap(Intensity::of(...)) + ->flatMap(Green::fromIntensity(...)); $blue = $matches ->get('blue') - ->filter(static fn($blue) => \is_numeric($blue)) + ->filter(\is_numeric(...)) ->map(static fn($blue) => (int) $blue) - ->flatMap(static fn($blue) => Intensity::of($blue)) - ->flatMap(static fn($blue) => Blue::fromIntensity($blue)); - - return Maybe::all($red, $green, $blue)->map( - static fn(Red $red, Green $green, Blue $blue) => new self( - $red, - $green, - $blue, + ->attempt(static fn() => new \DomainException("Blue not found in '{$colour->toString()}'")) + ->flatMap(Intensity::of(...)) + ->flatMap(Blue::fromIntensity(...)); + + return $red->flatMap( + static fn($red) => $green->flatMap( + static fn($green) => $blue->map( + static fn($blue) => self::from( + $red, + $green, + $blue, + ), + ), ), ); } @@ -469,11 +510,11 @@ private static function fromRGBFunctionWithPercents(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function fromRGBAFunction(Str $colour): Maybe + private static function fromRGBAFunction(Str $colour): Attempt { - return self::fromRGBAFunctionWithPoints($colour)->otherwise( + return self::fromRGBAFunctionWithPoints($colour)->recover( static fn() => self::fromRGBAFunctionWithPercents($colour), ); } @@ -481,40 +522,50 @@ private static function fromRGBAFunction(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function fromRGBAFunctionWithPoints(Str $colour): Maybe + private static function fromRGBAFunctionWithPoints(Str $colour): Attempt { $matches = $colour ->capture(self::RGBA_FUNCTION_PATTERN) ->map(static fn($_, $match) => $match->toString()); $red = $matches ->get('red') - ->filter(static fn($red) => \is_numeric($red)) + ->filter(\is_numeric(...)) ->map(static fn($red) => (int) $red) - ->flatMap(static fn($red) => Red::of($red)); + ->attempt(static fn() => new \DomainException("Red not found in '{$colour->toString()}'")) + ->flatMap(Red::of(...)); $green = $matches ->get('green') - ->filter(static fn($green) => \is_numeric($green)) + ->filter(\is_numeric(...)) ->map(static fn($green) => (int) $green) - ->flatMap(static fn($green) => Green::of($green)); + ->attempt(static fn() => new \DomainException("Green not found in '{$colour->toString()}'")) + ->flatMap(Green::of(...)); $blue = $matches ->get('blue') ->filter(static fn($blue) => \is_numeric($blue)) ->map(static fn($blue) => (int) $blue) - ->flatMap(static fn($blue) => Blue::of($blue)); + ->attempt(static fn() => new \DomainException("Blue not found in '{$colour->toString()}'")) + ->flatMap(Blue::of(...)); $alpha = $matches ->get('alpha') - ->filter(static fn($alpha) => \is_numeric($alpha)) + ->filter(\is_numeric(...)) ->map(static fn($alpha) => (float) $alpha) - ->flatMap(static fn($alpha) => Alpha::of($alpha)); - - return Maybe::all($red, $green, $blue, $alpha)->map( - static fn(Red $red, Green $green, Blue $blue, Alpha $alpha) => new self( - $red, - $green, - $blue, - $alpha, + ->attempt(static fn() => new \DomainException("Alpha not found in '{$colour->toString()}'")) + ->flatMap(Alpha::of(...)); + + return $red->flatMap( + static fn($red) => $green->flatMap( + static fn($green) => $blue->flatMap( + static fn($blue) => $alpha->map( + static fn($alpha) => self::from( + $red, + $green, + $blue, + $alpha, + ), + ), + ), ), ); } @@ -522,43 +573,53 @@ private static function fromRGBAFunctionWithPoints(Str $colour): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - private static function fromRGBAFunctionWithPercents(Str $colour): Maybe + private static function fromRGBAFunctionWithPercents(Str $colour): Attempt { $matches = $colour ->capture(self::PERCENTED_RGBA_FUNCTION_PATTERN) ->map(static fn($_, $match) => $match->toString()); $red = $matches ->get('red') - ->filter(static fn($red) => \is_numeric($red)) + ->filter(\is_numeric(...)) ->map(static fn($red) => (int) $red) - ->flatMap(static fn($red) => Intensity::of($red)) - ->flatMap(static fn($red) => Red::fromIntensity($red)); + ->attempt(static fn() => new \DomainException("Red not found in '{$colour->toString()}'")) + ->flatMap(Intensity::of(...)) + ->flatMap(Red::fromIntensity(...)); $green = $matches ->get('green') - ->filter(static fn($green) => \is_numeric($green)) + ->filter(\is_numeric(...)) ->map(static fn($green) => (int) $green) - ->flatMap(static fn($green) => Intensity::of($green)) - ->flatMap(static fn($green) => Green::fromIntensity($green)); + ->attempt(static fn() => new \DomainException("Green not found in '{$colour->toString()}'")) + ->flatMap(Intensity::of(...)) + ->flatMap(Green::fromIntensity(...)); $blue = $matches ->get('blue') - ->filter(static fn($blue) => \is_numeric($blue)) + ->filter(\is_numeric(...)) ->map(static fn($blue) => (int) $blue) - ->flatMap(static fn($blue) => Intensity::of($blue)) - ->flatMap(static fn($blue) => Blue::fromIntensity($blue)); + ->attempt(static fn() => new \DomainException("Blue not found in '{$colour->toString()}'")) + ->flatMap(Intensity::of(...)) + ->flatMap(Blue::fromIntensity(...)); $alpha = $matches ->get('alpha') - ->filter(static fn($alpha) => \is_numeric($alpha)) + ->filter(\is_numeric(...)) ->map(static fn($alpha) => (float) $alpha) - ->flatMap(static fn($alpha) => Alpha::of($alpha)); - - return Maybe::all($red, $green, $blue, $alpha)->map( - static fn(Red $red, Green $green, Blue $blue, Alpha $alpha) => new self( - $red, - $green, - $blue, - $alpha, + ->attempt(static fn() => new \DomainException("Alpha not found in '{$colour->toString()}'")) + ->flatMap(Alpha::of(...)); + + return $red->flatMap( + static fn($red) => $green->flatMap( + static fn($green) => $blue->flatMap( + static fn($blue) => $alpha->map( + static fn($alpha) => self::from( + $red, + $green, + $blue, + $alpha, + ), + ), + ), ), ); } diff --git a/src/Red.php b/src/Red.php index 410393b..aa7b456 100644 --- a/src/Red.php +++ b/src/Red.php @@ -3,49 +3,51 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Red { - private int $integer; + /** + * @param int<0, 255> $integer + */ + private function __construct( + private int $integer, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 255> $value */ - public function __construct(int $integer) + public static function at(int $value): self { - if ($integer < 0 || $integer > 255) { - throw new InvalidValueRangeException((string) $integer); - } - - $this->integer = $integer; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 255) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function fromHexadecimal(string $hex): Maybe + public static function fromHexadecimal(string $hex): Attempt { if (\mb_strlen($hex) === 1) { $hex .= $hex; @@ -57,9 +59,9 @@ public static function fromHexadecimal(string $hex): Maybe /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function fromIntensity(Intensity $intensity): Maybe + public static function fromIntensity(Intensity $intensity): Attempt { return self::of( (int) \round((255 * $intensity->toInt()) / 100), @@ -101,6 +103,9 @@ public function atMinimum(): bool return $this->integer === 0; } + /** + * @return int<0, 255> + */ public function toInt(): int { return $this->integer; diff --git a/src/Saturation.php b/src/Saturation.php index 0240522..ee3034f 100644 --- a/src/Saturation.php +++ b/src/Saturation.php @@ -3,41 +3,43 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Saturation { - private int $value; + /** + * @param int<0, 100> $value + */ + private function __construct( + private int $value, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 100> $value */ - public function __construct(int $value) + public static function at(int $value): self { - if ($value < 0 || $value > 100) { - throw new InvalidValueRangeException((string) $value); - } - - $this->value = $value; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 100) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } public function add(self $saturation): self @@ -75,6 +77,9 @@ public function atMinimum(): bool return $this->value === 0; } + /** + * @return int<0, 100> + */ public function toInt(): int { return $this->value; diff --git a/src/Yellow.php b/src/Yellow.php index de646c0..697d7e7 100644 --- a/src/Yellow.php +++ b/src/Yellow.php @@ -3,41 +3,43 @@ namespace Innmind\Colour; -use Innmind\Colour\Exception\InvalidValueRangeException; -use Innmind\Immutable\Maybe; +use Innmind\Immutable\Attempt; /** * @psalm-immutable */ final class Yellow { - private int $value; + /** + * @param int<0, 100> $value + */ + private function __construct( + private int $value, + ) { + } /** - * @throws InvalidValueRangeException + * @psalm-pure + * + * @param int<0, 100> $value */ - public function __construct(int $value) + public static function at(int $value): self { - if ($value < 0 || $value > 100) { - throw new InvalidValueRangeException((string) $value); - } - - $this->value = $value; + return new self($value); } /** * @psalm-pure * - * @return Maybe + * @return Attempt */ - public static function of(int $value): Maybe + public static function of(int $value): Attempt { - try { - return Maybe::just(new self($value)); - } catch (InvalidValueRangeException $e) { - /** @var Maybe */ - return Maybe::nothing(); + if ($value < 0 || $value > 100) { + return Attempt::error(new \OutOfBoundsException((string) $value)); } + + return Attempt::result(new self($value)); } public function add(self $yellow): self @@ -75,6 +77,9 @@ public function atMinimum(): bool return $this->value === 0; } + /** + * @return int<0, 100> + */ public function toInt(): int { return $this->value; diff --git a/tests/AlphaTest.php b/tests/AlphaTest.php index f4fd246..2806c6b 100644 --- a/tests/AlphaTest.php +++ b/tests/AlphaTest.php @@ -3,17 +3,15 @@ namespace Tests\Innmind\Colour; -use Innmind\Colour\{ - Alpha, - Exception\InvalidValueRangeException, -}; -use PHPUnit\Framework\TestCase; +use Innmind\Colour\Alpha; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; class AlphaTest extends TestCase { public function testInterface() { - $alpha = new Alpha(0.5); + $alpha = Alpha::of(0.5)->unwrap(); $this->assertSame(0.5, $alpha->toFloat()); $this->assertSame('0.5', $alpha->toString()); @@ -21,68 +19,67 @@ public function testInterface() public function testAdd() { - $alpha = (new Alpha(0.12))->add(new Alpha(0.30)); + $alpha = Alpha::of(0.12)->unwrap()->add(Alpha::of(0.30)->unwrap()); $this->assertInstanceOf(Alpha::class, $alpha); $this->assertSame(0.42, $alpha->toFloat()); $this->assertSame( 1.0, - (new Alpha(0.6))->add(new Alpha(0.7))->toFloat(), + Alpha::of(0.6)->unwrap()->add(Alpha::of(0.7)->unwrap())->toFloat(), ); } public function testSub() { - $alpha = (new Alpha(0.54))->subtract(new Alpha(0.12)); + $alpha = Alpha::of(0.54)->unwrap()->subtract(Alpha::of(0.12)->unwrap()); $this->assertInstanceOf(Alpha::class, $alpha); - $this->assertEqualsWithDelta(0.42, $alpha->toFloat(), 0.001); + $this->assertGreaterThanOrEqual(0.4199, $alpha->toFloat()); + $this->assertLessThanOrEqual(0.421, $alpha->toFloat()); $this->assertSame( 0.0, - (new Alpha(0.5))->subtract(new Alpha(0.7))->toFloat(), + Alpha::of(0.5)->unwrap()->subtract(Alpha::of(0.7)->unwrap())->toFloat(), ); } public function testThrowWhenValueIsTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-0.1'); - new Alpha(-0.1); + $_ = Alpha::of(-0.1)->unwrap(); } public function testThrowWhenValueIsTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('1.1'); - new Alpha(1.1); + $_ = Alpha::of(1.1)->unwrap(); } public function testAtMaximum() { - $this->assertTrue((new Alpha(1))->atMaximum()); - $this->assertFalse((new Alpha(0))->atMaximum()); - $this->assertFalse((new Alpha(0.5))->atMaximum()); + $this->assertTrue(Alpha::of(1)->unwrap()->atMaximum()); + $this->assertFalse(Alpha::of(0)->unwrap()->atMaximum()); + $this->assertFalse(Alpha::of(0.5)->unwrap()->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Alpha(1))->atMinimum()); - $this->assertTrue((new Alpha(0))->atMinimum()); - $this->assertFalse((new Alpha(0.5))->atMinimum()); + $this->assertFalse(Alpha::of(1)->unwrap()->atMinimum()); + $this->assertTrue(Alpha::of(0)->unwrap()->atMinimum()); + $this->assertFalse(Alpha::of(0.5)->unwrap()->atMinimum()); } - /** - * @dataProvider hexadecimals - */ + #[DataProvider('hexadecimals')] public function testHexadecimal($hex, $percent) { $this->assertSame( $hex, - (new Alpha($percent))->toHexadecimal(), + Alpha::of($percent)->unwrap()->toHexadecimal(), ); $alpha = Alpha::fromHexadecimal($hex)->match( @@ -122,7 +119,7 @@ public static function hexadecimals() public function testEquals() { - $this->assertTrue((new Alpha(0.5))->equals(new Alpha(0.5))); - $this->assertFalse((new Alpha(1.0))->equals(new Alpha(0.5))); + $this->assertTrue(Alpha::of(0.5)->unwrap()->equals(Alpha::of(0.5)->unwrap())); + $this->assertFalse(Alpha::of(1.0)->unwrap()->equals(Alpha::of(0.5)->unwrap())); } } diff --git a/tests/BlackTest.php b/tests/BlackTest.php index c78d5cc..132ad72 100644 --- a/tests/BlackTest.php +++ b/tests/BlackTest.php @@ -3,17 +3,14 @@ namespace Tests\Innmind\Colour; -use Innmind\Colour\{ - Black, - Exception\InvalidValueRangeException, -}; -use PHPUnit\Framework\TestCase; +use Innmind\Colour\Black; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class BlackTest extends TestCase { public function testInterface() { - $black = new Black(50); + $black = Black::at(50); $this->assertSame(50, $black->toInt()); $this->assertSame('50', $black->toString()); @@ -21,25 +18,25 @@ public function testInterface() public function testThrowWhenValueTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-1'); - new Black(-1); + $_ = Black::of(-1)->unwrap(); } public function testThrowWhenValueTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('101'); - new Black(101); + $_ = Black::of(101)->unwrap(); } public function testAdd() { - $black = new Black(50); + $black = Black::at(50); - $black2 = $black->add(new Black(25)); + $black2 = $black->add(Black::at(25)); $this->assertInstanceOf(Black::class, $black2); $this->assertNotSame($black, $black2); @@ -49,9 +46,9 @@ public function testAdd() public function testSubtract() { - $black = new Black(50); + $black = Black::at(50); - $black2 = $black->subtract(new Black(25)); + $black2 = $black->subtract(Black::at(25)); $this->assertInstanceOf(Black::class, $black2); $this->assertNotSame($black, $black2); @@ -61,21 +58,21 @@ public function testSubtract() public function testEquals() { - $this->assertTrue((new Black(50))->equals(new Black(50))); - $this->assertFalse((new Black(100))->equals(new Black(50))); + $this->assertTrue(Black::at(50)->equals(Black::at(50))); + $this->assertFalse(Black::at(100)->equals(Black::at(50))); } public function testAtMaximum() { - $this->assertTrue((new Black(100))->atMaximum()); - $this->assertFalse((new Black(0))->atMaximum()); - $this->assertFalse((new Black(50))->atMaximum()); + $this->assertTrue(Black::at(100)->atMaximum()); + $this->assertFalse(Black::at(0)->atMaximum()); + $this->assertFalse(Black::at(50)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Black(100))->atMinimum()); - $this->assertTrue((new Black(0))->atMinimum()); - $this->assertFalse((new Black(50))->atMinimum()); + $this->assertFalse(Black::at(100)->atMinimum()); + $this->assertTrue(Black::at(0)->atMinimum()); + $this->assertFalse(Black::at(50)->atMinimum()); } } diff --git a/tests/BlueTest.php b/tests/BlueTest.php index a31322b..14836b3 100644 --- a/tests/BlueTest.php +++ b/tests/BlueTest.php @@ -6,15 +6,14 @@ use Innmind\Colour\{ Blue, Intensity, - Exception\InvalidValueRangeException, }; -use PHPUnit\Framework\TestCase; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class BlueTest extends TestCase { public function testInterface() { - $blue = new Blue(255); + $blue = Blue::at(255); $this->assertSame(255, $blue->toInt()); $this->assertSame('ff', $blue->toString()); @@ -34,63 +33,63 @@ public function testFromHexadecimal() public function testAdd() { - $blue = (new Blue(12))->add(new Blue(30)); + $blue = Blue::at(12)->add(Blue::at(30)); $this->assertInstanceOf(Blue::class, $blue); $this->assertSame(42, $blue->toInt()); $this->assertSame( 255, - (new Blue(150))->add(new Blue(150))->toInt(), + Blue::at(150)->add(Blue::at(150))->toInt(), ); } public function testSub() { - $blue = (new Blue(54))->subtract(new Blue(12)); + $blue = Blue::at(54)->subtract(Blue::at(12)); $this->assertInstanceOf(Blue::class, $blue); $this->assertSame(42, $blue->toInt()); $this->assertSame( 0, - (new Blue(150))->subtract(new Blue(255))->toInt(), + Blue::at(150)->subtract(Blue::at(255))->toInt(), ); } public function testThrowWhenValueIsTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-42'); - new Blue(-42); + $_ = Blue::of(-42)->unwrap(); } public function testThrowWhenValueIsTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('512'); - new Blue(512); + $_ = Blue::of(512)->unwrap(); } public function testAtMaximum() { - $this->assertTrue((new Blue(255))->atMaximum()); - $this->assertFalse((new Blue(0))->atMaximum()); - $this->assertFalse((new Blue(122))->atMaximum()); + $this->assertTrue(Blue::at(255)->atMaximum()); + $this->assertFalse(Blue::at(0)->atMaximum()); + $this->assertFalse(Blue::at(122)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Blue(255))->atMinimum()); - $this->assertTrue((new Blue(0))->atMinimum()); - $this->assertFalse((new Blue(122))->atMinimum()); + $this->assertFalse(Blue::at(255)->atMinimum()); + $this->assertTrue(Blue::at(0)->atMinimum()); + $this->assertFalse(Blue::at(122)->atMinimum()); } public function testFromIntensity() { - $blue = Blue::fromIntensity(new Intensity(100))->match( + $blue = Blue::fromIntensity(Intensity::at(100))->match( static fn($blue) => $blue, static fn() => null, ); @@ -99,28 +98,28 @@ public function testFromIntensity() $this->assertSame(255, $blue->toInt()); $this->assertSame( 191, - Blue::fromIntensity(new Intensity(75))->match( + Blue::fromIntensity(Intensity::at(75))->match( static fn($blue) => $blue->toInt(), static fn() => null, ), ); $this->assertSame( 128, - Blue::fromIntensity(new Intensity(50))->match( + Blue::fromIntensity(Intensity::at(50))->match( static fn($blue) => $blue->toInt(), static fn() => null, ), ); $this->assertSame( 64, - Blue::fromIntensity(new Intensity(25))->match( + Blue::fromIntensity(Intensity::at(25))->match( static fn($blue) => $blue->toInt(), static fn() => null, ), ); $this->assertSame( 0, - Blue::fromIntensity(new Intensity(0))->match( + Blue::fromIntensity(Intensity::at(0))->match( static fn($blue) => $blue->toInt(), static fn() => null, ), @@ -129,7 +128,7 @@ public function testFromIntensity() public function testEquals() { - $this->assertTrue((new Blue(50))->equals(new Blue(50))); - $this->assertFalse((new Blue(100))->equals(new Blue(50))); + $this->assertTrue(Blue::at(50)->equals(Blue::at(50))); + $this->assertFalse(Blue::at(100)->equals(Blue::at(50))); } } diff --git a/tests/CMYKATest.php b/tests/CMYKATest.php index 668e6e2..f7fb1d1 100644 --- a/tests/CMYKATest.php +++ b/tests/CMYKATest.php @@ -12,17 +12,18 @@ Alpha, RGBA, }; -use PHPUnit\Framework\TestCase; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; class CMYKATest extends TestCase { public function testInterface() { - $cmyk = new CMYKA( - $cyan = new Cyan(10), - $magenta = new Magenta(20), - $yellow = new Yellow(30), - $black = new Black(40), + $cmyk = CMYKA::from( + $cyan = Cyan::at(10), + $magenta = Magenta::at(20), + $yellow = Yellow::at(30), + $black = Black::at(40), ); $this->assertSame($cyan, $cmyk->cyan()); @@ -32,12 +33,12 @@ public function testInterface() $this->assertSame(1.0, $cmyk->alpha()->toFloat()); $this->assertSame('device-cmyk(10%, 20%, 30%, 40%)', $cmyk->toString()); - $cmyka = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), - $alpha = new Alpha(0.5), + $cmyka = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), + $alpha = Alpha::of(0.5)->unwrap(), ); $this->assertSame($alpha, $cmyka->alpha()); @@ -46,14 +47,14 @@ public function testInterface() public function testAddCyan() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), ); - $cmyk2 = $cmyk->addCyan(new Cyan(1)); + $cmyk2 = $cmyk->addCyan(Cyan::at(1)); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -71,14 +72,14 @@ public function testAddCyan() public function testSubtractCyan() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), ); - $cmyk2 = $cmyk->subtractCyan(new Cyan(1)); + $cmyk2 = $cmyk->subtractCyan(Cyan::at(1)); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -96,14 +97,14 @@ public function testSubtractCyan() public function testAddMagenta() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), ); - $cmyk2 = $cmyk->addMagenta(new Magenta(1)); + $cmyk2 = $cmyk->addMagenta(Magenta::at(1)); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -121,14 +122,14 @@ public function testAddMagenta() public function testSubtractMagenta() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), ); - $cmyk2 = $cmyk->subtractMagenta(new Magenta(1)); + $cmyk2 = $cmyk->subtractMagenta(Magenta::at(1)); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -146,14 +147,14 @@ public function testSubtractMagenta() public function testAddYellow() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), ); - $cmyk2 = $cmyk->addYellow(new Yellow(1)); + $cmyk2 = $cmyk->addYellow(Yellow::at(1)); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -171,14 +172,14 @@ public function testAddYellow() public function testSubtractYellow() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), ); - $cmyk2 = $cmyk->subtractYellow(new Yellow(1)); + $cmyk2 = $cmyk->subtractYellow(Yellow::at(1)); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -196,14 +197,14 @@ public function testSubtractYellow() public function testAddBlack() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), ); - $cmyk2 = $cmyk->addBlack(new Black(1)); + $cmyk2 = $cmyk->addBlack(Black::at(1)); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -221,14 +222,14 @@ public function testAddBlack() public function testSubtractBlack() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), ); - $cmyk2 = $cmyk->subtractBlack(new Black(1)); + $cmyk2 = $cmyk->subtractBlack(Black::at(1)); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -246,15 +247,15 @@ public function testSubtractBlack() public function testAddAlpha() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), - new Alpha(0.1), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), + Alpha::of(0.1)->unwrap(), ); - $cmyk2 = $cmyk->addAlpha(new Alpha(0.1)); + $cmyk2 = $cmyk->addAlpha(Alpha::of(0.1)->unwrap()); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -272,14 +273,14 @@ public function testAddAlpha() public function testSubtractAlpha() { - $cmyk = new CMYKA( - new Cyan(10), - new Magenta(20), - new Yellow(30), - new Black(40), + $cmyk = CMYKA::from( + Cyan::at(10), + Magenta::at(20), + Yellow::at(30), + Black::at(40), ); - $cmyk2 = $cmyk->subtractAlpha(new Alpha(0.9)); + $cmyk2 = $cmyk->subtractAlpha(Alpha::of(0.9)->unwrap()); $this->assertInstanceOf(CMYKA::class, $cmyk2); $this->assertNotSame($cmyk, $cmyk2); @@ -292,12 +293,11 @@ public function testSubtractAlpha() $this->assertSame(20, $cmyk2->magenta()->toInt()); $this->assertSame(30, $cmyk2->yellow()->toInt()); $this->assertSame(40, $cmyk2->black()->toInt()); - $this->assertEqualsWithDelta(0.1, $cmyk2->alpha()->toFloat(), 0.01); + $this->assertGreaterThanOrEqual(0.09, $cmyk2->alpha()->toFloat()); + $this->assertLessThanOrEqual(0.11, $cmyk2->alpha()->toFloat()); } - /** - * @dataProvider withAlpha - */ + #[DataProvider('withAlpha')] public function testWithAlpha( string $string, int $cyan, @@ -328,9 +328,7 @@ public static function withAlpha() ]; } - /** - * @dataProvider withoutAlpha - */ + #[DataProvider('withoutAlpha')] public function testWithoutAlpha( string $string, int $cyan, @@ -356,16 +354,14 @@ public static function withoutAlpha() ]; } - /** - * @dataProvider colours - */ + #[DataProvider('colours')] public function testOf( string $string, int $cyan, int $magenta, int $yellow, int $black, - float $alpha = null, + ?float $alpha = null, ) { $cmyka = CMYKA::of($string); diff --git a/tests/ColourTest.php b/tests/ColourTest.php index 834047f..cfd8f15 100644 --- a/tests/ColourTest.php +++ b/tests/ColourTest.php @@ -8,13 +8,24 @@ RGBA, HSLA, CMYKA, - Exception\DomainException, + Alpha, + Black, + Blue, + Cyan, + Green, + Hue, + Lightness, + Magenta, + Red, + Saturation, + Yellow, }; -use PHPUnit\Framework\TestCase; use Innmind\BlackBox\{ + PHPUnit\Framework\TestCase, PHPUnit\BlackBox, Set, }; +use PHPUnit\Framework\Attributes\DataProvider; class ColourTest extends TestCase { @@ -39,7 +50,7 @@ public function testOf() public function testReturnNothingForRandomStrings() { $this - ->forAll(Set\Unicode::strings()) + ->forAll(Set::strings()->unicode()) ->then(function($string) { $this->assertNull(Colour::maybe($string)->match( static fn($colour) => $colour, @@ -50,10 +61,10 @@ public function testReturnNothingForRandomStrings() public function testThrowWhenNoFormatRecognized() { - $this->expectException(DomainException::class); - $this->expectExceptionMessage('foo'); + $this->expectException(\DomainException::class); + $this->expectExceptionMessage("Cyan not found in 'foo'"); - Colour::of('foo'); + $_ = Colour::of('foo'); } public function testLiterals() @@ -61,9 +72,7 @@ public function testLiterals() $this->assertCount(98, Colour::cases()); } - /** - * @dataProvider literals - */ + #[DataProvider('literals')] public function testFromLiteral(Colour|RGBA $colour, string $hex) { $rgba = $colour->toRGBA(); @@ -72,6 +81,68 @@ public function testFromLiteral(Colour|RGBA $colour, string $hex) $this->assertSame($hex, $rgba->toHexadecimal()); } + public function testAllColoursAreConvertibleToAnyFormat(): BlackBox\Proof + { + $alpha = Set::realNumbers() + ->between(0, 1) + ->map(static fn($value) => Alpha::of($value)->unwrap()) + ->nullable(); + $rgba = Set::compose( + RGBA::from(...), + Set::integers() + ->between(0, 255) + ->map(Red::at(...)), + Set::integers() + ->between(0, 255) + ->map(Green::at(...)), + Set::integers() + ->between(0, 255) + ->map(Blue::at(...)), + $alpha, + ); + $cmyka = Set::compose( + CMYKA::from(...), + Set::integers() + ->between(1, 100) + ->map(Cyan::at(...)), + Set::integers() + ->between(1, 100) + ->map(Magenta::at(...)), + Set::integers() + ->between(1, 100) + ->map(Yellow::at(...)), + Set::integers() + ->between(1, 100) + ->map(Black::at(...)), + $alpha, + ); + $hsla = Set::compose( + HSLA::from(...), + Set::integers() + ->between(0, 359) + ->map(Hue::at(...)), + Set::integers() + ->between(0, 100) + ->map(Saturation::at(...)), + Set::integers() + ->between(0, 100) + ->map(Lightness::at(...)), + $alpha, + ); + + return $this + ->forAll(Set::either( + $rgba, + $cmyka, + $hsla, + )) + ->prove(function($colour) { + $this->assertInstanceOf(RGBA::class, $colour->toRGBA()); + $this->assertInstanceOf(CMYKA::class, $colour->toCMYKA()); + $this->assertInstanceOf(HSLA::class, $colour->toHSLA()); + }); + } + public static function literals() { return [ diff --git a/tests/CyanTest.php b/tests/CyanTest.php index 2539c35..b9bb10d 100644 --- a/tests/CyanTest.php +++ b/tests/CyanTest.php @@ -3,17 +3,14 @@ namespace Tests\Innmind\Colour; -use Innmind\Colour\{ - Cyan, - Exception\InvalidValueRangeException, -}; -use PHPUnit\Framework\TestCase; +use Innmind\Colour\Cyan; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class CyanTest extends TestCase { public function testInterface() { - $cyan = new Cyan(50); + $cyan = Cyan::at(50); $this->assertSame(50, $cyan->toInt()); $this->assertSame('50', $cyan->toString()); @@ -21,25 +18,25 @@ public function testInterface() public function testThrowWhenValueTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-1'); - new Cyan(-1); + $_ = Cyan::of(-1)->unwrap(); } public function testThrowWhenValueTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('101'); - new Cyan(101); + $_ = Cyan::of(101)->unwrap(); } public function testAdd() { - $cyan = new Cyan(50); + $cyan = Cyan::at(50); - $cyan2 = $cyan->add(new Cyan(25)); + $cyan2 = $cyan->add(Cyan::at(25)); $this->assertInstanceOf(Cyan::class, $cyan2); $this->assertNotSame($cyan, $cyan2); @@ -49,9 +46,9 @@ public function testAdd() public function testSubtract() { - $cyan = new Cyan(50); + $cyan = Cyan::at(50); - $cyan2 = $cyan->subtract(new Cyan(25)); + $cyan2 = $cyan->subtract(Cyan::at(25)); $this->assertInstanceOf(Cyan::class, $cyan2); $this->assertNotSame($cyan, $cyan2); @@ -61,21 +58,21 @@ public function testSubtract() public function testEquals() { - $this->assertTrue((new Cyan(50))->equals(new Cyan(50))); - $this->assertFalse((new Cyan(100))->equals(new Cyan(50))); + $this->assertTrue(Cyan::at(50)->equals(Cyan::at(50))); + $this->assertFalse(Cyan::at(100)->equals(Cyan::at(50))); } public function testAtMaximum() { - $this->assertTrue((new Cyan(100))->atMaximum()); - $this->assertFalse((new Cyan(0))->atMaximum()); - $this->assertFalse((new Cyan(50))->atMaximum()); + $this->assertTrue(Cyan::at(100)->atMaximum()); + $this->assertFalse(Cyan::at(0)->atMaximum()); + $this->assertFalse(Cyan::at(50)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Cyan(100))->atMinimum()); - $this->assertTrue((new Cyan(0))->atMinimum()); - $this->assertFalse((new Cyan(50))->atMinimum()); + $this->assertFalse(Cyan::at(100)->atMinimum()); + $this->assertTrue(Cyan::at(0)->atMinimum()); + $this->assertFalse(Cyan::at(50)->atMinimum()); } } diff --git a/tests/Fixtures/ColourTest.php b/tests/Fixtures/ColourTest.php index 91a02f7..ff3d2ec 100644 --- a/tests/Fixtures/ColourTest.php +++ b/tests/Fixtures/ColourTest.php @@ -6,10 +6,10 @@ use Fixtures\Innmind\Colour\Colour; use Innmind\Colour\RGBA; use Innmind\BlackBox\{ + PHPUnit\Framework\TestCase, Set, Random, }; -use PHPUnit\Framework\TestCase; class ColourTest extends TestCase { @@ -21,13 +21,7 @@ public function testInterface() foreach ($set->values(Random::default) as $value) { $this->assertInstanceOf(Set\Value::class, $value); - - if (\interface_exists(Set\Implementation::class)) { - $this->assertTrue($value->immutable()); - } else { - $this->assertTrue($value->isImmutable()); - } - + $this->assertTrue($value->immutable()); $this->assertInstanceOf(RGBA::class, $value->unwrap()); } } diff --git a/tests/GreenTest.php b/tests/GreenTest.php index fc310ac..025aaee 100644 --- a/tests/GreenTest.php +++ b/tests/GreenTest.php @@ -6,15 +6,14 @@ use Innmind\Colour\{ Green, Intensity, - Exception\InvalidValueRangeException, }; -use PHPUnit\Framework\TestCase; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class GreenTest extends TestCase { public function testInterface() { - $green = new Green(255); + $green = Green::at(255); $this->assertSame(255, $green->toInt()); $this->assertSame('ff', $green->toString()); @@ -34,63 +33,63 @@ public function testFromHexadecimal() public function testAdd() { - $Green = (new Green(12))->add(new Green(30)); + $Green = Green::at(12)->add(Green::at(30)); $this->assertInstanceOf(Green::class, $Green); $this->assertSame(42, $Green->toInt()); $this->assertSame( 255, - (new Green(150))->add(new Green(150))->toInt(), + Green::at(150)->add(Green::at(150))->toInt(), ); } public function testSub() { - $green = (new Green(54))->subtract(new Green(12)); + $green = Green::at(54)->subtract(Green::at(12)); $this->assertInstanceOf(Green::class, $green); $this->assertSame(42, $green->toInt()); $this->assertSame( 0, - (new Green(150))->subtract(new Green(255))->toInt(), + Green::at(150)->subtract(Green::at(255))->toInt(), ); } public function testThrowWhenValueIsTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-42'); - new Green(-42); + $_ = Green::of(-42)->unwrap(); } public function testThrowWhenValueIsTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('512'); - new Green(512); + $_ = Green::of(512)->unwrap(); } public function testAtMaximum() { - $this->assertTrue((new Green(255))->atMaximum()); - $this->assertFalse((new Green(0))->atMaximum()); - $this->assertFalse((new Green(122))->atMaximum()); + $this->assertTrue(Green::at(255)->atMaximum()); + $this->assertFalse(Green::at(0)->atMaximum()); + $this->assertFalse(Green::at(122)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Green(255))->atMinimum()); - $this->assertTrue((new Green(0))->atMinimum()); - $this->assertFalse((new Green(122))->atMinimum()); + $this->assertFalse(Green::at(255)->atMinimum()); + $this->assertTrue(Green::at(0)->atMinimum()); + $this->assertFalse(Green::at(122)->atMinimum()); } public function testFromIntensity() { - $green = Green::fromIntensity(new Intensity(100))->match( + $green = Green::fromIntensity(Intensity::at(100))->match( static fn($green) => $green, static fn() => null, ); @@ -99,28 +98,28 @@ public function testFromIntensity() $this->assertSame(255, $green->toInt()); $this->assertSame( 191, - Green::fromIntensity(new Intensity(75))->match( + Green::fromIntensity(Intensity::at(75))->match( static fn($green) => $green->toInt(), static fn() => null, ), ); $this->assertSame( 128, - Green::fromIntensity(new Intensity(50))->match( + Green::fromIntensity(Intensity::at(50))->match( static fn($green) => $green->toInt(), static fn() => null, ), ); $this->assertSame( 64, - Green::fromIntensity(new Intensity(25))->match( + Green::fromIntensity(Intensity::at(25))->match( static fn($green) => $green->toInt(), static fn() => null, ), ); $this->assertSame( 0, - Green::fromIntensity(new Intensity(0))->match( + Green::fromIntensity(Intensity::at(0))->match( static fn($green) => $green->toInt(), static fn() => null, ), @@ -129,7 +128,7 @@ public function testFromIntensity() public function testEquals() { - $this->assertTrue((new Green(50))->equals(new Green(50))); - $this->assertFalse((new Green(100))->equals(new Green(50))); + $this->assertTrue(Green::at(50)->equals(Green::at(50))); + $this->assertFalse(Green::at(100)->equals(Green::at(50))); } } diff --git a/tests/HSLATest.php b/tests/HSLATest.php index 5d31a9a..e3eaf21 100644 --- a/tests/HSLATest.php +++ b/tests/HSLATest.php @@ -12,16 +12,17 @@ RGBA, CMYKA, }; -use PHPUnit\Framework\TestCase; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; class HSLATest extends TestCase { public function testInterface() { - $hsl = new HSLA( - $hue = new Hue(150), - $saturation = new Saturation(42), - $lightness = new Lightness(24), + $hsl = HSLA::from( + $hue = Hue::at(150), + $saturation = Saturation::at(42), + $lightness = Lightness::at(24), ); $this->assertSame($hue, $hsl->hue()); @@ -30,11 +31,11 @@ public function testInterface() $this->assertSame(1.0, $hsl->alpha()->toFloat()); $this->assertSame('hsl(150, 42%, 24%)', $hsl->toString()); - $hsla = new HSLA( - new Hue(150), - new Saturation(42), - new Lightness(24), - $alpha = new Alpha(0.5), + $hsla = HSLA::from( + Hue::at(150), + Saturation::at(42), + Lightness::at(24), + $alpha = Alpha::of(0.5)->unwrap(), ); $this->assertSame($alpha, $hsla->alpha()); @@ -43,10 +44,10 @@ public function testInterface() public function testRotateBy() { - $hsl = new HSLA( - new Hue(150), - new Saturation(42), - new Lightness(24), + $hsl = HSLA::from( + Hue::at(150), + Saturation::at(42), + Lightness::at(24), ); $hsl2 = $hsl->rotateBy(50); @@ -65,13 +66,13 @@ public function testRotateBy() public function testAddSaturation() { - $hsl = new HSLA( - new Hue(150), - new Saturation(42), - new Lightness(24), + $hsl = HSLA::from( + Hue::at(150), + Saturation::at(42), + Lightness::at(24), ); - $hsl2 = $hsl->addSaturation(new Saturation(58)); + $hsl2 = $hsl->addSaturation(Saturation::at(58)); $this->assertInstanceOf(HSLA::class, $hsl2); $this->assertNotSame($hsl, $hsl2); @@ -87,13 +88,13 @@ public function testAddSaturation() public function testSubtractSaturation() { - $hsl = new HSLA( - new Hue(150), - new Saturation(42), - new Lightness(24), + $hsl = HSLA::from( + Hue::at(150), + Saturation::at(42), + Lightness::at(24), ); - $hsl2 = $hsl->SubtractSaturation(new Saturation(22)); + $hsl2 = $hsl->SubtractSaturation(Saturation::at(22)); $this->assertInstanceOf(HSLA::class, $hsl2); $this->assertNotSame($hsl, $hsl2); @@ -109,13 +110,13 @@ public function testSubtractSaturation() public function testAddLightness() { - $hsl = new HSLA( - new Hue(150), - new Saturation(42), - new Lightness(24), + $hsl = HSLA::from( + Hue::at(150), + Saturation::at(42), + Lightness::at(24), ); - $hsl2 = $hsl->addLightness(new Lightness(6)); + $hsl2 = $hsl->addLightness(Lightness::at(6)); $this->assertInstanceOf(HSLA::class, $hsl2); $this->assertNotSame($hsl, $hsl2); @@ -131,13 +132,13 @@ public function testAddLightness() public function testSubtractLightness() { - $hsl = new HSLA( - new Hue(150), - new Saturation(42), - new Lightness(24), + $hsl = HSLA::from( + Hue::at(150), + Saturation::at(42), + Lightness::at(24), ); - $hsl2 = $hsl->subtractLightness(new Lightness(22)); + $hsl2 = $hsl->subtractLightness(Lightness::at(22)); $this->assertInstanceOf(HSLA::class, $hsl2); $this->assertNotSame($hsl, $hsl2); @@ -153,14 +154,14 @@ public function testSubtractLightness() public function testAddAlpha() { - $hsl = new HSLA( - new Hue(150), - new Saturation(42), - new Lightness(24), - new Alpha(0.1), + $hsl = HSLA::from( + Hue::at(150), + Saturation::at(42), + Lightness::at(24), + Alpha::of(0.1)->unwrap(), ); - $hsl2 = $hsl->addALpha(new Alpha(0.1)); + $hsl2 = $hsl->addALpha(Alpha::of(0.1)->unwrap()); $this->assertInstanceOf(HSLA::class, $hsl2); $this->assertNotSame($hsl, $hsl2); @@ -176,13 +177,13 @@ public function testAddAlpha() public function testSubtractAlpha() { - $hsl = new HSLA( - new Hue(150), - new Saturation(42), - new Lightness(24), + $hsl = HSLA::from( + Hue::at(150), + Saturation::at(42), + Lightness::at(24), ); - $hsl2 = $hsl->subtractAlpha(new Alpha(0.3)); + $hsl2 = $hsl->subtractAlpha(Alpha::of(0.3)->unwrap()); $this->assertInstanceOf(HSLA::class, $hsl2); $this->assertNotSame($hsl, $hsl2); @@ -196,9 +197,7 @@ public function testSubtractAlpha() $this->assertSame(0.7, $hsl2->alpha()->toFloat()); } - /** - * @dataProvider withAlpha - */ + #[DataProvider('withAlpha')] public function testWithAlpha( string $string, int $hue, @@ -227,9 +226,7 @@ public static function withAlpha() ]; } - /** - * @dataProvider withoutAlpha - */ + #[DataProvider('withoutAlpha')] public function testWithoutAlpha( string $string, int $hue, @@ -253,15 +250,13 @@ public static function withoutAlpha() ]; } - /** - * @dataProvider colours - */ + #[DataProvider('colours')] public function testOf( string $string, int $hue, int $saturation, int $lightness, - float $alpha = null, + ?float $alpha = null, ) { $hsla = HSLA::of($string); diff --git a/tests/HueTest.php b/tests/HueTest.php index 25bb368..8536b56 100644 --- a/tests/HueTest.php +++ b/tests/HueTest.php @@ -3,17 +3,15 @@ namespace Tests\Innmind\Colour; -use Innmind\Colour\{ - Hue, - Exception\InvalidValueRangeException, -}; -use PHPUnit\Framework\TestCase; +use Innmind\Colour\Hue; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; class HueTest extends TestCase { public function testInterface() { - $hue = new Hue(260); + $hue = Hue::at(260); $this->assertSame(260, $hue->toInt()); $this->assertSame('260', $hue->toString()); @@ -21,26 +19,24 @@ public function testInterface() public function testThrowWhenValueTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-20'); - new Hue(-20); + $_ = Hue::of(-20)->unwrap(); } public function testThrowWhenValueTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('360'); - new Hue(360); + $_ = Hue::of(360)->unwrap(); } - /** - * @dataProvider rotations - */ + #[DataProvider('rotations')] public function testRotateBy($initial, $degrees, $expected) { - $hue = (new Hue($initial))->rotateBy($degrees); + $hue = Hue::at($initial)->rotateBy($degrees); $this->assertInstanceOf(Hue::class, $hue); $this->assertSame($expected, $hue->toInt()); @@ -58,7 +54,7 @@ public static function rotations(): array public function testOpposite() { - $hue = (new Hue(150))->opposite(); + $hue = Hue::at(150)->opposite(); $this->assertInstanceOf(Hue::class, $hue); $this->assertSame(330, $hue->toInt()); @@ -66,21 +62,21 @@ public function testOpposite() public function testEquals() { - $this->assertTrue((new Hue(50))->equals(new Hue(50))); - $this->assertFalse((new Hue(100))->equals(new Hue(50))); + $this->assertTrue(Hue::at(50)->equals(Hue::at(50))); + $this->assertFalse(Hue::at(100)->equals(Hue::at(50))); } public function testAtMaximum() { - $this->assertTrue((new Hue(359))->atMaximum()); - $this->assertFalse((new Hue(0))->atMaximum()); - $this->assertFalse((new Hue(50))->atMaximum()); + $this->assertTrue(Hue::at(359)->atMaximum()); + $this->assertFalse(Hue::at(0)->atMaximum()); + $this->assertFalse(Hue::at(50)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Hue(359))->atMinimum()); - $this->assertTrue((new Hue(0))->atMinimum()); - $this->assertFalse((new Hue(50))->atMinimum()); + $this->assertFalse(Hue::at(359)->atMinimum()); + $this->assertTrue(Hue::at(0)->atMinimum()); + $this->assertFalse(Hue::at(50)->atMinimum()); } } diff --git a/tests/IntensityTest.php b/tests/IntensityTest.php index b1c641c..532de5b 100644 --- a/tests/IntensityTest.php +++ b/tests/IntensityTest.php @@ -3,34 +3,31 @@ namespace Tests\Innmind\Colour; -use Innmind\Colour\{ - Intensity, - Exception\InvalidValueRangeException, -}; -use PHPUnit\Framework\TestCase; +use Innmind\Colour\Intensity; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class IntensityTest extends TestCase { public function testInterface() { - $intensity = new Intensity(42); + $intensity = Intensity::at(42); $this->assertSame(42, $intensity->toInt()); } public function testThrowWhenValueIsTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-1'); - new Intensity(-1); + $_ = Intensity::of(-1)->unwrap(); } public function testThrowWhenValueIsTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('101'); - new Intensity(101); + $_ = Intensity::of(101)->unwrap(); } } diff --git a/tests/LightnessTest.php b/tests/LightnessTest.php index eba5e92..80014af 100644 --- a/tests/LightnessTest.php +++ b/tests/LightnessTest.php @@ -3,17 +3,14 @@ namespace Tests\Innmind\Colour; -use Innmind\Colour\{ - Lightness, - Exception\InvalidValueRangeException, -}; -use PHPUnit\Framework\TestCase; +use Innmind\Colour\Lightness; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class LightnessTest extends TestCase { public function testInterface() { - $lightness = new Lightness(100); + $lightness = Lightness::at(100); $this->assertSame(100, $lightness->toInt()); $this->assertSame('100', $lightness->toString()); @@ -21,63 +18,63 @@ public function testInterface() public function testAdd() { - $lightness = (new Lightness(12))->add(new Lightness(30)); + $lightness = Lightness::at(12)->add(Lightness::at(30)); $this->assertInstanceOf(Lightness::class, $lightness); $this->assertSame(42, $lightness->toInt()); $this->assertSame( 100, - (new Lightness(50))->add(new Lightness(75))->toInt(), + Lightness::at(50)->add(Lightness::at(75))->toInt(), ); } public function testSub() { - $lightness = (new Lightness(54))->subtract(new Lightness(12)); + $lightness = Lightness::at(54)->subtract(Lightness::at(12)); $this->assertInstanceOf(Lightness::class, $lightness); $this->assertSame(42, $lightness->toInt()); $this->assertSame( 0, - (new Lightness(50))->subtract(new Lightness(75))->toInt(), + Lightness::at(50)->subtract(Lightness::at(75))->toInt(), ); } public function testThrowWhenValueIsTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-42'); - new Lightness(-42); + $_ = Lightness::of(-42)->unwrap(); } public function testThrowWhenValueIsTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('101'); - new Lightness(101); + $_ = Lightness::of(101)->unwrap(); } public function testEquals() { - $this->assertTrue((new Lightness(50))->equals(new Lightness(50))); - $this->assertFalse((new Lightness(100))->equals(new Lightness(50))); + $this->assertTrue(Lightness::at(50)->equals(Lightness::at(50))); + $this->assertFalse(Lightness::at(100)->equals(Lightness::at(50))); } public function testAtMaximum() { - $this->assertTrue((new Lightness(100))->atMaximum()); - $this->assertFalse((new Lightness(0))->atMaximum()); - $this->assertFalse((new Lightness(50))->atMaximum()); + $this->assertTrue(Lightness::at(100)->atMaximum()); + $this->assertFalse(Lightness::at(0)->atMaximum()); + $this->assertFalse(Lightness::at(50)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Lightness(100))->atMinimum()); - $this->assertTrue((new Lightness(0))->atMinimum()); - $this->assertFalse((new Lightness(50))->atMinimum()); + $this->assertFalse(Lightness::at(100)->atMinimum()); + $this->assertTrue(Lightness::at(0)->atMinimum()); + $this->assertFalse(Lightness::at(50)->atMinimum()); } } diff --git a/tests/MagentaTest.php b/tests/MagentaTest.php index 9f1c502..c70346f 100644 --- a/tests/MagentaTest.php +++ b/tests/MagentaTest.php @@ -3,17 +3,14 @@ namespace Tests\Innmind\Colour; -use Innmind\Colour\{ - Magenta, - Exception\InvalidValueRangeException, -}; -use PHPUnit\Framework\TestCase; +use Innmind\Colour\Magenta; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class MagentaTest extends TestCase { public function testInterface() { - $magenta = new Magenta(50); + $magenta = Magenta::at(50); $this->assertSame(50, $magenta->toInt()); $this->assertSame('50', $magenta->toString()); @@ -21,25 +18,25 @@ public function testInterface() public function testThrowWhenValueTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-1'); - new Magenta(-1); + $_ = Magenta::of(-1)->unwrap(); } public function testThrowWhenValueTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('101'); - new Magenta(101); + $_ = Magenta::of(101)->unwrap(); } public function testAdd() { - $magenta = new Magenta(50); + $magenta = Magenta::at(50); - $magenta2 = $magenta->add(new Magenta(25)); + $magenta2 = $magenta->add(Magenta::at(25)); $this->assertInstanceOf(Magenta::class, $magenta2); $this->assertNotSame($magenta, $magenta2); @@ -49,9 +46,9 @@ public function testAdd() public function testSubtract() { - $magenta = new Magenta(50); + $magenta = Magenta::at(50); - $magenta2 = $magenta->subtract(new Magenta(25)); + $magenta2 = $magenta->subtract(Magenta::at(25)); $this->assertInstanceOf(Magenta::class, $magenta2); $this->assertNotSame($magenta, $magenta2); @@ -61,21 +58,21 @@ public function testSubtract() public function testEquals() { - $this->assertTrue((new Magenta(50))->equals(new Magenta(50))); - $this->assertFalse((new Magenta(100))->equals(new Magenta(50))); + $this->assertTrue(Magenta::at(50)->equals(Magenta::at(50))); + $this->assertFalse(Magenta::at(100)->equals(Magenta::at(50))); } public function testAtMaximum() { - $this->assertTrue((new Magenta(100))->atMaximum()); - $this->assertFalse((new Magenta(0))->atMaximum()); - $this->assertFalse((new Magenta(50))->atMaximum()); + $this->assertTrue(Magenta::at(100)->atMaximum()); + $this->assertFalse(Magenta::at(0)->atMaximum()); + $this->assertFalse(Magenta::at(50)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Magenta(100))->atMinimum()); - $this->assertTrue((new Magenta(0))->atMinimum()); - $this->assertFalse((new Magenta(50))->atMinimum()); + $this->assertFalse(Magenta::at(100)->atMinimum()); + $this->assertTrue(Magenta::at(0)->atMinimum()); + $this->assertFalse(Magenta::at(50)->atMinimum()); } } diff --git a/tests/RGBATest.php b/tests/RGBATest.php index 3fa5f89..4c06739 100644 --- a/tests/RGBATest.php +++ b/tests/RGBATest.php @@ -11,19 +11,19 @@ RGBA, HSLA, CMYKA, - Exception\DomainException, }; -use PHPUnit\Framework\TestCase; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; class RGBATest extends TestCase { public function testInterface() { - $rgba = new RGBA( - $red = new Red(0), - $green = new Green(255), - $blue = new Blue(122), - $alpha = new Alpha(0.5), + $rgba = RGBA::from( + $red = Red::at(0), + $green = Green::at(255), + $blue = Blue::at(122), + $alpha = Alpha::of(0.5)->unwrap(), ); $this->assertSame($red, $rgba->red()); @@ -35,10 +35,10 @@ public function testInterface() public function testWithoutAlpha() { - $rgba = new RGBA( - new Red(0), - new Green(255), - new Blue(122), + $rgba = RGBA::from( + Red::at(0), + Green::at(255), + Blue::at(122), ); $this->assertSame(1.0, $rgba->alpha()->toFloat()); @@ -46,25 +46,25 @@ public function testWithoutAlpha() public function testStringCast() { - $rgba = new RGBA( - new Red(0), - new Green(255), - new Blue(122), + $rgba = RGBA::from( + Red::at(0), + Green::at(255), + Blue::at(122), ); $this->assertSame('#00ff7a', $rgba->toString()); $this->assertSame( 'rgba(0, 255, 122, 0.5)', - $rgba->subtractAlpha(new Alpha(0.5))->toString(), + $rgba->subtractAlpha(Alpha::of(0.5)->unwrap())->toString(), ); } public function testToHexadecimal() { - $rgba = new RGBA( - new Red(0), - new Green(255), - new Blue(122), + $rgba = RGBA::from( + Red::at(0), + Green::at(255), + Blue::at(122), ); $this->assertSame( @@ -73,20 +73,20 @@ public function testToHexadecimal() ); $this->assertSame( '00ff7a80', - $rgba->subtractAlpha(new Alpha(0.5))->toHexadecimal(), + $rgba->subtractAlpha(Alpha::of(0.5)->unwrap())->toHexadecimal(), ); } public function testAddRed() { - $rgba = new RGBA( - new Red(10), - new Green(255), - new Blue(122), - new Alpha(0.5), + $rgba = RGBA::from( + Red::at(10), + Green::at(255), + Blue::at(122), + Alpha::of(0.5)->unwrap(), ); - $rgba2 = $rgba->addRed(new Red(150)); + $rgba2 = $rgba->addRed(Red::at(150)); $this->assertInstanceOf(RGBA::class, $rgba2); $this->assertNotSame($rgba, $rgba2); $this->assertSame(10, $rgba->red()->toInt()); @@ -101,14 +101,14 @@ public function testAddRed() public function testSubtractRed() { - $rgba = new RGBA( - new Red(150), - new Green(255), - new Blue(122), - new Alpha(0.5), + $rgba = RGBA::from( + Red::at(150), + Green::at(255), + Blue::at(122), + Alpha::of(0.5)->unwrap(), ); - $rgba2 = $rgba->subtractRed(new Red(10)); + $rgba2 = $rgba->subtractRed(Red::at(10)); $this->assertInstanceOf(RGBA::class, $rgba2); $this->assertNotSame($rgba, $rgba2); $this->assertSame(150, $rgba->red()->toInt()); @@ -123,14 +123,14 @@ public function testSubtractRed() public function testAddBlue() { - $rgba = new RGBA( - new Red(10), - new Green(255), - new Blue(122), - new Alpha(0.5), + $rgba = RGBA::from( + Red::at(10), + Green::at(255), + Blue::at(122), + Alpha::of(0.5)->unwrap(), ); - $rgba2 = $rgba->addBlue(new Blue(12)); + $rgba2 = $rgba->addBlue(Blue::at(12)); $this->assertInstanceOf(RGBA::class, $rgba2); $this->assertNotSame($rgba, $rgba2); $this->assertSame(10, $rgba->red()->toInt()); @@ -145,14 +145,14 @@ public function testAddBlue() public function testSubtractBlue() { - $rgba = new RGBA( - new Red(10), - new Green(255), - new Blue(122), - new Alpha(0.5), + $rgba = RGBA::from( + Red::at(10), + Green::at(255), + Blue::at(122), + Alpha::of(0.5)->unwrap(), ); - $rgba2 = $rgba->subtractBlue(new Blue(10)); + $rgba2 = $rgba->subtractBlue(Blue::at(10)); $this->assertInstanceOf(RGBA::class, $rgba2); $this->assertNotSame($rgba, $rgba2); $this->assertSame(10, $rgba->red()->toInt()); @@ -167,14 +167,14 @@ public function testSubtractBlue() public function testAddGreen() { - $rgba = new RGBA( - new Red(10), - new Green(205), - new Blue(122), - new Alpha(0.5), + $rgba = RGBA::from( + Red::at(10), + Green::at(205), + Blue::at(122), + Alpha::of(0.5)->unwrap(), ); - $rgba2 = $rgba->addGreen(new Green(15)); + $rgba2 = $rgba->addGreen(Green::at(15)); $this->assertInstanceOf(RGBA::class, $rgba2); $this->assertNotSame($rgba, $rgba2); $this->assertSame(10, $rgba->red()->toInt()); @@ -189,14 +189,14 @@ public function testAddGreen() public function testSubtractGreen() { - $rgba = new RGBA( - new Red(10), - new Green(255), - new Blue(122), - new Alpha(0.5), + $rgba = RGBA::from( + Red::at(10), + Green::at(255), + Blue::at(122), + Alpha::of(0.5)->unwrap(), ); - $rgba2 = $rgba->subtractGreen(new Green(10)); + $rgba2 = $rgba->subtractGreen(Green::at(10)); $this->assertInstanceOf(RGBA::class, $rgba2); $this->assertNotSame($rgba, $rgba2); $this->assertSame(10, $rgba->red()->toInt()); @@ -209,9 +209,7 @@ public function testSubtractGreen() $this->assertSame(0.5, $rgba2->alpha()->toFloat()); } - /** - * @dataProvider hexadecimalWithAlpha - */ + #[DataProvider('hexadecimalWithAlpha')] public function testFromHexadecimalWithAlpha( string $string, int $red, @@ -238,9 +236,7 @@ public static function hexadecimalWithAlpha() ]; } - /** - * @dataProvider hexadecimalWithoutAlpha - */ + #[DataProvider('hexadecimalWithoutAlpha')] public function testFromHexadecimalWithoutAlpha( string $string, int $red, @@ -269,15 +265,13 @@ public static function hexadecimalWithoutAlpha() ]; } - /** - * @dataProvider hexadecimals - */ + #[DataProvider('hexadecimals')] public function testFromHexadecimal( string $string, int $red, int $green, int $blue, - float $alpha = null, + ?float $alpha = null, ) { $rgba = RGBA::of($string); @@ -315,10 +309,10 @@ public function testFromRGBFunctionWithPoints() public function testThrowWhenInvalidRGBFunctionWithPoints() { - $this->expectException(DomainException::class); - $this->expectExceptionMessage('rgb(10, 20%, 30)'); + $this->expectException(\DomainException::class); + $this->expectExceptionMessage("Red not found in 'rgb(10, 20%, 30)'"); - RGBA::of('rgb(10, 20%, 30)'); + $_ = RGBA::of('rgb(10, 20%, 30)'); } public function testFromRGBFunctionWithPercents() @@ -334,10 +328,10 @@ public function testFromRGBFunctionWithPercents() public function testThrowWhenInvalidRGBFunctionWithPercents() { - $this->expectException(DomainException::class); - $this->expectExceptionMessage('rgb(10, 20%, 30)'); + $this->expectException(\DomainException::class); + $this->expectExceptionMessage("Red not found in 'rgb(10, 20%, 30)'"); - RGBA::of('rgb(10, 20%, 30)'); + $_ = RGBA::of('rgb(10, 20%, 30)'); } public function testFromRGBFunction() @@ -372,8 +366,8 @@ public function testFromRGBAFunctionWithPoints() public function testThrowWhenInvalidRGBAFunctionWithPoints() { - $this->expectException(DomainException::class); - $this->expectExceptionMessage('rgba(10, 20%, 30, 2.0)'); + $this->expectException(\DomainException::class); + $this->expectExceptionMessage("Red not found in 'rgba(10, 20%, 30, 2.0)'"); RGBA::of('rgba(10, 20%, 30, 2.0)'); } @@ -391,8 +385,8 @@ public function testFromRGBAFunctionWithPercents() public function testThrowWhenInvalidRGBAFunctionWithPercents() { - $this->expectException(DomainException::class); - $this->expectExceptionMessage('rgba(10, 20%, 30, 1)'); + $this->expectException(\DomainException::class); + $this->expectExceptionMessage("Red not found in 'rgba(10, 20%, 30, 1)'"); RGBA::of('rgba(10, 20%, 30, 1)'); } @@ -416,9 +410,7 @@ public function testFromRGBAFunction() $this->assertTrue($rgb->alpha()->atMaximum()); } - /** - * @dataProvider allFormats - */ + #[DataProvider('allFormats')] public function testOf( string $colour, int $red, diff --git a/tests/RedTest.php b/tests/RedTest.php index 1fd0580..e5532a3 100644 --- a/tests/RedTest.php +++ b/tests/RedTest.php @@ -6,15 +6,14 @@ use Innmind\Colour\{ Red, Intensity, - Exception\InvalidValueRangeException, }; -use PHPUnit\Framework\TestCase; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class RedTest extends TestCase { public function testInterface() { - $red = new Red(255); + $red = Red::at(255); $this->assertSame(255, $red->toInt()); $this->assertSame('ff', $red->toString()); @@ -34,63 +33,63 @@ public function testFromHexadecimal() public function testAdd() { - $red = (new Red(12))->add(new Red(30)); + $red = Red::at(12)->add(Red::at(30)); $this->assertInstanceOf(Red::class, $red); $this->assertSame(42, $red->toInt()); $this->assertSame( 255, - (new Red(150))->add(new Red(150))->toInt(), + Red::at(150)->add(Red::at(150))->toInt(), ); } public function testSub() { - $red = (new Red(54))->subtract(new Red(12)); + $red = Red::at(54)->subtract(Red::at(12)); $this->assertInstanceOf(Red::class, $red); $this->assertSame(42, $red->toInt()); $this->assertSame( 0, - (new Red(150))->subtract(new Red(255))->toInt(), + Red::at(150)->subtract(Red::at(255))->toInt(), ); } public function testThrowWhenValueIsTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-42'); - new Red(-42); + $_ = Red::of(-42)->unwrap(); } public function testThrowWhenValueIsTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('512'); - new Red(512); + $_ = Red::of(512)->unwrap(); } public function testAtMaximum() { - $this->assertTrue((new Red(255))->atMaximum()); - $this->assertFalse((new Red(0))->atMaximum()); - $this->assertFalse((new Red(122))->atMaximum()); + $this->assertTrue(Red::at(255)->atMaximum()); + $this->assertFalse(Red::at(0)->atMaximum()); + $this->assertFalse(Red::at(122)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Red(255))->atMinimum()); - $this->assertTrue((new Red(0))->atMinimum()); - $this->assertFalse((new Red(122))->atMinimum()); + $this->assertFalse(Red::at(255)->atMinimum()); + $this->assertTrue(Red::at(0)->atMinimum()); + $this->assertFalse(Red::at(122)->atMinimum()); } public function testFromIntensity() { - $red = Red::fromIntensity(new Intensity(100))->match( + $red = Red::fromIntensity(Intensity::at(100))->match( static fn($red) => $red, static fn() => null, ); @@ -99,28 +98,28 @@ public function testFromIntensity() $this->assertSame(255, $red->toInt()); $this->assertSame( 191, - Red::fromIntensity(new Intensity(75))->match( + Red::fromIntensity(Intensity::at(75))->match( static fn($red) => $red->toInt(), static fn() => null, ), ); $this->assertSame( 128, - Red::fromIntensity(new Intensity(50))->match( + Red::fromIntensity(Intensity::at(50))->match( static fn($red) => $red->toInt(), static fn() => null, ), ); $this->assertSame( 64, - Red::fromIntensity(new Intensity(25))->match( + Red::fromIntensity(Intensity::at(25))->match( static fn($red) => $red->toInt(), static fn() => null, ), ); $this->assertSame( 0, - Red::fromIntensity(new Intensity(0))->match( + Red::fromIntensity(Intensity::at(0))->match( static fn($red) => $red->toInt(), static fn() => null, ), @@ -129,7 +128,7 @@ public function testFromIntensity() public function testEquals() { - $this->assertTrue((new Red(50))->equals(new Red(50))); - $this->assertFalse((new Red(100))->equals(new Red(50))); + $this->assertTrue(Red::at(50)->equals(Red::at(50))); + $this->assertFalse(Red::at(100)->equals(Red::at(50))); } } diff --git a/tests/SaturationTest.php b/tests/SaturationTest.php index 97d5b58..a468525 100644 --- a/tests/SaturationTest.php +++ b/tests/SaturationTest.php @@ -3,17 +3,14 @@ namespace Tests\Innmind\Colour; -use Innmind\Colour\{ - Saturation, - Exception\InvalidValueRangeException, -}; -use PHPUnit\Framework\TestCase; +use Innmind\Colour\Saturation; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class SaturationTest extends TestCase { public function testInterface() { - $saturation = new Saturation(100); + $saturation = Saturation::at(100); $this->assertSame(100, $saturation->toInt()); $this->assertSame('100', $saturation->toString()); @@ -21,63 +18,63 @@ public function testInterface() public function testAdd() { - $saturation = (new Saturation(12))->add(new Saturation(30)); + $saturation = Saturation::at(12)->add(Saturation::at(30)); $this->assertInstanceOf(Saturation::class, $saturation); $this->assertSame(42, $saturation->toInt()); $this->assertSame( 100, - (new Saturation(50))->add(new Saturation(75))->toInt(), + Saturation::at(50)->add(Saturation::at(75))->toInt(), ); } public function testSub() { - $saturation = (new Saturation(54))->subtract(new Saturation(12)); + $saturation = Saturation::at(54)->subtract(Saturation::at(12)); $this->assertInstanceOf(Saturation::class, $saturation); $this->assertSame(42, $saturation->toInt()); $this->assertSame( 0, - (new Saturation(50))->subtract(new Saturation(75))->toInt(), + Saturation::at(50)->subtract(Saturation::at(75))->toInt(), ); } public function testThrowWhenValueIsTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-42'); - new Saturation(-42); + $_ = Saturation::of(-42)->unwrap(); } public function testThrowWhenValueIsTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('101'); - new Saturation(101); + $_ = Saturation::of(101)->unwrap(); } public function testEquals() { - $this->assertTrue((new Saturation(50))->equals(new Saturation(50))); - $this->assertFalse((new Saturation(100))->equals(new Saturation(50))); + $this->assertTrue(Saturation::at(50)->equals(Saturation::at(50))); + $this->assertFalse(Saturation::at(100)->equals(Saturation::at(50))); } public function testAtMaximum() { - $this->assertTrue((new Saturation(100))->atMaximum()); - $this->assertFalse((new Saturation(0))->atMaximum()); - $this->assertFalse((new Saturation(50))->atMaximum()); + $this->assertTrue(Saturation::at(100)->atMaximum()); + $this->assertFalse(Saturation::at(0)->atMaximum()); + $this->assertFalse(Saturation::at(50)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Saturation(100))->atMinimum()); - $this->assertTrue((new Saturation(0))->atMinimum()); - $this->assertFalse((new Saturation(50))->atMinimum()); + $this->assertFalse(Saturation::at(100)->atMinimum()); + $this->assertTrue(Saturation::at(0)->atMinimum()); + $this->assertFalse(Saturation::at(50)->atMinimum()); } } diff --git a/tests/YellowTest.php b/tests/YellowTest.php index c47b479..68ddaf9 100644 --- a/tests/YellowTest.php +++ b/tests/YellowTest.php @@ -3,17 +3,14 @@ namespace Tests\Innmind\Colour; -use Innmind\Colour\{ - Yellow, - Exception\InvalidValueRangeException, -}; -use PHPUnit\Framework\TestCase; +use Innmind\Colour\Yellow; +use Innmind\BlackBox\PHPUnit\Framework\TestCase; class YellowTest extends TestCase { public function testInterface() { - $yellow = new Yellow(50); + $yellow = Yellow::at(50); $this->assertSame(50, $yellow->toInt()); $this->assertSame('50', $yellow->toString()); @@ -21,25 +18,25 @@ public function testInterface() public function testThrowWhenValueTooLow() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('-1'); - new Yellow(-1); + $_ = Yellow::of(-1)->unwrap(); } public function testThrowWhenValueTooHigh() { - $this->expectException(InvalidValueRangeException::class); + $this->expectException(\OutOfBoundsException::class); $this->expectExceptionMessage('101'); - new Yellow(101); + $_ = Yellow::of(101)->unwrap(); } public function testAdd() { - $yellow = new Yellow(50); + $yellow = Yellow::at(50); - $yellow2 = $yellow->add(new Yellow(25)); + $yellow2 = $yellow->add(Yellow::at(25)); $this->assertInstanceOf(Yellow::class, $yellow2); $this->assertNotSame($yellow, $yellow2); @@ -49,9 +46,9 @@ public function testAdd() public function testSubtract() { - $yellow = new Yellow(50); + $yellow = Yellow::at(50); - $yellow2 = $yellow->subtract(new Yellow(25)); + $yellow2 = $yellow->subtract(Yellow::at(25)); $this->assertInstanceOf(Yellow::class, $yellow2); $this->assertNotSame($yellow, $yellow2); @@ -61,21 +58,21 @@ public function testSubtract() public function testEquals() { - $this->assertTrue((new Yellow(50))->equals(new Yellow(50))); - $this->assertFalse((new Yellow(100))->equals(new Yellow(50))); + $this->assertTrue(Yellow::at(50)->equals(Yellow::at(50))); + $this->assertFalse(Yellow::at(100)->equals(Yellow::at(50))); } public function testAtMaximum() { - $this->assertTrue((new Yellow(100))->atMaximum()); - $this->assertFalse((new Yellow(0))->atMaximum()); - $this->assertFalse((new Yellow(50))->atMaximum()); + $this->assertTrue(Yellow::at(100)->atMaximum()); + $this->assertFalse(Yellow::at(0)->atMaximum()); + $this->assertFalse(Yellow::at(50)->atMaximum()); } public function testAtMinimum() { - $this->assertFalse((new Yellow(100))->atMinimum()); - $this->assertTrue((new Yellow(0))->atMinimum()); - $this->assertFalse((new Yellow(50))->atMinimum()); + $this->assertFalse(Yellow::at(100)->atMinimum()); + $this->assertTrue(Yellow::at(0)->atMinimum()); + $this->assertFalse(Yellow::at(50)->atMinimum()); } }