From 4bf7525db5993b402905f4272006df64986ac5ab Mon Sep 17 00:00:00 2001 From: Michal Sniatala Date: Mon, 10 Jun 2024 17:46:28 +0200 Subject: [PATCH] feat: add HTML formatter (#69) * add html formatter * update workflow * update workflow * cs-fix * workflow update * workflow update --- .github/workflows/deptrac.yml | 11 ++-- .github/workflows/phpcsfixer.yml | 2 +- .github/workflows/phpstan.yml | 6 +- .github/workflows/phpunit.yml | 6 +- .github/workflows/psalm.yml | 4 +- .github/workflows/rector.yml | 17 +++-- .php-cs-fixer.dist.php | 17 +++-- composer.json | 2 +- docs/html_formatter.md | 51 +++++++++++++++ docs/index.md | 1 + phpstan.neon.dist | 8 +-- phpunit.xml.dist | 87 +++++++++----------------- psalm.xml | 4 +- psalm_autoload.php | 2 + rector.php | 45 ++++++++++--- src/Commands/HtmxPublish.php | 20 ++++++ src/Format/HTMLFormatter.php | 68 ++++++++++++++++++++ src/HTTP/IncomingRequest.php | 2 +- src/HTTP/RedirectResponse.php | 4 +- src/View/View.php | 2 +- tests/CommonTest.php | 2 +- tests/Format/HTMLFormatterTest.php | 75 ++++++++++++++++++++++ tests/View/ErrorModelDecoratorTest.php | 6 +- tests/View/ToolbarDecoratorTest.php | 6 +- tests/View/ViewTest.php | 4 +- 25 files changed, 341 insertions(+), 111 deletions(-) create mode 100644 docs/html_formatter.md create mode 100644 src/Format/HTMLFormatter.php create mode 100644 tests/Format/HTMLFormatterTest.php diff --git a/.github/workflows/deptrac.yml b/.github/workflows/deptrac.yml index 2021f8d..5ef4dea 100644 --- a/.github/workflows/deptrac.yml +++ b/.github/workflows/deptrac.yml @@ -32,7 +32,6 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: '8.1' - tools: phive extensions: intl, json, mbstring, xml coverage: none env: @@ -42,7 +41,7 @@ jobs: run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV - name: Cache composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.COMPOSER_CACHE_FILES_DIR }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} @@ -52,7 +51,7 @@ jobs: run: mkdir -p build/ - name: Cache Deptrac results - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build key: ${{ runner.os }}-deptrac-${{ github.sha }} @@ -68,7 +67,5 @@ jobs: - name: Trace dependencies run: | - sudo phive --no-progress install --global --trust-gpg-keys B8F640134AB1782E,A98E898BB53EB748 qossmic/deptrac - deptrac analyze --cache-file=build/deptrac.cache - env: - GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + composer require --dev qossmic/deptrac-shim + vendor/bin/deptrac analyze --cache-file=build/deptrac.cache diff --git a/.github/workflows/phpcsfixer.yml b/.github/workflows/phpcsfixer.yml index 59c867c..9ac8b7f 100644 --- a/.github/workflows/phpcsfixer.yml +++ b/.github/workflows/phpcsfixer.yml @@ -37,7 +37,7 @@ jobs: run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV - name: Cache composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.COMPOSER_CACHE_FILES_DIR }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 026db2d..85d1265 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['8.0', '8.1'] + php-versions: ['8.1', '8.2', '8.3'] steps: - name: Checkout @@ -46,7 +46,7 @@ jobs: run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV - name: Cache composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.COMPOSER_CACHE_FILES_DIR }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} @@ -56,7 +56,7 @@ jobs: run: mkdir -p build/phpstan - name: Cache PHPStan results - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/phpstan key: ${{ runner.os }}-phpstan-${{ github.sha }} diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 0f71688..e7300f3 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -25,7 +25,7 @@ jobs: if: "!contains(github.event.head_commit.message, '[ci skip]')" strategy: matrix: - php-versions: ['8.0', '8.1'] + php-versions: ['8.1', '8.2', '8.3'] steps: - name: Checkout @@ -45,7 +45,7 @@ jobs: run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV - name: Cache composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.COMPOSER_CACHE_FILES_DIR }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} @@ -60,7 +60,7 @@ jobs: fi - name: Test with PHPUnit - run: vendor/bin/phpunit --verbose --coverage-text + run: vendor/bin/phpunit --coverage-text env: TERM: xterm-256color TACHYCARDIA_MONITOR_GA: enabled diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index b28b1fc..1d3c7cb 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -42,7 +42,7 @@ jobs: run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV - name: Cache composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.COMPOSER_CACHE_FILES_DIR }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} @@ -52,7 +52,7 @@ jobs: run: mkdir -p build/psalm - name: Cache Psalm results - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/psalm key: ${{ runner.os }}-psalm-${{ github.sha }} diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml index 02aa4e6..29e22ba 100644 --- a/.github/workflows/rector.yml +++ b/.github/workflows/rector.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['8.0', '8.1'] + php-versions: ['8.1', '8.2', '8.3'] steps: - name: Checkout @@ -46,7 +46,7 @@ jobs: run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV - name: Cache composer dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.COMPOSER_CACHE_FILES_DIR }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} @@ -60,7 +60,14 @@ jobs: composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader fi + - name: Rector Cache + uses: actions/cache@v4 + with: + path: /tmp/rector + key: ${{ runner.os }}-rector-${{ github.run_id }} + restore-keys: ${{ runner.os }}-rector- + + - run: mkdir -p /tmp/rector + - name: Analyze for refactoring - run: | - composer global require --dev rector/rector:^0.15.1 - rector process --dry-run --no-progress-bar + run: vendor/bin/rector process --dry-run --no-progress-bar diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 522639b..a0a7091 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -8,12 +8,21 @@ ->files() ->in([ __DIR__ . '/src/', - // __DIR__ . '/tests/', + __DIR__ . '/tests/', ]) - ->exclude('build') - ->append([__FILE__]); + ->exclude([ + 'build', + 'Views', + ]) + ->append([ + __FILE__, + __DIR__ . '/rector.php', + ]); -$overrides = []; +$overrides = [ + // 'declare_strict_types' => true, + // 'void_return' => true, +]; $options = [ 'finder' => $finder, diff --git a/composer.json b/composer.json index 2f5a695..eec9c34 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ }, "require-dev": { "codeigniter4/devkit": "^1.0", - "codeigniter4/framework": "^4.1" + "codeigniter4/framework": "^4.3" }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/docs/html_formatter.md b/docs/html_formatter.md new file mode 100644 index 0000000..6fa08ca --- /dev/null +++ b/docs/html_formatter.md @@ -0,0 +1,51 @@ +# HTML Formatter + +There are times when we want to work with HTMX through an API. In such cases, we may want to use [Response Trait API](https://codeigniter.com/user_guide/outgoing/api_responses.html). + +Unfortunately, CodeIgniter does not support HTML formatting for API by default. That's why such a formatter is included here. It will make it easier to work with the API when we want to return data in HTML format. + +### Configuration + +We should edit the `app/Config/Format.php` file to include the necessary changes. We should add `'text/html'` to the `$supportedResponseFormats` array, and `'text/html' => HTMLFormatter::class` to the `$formatters` array. This will be done automatically when you run the command: + + php spark htmx:publish + +Since content negotiation will be triggered for any format other than `json` or `xml`, we have two options: + +1. Set the custom headers for every request via HTML tag + ```html + hx-headers='{"Accept":"text/html"}' + ``` +2. Move the `'text/html'` entry from the `$supportedResponseFormats` config array to the first position in the array - this way it will be used as the default value. + ```php + public array $supportedResponseFormats = [ + 'text/html' + 'application/json', + 'application/xml', // machine-readable XML + 'text/xml', // human-readable XML + ]; + ``` + +### Example + +This is an sample of using HTML formatter: + +```php +format = 'html'; + return $this->respondCreated('
Some data
'); + } +} +``` diff --git a/docs/index.md b/docs/index.md index 7c03cb6..f4a5a08 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,6 +19,7 @@ It also provides some additional help with **handling errors** and **Debug Toolb * [Response](response.md) * [RediretResponse](redirect_response.md) * [Debug Toolbar](debug_toolbar.md) +* [HTML Formatter](html_formatter.md) * [Troubleshooting](troubleshooting.md) ### Demos diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 8f500bd..e9478cf 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -7,11 +7,11 @@ parameters: bootstrapFiles: - vendor/codeigniter4/framework/system/Test/bootstrap.php excludePaths: - - src/Debug/Toolbar.php + - src/Debug/Toolbar.php + - src/Views/* ignoreErrors: - - '#Call to deprecated method getStatusCode\(\) of class CodeIgniter\\HTTP\\Response:\nTo be replaced by the PSR-7 version \(compatible\)#' - - '#Variable \$testString might not be defined.#' - - '#Variable \$this might not be defined.#' + - '#Variable \$testString might not be defined.#' + - '#Variable \$this might not be defined.#' universalObjectCratesClasses: - CodeIgniter\Entity - CodeIgniter\Entity\Entity diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d8ef6a6..f80f461 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,33 +1,20 @@ - - - - ./src/ - - - ./src/Config - ./src/Commands/HtmxPublish.php - ./src/Debug/Toolbar.php - + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" + bootstrap="vendor/codeigniter4/framework/system/Test/bootstrap.php" + backupGlobals="false" + beStrictAboutOutputDuringTests="true" + colors="true" + executionOrder="random" + failOnRisky="true" + failOnWarning="true" + stopOnError="false" + stopOnFailure="false" + stopOnIncomplete="false" + stopOnSkipped="false" + cacheDirectory=".phpunit.cache" + beStrictAboutCoverageMetadata="true"> + @@ -36,59 +23,34 @@ - ./tests - - - - - - 0.50 - - - 30 - - - 2 - - - true - - - true - - - - + + + + + - - - - - - - + + + ./src/ + + + ./src/Config + ./src/Views + + diff --git a/psalm.xml b/psalm.xml index 3917684..696215c 100644 --- a/psalm.xml +++ b/psalm.xml @@ -7,13 +7,15 @@ xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" autoloader="psalm_autoload.php" cacheDirectory="build/psalm/" + findUnusedBaselineEntry="true" + findUnusedCode="false" > - + diff --git a/psalm_autoload.php b/psalm_autoload.php index 9a8cd57..d1fab7d 100644 --- a/psalm_autoload.php +++ b/psalm_autoload.php @@ -22,3 +22,5 @@ require_once $filePath; } } + +chdir(__DIR__); diff --git a/rector.php b/rector.php index 0977c6c..f4530be 100644 --- a/rector.php +++ b/rector.php @@ -1,23 +1,30 @@ sets([ SetList::DEAD_CODE, - LevelSetList::UP_TO_PHP_80, + LevelSetList::UP_TO_PHP_74, PHPUnitSetList::PHPUNIT_CODE_QUALITY, PHPUnitSetList::PHPUNIT_100, ]); $rectorConfig->parallel(); + // Github action cache + $rectorConfig->cacheClass(FileCacheStorage::class); + if (is_dir('/tmp')) { + $rectorConfig->cacheDirectory('/tmp/rector'); + } + // The paths to refactor (can also be supplied with CLI arguments) $rectorConfig->paths([ __DIR__ . '/src/', @@ -64,26 +82,25 @@ } // Set the target version for refactoring - $rectorConfig->phpVersion(PhpVersion::PHP_81); + $rectorConfig->phpVersion(PhpVersion::PHP_74); // Auto-import fully qualified class names $rectorConfig->importNames(); // Are there files or rules you need to skip? $rectorConfig->skip([ - __DIR__ . '/app/Views', + __DIR__ . '/src/Views', JsonThrowOnErrorRector::class, StringifyStrNeedlesRector::class, + YieldDataProviderRector::class, // Note: requires php 8 RemoveUnusedPromotedPropertyRector::class, + AnnotationWithValueToAttributeRector::class, // May load view files directly when detecting classes StringClassNameToClassConstantRector::class, - - // Supported from PHPUnit 10 - DataProviderAnnotationToAttributeRector::class, ]); // auto import fully qualified class names @@ -108,10 +125,16 @@ $rectorConfig->rule(FuncGetArgsToVariadicParamRector::class); $rectorConfig->rule(MakeInheritedMethodVisibilitySameAsParentRector::class); $rectorConfig->rule(SimplifyEmptyArrayCheckRector::class); + $rectorConfig->rule(SimplifyEmptyCheckOnEmptyArrayRector::class); + $rectorConfig->rule(TernaryEmptyArrayArrayDimFetchToCoalesceRector::class); + $rectorConfig->rule(EmptyOnNullableObjectToInstanceOfRector::class); + $rectorConfig->rule(DisallowedEmptyRuleFixerRector::class); $rectorConfig ->ruleWithConfiguration(TypedPropertyFromAssignsRector::class, [ /** - * The INLINE_PUBLIC value is default to false to avoid BC break, if you use for libraries and want to preserve BC break, you don't need to configure it, as it included in LevelSetList::UP_TO_PHP_74 + * The INLINE_PUBLIC value is default to false to avoid BC break, + * if you use for libraries and want to preserve BC break, you don't + * need to configure it, as it included in LevelSetList::UP_TO_PHP_74 * Set to true for projects that allow BC break */ TypedPropertyFromAssignsRector::INLINE_PUBLIC => false, @@ -119,4 +142,8 @@ $rectorConfig->rule(StringClassNameToClassConstantRector::class); $rectorConfig->rule(PrivatizeFinalClassPropertyRector::class); $rectorConfig->rule(CompleteDynamicPropertiesRector::class); + $rectorConfig->rule(BooleanInIfConditionRuleFixerRector::class); + $rectorConfig->rule(SingleInArrayToCompareRector::class); + $rectorConfig->rule(VersionCompareFuncCallToConstantRector::class); + $rectorConfig->rule(ExplicitBoolCompareRector::class); }; diff --git a/src/Commands/HtmxPublish.php b/src/Commands/HtmxPublish.php index 755ab10..a9cb177 100644 --- a/src/Commands/HtmxPublish.php +++ b/src/Commands/HtmxPublish.php @@ -40,6 +40,26 @@ public function run(array $params) file_put_contents($file, $contents); } + $file = APPPATH . 'Config/Format.php'; + + $publisher->addLineAfter( + $file, + " 'text/html'", + "'text/xml', // human-readable XML", + ); + + $publisher->addLineAfter( + $file, + " 'text/html' => HTMLFormatter::class,", + "'text/xml' => XMLFormatter::class,", + ); + + $publisher->addLineAfter( + $file, + 'use Michalsn\\CodeIgniterHtmx\\Format\\HTMLFormatter;', + 'use CodeIgniter\\Format\\XMLFormatter;', + ); + CLI::write(CLI::color(' Published! ', 'green') . 'You can customize the configuration by editing the "app/Config/Htmx.php" file.'); } } diff --git a/src/Format/HTMLFormatter.php b/src/Format/HTMLFormatter.php new file mode 100644 index 0000000..d7b119c --- /dev/null +++ b/src/Format/HTMLFormatter.php @@ -0,0 +1,68 @@ +formatTable($data); + } + + return $data; + } + + /** + * Format data as a table. + * + * @param mixed $data + */ + protected function formatTable($data): string + { + if (isset($data[0]) && count($data) !== count($data, COUNT_RECURSIVE)) { + // Multi-dimensional array + $headings = array_keys($data[0]); + } else { + // Single array + $headings = array_keys($data); + $data = [$data]; + } + + $table = new Table(); + $table->setHeading($headings); + + foreach ($data as $row) { + // Suppressing the "array to string conversion" notice + // Keep the "evil" @ here + $row = @array_map('strval', $row); + + $table->addRow($row); + } + + return $table->generate(); + } +} diff --git a/src/HTTP/IncomingRequest.php b/src/HTTP/IncomingRequest.php index 8cf3a97..5601b2e 100644 --- a/src/HTTP/IncomingRequest.php +++ b/src/HTTP/IncomingRequest.php @@ -110,7 +110,7 @@ private function getHtmxHeaderToBool(string $header): bool /** * Checks this request type. * - * @param string $type HTTP verb or 'json' or 'ajax' or 'htmx' or 'boosted' + * @param string $type HTTP verb or 'json' or 'ajax' or 'htmx' or 'boosted' * @phpstan-param string|'get'|'post'|'put'|'delete'|'head'|'patch'|'options'|'json'|'ajax'|'htmx'|'boosted' $type */ public function is(string $type): bool diff --git a/src/HTTP/RedirectResponse.php b/src/HTTP/RedirectResponse.php index 6aed2e6..8c52007 100644 --- a/src/HTTP/RedirectResponse.php +++ b/src/HTTP/RedirectResponse.php @@ -40,11 +40,11 @@ public function hxLocation( $data['swap'] = $swap; } - if (! empty($values)) { + if ($values !== null && $values !== []) { $data['values'] = $values; } - if (! empty($headers)) { + if ($headers !== null && $headers !== []) { $data['headers'] = $headers; } diff --git a/src/View/View.php b/src/View/View.php index 50a24f1..4fad561 100644 --- a/src/View/View.php +++ b/src/View/View.php @@ -23,7 +23,7 @@ class View extends BaseView * The name of the current section being rendered, * if any. * - * @var array + * @var list */ protected array $fragmentStack = []; diff --git a/tests/CommonTest.php b/tests/CommonTest.php index 4adbfe6..b94ef5c 100644 --- a/tests/CommonTest.php +++ b/tests/CommonTest.php @@ -83,7 +83,7 @@ public function testViewFragmentFromLayout(): void 'testString2' => 'Hello World', ]; - $expected = "Page bottom"; + $expected = 'Page bottom'; $this->assertSame($expected, view_fragment('with_fragment', 'sample0', $data)); } diff --git a/tests/Format/HTMLFormatterTest.php b/tests/Format/HTMLFormatterTest.php new file mode 100644 index 0000000..5c3902a --- /dev/null +++ b/tests/Format/HTMLFormatterTest.php @@ -0,0 +1,75 @@ +htmlFormatter = new HTMLFormatter(); + } + + public function testEmptyHTML(): void + { + $data = []; + + $expected = ''; + + $this->assertSame($expected, $this->htmlFormatter->format($data)); + } + + public function testBasicHTML(): void + { + $data = '
Hello
'; + + $expected = '
Hello
'; + + $this->assertSame($expected, $this->htmlFormatter->format($data)); + } + + public function testFormatFailArray(): void + { + $data = [ + 'status' => 400, + 'error' => 400, + 'messages' => ['error' => '
Error
'], + ]; + + $expected = '
Error
'; + + $this->assertSame($expected, $this->htmlFormatter->format($data)); + } + + public function testFormatFailArrayWithManyMessages(): void + { + $data = [ + 'status' => 400, + 'error' => 400, + 'messages' => ['error' => '
Error
', 'example' => '
Example
'], + ]; + + $expected = <<<'EOH' + + + + + + + + + +
errorexample
Error
Example
+ EOH; + + $this->assertSame($expected, $this->htmlFormatter->format($data)); + } +} diff --git a/tests/View/ErrorModelDecoratorTest.php b/tests/View/ErrorModelDecoratorTest.php index 04aba04..0bceacf 100644 --- a/tests/View/ErrorModelDecoratorTest.php +++ b/tests/View/ErrorModelDecoratorTest.php @@ -2,7 +2,7 @@ namespace Tests\View; -use CodeIgniter\Autoloader\FileLocator; +use CodeIgniter\Autoloader\FileLocatorInterface; use CodeIgniter\Config\Factories; use CodeIgniter\Config\Services; use CodeIgniter\Test\CIUnitTestCase; @@ -16,7 +16,7 @@ */ final class ErrorModelDecoratorTest extends CIUnitTestCase { - private FileLocator $loader; + private FileLocatorInterface $loader; private string $viewsDir; private ViewConfig $config; @@ -63,7 +63,7 @@ public function testDecoratorApply(): void public function testDecoratorDisabled(): void { - $htmxConfig = new HtmxConfig(); + $htmxConfig = new HtmxConfig(); $htmxConfig->errorModalDecorator = false; Factories::injectMock('config', 'Htmx', $htmxConfig); diff --git a/tests/View/ToolbarDecoratorTest.php b/tests/View/ToolbarDecoratorTest.php index ea7eeab..dc43b6e 100644 --- a/tests/View/ToolbarDecoratorTest.php +++ b/tests/View/ToolbarDecoratorTest.php @@ -2,7 +2,7 @@ namespace Tests\View; -use CodeIgniter\Autoloader\FileLocator; +use CodeIgniter\Autoloader\FileLocatorInterface; use CodeIgniter\Config\Factories; use CodeIgniter\Config\Services; use CodeIgniter\Test\CIUnitTestCase; @@ -16,7 +16,7 @@ */ final class ToolbarDecoratorTest extends CIUnitTestCase { - private FileLocator $loader; + private FileLocatorInterface $loader; private string $viewsDir; private ViewConfig $config; @@ -63,7 +63,7 @@ public function testDecoratorApply(): void public function testDecoratorDisabled(): void { - $htmxConfig = new HtmxConfig(); + $htmxConfig = new HtmxConfig(); $htmxConfig->toolbarDecorator = false; Factories::injectMock('config', 'Htmx', $htmxConfig); diff --git a/tests/View/ViewTest.php b/tests/View/ViewTest.php index d62c73e..06bd70d 100644 --- a/tests/View/ViewTest.php +++ b/tests/View/ViewTest.php @@ -2,7 +2,7 @@ namespace Tests\View; -use CodeIgniter\Autoloader\FileLocator; +use CodeIgniter\Autoloader\FileLocatorInterface; use CodeIgniter\Config\Services; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\View\Exceptions\ViewException; @@ -15,7 +15,7 @@ */ final class ViewTest extends CIUnitTestCase { - private FileLocator $loader; + private FileLocatorInterface $loader; private string $viewsDir; private ViewConfig $config;