Skip to content

Commit efc13e3

Browse files
committed
Migrate tests from PHPUnit to Pest
Replace phpunit/phpunit direct dep with pestphp/pest.
1 parent e1f3eb3 commit efc13e3

7 files changed

Lines changed: 732 additions & 1123 deletions

File tree

composer.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,6 @@
1515
"STS\\Phpinfo\\": "src/"
1616
}
1717
},
18-
"autoload-dev": {
19-
"psr-4": {
20-
"STS\\Phpinfo\\Tests\\": "tests/"
21-
}
22-
},
2318
"authors": [
2419
{
2520
"name": "Joseph Szobody",
@@ -31,7 +26,12 @@
3126
"ext-dom": "*"
3227
},
3328
"require-dev": {
34-
"phpunit/phpunit": "^11.0|^12.0",
35-
"laravel/pint": "^1.29"
29+
"laravel/pint": "^1.29",
30+
"pestphp/pest": "^4.0"
31+
},
32+
"config": {
33+
"allow-plugins": {
34+
"pestphp/pest-plugin": true
35+
}
3636
}
3737
}

tests/HtmlParserTest.php

Lines changed: 111 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -1,224 +1,156 @@
11
<?php
22

3-
namespace STS\Phpinfo\Tests;
4-
5-
use InvalidArgumentException;
6-
use PHPUnit\Framework\Attributes\Test;
7-
use PHPUnit\Framework\TestCase;
83
use STS\Phpinfo\Info;
94
use STS\Phpinfo\Parsers\HtmlParser;
105
use STS\Phpinfo\PhpInfo;
116

12-
class HtmlParserTest extends TestCase
7+
function htmlInfo(): PhpInfo
138
{
14-
private static ?PhpInfo $info = null;
15-
16-
private static function info(): PhpInfo
17-
{
18-
if (self::$info === null) {
19-
self::$info = Info::fromHtml(
20-
file_get_contents(__DIR__.'/fixtures/html-php83.html')
21-
);
22-
}
9+
static $info = null;
2310

24-
return self::$info;
25-
}
11+
return $info ??= Info::fromHtml(
12+
file_get_contents(__DIR__.'/fixtures/html-php83.html')
13+
);
14+
}
2615

27-
#[Test]
28-
public function it_can_detect_html_content(): void
29-
{
30-
$html = file_get_contents(__DIR__.'/fixtures/html-php83.html');
16+
it('can detect html content', function () {
17+
$html = file_get_contents(__DIR__.'/fixtures/html-php83.html');
3118

32-
$this->assertTrue(HtmlParser::canParse($html));
33-
$this->assertFalse(HtmlParser::canParse('not phpinfo'));
34-
$this->assertFalse(HtmlParser::canParse(''));
35-
}
19+
expect(HtmlParser::canParse($html))->toBeTrue()
20+
->and(HtmlParser::canParse('not phpinfo'))->toBeFalse()
21+
->and(HtmlParser::canParse(''))->toBeFalse();
22+
});
3623

37-
#[Test]
38-
public function it_rejects_invalid_content(): void
39-
{
40-
$this->expectException(InvalidArgumentException::class);
41-
Info::fromHtml('not phpinfo content');
42-
}
24+
it('rejects invalid content', function () {
25+
Info::fromHtml('not phpinfo content');
26+
})->throws(InvalidArgumentException::class);
4327

44-
#[Test]
45-
public function it_returns_phpinfo_instance(): void
46-
{
47-
$this->assertInstanceOf(PhpInfo::class, self::info());
48-
}
28+
it('returns phpinfo instance', function () {
29+
expect(htmlInfo())->toBeInstanceOf(PhpInfo::class);
30+
});
4931

50-
#[Test]
51-
public function it_parses_php_version(): void
52-
{
53-
$this->assertNotEmpty(self::info()->version());
54-
$this->assertMatchesRegularExpression('/^\d+\.\d+\.\d+/', self::info()->version());
55-
}
32+
it('parses php version', function () {
33+
expect(htmlInfo()->version())
34+
->not->toBeEmpty()
35+
->toMatch('/^\d+\.\d+\.\d+/');
36+
});
5637

57-
#[Test]
58-
public function it_parses_modules(): void
59-
{
60-
$modules = self::info()->modules();
38+
it('parses modules', function () {
39+
$modules = htmlInfo()->modules();
6140

62-
$this->assertGreaterThan(5, $modules->count());
63-
$this->assertEquals('General', $modules->first()->name());
64-
}
41+
expect($modules->count())->toBeGreaterThan(5)
42+
->and($modules->first()->name())->toBe('General');
43+
});
6544

