Skip to content

Commit

Permalink
Modernize codebase and add more code quality tools (#37)
Browse files Browse the repository at this point in the history
* Added github actions for php 8.2 and 8.3
* Create dependabot.yml
* Added more code quality tools
---------

Co-authored-by: TavoNiievez <ganieves@outlook.com>
  • Loading branch information
indy2kro and TavoNiievez authored Jul 28, 2024
1 parent a972411 commit 8a7f950
Show file tree
Hide file tree
Showing 24 changed files with 727 additions and 581 deletions.
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
-
package-ecosystem: composer
directory: "/"
schedule:
interval: monthly
versioning-strategy: auto
groups:
dev-dependencies:
dependency-type: "development"
10 changes: 8 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ jobs:

strategy:
matrix:
php: [8.0, 8.1]
php: [8.1, 8.2, 8.3]

steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
Expand All @@ -26,6 +26,12 @@ jobs:
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-interaction --no-suggest

- name: Execute Code Sniffer
run: vendor/bin/phpcs

- name: Execute PHP Stan
run: vendor/bin/phpstan

- name: Run test suite
run: |
php -S 127.0.0.1:8000 -t tests/data/app >/dev/null 2>&1 &
Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@
],
"homepage": "https://codeception.com/",
"require": {
"php": "^8.0",
"php": "^8.1",
"ext-json": "*",
"codeception/codeception": "*@dev",
"codeception/lib-innerbrowser": "*@dev",
"guzzlehttp/guzzle": "^7.4",
"symfony/browser-kit": "^5.4 || ^6.0 || ^7.0"
"symfony/browser-kit": "^5.4 | ^6.0 | ^7.0"
},
"require-dev": {
"ext-curl": "*",
"squizlabs/php_codesniffer": "^3.10",
"phpstan/phpstan": "^1.10",
"aws/aws-sdk-php": "^3.199",
"codeception/module-rest": "^2.0 || *@dev"
"codeception/module-rest": "^2.0 | *@dev"
},
"conflict": {
"codeception/codeception": "<5.0",
Expand All @@ -37,7 +39,6 @@
"suggest": {
"codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests"
},
"minimum-stability": "dev",
"autoload": {
"classmap": [
"src/"
Expand Down
23 changes: 23 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="PHP_CodeSniffer" xsi:noNamespaceSchemaLocation="phpcs.xsd">
<description>The coding standard.</description>

<config name="testVersion" value="8.1-"/>

<file>src</file>

<arg name="basepath" value="./"/>
<arg name="colors"/>
<arg name="parallel" value="5"/>
<arg value="np"/>

<rule ref="Internal.Tokenizer.Exception">
<type>error</type>
</rule>

<rule ref="PSR12"/>

<rule ref="PSR2.Methods.MethodDeclaration.Underscore">
<type>warning</type>
</rule>
</ruleset>
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
parameters:
paths:
- ./src
level: 5
58 changes: 39 additions & 19 deletions src/Codeception/Lib/Connector/Guzzle.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@

class Guzzle extends AbstractBrowser
{
/**
* @var array<string, mixed>
*/
protected array $requestOptions = [
'allow_redirects' => false,
'headers' => [],
Expand Down Expand Up @@ -115,7 +118,7 @@ protected function createResponse(Psr7Response $psr7Response): BrowserKitRespons
$contentType = 'text/html';
}

if (strpos($contentType, 'charset=') === false) {
if (str_contains($contentType, 'charset=') === false) {
if (preg_match('#<meta[^>]+charset *= *["\']?([a-zA-Z\-0-9]+)#i', $body, $matches)) {
$contentType .= ';charset=' . $matches[1];
}
Expand Down Expand Up @@ -159,10 +162,10 @@ protected function createResponse(Psr7Response $psr7Response): BrowserKitRespons
protected function getAbsoluteUri(string $uri): string
{
$baseUri = $this->client->getConfig('base_uri');
if (strpos($uri, '://') === false && strpos($uri, '//') !== 0) {
if (strpos($uri, '/') === 0) {
if (str_contains($uri, '://') === false && !str_starts_with($uri, '//')) {
if (str_starts_with($uri, '/')) {
$baseUriPath = $baseUri->getPath();
if (!empty($baseUriPath) && strpos($uri, (string) $baseUriPath) === 0) {
if (!empty($baseUriPath) && str_starts_with($uri, (string) $baseUriPath)) {
$uri = substr($uri, strlen($baseUriPath));
}

Expand All @@ -178,9 +181,9 @@ protected function getAbsoluteUri(string $uri): string
return Uri::mergeUrls((string)$baseUri, $uri);
}

protected function doRequest($request)
protected function doRequest(object $request)
{
/** @var $request BrowserKitRequest **/
/** @var BrowserKitRequest $request **/
$guzzleRequest = new Psr7Request(
$request->getMethod(),
$request->getUri(),
Expand All @@ -190,17 +193,17 @@ protected function doRequest($request)
$options = $this->requestOptions;
$options['cookies'] = $this->extractCookies($guzzleRequest->getUri()->getHost());
$multipartData = $this->extractMultipartFormData($request);
if (!empty($multipartData)) {
if ($multipartData !== []) {
$options['multipart'] = $multipartData;
}

$formData = $this->extractFormData($request);
if (empty($multipartData) && $formData) {
if ($multipartData === [] && $formData) {
$options['form_params'] = $formData;
}

try {
if (null !== $this->awsCredentials) {
if ($this->awsCredentials instanceof AwsCredentials) {
$response = $this->client->send($this->awsSignature->signRequest($guzzleRequest, $this->awsCredentials), $options);
} else {
$response = $this->client->send($guzzleRequest, $options);
Expand All @@ -213,6 +216,7 @@ protected function doRequest($request)
$response = $exception->getResponse();
}

// @phpstan-ignore-next-line
return $this->createResponse($response);
}

Expand All @@ -227,7 +231,7 @@ protected function extractHeaders(BrowserKitRequest $request): array
$contentHeaders = ['Content-Length' => true, 'Content-Md5' => true, 'Content-Type' => true];
foreach ($server as $header => $val) {
$header = html_entity_decode(implode('-', array_map('ucfirst', explode('-', strtolower(str_replace('_', '-', $header))))), ENT_NOQUOTES);
if (strpos($header, 'Http-') === 0) {
if (str_starts_with($header, 'Http-')) {
$headers[substr($header, 5)] = $val;
} elseif (isset($contentHeaders[$header])) {
$headers[$header] = $val;
Expand All @@ -237,6 +241,9 @@ protected function extractHeaders(BrowserKitRequest $request): array
return $headers;
}

/**
* @return array<int, mixed>|null
*/
protected function extractFormData(BrowserKitRequest $browserKitRequest): ?array
{
if (!in_array(strtoupper($browserKitRequest->getMethod()), ['POST', 'PUT', 'PATCH', 'DELETE'])) {
Expand All @@ -257,14 +264,17 @@ protected function extractFormData(BrowserKitRequest $browserKitRequest): ?array
return $browserKitRequest->getParameters();
}

protected function extractMultipartFormData(BrowserKitRequest $browserKitRequest)
/**
* @return array<string, mixed>
*/
protected function extractMultipartFormData(BrowserKitRequest $browserKitRequest): array
{
if (!in_array(strtoupper($browserKitRequest->getMethod()), ['POST', 'PUT', 'PATCH'])) {
return [];
}

$parts = $this->mapFiles($browserKitRequest->getFiles());
if (empty($parts)) {
if ($parts === []) {
return [];
}

Expand All @@ -275,11 +285,14 @@ protected function extractMultipartFormData(BrowserKitRequest $browserKitRequest
return $parts;
}

protected function formatMultipart($parts, $key, $value)
/**
* @return array<string, mixed>
*/
protected function formatMultipart(mixed $parts, string $key, mixed $value): array
{
if (is_array($value)) {
foreach ($value as $subKey => $subValue) {
$parts = array_merge($this->formatMultipart([], $key.sprintf('[%s]', $subKey), $subValue), $parts);
$parts = array_merge($this->formatMultipart([], $key . sprintf('[%s]', $subKey), $subValue), $parts);
}

return $parts;
Expand All @@ -289,7 +302,11 @@ protected function formatMultipart($parts, $key, $value)
return $parts;
}

protected function mapFiles($requestFiles, $arrayName = ''): array
/**
* @param array<int, mixed> $requestFiles
* @return array<int, mixed>
*/
protected function mapFiles(array $requestFiles, ?string $arrayName = ''): array
{
$files = [];
foreach ($requestFiles as $name => $info) {
Expand Down Expand Up @@ -329,7 +346,7 @@ protected function mapFiles($requestFiles, $arrayName = ''): array
return $files;
}

protected function extractCookies($host): GuzzleCookieJar
protected function extractCookies(string $host): GuzzleCookieJar
{
$jar = [];
$cookies = $this->getCookieJar()->all();
Expand All @@ -345,7 +362,7 @@ protected function extractCookies($host): GuzzleCookieJar
return new GuzzleCookieJar(false, $jar);
}

public static function createHandler($handler): GuzzleHandlerStack
public static function createHandler(mixed $handler): GuzzleHandlerStack
{
if ($handler instanceof GuzzleHandlerStack) {
return $handler;
Expand All @@ -360,7 +377,7 @@ public static function createHandler($handler): GuzzleHandlerStack
}

if (is_string($handler) && class_exists($handler)) {
return GuzzleHandlerStack::create(new $handler);
return GuzzleHandlerStack::create(new $handler());
}

if (is_callable($handler)) {
Expand All @@ -370,7 +387,10 @@ public static function createHandler($handler): GuzzleHandlerStack
return GuzzleHandlerStack::create();
}

public function setAwsAuth($config): void
/**
* @param array<string, mixed> $config
*/
public function setAwsAuth(array $config): void
{
$this->awsCredentials = new AwsCredentials($config['key'], $config['secret']);
$this->awsSignature = new AwsSignatureV4($config['service'], $config['region']);
Expand Down
40 changes: 23 additions & 17 deletions src/Codeception/Module/PhpBrowser.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public function _initialize()

public function _before(TestInterface $test)
{
if (!$this->client) {
if (!$this->client instanceof AbstractBrowser) {
$this->client = new Guzzle();
}

Expand All @@ -155,12 +155,14 @@ public function setHeader(string $name, string $value): void
$this->haveHttpHeader($name, $value);
}

public function amHttpAuthenticated($username, $password): void
public function amHttpAuthenticated(string $username, string $password): void
{
$this->client->setAuth($username, $password);
if ($this->client instanceof Guzzle) {
$this->client->setAuth($username, $password);
}
}

public function amOnUrl($url): void
public function amOnUrl(string $url): void
{
$host = Uri::retrieveHost($url);
$config = $this->config;
Expand All @@ -175,7 +177,7 @@ public function amOnUrl($url): void
$this->amOnPage($page);
}

public function amOnSubdomain($subdomain): void
public function amOnSubdomain(string $subdomain): void
{
$url = $this->config['url'];
$url = preg_replace('#(https?://)(.*\.)(.*\.)#', "$1$3", $url); // removing current subdomain
Expand Down Expand Up @@ -206,18 +208,13 @@ protected function onReconfigure()
*
* It is not recommended to use this command on a regular basis.
* If Codeception lacks important Guzzle Client methods, implement them and submit patches.
*
* @return mixed
*/
public function executeInGuzzle(Closure $function)
public function executeInGuzzle(Closure $function): mixed
{
return $function($this->guzzle);
}
/**
* @return int|string
*/
public function _getResponseCode()
public function _getResponseCode(): int|string
{
return $this->getResponseStatusCode();
}
Expand Down Expand Up @@ -245,21 +242,24 @@ public function _prepareSession(): void
$defaults['base_uri'] = $this->config['url'];
$defaults['curl'] = $curlOptions;
$handler = Guzzle::createHandler($this->config['handler']);
if ($handler && is_array($this->config['middleware'])) {
$handlerStack = Guzzle::createHandler($this->config['handler']);
if (is_array($this->config['middleware'])) {
foreach ($this->config['middleware'] as $middleware) {
$handler->push($middleware);
$handlerStack->push($middleware);
}
}
$defaults['handler'] = $handler;
$defaults['handler'] = $handlerStack;
$this->guzzle = new GuzzleClient($defaults);
$this->client->setRefreshMaxInterval($this->config['refresh_max_interval']);
$this->client->setClient($this->guzzle);
}
public function _backupSession(): array
/**
* @return array<string, mixed>
*/
public function _backupSession()
{
return [
'client' => $this->client,
Expand All @@ -269,13 +269,19 @@ public function _backupSession(): array
];
}
/**
* @param array<string, mixed> $session
*/
public function _loadSession($session): void
{
foreach ($session as $key => $val) {
$this->$key = $val;
}
}
/**
* @param ?array<string, mixed> $session
*/
public function _closeSession($session = null): void
{
unset($session);
Expand Down
1 change: 0 additions & 1 deletion tests/_support/UnitTester.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php


/**
* Inherited Methods
* @method void wantToTest($text)
Expand Down
Loading

0 comments on commit 8a7f950

Please sign in to comment.