diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 848e3d5..e5502f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,11 +29,17 @@ jobs: operating-system: ['ubuntu-20.04'] php-versions: ['7.4', '8.0', 'latest'] phpunit-versions: ['latest', '9.5'] + exclude: + - php-versions: '7.4' + phpunit-versions: 'latest' + - php-versions: '8.0' + phpunit-versions: 'latest' steps: - name: Setup github ssh key run: mkdir -p ~/.ssh/ && ssh-keyscan -t rsa github.com > ~/.ssh/known_hosts - name: Checkout uses: actions/checkout@v2 + - name: Setup PHP uses: shivammathur/setup-php@v2 with: diff --git a/.github/workflows/phpdoc.yml b/.github/workflows/phpdoc.yml index 365812f..14eee9d 100644 --- a/.github/workflows/phpdoc.yml +++ b/.github/workflows/phpdoc.yml @@ -40,7 +40,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: '8.1' extensions: bcmath, ctype, curl, dom, gd, gettext, iconv, imagick, json, ldap, mbstring, mysql, opcache, openssl, pcntl, pdo, posix, redis, soap, sockets, sqlite, tokenizer, xmlwriter ini-values: post_max_size=512M, max_execution_time=360 coverage: xdebug @@ -60,7 +60,8 @@ jobs: echo "Creating UUT related dir in docu repo" mkdir -p $UUT_DIR/phpdoc-git/${GITHUB_REF##*/}/${REPO}/ ## Look into any of lib, src, app (if they exist) but not test, migration, bin, locale or script dirs - $BIN_DIR/phpdocumentor -d $UUT_DIR/lib/ -d $UUT_DIR/src/ -d $UUT_DIR/app/ -t "${UUT_DIR}/phpdoc-git/${GITHUB_REF##*/}/${REPO}/" + cd $UUT_DIR + $BIN_DIR/phpdocumentor -d lib/ -d src/ -d app/ -t "phpdoc-git/${GITHUB_REF##*/}/${REPO}/" cd ${UUT_DIR}/phpdoc-git git add "${GITHUB_REF##*/}/${REPO}" php indexer.php ${GITHUB_REF##*/} $REPO diff --git a/.github/workflows/update-satis.yml b/.github/workflows/update-satis.yml index 5049bd0..2c8daf5 100644 --- a/.github/workflows/update-satis.yml +++ b/.github/workflows/update-satis.yml @@ -38,7 +38,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: '8.1' extensions: bcmath, ctype, curl, dom, gd, gettext, iconv, imagick, json, ldap, mbstring, mysql, opcache, openssl, pcntl, pdo, posix, redis, soap, sockets, sqlite, tokenizer, xmlwriter ini-values: post_max_size=512M, max_execution_time=3600 coverage: xdebug diff --git a/.gitignore b/.gitignore index 4e78ae3..c959753 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,10 @@ run-tests.log /test/*/*/*/*.log /test/*/*/*/*.out +/vendor +/var +/composer.lock +/web +/.phpunit.cache +.phpunit.results.cache +.php-cs-fixer.cache diff --git a/composer.json b/composer.json index c4bb637..7201eac 100644 --- a/composer.json +++ b/composer.json @@ -58,5 +58,10 @@ "psr-4": { "Horde\\Test\\Test\\": "test/" } + }, + "config": { + "allow-plugins": { + "horde/horde-installer-plugin": true + } } -} \ No newline at end of file +} diff --git a/src/TestCase.php b/src/TestCase.php index 87ab351..1d68a36 100644 --- a/src/TestCase.php +++ b/src/TestCase.php @@ -16,7 +16,10 @@ namespace Horde\Test; use Horde_Support_Backtrace; +use PHPUnit\Framework\MockObject\MockObject; use ReflectionClass; +use ReflectionNamedType; +use ReflectionUnionType; /** * Basic Horde test case helper. @@ -118,6 +121,9 @@ public function getMockDependencies(string $class, array $overrides = []) $dependencies = []; foreach ($parameters as $parameter) { $name = $parameter->getName(); + /** + * @var ReflectionNamedType|ReflectionUnionType|null $type + */ $type = $parameter->getType(); $override = $overrides[$name] ?? null; if ($override) { @@ -148,4 +154,45 @@ public function getMockDependencies(string $class, array $overrides = []) } return new MockDependencies($class, $dependencies); } + + /** + * Use this to expect a mock object method to be called multiple times with potentially different arguments and return values + * The number of expected invocations is based on the count of $argsArrays + * Phpunits "at" as well as "withConsecutive" are deprecated, so this is a helper to get around that for this usecase + * + * @param MockObject $mockObject The mock object + * @param string $method The method to you expect to be called multiple times + * @param array $argsArrays The array of expected arguments, the method should be called with + * The array index+1 matches the invocation number of the method + * @param array $returnValues The array of return values of the mocked method + * The array index+1 matches the invocation number of the method + * Some or all indices can be left empty, if nothing should be returned + * @param bool $exact If true, matches args with "assertSame", otherwise with "assertEquals" + */ + public function matchConsecutiveInvocations( + MockObject $mockObject, + string $method, + array $argsArrays, + array $returnValues = [], + bool $exact = true + ): void { + $assertionMethod = $exact ? 'assertSame' : 'assertEquals'; + $invocations = count($argsArrays); + $matcher = $this->exactly($invocations); + $mockObject->expects($matcher)->method($method)->willReturnCallback(function() use ($argsArrays, $returnValues, $matcher, $assertionMethod) { + $invocation = $matcher->getInvocationCount(); + $idx = $invocation - 1; + $args = func_get_args(); + $expectedArgs = $argsArrays[$idx]; + $expectedArgCount = count($expectedArgs); + self::assertSame($expectedArgCount, count($args)); + foreach($expectedArgs as $pos => $expectedArg) { + self::$assertionMethod($expectedArg, $args[$pos]); + } + + if (array_key_exists($idx, $returnValues)){ + return $returnValues[$idx]; + } + }); + } }