Skip to content

Commit f4d2ede

Browse files
authored
Test class Generator (#8333)
* fixing stuff and replacing files lost in rebase * Fixing namespace test
1 parent e0eea00 commit f4d2ede

File tree

8 files changed

+192
-452
lines changed

8 files changed

+192
-452
lines changed

phpstan-baseline.php

-425
Large diffs are not rendered by default.

system/CLI/GeneratorTrait.php

+40-27
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ trait GeneratorTrait
5959
*/
6060
protected $classNameLang = '';
6161

62+
/**
63+
* Namespace to use for class.
64+
* Leave null to use the default namespace.
65+
*/
66+
protected ?string $namespace = null;
67+
6268
/**
6369
* Whether to require class name.
6470
*
@@ -108,7 +114,7 @@ protected function execute(array $params): void
108114
/**
109115
* Generates a class file from an existing template.
110116
*/
111-
protected function generateClass(array $params)
117+
protected function generateClass(array $params): void
112118
{
113119
$this->params = $params;
114120

@@ -119,7 +125,7 @@ protected function generateClass(array $params)
119125
$target = $this->buildPath($class);
120126

121127
// Check if path is empty.
122-
if (empty($target)) {
128+
if ($target === '') {
123129
return;
124130
}
125131

@@ -131,14 +137,14 @@ protected function generateClass(array $params)
131137
*
132138
* @param string $view namespaced view name that is generated
133139
*/
134-
protected function generateView(string $view, array $params)
140+
protected function generateView(string $view, array $params): void
135141
{
136142
$this->params = $params;
137143

138144
$target = $this->buildPath($view);
139145

140146
// Check if path is empty.
141-
if (empty($target)) {
147+
if ($target === '') {
142148
return;
143149
}
144150

@@ -263,8 +269,10 @@ protected function qualifyClassName(): string
263269

264270
if ($class === null && $this->hasClassName) {
265271
// @codeCoverageIgnoreStart
266-
$nameLang = $this->classNameLang ?: 'CLI.generator.className.default';
267-
$class = CLI::prompt(lang($nameLang), null, 'required');
272+
$nameLang = $this->classNameLang !== ''
273+
? $this->classNameLang
274+
: 'CLI.generator.className.default';
275+
$class = CLI::prompt(lang($nameLang), null, 'required');
268276
CLI::newLine();
269277
// @codeCoverageIgnoreEnd
270278
}
@@ -302,20 +310,15 @@ protected function qualifyClassName(): string
302310
);
303311

304312
// Gets the namespace from input. Don't forget the ending backslash!
305-
$namespace = trim(
306-
str_replace(
307-
'/',
308-
'\\',
309-
$this->getOption('namespace') ?? APP_NAMESPACE
310-
),
311-
'\\'
312-
) . '\\';
313+
$namespace = $this->getNamespace() . '\\';
313314

314315
if (strncmp($class, $namespace, strlen($namespace)) === 0) {
315316
return $class; // @codeCoverageIgnore
316317
}
317318

318-
return $namespace . $this->directory . '\\' . str_replace('/', '\\', $class);
319+
$directoryString = ($this->directory !== null) ? $this->directory . '\\' : '';
320+
321+
return $namespace . $directoryString . str_replace('/', '\\', $class);
319322
}
320323

321324
/**
@@ -403,14 +406,7 @@ protected function buildContent(string $class): string
403406
*/
404407
protected function buildPath(string $class): string
405408
{
406-
$namespace = trim(
407-
str_replace(
408-
'/',
409-
'\\',
410-
$this->getOption('namespace') ?? APP_NAMESPACE
411-
),
412-
'\\'
413-
);
409+
$namespace = $this->getNamespace();
414410

415411
// Check if the namespace is actually defined and we are not just typing gibberish.
416412
$base = Services::autoloader()->getNamespace($namespace);
@@ -426,7 +422,9 @@ protected function buildPath(string $class): string
426422
return '';
427423
}
428424

429-
$base = realpath($base) ?: $base;
425+
$realpath = realpath($base);
426+
$base = ($realpath !== false) ? $realpath : $base;
427+
430428
$file = $base . DIRECTORY_SEPARATOR
431429
. str_replace(
432430
'\\',
@@ -444,6 +442,23 @@ protected function buildPath(string $class): string
444442
) . DIRECTORY_SEPARATOR . $this->basename($file);
445443
}
446444

445+
/**
446+
* Gets the namespace from the command-line option,
447+
* or the default namespace if the option is not set.
448+
* Can be overridden by directly setting $this->namespace.
449+
*/
450+
protected function getNamespace(): string
451+
{
452+
return $this->namespace ?? trim(
453+
str_replace(
454+
'/',
455+
'\\',
456+
$this->getOption('namespace') ?? APP_NAMESPACE
457+
),
458+
'\\'
459+
);
460+
}
461+
447462
/**
448463
* Allows child generators to modify the internal `$hasClassName` flag.
449464
*
@@ -483,10 +498,8 @@ protected function setEnabledSuffixing(bool $enabledSuffixing)
483498
/**
484499
* Gets a single command-line option. Returns TRUE if the option exists,
485500
* but doesn't have a value, and is simply acting as a flag.
486-
*
487-
* @return mixed
488501
*/
489-
protected function getOption(string $name)
502+
protected function getOption(string $name): string|bool|null
490503
{
491504
if (! array_key_exists($name, $this->params)) {
492505
return CLI::getOption($name);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) CodeIgniter Foundation <[email protected]>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace CodeIgniter\Commands\Generators;
15+
16+
use CodeIgniter\CLI\BaseCommand;
17+
use CodeIgniter\CLI\GeneratorTrait;
18+
19+
/**
20+
* Generates a skeleton command file.
21+
*/
22+
class TestGenerator extends BaseCommand
23+
{
24+
use GeneratorTrait;
25+
26+
/**
27+
* The Command's Group
28+
*
29+
* @var string
30+
*/
31+
protected $group = 'Generators';
32+
33+
/**
34+
* The Command's Name
35+
*
36+
* @var string
37+
*/
38+
protected $name = 'make:test';
39+
40+
/**
41+
* The Command's Description
42+
*
43+
* @var string
44+
*/
45+
protected $description = 'Generates a new test file.';
46+
47+
/**
48+
* The Command's Usage
49+
*
50+
* @var string
51+
*/
52+
protected $usage = 'make:test <name> [options]';
53+
54+
/**
55+
* The Command's Arguments
56+
*
57+
* @var array<string, string>
58+
*/
59+
protected $arguments = [
60+
'name' => 'The command class name.',
61+
];
62+
63+
/**
64+
* The Command's Options
65+
*
66+
* @var array<string, string>
67+
*/
68+
protected $options = [
69+
'--namespace' => 'Set root namespace. Default: "APP_NAMESPACE".',
70+
'--force' => 'Force overwrite existing file.',
71+
];
72+
73+
/**
74+
* Actually execute a command.
75+
*/
76+
public function run(array $params)
77+
{
78+
$this->component = 'Test';
79+
$this->template = 'test.tpl.php';
80+
$this->namespace = 'Tests';
81+
82+
$this->classNameLang = 'CLI.generator.className.test';
83+
$this->generateClass($params);
84+
}
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<@php
2+
3+
namespace {namespace};
4+
5+
use CodeIgniter\Test\CIUnitTestCase;
6+
7+
class {class} extends CIUnitTestCase
8+
{
9+
protected function setUp(): void
10+
{
11+
parent::setUp();
12+
}
13+
14+
public function testExample(): void
15+
{
16+
//
17+
}
18+
}

system/Config/AutoloadConfig.php

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class AutoloadConfig
9393
protected $corePsr4 = [
9494
'CodeIgniter' => SYSTEMPATH,
9595
'Config' => APPPATH . 'Config',
96+
'Tests' => ROOTPATH . 'tests',
9697
];
9798

9899
/**

system/Language/en/CLI.php

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
'migration' => 'Migration class name',
3030
'model' => 'Model class name',
3131
'seeder' => 'Seeder class name',
32+
'test' => 'Test class name',
3233
'validation' => 'Validation class name',
3334
],
3435
'commandType' => 'Command type',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) CodeIgniter Foundation <[email protected]>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace CodeIgniter\Commands;
15+
16+
use CodeIgniter\Test\CIUnitTestCase;
17+
use CodeIgniter\Test\StreamFilterTrait;
18+
19+
/**
20+
* @internal
21+
*
22+
* @group Others
23+
*/
24+
final class TestGeneratorTest extends CIUnitTestCase
25+
{
26+
use StreamFilterTrait;
27+
28+
protected function tearDown(): void
29+
{
30+
$result = str_replace(["\033[0;32m", "\033[0m", "\n"], '', $this->getStreamFilterBuffer());
31+
$file = str_replace('ROOTPATH' . DIRECTORY_SEPARATOR, ROOTPATH, trim(substr($result, 14)));
32+
$dir = dirname($file);
33+
if (is_file($file)) {
34+
unlink($file);
35+
}
36+
if (is_dir($dir)) {
37+
rmdir($dir);
38+
}
39+
}
40+
41+
public function testGenerateTest(): void
42+
{
43+
command('make:test Foo/Bar');
44+
$this->assertFileExists(ROOTPATH . 'tests/Foo/Bar.php');
45+
}
46+
}

tests/system/Commands/Utilities/NamespacesTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public function testNamespacesCommandCodeIgniterOnly(): void
5959
+---------------+-------------------------+--------+
6060
| CodeIgniter | ROOTPATH/system | Yes |
6161
| Config | APPPATH/Config | Yes |
62+
| Tests | ROOTPATH/tests | Yes |
6263
| App | ROOTPATH/app | Yes |
6364
| Tests\Support | ROOTPATH/tests/_support | Yes |
6465
+---------------+-------------------------+--------+

0 commit comments

Comments
 (0)