Skip to content

Commit b0b29d5

Browse files
committed
WIP Improve test
There are still issues with the color math that prevent a successfull conversion back and forth between rgb and hsla
1 parent d9fdae8 commit b0b29d5

9 files changed

Lines changed: 196 additions & 20 deletions

File tree

Build/Travis/functional-tests.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
timeoutForSmallTests="0">
1111
<testsuites>
1212
<testsuite name="All tests">
13-
<directory>Packages/Application/PackageFactory.AtomicFusion.PropTypes/Tests/Functional</directory>
13+
<directory>Packages/Application/PackageFactory.ColorHelper/Tests/Functional</directory>
1414
</testsuite>
1515
</testsuites>
1616
<filter>

Classes/Domain/ValueObject/HslaColor.php

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,33 +93,40 @@ public function asRgba(): RgbaColor
9393
{
9494
$S = $this->saturation / 100;
9595
$L = $this->lightness / 100;
96+
$H = $this->hue;
97+
9698
$C = (1 - abs((2 * $L) - 1)) * $S;
97-
$X = $C * (1 - abs((($this->hue / 60) % 2) - 1));
99+
$X = $C * (1 - abs((($H / 60) % 2) - 1));
98100
$m = $L - ($C / 2);
99101

102+
if ($S == 0) {
103+
$rgb = (int) round($L * 255);
104+
return new RgbaColor($rgb, $rgb, $rgb, $this->alpha);
105+
}
106+
100107
if ($this->hue < 0) {
101108
throw new \UnexpectedValueException('this should never be thrown');
102-
} elseif ($this->hue < 60) {
109+
} elseif ($H < 60) {
103110
$r = $C;
104111
$g = $X;
105112
$b = 0;
106-
} elseif ($this->hue < 120) {
113+
} elseif ($H < 120) {
107114
$r = $X;
108115
$g = $C;
109116
$b = 0;
110-
} elseif ($this->hue < 180) {
117+
} elseif ($H < 180) {
111118
$r = 0;
112119
$g = $C;
113120
$b = $X;
114-
} elseif ($this->hue < 240) {
121+
} elseif ($H < 240) {
115122
$r = 0;
116123
$g = $X;
117124
$b = $C;
118-
} elseif ($this->hue < 300) {
125+
} elseif ($H < 300) {
119126
$r = $X;
120127
$g = 0;
121128
$b = $C;
122-
} elseif ($this->hue < 360) {
129+
} elseif ($H < 360) {
123130
$r = $C;
124131
$g = 0;
125132
$b = $X;
@@ -142,7 +149,7 @@ public function asRgba(): RgbaColor
142149
/**
143150
* @return HslaColor
144151
*/
145-
public function asHsla(): self
152+
public function asHsla(): HslaColor
146153
{
147154
return $this;
148155
}

Classes/Domain/ValueObject/RgbaColor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public function getAlpha(): int
9090
/**
9191
* @return RgbaColor
9292
*/
93-
public function asRgba(): self
93+
public function asRgba(): RgbaColor
9494
{
9595
return $this;
9696
}

Classes/Eel/ColorBuilder.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88

99
class ColorBuilder implements ProtectedContextAwareInterface
1010
{
11-
const PATTERN_HEX_LONG = '/^#?(?<red>[0-9abcdefABCDEF]{2})(?<green>[0-9abcdefABCDEF]{2})(?<blue>[0-9abcdefABCDEF]{2})(?:(?<alpha>[0-9abcdefABCDEF]{2}))?^$/u';
11+
const PATTERN_HEX_LONG = '/^#(?<red>[0-9abcdef]{2})(?<green>[0-9abcdef]{2})(?<blue>[0-9abcdef]{2})(?:(?<alpha>[0-9abcdef]{2}))?$/';
1212

13-
const PATTERN_HEX_SHORT = '/#?(?<red>[0-9abcdefABCDEF]{1})(?<green>[0-9abcdefABCDEF]{1})(?<blue>[0-9abcdefABCDEF]{1})(?:(?<alpha>[0-9abcdefABCDEF]{1}))?$/u';
13+
const PATTERN_HEX_SHORT = '/^#(?<red>[0-9abcdef]{1})(?<green>[0-9abcdef]{1})(?<blue>[0-9abcdef]{1})(?:(?<alpha>[0-9abcdef]{1}))?$/u';
1414

1515
const PATTERN_RGBA = '/^rgba?\\s*\\(\\s*(?<red>[0-9\\.]+%?)\\s*,?\\s*(?<green>[0-9\\.]+%?)\\s*,?\\s*(?<blue>[0-9\\.]+%?)\\s*(?:,?\\s*(?<alpha>[0-9\\.]+%?)\\s*)?\\)$/u';
1616

17-
const PATTERN_HSLA = '/hsla?\\s*\\(\\s*(?<hue>[0-9\\.]+)\\s*,?\\s*(?<saturation>[0-9\\.]+%)\\s*,?\\s*(?<lightness>[0-9\\.]+%)\\s*(?:,?\\s*(?<alpha>[0-9\\.]+%?)\\s*)?\\)$/u';
17+
const PATTERN_HSLA = '/^hsla?\\s*\\(\\s*(?<hue>[0-9\\.]+)\\s*,?\\s*(?<saturation>[0-9\\.]+%)\\s*,?\\s*(?<lightness>[0-9\\.]+%)\\s*(?:,?\\s*(?<alpha>[0-9\\.]+%?)\\s*)?\\)$/u';
1818

1919
/**
2020
* @param int $red 0-255
@@ -35,14 +35,13 @@ public function rgb(int $red, int $green, int $blue, int $alpha = 255): ColorHel
3535
* @param int $hue 0-355
3636
* @param int $saturatiom 0-100
3737
* @param int $lightness 0-100
38-
* @param int $alpha 0-100
38+
* @param float $alpha 0-1
3939
*
4040
* @return ColorHelper
4141
*/
42-
public function hsl(int $hue, int $saturatiom, int $lightness, int $alpha = 100): ColorHelper
42+
public function hsl(int $hue, int $saturatiom, int $lightness, float $alpha = 1): ColorHelper
4343
{
44-
$alpha = (int) round($alpha / 100 * 255);
45-
44+
$alpha = (int) round($alpha * 255);
4645
return new ColorHelper(
4746
new HslaColor($hue, $saturatiom, $lightness, $alpha)
4847
);
@@ -55,7 +54,9 @@ public function hsl(int $hue, int $saturatiom, int $lightness, int $alpha = 100)
5554
*/
5655
public function hex(string $hex): ?ColorHelper
5756
{
57+
$hex = strtolower($hex);
5858
if (preg_match(self::PATTERN_HEX_SHORT, $hex, $matches)) {
59+
5960
$red = (int) hexdec($matches['red'].$matches['red']);
6061
$green = (int) hexdec($matches['green'].$matches['green']);
6162
$blue = (int) hexdec($matches['blue'].$matches['blue']);
@@ -65,6 +66,7 @@ public function hex(string $hex): ?ColorHelper
6566
new RgbaColor($red, $green, $blue, $alpha)
6667
);
6768
} elseif (preg_match(self::PATTERN_HEX_LONG, $hex, $matches)) {
69+
6870
$red = (int) hexdec($matches['red']);
6971
$green = (int) hexdec($matches['green']);
7072
$blue = (int) hexdec($matches['blue']);
@@ -87,6 +89,7 @@ public function hex(string $hex): ?ColorHelper
8789
*/
8890
public function css(string $colorString): ?ColorHelper
8991
{
92+
$colorString = strtolower($colorString);
9093
if (preg_match(self::PATTERN_HEX_SHORT, $colorString, $matches)) {
9194
$red = (int) hexdec($matches['red'].$matches['red']);
9295
$green = (int) hexdec($matches['green'].$matches['green']);
@@ -100,7 +103,7 @@ public function css(string $colorString): ?ColorHelper
100103
$red = (int) hexdec($matches['red']);
101104
$green = (int) hexdec($matches['green']);
102105
$blue = (int) hexdec($matches['blue']);
103-
$alpha = (int) hexdec($matches['alpha'] ? $matches['alpha'] : 'ff');
106+
$alpha = (int) hexdec(isset($matches['alpha']) ? $matches['alpha'] : 'ff');
104107

105108
return new ColorHelper(
106109
new RgbaColor($red, $green, $blue, $alpha)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ The package provides the `Color` helper that exposes the following methods to Fu
77

88
Colors can be created from hex, rgb and hsl values
99
- `color = ${ Color.hex('#80e619') }` expects a hex string of 3 or 6 chars
10-
- `color = ${ Color.rgb(100, 0, 256) }` expects three integers each between 0 and 255
10+
- `color = ${ Color.rgb(100, 0, 255) }` expects three integers each between 0 and 255
1111
- `color = ${ Color.hsl(156, 25, 75) }` expects three integers a degree 0-355 and two percent values 0-100
1212

1313
The methods rgb and hsl allow to specify the alpha as fourth argument
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
namespace PackageFactory\ColorHelper\Tests\Functional;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use PackageFactory\ColorHelper\Eel\ColorBuilder;
7+
use PackageFactory\ColorHelper\Eel\ColorHelper;
8+
9+
class ColorHelperTest extends TestCase
10+
{
11+
private $builder;
12+
13+
public function setUp(): void
14+
{
15+
$this->builder = new ColorBuilder();
16+
}
17+
18+
public function colorsCanBeCreatedViaRgbFactoryMethodDataProvider():array
19+
{
20+
return [
21+
[100,0,255,null,'#6400ff'],
22+
[0,0,0,null,'#000000'],
23+
[100,0,255,128,'#6400ff80']
24+
];
25+
}
26+
27+
/**
28+
* @test
29+
* @dataProvider colorsCanBeCreatedViaRgbFactoryMethodDataProvider
30+
*/
31+
public function colorsCanBeCreatedViaRgbFactoryMethod($red, $green, $blue, $alpha, $hex)
32+
{
33+
$this->assertEquals($hex, $this->builder->rgb($red, $green, $blue, $alpha ?? 255)->__toString());
34+
}
35+
36+
public function colorsCanBeCreatedViaHslFactoryMethodDataProvider():array
37+
{
38+
return [
39+
[100,25,75,1,'#cfcfaf'],
40+
[100,25,100,1,'#ffffff'],
41+
[100,25,0,1,'#000000']
42+
];
43+
}
44+
45+
/**
46+
* @test
47+
* @dataProvider colorsCanBeCreatedViaHslFactoryMethodDataProvider
48+
*/
49+
public function colorsCanBeCreatedViaHslFactoryMethod($hue, $saturation, $lightness, $alpha, $hex)
50+
{
51+
$this->assertEquals($hex, $this->builder->hsl($hue, $saturation, $lightness, $alpha ?? 1)->__toString());
52+
}
53+
54+
public function colorsCanBeCreatedViaHexFactoryMethodDataProvider():array
55+
{
56+
return [
57+
['#ae8','#aaee88'],
58+
['#6400ff','#6400ff'],
59+
['#FFAAEEDD','#ffaaeedd'],
60+
['#ffeeaa88','#ffeeaa88']
61+
];
62+
}
63+
64+
/**
65+
* @test
66+
* @dataProvider colorsCanBeCreatedViaHexFactoryMethodDataProvider
67+
*/
68+
public function colorsCanBeCreatedViaHexFactoryMethod($string, $hex)
69+
{
70+
$this->assertEquals($hex, $this->builder->hex($string)->__toString());
71+
}
72+
73+
public function colorsCanBeCreatedViaCssFactoryMethodDataProvider():array
74+
{
75+
return [
76+
['#ae8','#aaee88'],
77+
['#6400ff','#6400ff'],
78+
['#FFAAEEDD','#ffaaeedd'],
79+
['#ffeeaa88','#ffeeaa88'],
80+
['rgb(128,128,128)','#808080'],
81+
['rgba(128,128,128,255)','#808080'],
82+
['hsl(66,100%,75%)','#ffff80'],
83+
['hsl(66,100%,75%,1)','#ffff80']
84+
];
85+
}
86+
87+
/**
88+
* @test
89+
* @dataProvider colorsCanBeCreatedViaCssFactoryMethodDataProvider
90+
*/
91+
public function colorsCanBeCreatedViaCssFactoryMethod($string, $hex)
92+
{
93+
$this->assertEquals($hex, $this->builder->css($string)->__toString());
94+
}
95+
}

Tests/Unit/ColorTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,62 @@ public function conversionOfRgbToHslWorks($colorFixture)
4848
self::assertEquals($hsl[2], $hslColor->getLightness());
4949
}
5050

51+
public function conversionOfRgbToHslAndBackWorksDataProvider():array
52+
{
53+
$interval=20;
54+
$testArgumentSets = [];
55+
for ($r = 0; $r < 256; $r+=$interval) {
56+
for ($g = 0; $g < 256; $g+=$interval) {
57+
for ($b = 0; $b < 256; $b+=$interval) {
58+
$testArgumentSets[] = [$r,$g,$b];
59+
}
60+
}
61+
}
62+
return $testArgumentSets;
63+
}
64+
65+
/**
66+
* @__test__
67+
* @dataProvider conversionOfRgbToHslAndBackWorksDataProvider
68+
*/
69+
public function conversionOfRgbToHslAndBackWorks(int $r, int $g, int $b)
70+
{
71+
$original = new RgbaColor($r, $g, $b);
72+
$converted = $original->asHsla()->asRgba();
73+
self::assertEquals(
74+
[$original->getRed(), $original->getGreen(), $original->getBlue()],
75+
[$converted->getRed(), $converted->getGreen(), $converted->getBlue()]
76+
);
77+
}
78+
79+
public function conversionOfHslToRgbAndBackWorksDataProvider():array
80+
{
81+
$interval=20;
82+
$testArgumentSets = [];
83+
for ($h = 0; $h < 360; $h+=$interval) {
84+
for ($l = 0; $l < 100; $l+=$interval) {
85+
for ($s = 0; $s < 100; $s+=$interval) {
86+
$testArgumentSets[] = [$h, $s, $l];
87+
}
88+
}
89+
}
90+
return $testArgumentSets;
91+
}
92+
93+
/**
94+
* @__test__
95+
* @dataProvider conversionOfHslToRgbAndBackWorksDataProvider
96+
*/
97+
public function conversionOfHslToRgbAndBackWorks(int $h, int $s, int $l)
98+
{
99+
$original = new HslaColor($h, $l, $s);
100+
$converted = $original->asRgba()->asHsla();
101+
self::assertEquals(
102+
[$original->getHue(), $original->getSaturation(), $original->getLightness()],
103+
[$converted->getHue(), $converted->getSaturation(), $converted->getLightness()]
104+
);
105+
}
106+
51107
/**
52108
* @test
53109
* @dataProvider getColorFixtures

Tests/Unit/Colors.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,11 @@ navy:
6262
hsl: [240,100,25]
6363
hex: '#000080'
6464
rgb: [0,0,128]
65+
#strange:
66+
# hsl: [10,25,75]
67+
# hex: '#CFB5AF'
68+
# rgb: [207,181,175]
69+
#strange2:
70+
# hsl: [10,100,75]
71+
# hex: '#FF9580'
72+
# rgb: [255,149,128]

composer.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,16 @@
3636
"composer test:prepare",
3737
"Build/Travis/bin/phpunit --verbose -c Build/Travis/unit-tests.xml"
3838
],
39+
"test:functional": [
40+
"composer test:prepare",
41+
"cd Build/Travis && FLOW_CONTEXT=Testing ./flow flow:cache:flush",
42+
"cd Build/Travis && FLOW_CONTEXT=Testing ./flow flow:package:rescan",
43+
"FLOW_CONTEXT=Testing Build/Travis/bin/phpunit --verbose -c Build/Travis/functional-tests.xml"
44+
],
3945
"test": [
4046
"composer test:phpstan",
41-
"composer test:unit"
47+
"composer test:unit",
48+
"composer test:functional"
4249
]
4350
}
4451
}

0 commit comments

Comments
 (0)