66-
#[Test]
67-
public function it_has_general_module_with_configs(): void
68-
{
69-
$general = self::info()->module('General');
45+
it('has general module with configs', function () {
46+
$general = htmlInfo()->module('General');
7047

71-
$this->assertNotNull($general);
72-
$this->assertGreaterThan(0, $general->configs()->count());
73-
}
48+
expect($general)->not->toBeNull()
49+
->and($general->configs()->count())->toBeGreaterThan(0);
50+
});
7451

75-
#[Test]
76-
public function has_module_is_case_insensitive(): void
77-
{
78-
$firstModuleName = self::info()->modules()->skip(1)->first()->name();
52+
it('has case insensitive module lookup', function () {
53+
$name = htmlInfo()->modules()->skip(1)->first()->name();
7954

80-
$this->assertTrue(self::info()->hasModule($firstModuleName));
81-
$this->assertTrue(self::info()->hasModule(strtolower($firstModuleName)));
82-
$this->assertTrue(self::info()->hasModule(strtoupper($firstModuleName)));
83-
}
55+
expect(htmlInfo()->hasModule($name))->toBeTrue()
56+
->and(htmlInfo()->hasModule(strtolower($name)))->toBeTrue()
57+
->and(htmlInfo()->hasModule(strtoupper($name)))->toBeTrue();
58+
});
8459

85-
#[Test]
86-
public function it_returns_null_for_missing_module(): void
87-
{
88-
$this->assertNull(self::info()->module('nonexistent_module_xyz'));
89-
$this->assertFalse(self::info()->hasModule('nonexistent_module_xyz'));
90-
}
60+
it('returns null for missing module', function () {
61+
expect(htmlInfo()->module('nonexistent_module_xyz'))->toBeNull()
62+
->and(htmlInfo()->hasModule('nonexistent_module_xyz'))->toBeFalse();
63+
});
9164

92-
#[Test]
93-
public function it_parses_configs(): void
94-
{
95-
$this->assertGreaterThan(50, self::info()->configs()->count());
96-
}
65+
it('parses configs', function () {
66+
expect(htmlInfo()->configs()->count())->toBeGreaterThan(50);
67+
});
9768

98-
#[Test]
99-
public function it_can_query_individual_configs(): void
100-
{
101-
$this->assertTrue(self::info()->hasConfig('System'));
102-
$this->assertNotNull(self::info()->config('System'));
103-
}
69+
it('can query individual configs', function () {
70+
expect(htmlInfo()->hasConfig('System'))->toBeTrue()
71+
->and(htmlInfo()->config('System'))->not->toBeNull();
72+
});
10473

