Skip to content

Commit 0881bbe

Browse files
authored
Merge pull request #1022 from hydephp/improve-type-coverage
Create superset Config facade with strongly typed accessors
2 parents 9c41ddb + 0e9bb47 commit 0881bbe

File tree

3 files changed

+335
-0
lines changed

3 files changed

+335
-0
lines changed

app/config.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
'Author' => \Hyde\Facades\Author::class,
9797
'Includes' => \Hyde\Facades\Includes::class,
9898
'Features' => \Hyde\Facades\Features::class,
99+
'Config' => \Hyde\Facades\Config::class,
99100
'BladePage' => \Hyde\Pages\BladePage::class,
100101
'MarkdownPage' => \Hyde\Pages\MarkdownPage::class,
101102
'MarkdownPost' => \Hyde\Pages\MarkdownPost::class,
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Hyde\Facades;
6+
7+
/**
8+
* An extension of the Laravel Config facade with extra
9+
* accessors that ensure the types of the returned values.
10+
*
11+
* @internal This facade is not meant to be used by the end user.
12+
* @experimental This facade is experimental and may change in the future.
13+
*
14+
* @todo If class is kept internal, the facade alias should be removed from config.
15+
*
16+
* @see \Illuminate\Config\Repository
17+
* @see \Illuminate\Support\Facades\Config
18+
* @see \Hyde\Framework\Testing\Feature\TypedConfigFacadeTest
19+
*/
20+
class Config extends \Illuminate\Support\Facades\Config
21+
{
22+
/** @var false {@todo Consider setting to true} */
23+
protected const STRICT_DEFAULT = false;
24+
25+
public static function getArray(array|string $key, array $default = null, bool $strict = self::STRICT_DEFAULT): array
26+
{
27+
return $strict ? static::get($key, $default) : (array) static::get($key, $default);
28+
}
29+
30+
public static function getString(string $key, string $default = null, bool $strict = self::STRICT_DEFAULT): string
31+
{
32+
return $strict ? static::get($key, $default) : (string) static::get($key, $default);
33+
}
34+
35+
public static function getInt(string $key, int $default = null, bool $strict = self::STRICT_DEFAULT): int
36+
{
37+
return $strict ? static::get($key, $default) : (int) static::get($key, $default);
38+
}
39+
40+
public static function getBool(string $key, bool $default = null, bool $strict = self::STRICT_DEFAULT): bool
41+
{
42+
return $strict ? static::get($key, $default) : (bool) static::get($key, $default);
43+
}
44+
45+
public static function getFloat(string $key, float $default = null, bool $strict = self::STRICT_DEFAULT): float
46+
{
47+
return $strict ? static::get($key, $default) : (float) static::get($key, $default);
48+
}
49+
}
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Hyde\Framework\Testing\Feature;
6+
7+
use ErrorException;
8+
use Hyde\Facades\Config;
9+
use Hyde\Testing\TestCase;
10+
use TypeError;
11+
use function config;
12+
13+
/**
14+
* @covers \Hyde\Facades\Config
15+
*/
16+
class TypedConfigFacadeTest extends TestCase
17+
{
18+
public function testGetArray()
19+
{
20+
$this->assertIsArray(Config::getArray('foo'));
21+
}
22+
23+
public function testGetString()
24+
{
25+
$this->assertIsString(Config::getString('foo'));
26+
}
27+
28+
public function testGetBool()
29+
{
30+
$this->assertIsBool(Config::getBool('foo'));
31+
}
32+
33+
public function testGetInt()
34+
{
35+
$this->assertIsInt(Config::getInt('foo'));
36+
}
37+
38+
public function testGetFloat()
39+
{
40+
$this->assertIsFloat(Config::getFloat('foo'));
41+
}
42+
43+
public function testGetArrayWithDefaultValue()
44+
{
45+
$this->assertSame(['bar'], Config::getArray('foo', ['bar']));
46+
}
47+
48+
public function testGetStringWithDefaultValue()
49+
{
50+
$this->assertSame('bar', Config::getString('foo', 'bar'));
51+
}
52+
53+
public function testGetBoolWithDefaultValue()
54+
{
55+
$this->assertSame(true, Config::getBool('foo', true));
56+
}
57+
58+
public function testGetIntWithDefaultValue()
59+
{
60+
$this->assertSame(10, Config::getInt('foo', 10));
61+
}
62+
63+
public function testGetFloatWithDefaultValue()
64+
{
65+
$this->assertSame(10.0, Config::getFloat('foo', 10.0));
66+
}
67+
68+
public function testGetArrayWithStrictMode()
69+
{
70+
$this->runUnitTestStrict(['bar'], ['bar'], Config::getArray(...));
71+
}
72+
73+
public function testGetStringWithStrictMode()
74+
{
75+
$this->runUnitTestStrict('bar', 'bar', Config::getString(...));
76+
}
77+
78+
public function testGetBoolWithStrictMode()
79+
{
80+
$this->runUnitTestStrict(true, true, Config::getBool(...));
81+
}
82+
83+
public function testGetIntWithStrictMode()
84+
{
85+
$this->runUnitTestStrict(10, 10, Config::getInt(...));
86+
}
87+
88+
public function testGetFloatWithStrictMode()
89+
{
90+
$this->runUnitTestStrict(10.0, 10.0, Config::getFloat(...));
91+
}
92+
93+
public function testGetArrayWithFailingStrictMode()
94+
{
95+
$this->expectException(TypeError::class);
96+
$this->runUnitTestStrict(null, null, Config::getArray(...));
97+
}
98+
99+
public function testGetStringWithFailingStrictMode()
100+
{
101+
$this->expectException(TypeError::class);
102+
$this->runUnitTestStrict(null, null, Config::getString(...));
103+
}
104+
105+
public function testGetBoolWithFailingStrictMode()
106+
{
107+
$this->expectException(TypeError::class);
108+
$this->runUnitTestStrict(null, null, Config::getBool(...));
109+
}
110+
111+
public function testGetIntWithFailingStrictMode()
112+
{
113+
$this->expectException(TypeError::class);
114+
$this->runUnitTestStrict(null, null, Config::getInt(...));
115+
}
116+
117+
public function testGetFloatWithFailingStrictMode()
118+
{
119+
$this->expectException(TypeError::class);
120+
$this->runUnitTestStrict(null, null, Config::getFloat(...));
121+
}
122+
123+
public function testGetArrayWithArray()
124+
{
125+
$this->runUnitTest(['bar' => 'baz'], ['bar' => 'baz'], Config::getArray(...));
126+
}
127+
128+
public function testGetArrayWithNull()
129+
{
130+
$this->runUnitTest(null, [], Config::getArray(...));
131+
}
132+
133+
public function testGetArrayWithString()
134+
{
135+
$this->runUnitTest('bar', ['bar'], Config::getArray(...));
136+
}
137+
138+
public function testGetArrayWithBool()
139+
{
140+
$this->runUnitTest(true, [true], Config::getArray(...));
141+
}
142+
143+
public function testGetArrayWithInt()
144+
{
145+
$this->runUnitTest(1, [1], Config::getArray(...));
146+
}
147+
148+
public function testGetArrayWithFloat()
149+
{
150+
$this->runUnitTest(1.1, [1.1], Config::getArray(...));
151+
}
152+
153+
public function testGetStringWithArray()
154+
{
155+
$this->expectException(ErrorException::class);
156+
$this->runUnitTest(['bar' => 'baz'], 'Array', Config::getString(...));
157+
}
158+
159+
public function testGetStringWithNull()
160+
{
161+
$this->runUnitTest(null, '', Config::getString(...));
162+
}
163+
164+
public function testGetStringWithString()
165+
{
166+
$this->runUnitTest('bar', 'bar', Config::getString(...));
167+
}
168+
169+
public function testGetStringWithBool()
170+
{
171+
$this->runUnitTest(true, '1', Config::getString(...));
172+
}
173+
174+
public function testGetStringWithInt()
175+
{
176+
$this->runUnitTest(1, '1', Config::getString(...));
177+
}
178+
179+
public function testGetStringWithFloat()
180+
{
181+
$this->runUnitTest(1.1, '1.1', Config::getString(...));
182+
}
183+
184+
public function testGetBoolWithArray()
185+
{
186+
$this->runUnitTest(['bar' => 'baz'], true, Config::getBool(...));
187+
}
188+
189+
public function testGetBoolWithNull()
190+
{
191+
$this->runUnitTest(null, false, Config::getBool(...));
192+
}
193+
194+
public function testGetBoolWithString()
195+
{
196+
$this->runUnitTest('bar', true, Config::getBool(...));
197+
}
198+
199+
public function testGetBoolWithBool()
200+
{
201+
$this->runUnitTest(true, true, Config::getBool(...));
202+
}
203+
204+
public function testGetBoolWithInt()
205+
{
206+
$this->runUnitTest(1, true, Config::getBool(...));
207+
}
208+
209+
public function testGetBoolWithFloat()
210+
{
211+
$this->runUnitTest(1.1, true, Config::getBool(...));
212+
}
213+
214+
public function testGetIntWithArray()
215+
{
216+
$this->runUnitTest(0, 0, Config::getInt(...));
217+
}
218+
219+
public function testGetIntWithNull()
220+
{
221+
$this->runUnitTest(null, 0, Config::getInt(...));
222+
}
223+
224+
public function testGetIntWithString()
225+
{
226+
$this->runUnitTest('bar', 0, Config::getInt(...));
227+
}
228+
229+
public function testGetIntWithBool()
230+
{
231+
$this->runUnitTest(true, 1, Config::getInt(...));
232+
}
233+
234+
public function testGetIntWithInt()
235+
{
236+
$this->runUnitTest(1, 1, Config::getInt(...));
237+
}
238+
239+
public function testGetIntWithFloat()
240+
{
241+
$this->runUnitTest(1.1, 1, Config::getInt(...));
242+
}
243+
244+
public function testGetFloatWithArray()
245+
{
246+
$this->runUnitTest(['bar' => 'baz'], 1.0, Config::getFloat(...));
247+
}
248+
249+
public function testGetFloatWithNull()
250+
{
251+
$this->runUnitTest(null, 0.0, Config::getFloat(...));
252+
}
253+
254+
public function testGetFloatWithString()
255+
{
256+
$this->runUnitTest('bar', 0.0, Config::getFloat(...));
257+
}
258+
259+
public function testGetFloatWithBool()
260+
{
261+
$this->runUnitTest(true, 1.0, Config::getFloat(...));
262+
}
263+
264+
public function testGetFloatWithInt()
265+
{
266+
$this->runUnitTest(1, 1.0, Config::getFloat(...));
267+
}
268+
269+
public function testGetFloatWithFloat()
270+
{
271+
$this->runUnitTest(1.1, 1.1, Config::getFloat(...));
272+
}
273+
274+
protected function runUnitTest($actual, $expected, $method): void
275+
{
276+
config(['foo' => $actual]);
277+
$this->assertSame($expected, $method('foo'));
278+
}
279+
280+
protected function runUnitTestStrict($actual, $expected, $method): void
281+
{
282+
config(['foo' => $actual]);
283+
$this->assertSame($expected, $method('foo', strict: true));
284+
}
285+
}

0 commit comments

Comments
 (0)