Skip to content

Commit 4f711dd

Browse files
authored
Merge pull request #12 from KaririCode-Framework/develop
Develop
2 parents 39c8168 + 9ba5410 commit 4f711dd

14 files changed

Lines changed: 1628 additions & 0 deletions
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Devkit\Tests\Unit\Command;
6+
7+
use KaririCode\Devkit\Command\AbstractCommand;
8+
use KaririCode\Devkit\Core\Devkit;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
use PHPUnit\Framework\Attributes\Test;
11+
use PHPUnit\Framework\TestCase;
12+
13+
#[CoversClass(AbstractCommand::class)]
14+
final class AbstractCommandTest extends TestCase
15+
{
16+
private AbstractCommand $command;
17+
18+
protected function setUp(): void
19+
{
20+
$this->command = new class () extends AbstractCommand {
21+
public function name(): string
22+
{
23+
return 'test';
24+
}
25+
26+
public function description(): string
27+
{
28+
return 'Test command';
29+
}
30+
31+
public function execute(Devkit $devkit, array $arguments): int
32+
{
33+
return 0;
34+
}
35+
36+
/** @param list<string> $args */
37+
public function callHasFlag(array $args, string ...$flags): bool
38+
{
39+
return $this->hasFlag($args, ...$flags);
40+
}
41+
42+
/** @param list<string> $args */
43+
public function callOption(array $args, string $key, ?string $default = null): ?string
44+
{
45+
return $this->option($args, $key, $default);
46+
}
47+
48+
/** @param list<string> $args @return list<string> */
49+
public function callPositional(array $args): array
50+
{
51+
return $this->positional($args);
52+
}
53+
54+
/**
55+
* @param list<string> $args
56+
* @param list<string> $consume
57+
* @return list<string>
58+
*/
59+
public function callPassthrough(array $args, array $consume = []): array
60+
{
61+
return $this->passthrough($args, $consume);
62+
}
63+
64+
public function callInfo(string $msg): void
65+
{
66+
$this->info($msg);
67+
}
68+
69+
public function callWarning(string $msg): void
70+
{
71+
$this->warning($msg);
72+
}
73+
74+
public function callError(string $msg): void
75+
{
76+
$this->error($msg);
77+
}
78+
79+
public function callLine(string $msg = ''): void
80+
{
81+
$this->line($msg);
82+
}
83+
84+
public function callBanner(string $title): void
85+
{
86+
$this->banner($title);
87+
}
88+
89+
public function callSection(string $title): void
90+
{
91+
$this->section($title);
92+
}
93+
};
94+
}
95+
96+
// ── Identity ───────────────────────────────────────────────────
97+
98+
#[Test]
99+
public function nameReturnsCommandName(): void
100+
{
101+
$this->assertSame('test', $this->command->name());
102+
}
103+
104+
#[Test]
105+
public function descriptionReturnsDescription(): void
106+
{
107+
$this->assertSame('Test command', $this->command->description());
108+
}
109+
110+
// ── Argument helpers ───────────────────────────────────────────
111+
112+
#[Test]
113+
public function hasFlagReturnsTrueWhenFlagPresent(): void
114+
{
115+
$this->assertTrue($this->command->callHasFlag(['--verbose', '--check'], '--verbose'));
116+
}
117+
118+
#[Test]
119+
public function hasFlagReturnsFalseWhenFlagAbsent(): void
120+
{
121+
$this->assertFalse($this->command->callHasFlag(['--check'], '--verbose'));
122+
}
123+
124+
#[Test]
125+
public function hasFlagMatchesAnyOfMultipleFlags(): void
126+
{
127+
$this->assertTrue($this->command->callHasFlag(['--dry-run'], '--check', '--dry-run'));
128+
}
129+
130+
#[Test]
131+
public function hasFlagReturnsFalseWithEmptyArgs(): void
132+
{
133+
$this->assertFalse($this->command->callHasFlag([], '--any'));
134+
}
135+
136+
#[Test]
137+
public function optionExtractsValueFromArguments(): void
138+
{
139+
$result = $this->command->callOption(['--level=9', '--other=x'], 'level');
140+
$this->assertSame('9', $result);
141+
}
142+
143+
#[Test]
144+
public function optionReturnsDefaultWhenNotFound(): void
145+
{
146+
$result = $this->command->callOption(['--other=x'], 'level', 'default');
147+
$this->assertSame('default', $result);
148+
}
149+
150+
#[Test]
151+
public function optionReturnsNullWhenNotFoundAndNoDefault(): void
152+
{
153+
$this->assertNull($this->command->callOption([], 'level'));
154+
}
155+
156+
#[Test]
157+
public function positionalFiltersOutFlags(): void
158+
{
159+
$result = $this->command->callPositional(['file.php', '--verbose', 'other.php', '--dry-run']);
160+
$this->assertSame(['file.php', 'other.php'], $result);
161+
}
162+
163+
#[Test]
164+
public function positionalReturnsEmptyForAllFlags(): void
165+
{
166+
$result = $this->command->callPositional(['--a', '--b', '--c']);
167+
$this->assertSame([], $result);
168+
}
169+
170+
#[Test]
171+
public function passthroughRemovesConsumedFlags(): void
172+
{
173+
$result = $this->command->callPassthrough(
174+
['--verbose', '--coverage', '--check'],
175+
['--coverage'],
176+
);
177+
$this->assertSame(['--verbose', '--check'], $result);
178+
}
179+
180+
#[Test]
181+
public function passthroughWithNoConsumedFlagsReturnsAll(): void
182+
{
183+
$args = ['--verbose', '--check'];
184+
$result = $this->command->callPassthrough($args);
185+
$this->assertSame($args, $result);
186+
}
187+
188+
// ── Output helpers — fwrite(STDOUT/STDERR) cannot be captured by ob_start ─
189+
// We verify these methods exist and do not throw exceptions.
190+
191+
#[Test]
192+
public function infoDoesNotThrow(): void
193+
{
194+
$this->expectNotToPerformAssertions();
195+
$this->command->callInfo('hello');
196+
}
197+
198+
#[Test]
199+
public function warningDoesNotThrow(): void
200+
{
201+
$this->expectNotToPerformAssertions();
202+
$this->command->callWarning('caution');
203+
}
204+
205+
#[Test]
206+
public function errorDoesNotThrow(): void
207+
{
208+
$this->expectNotToPerformAssertions();
209+
$this->command->callError('something failed');
210+
}
211+
212+
#[Test]
213+
public function lineDoesNotThrow(): void
214+
{
215+
$this->expectNotToPerformAssertions();
216+
$this->command->callLine('some output');
217+
}
218+
219+
#[Test]
220+
public function bannerDoesNotThrow(): void
221+
{
222+
$this->expectNotToPerformAssertions();
223+
$this->command->callBanner('My Banner');
224+
}
225+
226+
#[Test]
227+
public function sectionDoesNotThrow(): void
228+
{
229+
$this->expectNotToPerformAssertions();
230+
$this->command->callSection('My Section');
231+
}
232+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Devkit\Tests\Unit\Configuration;
6+
7+
use KaririCode\Devkit\Configuration\CsFixerConfigGenerator;
8+
use KaririCode\Devkit\Core\ProjectContext;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
use PHPUnit\Framework\Attributes\Test;
11+
use PHPUnit\Framework\TestCase;
12+
13+
#[CoversClass(CsFixerConfigGenerator::class)]
14+
final class CsFixerConfigGeneratorTest extends TestCase
15+
{
16+
private CsFixerConfigGenerator $generator;
17+
18+
protected function setUp(): void
19+
{
20+
$this->generator = new CsFixerConfigGenerator();
21+
}
22+
23+
private function makeContext(array $rules = ['@PSR12' => true]): ProjectContext
24+
{
25+
return new ProjectContext(
26+
projectRoot: '/project',
27+
projectName: 'test/project',
28+
namespace: 'Test\\Project',
29+
phpVersion: '8.4',
30+
phpstanLevel: 9,
31+
psalmLevel: 3,
32+
sourceDirs: ['/project/src'],
33+
testDirs: ['/project/tests'],
34+
excludeDirs: [],
35+
testSuites: [],
36+
coverageExclude: [],
37+
csFixerRules: $rules,
38+
rectorSets: [],
39+
toolVersions: [],
40+
);
41+
}
42+
43+
#[Test]
44+
public function toolNameReturnsCsFixer(): void
45+
{
46+
$this->assertSame('cs-fixer', $this->generator->toolName());
47+
}
48+
49+
#[Test]
50+
public function outputPathReturnsPhpCsFixerPhp(): void
51+
{
52+
$this->assertSame('php-cs-fixer.php', $this->generator->outputPath());
53+
}
54+
55+
#[Test]
56+
public function generateContainsPhpDeclaration(): void
57+
{
58+
$output = $this->generator->generate($this->makeContext());
59+
$this->assertStringContainsString('<?php', $output);
60+
}
61+
62+
#[Test]
63+
public function generateContainsSourceDir(): void
64+
{
65+
$output = $this->generator->generate($this->makeContext());
66+
$this->assertStringContainsString("->in(__DIR__ . '/../src')", $output);
67+
}
68+
69+
#[Test]
70+
public function generateContainsTestDir(): void
71+
{
72+
$output = $this->generator->generate($this->makeContext());
73+
$this->assertStringContainsString("->in(__DIR__ . '/../tests')", $output);
74+
}
75+
76+
#[Test]
77+
public function generateContainsRulesFromContext(): void
78+
{
79+
$output = $this->generator->generate($this->makeContext(['@PSR12' => true, 'array_syntax' => ['syntax' => 'short']]));
80+
$this->assertStringContainsString('@PSR12', $output);
81+
$this->assertStringContainsString('array_syntax', $output);
82+
}
83+
84+
#[Test]
85+
public function generateContainsCacheFile(): void
86+
{
87+
$output = $this->generator->generate($this->makeContext());
88+
$this->assertStringContainsString('.php-cs-fixer.cache', $output);
89+
}
90+
91+
#[Test]
92+
public function generateContainsRiskyAllowed(): void
93+
{
94+
$output = $this->generator->generate($this->makeContext());
95+
$this->assertStringContainsString('setRiskyAllowed(true)', $output);
96+
}
97+
}

0 commit comments

Comments
 (0)