105-
#[Test]
106-
public function it_returns_null_for_missing_config(): void
107-
{
108-
$this->assertNull(self::info()->config('nonexistent_config_xyz'));
109-
$this->assertFalse(self::info()->hasConfig('nonexistent_config_xyz'));
110-
}
74+
it('returns null for missing config', function () {
75+
expect(htmlInfo()->config('nonexistent_config_xyz'))->toBeNull()
76+
->and(htmlInfo()->hasConfig('nonexistent_config_xyz'))->toBeFalse();
77+
});
78+
79+
it('has working convenience methods', function () {
80+
$os = htmlInfo()->os();
81+
$hostname = htmlInfo()->hostname();
11182

112-
#[Test]
113-
public function convenience_methods_work(): void
114-
{
115-
$os = self::info()->os();
116-
$hostname = self::info()->hostname();
83+
expect($os)->not->toBeNull()
84+
->and($hostname)->not->toBeNull()
85+
->and(htmlInfo()->config('System'))->toStartWith($os);
86+
});
11787

118-
$this->assertNotNull($os);
119-
$this->assertNotNull($hostname);
88+
it('handles local and master values', function () {
89+
$config = htmlInfo()->configs()->first(fn ($c) => $c->hasMasterValue());
12090

121-
$system = self::info()->config('System');
122-
$this->assertStringStartsWith($os, $system);
91+
if ($config) {
92+
expect(htmlInfo()->config($config->name(), 'local'))->not->toBeNull();
12393
}
12494

125-
#[Test]
126-
public function it_handles_local_and_master_values(): void
127-
{
128-
$configWithMaster = self::info()->configs()
129-
->first(fn ($config) => $config->hasMasterValue());
95+
expect(true)->toBeTrue();
96+
});
13097

131-
if ($configWithMaster) {
132-
$name = $configWithMaster->name();
133-
$this->assertNotNull(self::info()->config($name, 'local'));
134-
}
98+
it('parses groups with headings', function () {
99+
$groupWithHeadings = null;
135100

136-
$this->assertTrue(true);
137-
}
138-
139-
#[Test]
140-
public function it_parses_groups_with_headings(): void
141-
{
142-
$groupWithHeadings = null;
143-
144-
foreach (self::info()->modules() as $module) {
145-
foreach ($module->groups() as $group) {
146-
if ($group->hasHeadings()) {
147-
$groupWithHeadings = $group;
148-
break 2;
149-
}
101+
foreach (htmlInfo()->modules() as $module) {
102+
foreach ($module->groups() as $group) {
103+
if ($group->hasHeadings()) {
104+
$groupWithHeadings = $group;
105+
break 2;
150106
}
151107
}
152-
153-
if ($groupWithHeadings) {
154-
$this->assertGreaterThan(0, $groupWithHeadings->headings()->count());
155-
$this->assertNotNull($groupWithHeadings->heading(0));
156-
}
157-
158-
$this->assertTrue(true);
159108
}
160109

161-
#[Test]
162-
public function it_handles_svg_elements_in_html(): void
163-
{
164-
$infoWithSvg = Info::fromHtml(file_get_contents(__DIR__.'/fixtures/html-php83-with-svg.html'));
165-
$infoWithout = Info::fromHtml(file_get_contents(__DIR__.'/fixtures/html-php83.html'));
166-
167-
$this->assertEquals(
168-
$infoWithout->modules()->count(),
169-
$infoWithSvg->modules()->count()
170-
);
171-
$this->assertEquals(
172-
$infoWithout->configs()->count(),
173-
$infoWithSvg->configs()->count()
174-
);
110+
if ($groupWithHeadings) {
111+
expect($groupWithHeadings->headings()->count())->toBeGreaterThan(0)
112+
->and($groupWithHeadings->heading(0))->not->toBeNull();
175113
}
176114

177-
#[Test]
178-
public function it_parses_credits(): void
179-
{
180-
$credits = self::info()->module('PHP Credits');
115+
expect(true)->toBeTrue();
116+
});
181117

182-
$this->assertNotNull($credits);
183-
$this->assertNotEmpty($credits->name());
184-
$this->assertGreaterThan(0, $credits->groups()->count());
185-
}
118+
it('handles svg elements in html', function () {
119+
$infoWithSvg = Info::fromHtml(file_get_contents(__DIR__.'/fixtures/html-php83-with-svg.html'));
120+
$infoWithout = Info::fromHtml(file_get_contents(__DIR__.'/fixtures/html-php83.html'));
186121

187-
#[Test]
188-
public function it_parses_license(): void
189-
{
190-
$license = self::info()->module('PHP License');
122+
expect($infoWithSvg->modules()->count())->toBe($infoWithout->modules()->count())
123+
->and($infoWithSvg->configs()->count())->toBe($infoWithout->configs()->count());
124+
});
191125

192-
$this->assertNotNull($license);
193-
$this->assertNotEmpty($license->name());
194-
$this->assertGreaterThan(0, $license->groups()->count());
195-
}
126+
it('parses credits', function () {
127+
$credits = htmlInfo()->module('PHP Credits');
196128

197-
#[Test]
198-
public function it_is_json_serializable(): void
199-
{
200-
$json = json_encode(self::info());
129+
expect($credits)->not->toBeNull()
130+
->and($credits->name())->not->toBeEmpty()
131+
->and($credits->groups()->count())->toBeGreaterThan(0);
132+
});
201133

202-
$this->assertNotFalse($json);
134+
it('parses license', function () {
135+
$license = htmlInfo()->module('PHP License');
203136

204-
$data = json_decode($json, true);
205-
$this->assertArrayHasKey('version', $data);
206-
$this->assertArrayHasKey('modules', $data);
207-
$this->assertIsArray($data['modules']);
208-
$this->assertGreaterThan(0, count($data['modules']));
137+
expect($license)->not->toBeNull()
138+
->and($license->name())->not->toBeEmpty()
139+
->and($license->groups()->count())->toBeGreaterThan(0);
140+
});
209141

210-
$firstModule = $data['modules'][0];
211-
$this->assertArrayHasKey('key', $firstModule);
212-
$this->assertArrayHasKey('name', $firstModule);
213-
$this->assertArrayHasKey('groups', $firstModule);
214-
}
142+
it('is json serializable', function () {
143+
$json = json_encode(htmlInfo());
144+
$data = json_decode($json, true);
215145

216-
#[Test]
217-
public function modules_have_unique_keys(): void
218-
{
219-
$keys = self::info()->modules()->map(fn ($m) => $m->key());
220-
$uniqueKeys = $keys->unique();
146+
expect($json)->not->toBeFalse()
147+
->and($data)->toHaveKeys(['version', 'modules'])
148+
->and($data['modules'])->toBeArray()->not->toBeEmpty()
149+
->and($data['modules'][0])->toHaveKeys(['key', 'name', 'groups']);
150+
});
221151

222-
$this->assertEquals($keys->count(), $uniqueKeys->count());
223-
}
224-
}
152+
it('has unique module keys', function () {
153+
$keys = htmlInfo()->modules()->map(fn ($m) => $m->key());
154+
155+
expect($keys->unique()->count())->toBe($keys->count());
156+
});

0 commit comments

Comments
 (0)