Skip to content

Commit 6925382

Browse files
authored
fix: update static analysis (#224)
* fix: update .gitignore for vscode directory * feat: enhance phpstan configuration and tests * fix: update tests and phpcs configuration * fix: add return type hints for FakeHttpClient and tests * fix: remove unnecessary quotes in PHPStan command * fix: simplify label assertions in theme tests * refactor: update property type hints in test classes * fix: add error message for missing PHPStan config * fix: format file
1 parent a48e9b2 commit 6925382

47 files changed

Lines changed: 906 additions & 213 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.ddev/commands/web/phpstan

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ if [[ ! -f vendor/bin/phpstan ]]; then
2525
echo "PHPStan installation complete."
2626
fi
2727

28-
# Default target: the module source, symlinked into vendor via the Composer path repository
29-
TARGET_PATH="vendor/openforgeproject/mageforge/src"
28+
# Default target: none — analyse the paths declared in phpstan.neon.
29+
# An explicit path argument overrides that default.
30+
TARGET_PATH=""
3031
if [[ $# -gt 0 ]] && [[ ! $1 =~ ^- ]]; then
3132
TARGET_PATH="$1"
3233
shift # Remove the first argument
@@ -37,16 +38,16 @@ if [[ $# -gt 0 ]] && [[ ! $1 =~ ^- ]]; then
3738
fi
3839
fi
3940

40-
# Determine config file location
41-
if [[ -f "vendor/openforgeproject/mageforge/phpstan.neon" ]]; then
42-
PHPSTAN_CONFIG="vendor/openforgeproject/mageforge/phpstan.neon"
43-
elif [[ -f "../phpstan.neon" ]]; then
44-
PHPSTAN_CONFIG="../phpstan.neon"
45-
else
46-
echo "PHPStan config not found at vendor/openforgeproject/mageforge/phpstan.neon or ../phpstan.neon"
41+
PHPSTAN_CONFIG="vendor/openforgeproject/mageforge/phpstan.neon"
42+
if [[ ! -f ${PHPSTAN_CONFIG} ]]; then
43+
echo "PHPStan config not found at ${PHPSTAN_CONFIG}. Run 'ddev install-magento' first."
4744
exit 1
4845
fi
4946

5047
# Run PHPStan with the same configuration as CI pipeline
5148
echo "Running PHPStan analysis..."
52-
vendor/bin/phpstan analyse -c "${PHPSTAN_CONFIG}" "$@" "${TARGET_PATH}"
49+
if [[ -n ${TARGET_PATH} ]]; then
50+
vendor/bin/phpstan analyse -c "${PHPSTAN_CONFIG}" "$@" "${TARGET_PATH}"
51+
else
52+
vendor/bin/phpstan analyse -c "${PHPSTAN_CONFIG}" "$@"
53+
fi

.github/workflows/static-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ jobs:
164164
- name: Run PHPStan
165165
working-directory: magento2
166166
run: |
167-
vendor/bin/phpstan analyse -c vendor/openforgeproject/mageforge/phpstan.neon vendor/openforgeproject/mageforge/src
167+
vendor/bin/phpstan analyse -c vendor/openforgeproject/mageforge/phpstan.neon
168168
169169
mago-analyze:
170170
name: Mago Analyze

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
/.phpunit.cache/
1010
/reports/
1111

12-
.vscode
12+
/.vscode/
1313
/magento/
1414
/magento-temp/
1515

.vscode/settings.json

Lines changed: 0 additions & 7 deletions
This file was deleted.

phpcs.xml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<description>Magento2 coding standard with Mago-formatter compatibility.</description>
44

55
<file>src/</file>
6+
<file>tests/</file>
67

78
<arg name="extensions" value="php,phtml"/>
89

phpstan.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ parameters:
55
level: 9
66
paths:
77
- src
8+
- tests

tests/Unit/Block/InspectorTest.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,25 @@
1515

1616
class InspectorTest extends TestCase
1717
{
18-
private Context&MockObject $context;
19-
private State&MockObject $state;
20-
private ScopeConfigInterface&MockObject $scopeConfig;
21-
private DeveloperAccessChecker&MockObject $developerAccessChecker;
18+
/**
19+
* @var Context&MockObject
20+
*/
21+
private $context;
22+
/**
23+
* @var State&MockObject
24+
*/
25+
private $state;
26+
/**
27+
* @var ScopeConfigInterface&MockObject
28+
*/
29+
private $scopeConfig;
30+
/**
31+
* @var DeveloperAccessChecker&MockObject
32+
*/
33+
private $developerAccessChecker;
34+
/**
35+
* @var Inspector
36+
*/
2237
private Inspector $block;
2338

2439
protected function setUp(): void

tests/Unit/Console/Command/AbstractCommandTest.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
class AbstractCommandTest extends TestCase
1919
{
20+
/**
21+
* @var ConcreteTestCommand
22+
*/
2023
private ConcreteTestCommand $command;
2124

2225
protected function setUp(): void
@@ -280,6 +283,7 @@ public function testSetPromptEnvironmentAppliesSanitizedTerminalDefaults(): void
280283
// setPromptEnvironment() itself triggers to capture the "original" values), so a
281284
// second getEnvVar() call would not reliably reflect writes made afterwards.
282285
$storage = $this->readPrivateProperty('secureEnvStorage');
286+
$this->assertIsArray($storage);
283287
$this->assertSame('100', $storage['COLUMNS']);
284288
$this->assertSame('40', $storage['LINES']);
285289
$this->assertSame('xterm-256color', $storage['TERM']);
@@ -305,7 +309,9 @@ public function testResetPromptEnvironmentRemovesPreviouslyUnsetValues(): void
305309

306310
$this->command->callResetPromptEnvironment();
307311

308-
$this->assertArrayNotHasKey('COLUMNS', $this->readPrivateProperty('secureEnvStorage'));
312+
$storage = $this->readPrivateProperty('secureEnvStorage');
313+
$this->assertIsArray($storage);
314+
$this->assertArrayNotHasKey('COLUMNS', $storage);
309315
$this->assertNull($this->readPrivateProperty('cachedEnv'));
310316
}
311317

@@ -316,7 +322,9 @@ public function testResetPromptEnvironmentRestoresPreviouslySetValue(): void
316322

317323
$this->command->callResetPromptEnvironment();
318324

319-
$this->assertSame('75', $this->readPrivateProperty('secureEnvStorage')['COLUMNS']);
325+
$storage = $this->readPrivateProperty('secureEnvStorage');
326+
$this->assertIsArray($storage);
327+
$this->assertSame('75', $storage['COLUMNS']);
320328
}
321329

322330
public function testGetSecureEnvironmentValueShortCircuitsForNamesFailingTheAnchoredPattern(): void
@@ -365,7 +373,9 @@ public function testSetEnvVarStoresSanitizedValue(): void
365373
{
366374
$this->callPrivate('setEnvVar', ['TERM', 'xterm!256@color']);
367375

368-
$this->assertSame('xterm256color', $this->readPrivateProperty('secureEnvStorage')['TERM']);
376+
$storage = $this->readPrivateProperty('secureEnvStorage');
377+
$this->assertIsArray($storage);
378+
$this->assertSame('xterm256color', $storage['TERM']);
369379
}
370380

371381
public function testGetEnvVarReturnsSanitizedStoredValue(): void

tests/Unit/Console/Command/ConcreteTestCommand.php

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,33 @@
1717
*/
1818
class ConcreteTestCommand extends AbstractCommand
1919
{
20+
/**
21+
* @var int
22+
*/
2023
private int $executeCommandReturn = Cli::RETURN_SUCCESS;
24+
/**
25+
* @var ?\Throwable
26+
*/
2127
private ?\Throwable $throwOnExecute = null;
28+
/**
29+
* @var ?bool
30+
*/
2231
private ?bool $realTtyAvailableOverride = null;
2332

33+
/**
34+
* Configures the command name.
35+
*/
2436
protected function configure(): void
2537
{
2638
$this->setName('test:concrete-command');
2739
}
2840

41+
/**
42+
* Returns the preconfigured exit code, or throws the preconfigured exception.
43+
*
44+
* @param InputInterface $input
45+
* @param OutputInterface $output
46+
*/
2947
protected function executeCommand(InputInterface $input, OutputInterface $output): int
3048
{
3149
if ($this->throwOnExecute !== null) {
@@ -35,60 +53,114 @@ protected function executeCommand(InputInterface $input, OutputInterface $output
3553
return $this->executeCommandReturn;
3654
}
3755

56+
/**
57+
* Returns the overridden TTY availability, falling back to the parent implementation.
58+
*/
3859
protected function isRealTtyAvailable(): bool
3960
{
4061
return $this->realTtyAvailableOverride ?? parent::isRealTtyAvailable();
4162
}
4263

64+
/**
65+
* Overrides the TTY availability reported to the command.
66+
*
67+
* @param ?bool $available
68+
*/
4369
public function setRealTtyAvailable(?bool $available): void
4470
{
4571
$this->realTtyAvailableOverride = $available;
4672
}
4773

74+
/**
75+
* Sets the exit code returned by executeCommand().
76+
*
77+
* @param int $code
78+
*/
4879
public function setExecuteCommandReturn(int $code): void
4980
{
5081
$this->executeCommandReturn = $code;
5182
}
5283

84+
/**
85+
* Makes executeCommand() throw the given exception.
86+
*
87+
* @param \Throwable $exception
88+
*/
5389
public function setThrowOnExecute(\Throwable $exception): void
5490
{
5591
$this->throwOnExecute = $exception;
5692
}
5793

94+
/**
95+
* Injects the SymfonyStyle IO used by the command.
96+
*
97+
* @param SymfonyStyle $io
98+
*/
5899
public function setIoForTest(SymfonyStyle $io): void
59100
{
60101
$this->io = $io;
61102
}
62103

104+
/**
105+
* Exposes the protected getCommandName().
106+
*
107+
* @param string $group
108+
* @param string $command
109+
*/
63110
public function callGetCommandName(string $group, string $command): string
64111
{
65112
return $this->getCommandName($group, $command);
66113
}
67114

115+
/**
116+
* Exposes the protected isVerbose().
117+
*
118+
* @param OutputInterface $output
119+
*/
68120
public function callIsVerbose(OutputInterface $output): bool
69121
{
70122
return $this->isVerbose($output);
71123
}
72124

125+
/**
126+
* Exposes the protected isVeryVerbose().
127+
*
128+
* @param OutputInterface $output
129+
*/
73130
public function callIsVeryVerbose(OutputInterface $output): bool
74131
{
75132
return $this->isVeryVerbose($output);
76133
}
77134

135+
/**
136+
* Exposes the protected isDebug().
137+
*
138+
* @param OutputInterface $output
139+
*/
78140
public function callIsDebug(OutputInterface $output): bool
79141
{
80142
return $this->isDebug($output);
81143
}
82144

83145
/**
146+
* Exposes the protected resolveVendorThemes().
147+
*
84148
* @param array<string> $themeCodes
149+
* @param ThemeList $themeList
85150
* @return array<string>
86151
*/
87152
public function callResolveVendorThemes(array $themeCodes, ThemeList $themeList): array
88153
{
89154
return $this->resolveVendorThemes($themeCodes, $themeList);
90155
}
91156

157+
/**
158+
* Exposes the protected handleInvalidThemeWithSuggestions().
159+
*
160+
* @param string $invalidTheme
161+
* @param ThemeSuggester $themeSuggester
162+
* @param OutputInterface $output
163+
*/
92164
public function callHandleInvalidThemeWithSuggestions(
93165
string $invalidTheme,
94166
ThemeSuggester $themeSuggester,
@@ -97,16 +169,27 @@ public function callHandleInvalidThemeWithSuggestions(
97169
return $this->handleInvalidThemeWithSuggestions($invalidTheme, $themeSuggester, $output);
98170
}
99171

172+
/**
173+
* Exposes the protected isInteractiveTerminal().
174+
*
175+
* @param OutputInterface $output
176+
*/
100177
public function callIsInteractiveTerminal(OutputInterface $output): bool
101178
{
102179
return $this->isInteractiveTerminal($output);
103180
}
104181

182+
/**
183+
* Exposes the protected setPromptEnvironment().
184+
*/
105185
public function callSetPromptEnvironment(): void
106186
{
107187
$this->setPromptEnvironment();
108188
}
109189

190+
/**
191+
* Exposes the protected resetPromptEnvironment().
192+
*/
110193
public function callResetPromptEnvironment(): void
111194
{
112195
$this->resetPromptEnvironment();

tests/Unit/Console/Command/Dev/InspectorCommandTest.php

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,25 @@
1717

1818
class InspectorCommandTest extends TestCase
1919
{
20-
private WriterInterface&MockObject $configWriter;
21-
private State&MockObject $state;
22-
private CacheManager&MockObject $cacheManager;
23-
private ScopeConfigInterface&MockObject $scopeConfig;
20+
/**
21+
* @var WriterInterface&MockObject
22+
*/
23+
private $configWriter;
24+
/**
25+
* @var State&MockObject
26+
*/
27+
private $state;
28+
/**
29+
* @var CacheManager&MockObject
30+
*/
31+
private $cacheManager;
32+
/**
33+
* @var ScopeConfigInterface&MockObject
34+
*/
35+
private $scopeConfig;
36+
/**
37+
* @var InspectorCommand
38+
*/
2439
private InspectorCommand $command;
2540

2641
protected function setUp(): void
@@ -161,7 +176,8 @@ public function testEnableAnnouncesUsageAndCleansExactCacheTypes(): void
161176

162177
$display = (string) preg_replace('/\s+/', ' ', $tester->getDisplay());
163178
$this->assertStringContainsString('MageForge Inspector has been enabled!', $display);
164-
$this->assertStringContainsString('The inspector will now be active on the frontend for allowed IPs.', $display);
179+
$activeHint = 'The inspector will now be active on the frontend for allowed IPs.';
180+
$this->assertStringContainsString($activeHint, $display);
165181
$this->assertStringContainsString('Press Ctrl+Shift+I (or Cmd+Option+I on macOS)', $display);
166182
$this->assertStringContainsString('Hover over elements to see their template information', $display);
167183
$this->assertStringContainsString('Click to pin the inspector panel', $display);

0 commit comments

Comments
 (0)