Skip to content

Commit 1bf7688

Browse files
committed
test: Add Unit Tests
1 parent 3c16453 commit 1bf7688

7 files changed

Lines changed: 202 additions & 20 deletions

File tree

composer.json

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
"phpstan": "php ./vendor/bin/phpstan analyse --memory-limit=-1",
88
"pint": "./vendor/bin/pint --test -v",
99
"pint:fix": "./vendor/bin/pint",
10-
"refactor": "./vendor/bin/rector process"
10+
"refactor": "./vendor/bin/rector process",
11+
"test": "./vendor/bin/pest",
12+
"test:coverage": "XDEBUG_MODE=coverage ./vendor/bin/pest --coverage",
13+
"test:type-coverage": "./vendor/bin/pest --type-coverage --min=100"
1114
},
1215
"autoload": {
1316
"psr-4": {
@@ -16,7 +19,8 @@
1619
},
1720
"autoload-dev": {
1821
"psr-4": {
19-
"Artemeon\\Console\\Example\\": "example/"
22+
"Artemeon\\Console\\Example\\": "example/",
23+
"Artemeon\\Console\\Tests\\": "tests/"
2024
}
2125
},
2226
"authors": [
@@ -35,6 +39,13 @@
3539
"require-dev": {
3640
"laravel/pint": "^1.20.0",
3741
"phpstan/phpstan": "^2.1.2",
38-
"rector/rector": "^2.0.7"
42+
"rector/rector": "^2.0.7",
43+
"pestphp/pest": "^3.8",
44+
"pestphp/pest-plugin-type-coverage": "^3.6"
45+
},
46+
"config": {
47+
"allow-plugins": {
48+
"pestphp/pest-plugin": true
49+
}
3950
}
4051
}

phpunit.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
colors="true"
6+
>
7+
<testsuites>
8+
<testsuite name="Test Suite">
9+
<directory suffix="Test.php">./tests</directory>
10+
</testsuite>
11+
</testsuites>
12+
<source>
13+
<include>
14+
<directory>src</directory>
15+
</include>
16+
</source>
17+
</phpunit>

src/Parser.php

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -100,61 +100,61 @@ protected static function parseArgument(string $token): InputArgument
100100
*/
101101
protected static function parseOption(string $token): InputOption
102102
{
103-
[$token, $description] = static::extractDescription($token);
103+
[$name, $description] = static::extractDescription($token);
104104

105-
$matches = preg_split('/\s*\|\s*/', $token, 2);
105+
$matches = preg_split('/\s*\|\s*/', $name, 2);
106106

107107
if (isset($matches[1])) {
108-
[$shortcut, $token] = $matches;
108+
[$shortcut, $name] = $matches;
109109
} else {
110110
$shortcut = null;
111111
}
112112

113113
return match (true) {
114-
str_ends_with($token, '==') => new InputOption(
115-
trim($token, '='),
114+
str_ends_with($name, '==') => new InputOption(
115+
trim($name, '='),
116116
$shortcut,
117117
InputOption::VALUE_REQUIRED,
118118
$description,
119119
),
120-
str_ends_with($token, '=') => new InputOption(
121-
trim($token, '='),
120+
str_ends_with($name, '=') => new InputOption(
121+
trim($name, '='),
122122
$shortcut,
123123
InputOption::VALUE_OPTIONAL,
124124
$description,
125125
),
126-
str_ends_with($token, '==*') => new InputOption(
127-
trim($token, '=*'),
126+
str_ends_with($name, '==*') => new InputOption(
127+
trim($name, '=*'),
128128
$shortcut,
129129
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
130130
),
131-
str_ends_with($token, '=*') => new InputOption(
132-
trim($token, '=*'),
131+
str_ends_with($name, '=*') => new InputOption(
132+
trim($name, '=*'),
133133
$shortcut,
134134
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
135135
$description,
136136
),
137-
preg_match('/(.+)\=\*(.+)/', $token, $matches) === 1 => new InputOption(
137+
preg_match('/(.+)\=\*(.+)/', $name, $matches) === 1 => new InputOption(
138138
$matches[1],
139139
$shortcut,
140140
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
141141
$description,
142142
preg_split('/,\s?/', $matches[2]),
143143
),
144-
preg_match('/(.+)\=(.+)/', $token, $matches) === 1 => new InputOption(
144+
preg_match('/(.+)\=(.+)/', $name, $matches) === 1 => new InputOption(
145145
$matches[1],
146146
$shortcut,
147147
InputOption::VALUE_OPTIONAL,
148148
$description,
149149
$matches[2],
150150
),
151-
str_ends_with($token, '!') => new InputOption(
152-
trim($token, '!'),
151+
str_ends_with($name, '!') => new InputOption(
152+
trim($name, '!'),
153153
$shortcut,
154154
InputOption::VALUE_NEGATABLE,
155155
$description,
156156
),
157-
default => new InputOption($token, $shortcut, InputOption::VALUE_NONE, $description),
157+
default => new InputOption($name, $shortcut, InputOption::VALUE_NONE, $description),
158158
};
159159
}
160160

@@ -165,7 +165,7 @@ protected static function parseOption(string $token): InputOption
165165
*/
166166
protected static function extractDescription(string $token): array
167167
{
168-
$parts = preg_split('/\s+:\s+/', trim($token), 2);
168+
$parts = preg_split('/\s+:\s+/', $token, 2);
169169
if ($parts === false) {
170170
return [];
171171
}

tests/Feature/ExampleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
test('example', function () {
4+
expect(true)->toBeTrue();
5+
});

tests/Pest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/*
4+
|--------------------------------------------------------------------------
5+
| Test Case
6+
|--------------------------------------------------------------------------
7+
|
8+
| The closure you provide to your test functions is always bound to a specific PHPUnit test
9+
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
10+
| need to change it using the "pest()" function to bind a different classes or traits.
11+
|
12+
*/
13+
14+
pest()->extend(Artemeon\Console\Tests\TestCase::class)->in('Feature');
15+
16+
/*
17+
|--------------------------------------------------------------------------
18+
| Expectations
19+
|--------------------------------------------------------------------------
20+
|
21+
| When you're writing tests, you often need to check that values meet certain conditions. The
22+
| "expect()" function gives you access to a set of "expectations" methods that you can use
23+
| to assert different things. Of course, you may extend the Expectation API at any time.
24+
|
25+
*/
26+
27+
expect()->extend('toBeOne', function () {
28+
return $this->toBe(1);
29+
});
30+
31+
/*
32+
|--------------------------------------------------------------------------
33+
| Functions
34+
|--------------------------------------------------------------------------
35+
|
36+
| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
37+
| project that you don't want to repeat in every file. Here you can also expose helpers as
38+
| global functions to help you to reduce the number of lines of code in your test files.
39+
|
40+
*/
41+
42+
function something()
43+
{
44+
// ..
45+
}

tests/TestCase.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Artemeon\Console\Tests;
4+
5+
use PHPUnit\Framework\TestCase as BaseTestCase;
6+
7+
abstract class TestCase extends BaseTestCase
8+
{
9+
//
10+
}

tests/Unit/ParserTest.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
use Artemeon\Console\Parser;
4+
5+
covers(Parser::class);
6+
7+
it('can parse the name', function (): void {
8+
[$name] = Parser::parse('foo:bar');
9+
10+
expect($name)->toBe('foo:bar');
11+
});
12+
13+
it('throws an exception if the name is invalid', function (): void {
14+
expect(static fn () => Parser::parse(''))
15+
->toThrow(InvalidArgumentException::class, 'Unable to determine command name from signature.');
16+
});
17+
18+
it('can parse simple arguments', function (): void {
19+
[, $arguments] = Parser::parse('foo:bar {hello} {world}');
20+
21+
expect($arguments)
22+
->toHaveCount(2)
23+
->and($arguments[0]->getName())->toBe('hello')
24+
->and($arguments[0]->isRequired())->toBeTrue()
25+
->and($arguments[0]->getDescription())->toBe('')
26+
->and($arguments[1]->getName())->toBe('world')
27+
->and($arguments[1]->isRequired())->toBeTrue()
28+
->and($arguments[1]->getDescription())->toBe('');
29+
});
30+
31+
it('can parse optional arguments', function (): void {
32+
[, $arguments] = Parser::parse('foo:bar {hello?} {world?}');
33+
34+
expect($arguments)
35+
->toHaveCount(2)
36+
->and($arguments[0]->getName())->toBe('hello')
37+
->and($arguments[0]->isRequired())->toBeFalse()
38+
->and($arguments[1]->getName())->toBe('world')
39+
->and($arguments[1]->isRequired())->toBeFalse();
40+
});
41+
42+
it('can parse optional arguments with default value', function (): void {
43+
[, $arguments] = Parser::parse('foo:bar {hello=foo} {world=bar}');
44+
45+
expect($arguments)
46+
->toHaveCount(2)
47+
->and($arguments[0]->getName())->toBe('hello')
48+
->and($arguments[0]->isRequired())->toBeFalse()
49+
->and($arguments[0]->getDefault())->toBe('foo')
50+
->and($arguments[1]->getName())->toBe('world')
51+
->and($arguments[1]->isRequired())->toBeFalse()
52+
->and($arguments[1]->getDefault())->toBe('bar');
53+
});
54+
55+
it('can parse arguments with description', function (): void {
56+
[, $arguments] = Parser::parse('foo:bar {hello : Foo} {world : Bar : Baz }');
57+
58+
expect($arguments)
59+
->toHaveCount(2)
60+
->and($arguments[0]->getName())->toBe('hello')
61+
->and($arguments[0]->isRequired())->toBeTrue()
62+
->and($arguments[0]->getDescription())->toBe('Foo')
63+
->and($arguments[1]->getName())->toBe('world')
64+
->and($arguments[1]->isRequired())->toBeTrue()
65+
->and($arguments[1]->getDescription())->toBe('Bar : Baz');
66+
});
67+
68+
it('can parse simple options', function (): void {
69+
[,, $options] = Parser::parse('foo:bar {--hello} {--world}');
70+
71+
expect($options)
72+
->toHaveCount(2)
73+
->and($options[0]->getName())->toBe('hello')
74+
->and($options[0]->isArray())->toBeFalse()
75+
->and($options[0]->getDefault())->toBeFalse()
76+
->and($options[1]->getName())->toBe('world')
77+
->and($options[1]->isArray())->toBeFalse()
78+
->and($options[1]->getDefault())->toBeFalse();
79+
});
80+
81+
it('can parse options with shortcut', function (): void {
82+
[,, $options] = Parser::parse('foo:bar {--h|hello} {--w|world}');
83+
84+
expect($options)
85+
->toHaveCount(2)
86+
->and($options[0]->getName())->toBe('hello')
87+
->and($options[0]->isArray())->toBeFalse()
88+
->and($options[0]->getDefault())->toBeFalse()
89+
->and($options[0]->getShortcut())->toBe('h')
90+
->and($options[1]->getName())->toBe('world')
91+
->and($options[1]->isArray())->toBeFalse()
92+
->and($options[1]->getDefault())->toBeFalse()
93+
->and($options[1]->getShortcut())->toBe('w');
94+
});

0 commit comments

Comments
 (0)