Skip to content

Commit

Permalink
Merge pull request #11 from FriendsOfCake/cake-5.x
Browse files Browse the repository at this point in the history
Update for Cake 5.
  • Loading branch information
ADmad authored Sep 24, 2023
2 parents f067edf + 9516231 commit d6f2fd7
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 337 deletions.
23 changes: 11 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,54 @@ on:

jobs:
testsuite:
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
php-version: ['7.4', '8.0', '8.1']
php-version: ['8.2']
prefer-lowest: ['']
include:
- php-version: '7.2'
- php-version: '8.1'
prefer-lowest: 'prefer-lowest'

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: mbstring, intl, pdo_${{ matrix.db-type }}
extensions: mbstring, intl
coverage: none

- name: Composer install
run: |
composer --version
if ${{ matrix.prefer-lowest == 'prefer-lowest' }}; then
composer update --prefer-lowest --prefer-stable
else
composer install
composer update
fi
- name: Run PHPUnit
run: vendor/bin/phpunit

cs-stan:
name: Coding Standard & Static Analysis
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
php-version: '8.1'
extensions: mbstring, intl
coverage: none
tools: phpstan:1.7,cs2pr
tools: phpstan:1.10,cs2pr

- name: Composer Install
run: composer require cakephp/cakephp-codesniffer:^4.2
run: composer require cakephp/cakephp-codesniffer

- name: Run phpcs
run: vendor/bin/phpcs --report=checkstyle --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/ | cs2pr
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
composer.lock
phpunit.xml
vendor
.phpunit.cache
.phpunit.result.cache
79 changes: 2 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ composer require friendsofcake/cakephp-test-utilities
At this point there are two traits:

1. [`AccessibilityHelperTrait`](#accessibilityhelpertrait) : Gain access protected properties and methods.
2. [`CounterHelperTrait`](#counterhelpertrait) : Uses counters to help with the order of expectations.
2. [`CompareTrait`](#comparetrait) : Assert methods, comparing to files for: HTML, JSON, XML

### AccessibilityHelperTrait

Expand Down Expand Up @@ -109,81 +109,6 @@ public function testExample()
}
```

See [Cake's docs](https://book.cakephp.org/4/en/development/testing.html#comparing-test-results-to-a-file)
See [Cake's docs](https://book.cakephp.org/5/en/development/testing.html#comparing-test-results-to-a-file)
for more details on usage of `assertSameAsFile` on which these methods are
based.

### CounterHelperTrait

This trait helps with defining expectations that are order specific.

#### Setup

Add the trait at the top of your test case:

``` php
use \FriendsOfCake\TestUtilities\CounterHelperTrait;
```

That's it.

#### Single mock objects

Usually you would do something similar to this to set orders for your mock
objects:

``` php
$mock->expects($this->at(0))
->method('myMethod')
->with('myParameter')
->will($this->returnValue('myFirstReturnValue'));

$mock->expects($this->at(1))
->method('myMethod')
->with('myParameter')
->will($this->returnValue('mySecondReturnValue'));
```

Instead this trait implements a `CounterHelperTrait::next()` method. It will
track the indices for you, so you can easily switch calls or add some later,
without having to change them. Example:

``` php
$mock->expects($this->nextCounter()) // = $this->at(0)
->method('myMethod')
->with('myParameter')
->will($this->returnValue('myFirstReturnValue'));

$mock->expects($this->nextCounter()) // = $this->at(1)
->method('myMethod')
->with('myParameter')
->will($this->returnValue('mySecondReturnValue'));
```

#### Multiple mock objects

If you have multiple mock objects you need to use multiple independent
counters. For this to work you need to identify which counter you want to use
by passing an object (or a string):

``` php
$mock1->expects($this->nextCounter($mock1)) // = $this->at(0)
->method('myMethod')
->with('myParameter')
->will($this->returnValue('myFirstReturnValue'));

$mock2->expects($this->nextCounter($mock2)) // = $this->at(0)
->method('myMethod')
->with('myParameter')
->will($this->returnValue('myFirstReturnValue'));

$mock1->expects($this->nextCounter($mock1)) // = $this->at(1)
->method('myMethod')
->with('myParameter')
->will($this->returnValue('mySecondReturnValue'));

$mock2->expects($this->nextCounter($mock2)) // = $this->at(1)
->method('myMethod')
->with('myParameter')
->will($this->returnValue('mySecondReturnValue'));
```
16 changes: 12 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,32 @@
{
"name": "Christian Winther",
"role": "Author"
}, {
},
{
"name": "Andy Dawson",
"role": "Author"
}, {
},
{
"name": "Frank de Graaf",
"role": "Polisher"
}
],
"require": {
"cakephp/cakephp": "^4.0"
"cakephp/cakephp": "^5.0"
},
"require-dev": {
"phpunit/phpunit": "~8.5.0"
"phpunit/phpunit": "^10.1"
},
"autoload": {
"psr-4": {
"FriendsOfCake\\TestUtilities\\": "src",
"FriendsOfCake\\TestUtilities\\Test\\": "tests"
}
},
"config": {
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
parameters:
level: 6
level: 7
paths:
- src/
77 changes: 39 additions & 38 deletions src/AccessibilityHelperTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,28 @@ trait AccessibilityHelperTrait
*
* @var object|string
*/
public $defaultReflectionTarget = null;
public object|string $defaultReflectionTarget;

/**
* List of Reflection properties made public.
*
* @var array
*/
protected $_reflectionPropertyCache = [];
protected array $_reflectionPropertyCache = [];

/**
* List of Reflection methods made public.
*
* @var array
*/
protected $_reflectionMethodCache = [];
protected array $_reflectionMethodCache = [];

/**
* List of class names <=> instances used for invocation.
*
* @var array
*/
protected $_reflectionInstanceCache = [];
protected array $_reflectionInstanceCache = [];

/**
* Reset the internal reflection caches.
Expand All @@ -58,8 +58,8 @@ public function resetReflectionCache(): void
/**
* Map an instance of an object to its class name.
*
* @param object $instance an instance of a class
* @param string|null $class the key used in the reflection instance class
* @param object $instance an instance of a class
* @param string|null $class the key used in the reflection instance class
* @return void
*/
public function setReflectionClassInstance(object $instance, ?string $class = null): void
Expand All @@ -71,7 +71,7 @@ public function setReflectionClassInstance(object $instance, ?string $class = nu
/**
* Get working instance of "$class".
*
* @param string|null $class the class name
* @param string|null $class the class name
* @return object
* @throws \Exception
*/
Expand All @@ -92,12 +92,12 @@ public function getReflectionInstance(?string $class = null): object
/**
* Helper method to call a protected method.
*
* @param string $method the method name
* @param array $args Argument list to call $method with (call_user_func_array style)
* @param string|object|null $class Target reflection class
* @param string $method the method name
* @param array $args Argument list to call $method with (call_user_func_array style)
* @param object|string|null $class Target reflection class
* @return mixed
*/
public function callProtectedMethod(string $method, array $args = [], $class = null)
public function callProtectedMethod(string $method, array $args = [], object|string|null $class = null): mixed
{
$class = $this->_getReflectionTargetClass($class);
$cacheKey = $class . '_' . $method;
Expand All @@ -113,11 +113,11 @@ public function callProtectedMethod(string $method, array $args = [], $class = n
/**
* Helper method to get the value of a protected property.
*
* @param string $property the property to access/manipulate
* @param string $class Target reflection class
* @param string $property the property to access/manipulate
* @param string $class Target reflection class
* @return mixed
*/
public function getProtectedProperty(string $property, ?string $class = null)
public function getProtectedProperty(string $property, ?string $class = null): mixed
{
$Instance = $this->_getReflectionPropertyInstance($property, $class);

Expand All @@ -127,23 +127,22 @@ public function getProtectedProperty(string $property, ?string $class = null)
/**
* Helper method to set the value of a protected property.
*
* @param string $property the property to change
* @param mixed $value the value to set the property to
* @param string $class Target reflection class
* @return mixed
* @param string $property the property to change
* @param mixed $value the value to set the property to
* @param string $class Target reflection class
* @return void
*/
public function setProtectedProperty(string $property, $value, ?string $class = null)
public function setProtectedProperty(string $property, mixed $value, ?string $class = null): void
{
$Instance = $this->_getReflectionPropertyInstance($property, $class);

return $Instance->setValue($this->getReflectionInstance($class), $value);
$this->_getReflectionPropertyInstance($property, $class)
->setValue($this->getReflectionInstance($class), $value);
}

/**
* Get a reflection property object.
*
* @param string $property the property to access/manipulate
* @param string|null $class the class name
* @param string $property the property to access/manipulate
* @param string|null $class the class name
* @return \ReflectionProperty
*/
protected function _getReflectionPropertyInstance(string $property, ?string $class = null): ReflectionProperty
Expand All @@ -162,22 +161,24 @@ protected function _getReflectionPropertyInstance(string $property, ?string $cla
/**
* Get the reflection class name.
*
* @param string|object|null $class the class name
* @param object|string|null $class the class name
* @return string
* @throws \Exception
*/
protected function _getReflectionTargetClass($class = null): string
protected function _getReflectionTargetClass(object|string|null $class = null): string
{
$class = $class ?: $this->defaultReflectionTarget;

if (!$class) {
throw new Exception(
'Unable to find reflection target. '
. 'Have you set $defaultReflectionTarget or passed in a class name?'
);
if ($class === null) {
if (!isset($this->defaultReflectionTarget)) {
throw new Exception(
'Unable to find reflection target. '
. 'Have you set $defaultReflectionTarget or passed in a class name?'
);
}

$class = $this->defaultReflectionTarget;
}

if (!is_object($class)) {
if (is_string($class)) {
return $class;
}

Expand All @@ -187,8 +188,8 @@ protected function _getReflectionTargetClass($class = null): string
/**
* Gets a new ReflectionMethod instance. Extracted for testing purposes.
*
* @param string $class the class name
* @param string $method the method name
* @param string $class the class name
* @param string $method the method name
* @return \ReflectionMethod
*/
protected function _getNewReflectionMethod(string $class, string $method): ReflectionMethod
Expand All @@ -199,8 +200,8 @@ protected function _getNewReflectionMethod(string $class, string $method): Refle
/**
* Gets a new ReflectionProperty instance. Extracted for testing purposes.
*
* @param string $class the class name
* @param string $property the property to access/manipulate
* @param string $class the class name
* @param string $property the property to access/manipulate
* @return \ReflectionProperty
*/
protected function _getNewReflectionProperty(string $class, string $property): ReflectionProperty
Expand Down
Loading

0 comments on commit d6f2fd7

Please sign in to comment.