diff --git a/.gitattributes b/.gitattributes index ecb4618d..3323417e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,4 +8,5 @@ composer.json export-ignore composer.lock export-ignore grumphp.yml export-ignore phpcs.xml export-ignore -psalm.xml export-ignore \ No newline at end of file +psalm.xml export-ignore +tests export-ignore \ No newline at end of file diff --git a/.github/workflows/php-quality.yml b/.github/workflows/php-quality.yml index 3887269a..b4ef1524 100644 --- a/.github/workflows/php-quality.yml +++ b/.github/workflows/php-quality.yml @@ -1,6 +1,6 @@ name: PHP Quality -on: [push, pull_request] +on: [ pull_request ] jobs: run: @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: [ 7.4' ] + php-versions: [ '7.4' ] name: PHP ${{ matrix.php-versions }} Test steps: - name: Checkout @@ -18,8 +18,6 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} - extensions: mbstring, intl #optional, setup extensions - - name: Check composer run: composer validate @@ -32,4 +30,13 @@ jobs: - name: Check psalm run: | mkdir -p dist - composer psalm \ No newline at end of file + composer psalm + + - name: Check unit test + run: composer tests-cov -- --coverage-clover=./tests/coverage/xml/index.xml + + - name: Run codacy-coverage-reporter + uses: codacy/codacy-coverage-reporter-action@v1 + with: + project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} + coverage-reports: tests/coverage/xml/index.xml \ No newline at end of file diff --git a/.gitignore b/.gitignore index d34578a3..a841e817 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,7 @@ package-lock.json ### config /vendor/ composer.lock + +### Tests +.phpunit.result.cache +tests/coverage/ \ No newline at end of file diff --git a/composer.json b/composer.json index aaeac585..45fb53d6 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,8 @@ "phpro/grumphp-shim": "^0.19.1", "squizlabs/php_codesniffer": "^3.5", "vimeo/psalm": "^3.13", - "wp-coding-standards/wpcs": "^2.3" + "wp-coding-standards/wpcs": "^2.3", + "10up/wp_mock": "^0.4.2" }, "scripts": { "cs": [ @@ -20,7 +21,9 @@ ], "psalm": [ "./vendor/bin/psalm" - ] + ], + "tests": "./vendor/bin/phpunit", + "tests-cov": "phpdbg -qrr ./vendor/bin/phpunit --coverage-html ./tests/coverage/" }, "autoload": { "psr-4": { diff --git a/inc/Services/Acf.php b/inc/Services/Acf.php index 34373dbf..1ce64020 100644 --- a/inc/Services/Acf.php +++ b/inc/Services/Acf.php @@ -52,7 +52,7 @@ public function warning(): void { return; } - wp_die( sprintf( __( 'This theme can\'t work without ACF plugin. Please login to admin, and activate it !', 'framework-textdomain' ), esc_url( wp_login_url() ) ) ); // phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment, WordPress.Security.EscapeOutput.OutputNotEscaped + \wp_die( sprintf( __( 'This theme can\'t work without ACF plugin. Please login to admin, and activate it !', 'framework-textdomain' ), esc_url( wp_login_url() ) ) ); // phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment, WordPress.Security.EscapeOutput.OutputNotEscaped } /** @@ -147,7 +147,6 @@ public function init_acf(): void { if ( ! is_file( get_theme_file_path( $this->path . $file . '.php' ) ) ) { continue; } - require_once get_theme_file_path( $this->path . $file . '.php' ); } } diff --git a/inc/Services/Assets.php b/inc/Services/Assets.php index 032e3138..76631da0 100644 --- a/inc/Services/Assets.php +++ b/inc/Services/Assets.php @@ -59,17 +59,17 @@ public function register_assets(): void { // Js theme // Theme js dependencies - $scripts_dependencies = [ 'jquery' ]; + $scripts_dependencies = [ 'jquery', 'global-polyfill' ]; - // Async and footer - $file = $this->is_minified() ? $this->get_min_file( 'js' ) : 'app.js'; + // Polyfill + \wp_register_script( 'global-polyfill', 'https://cdn.polyfill.io/v3/polyfill.min.js?features=es5,es6,fetch,Array.prototype.includes,CustomEvent,Element.prototype.closest,NodeList.prototype.forEach', null, null, true ); //phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion - // Do not add version if minified - $version = $this->is_minified() ? null : $theme->get( 'Version' ); - $this->assets_tools->register_script( 'scripts', 'dist/' . $file, $scripts_dependencies, $version, true ); + // Async and footer + $file = ( ! defined( 'SCRIPT_DEBUG' ) || SCRIPT_DEBUG === false ) ? $this->get_min_file( 'js' ) : 'app.js'; + $this->assets_tools->register_script( 'scripts', 'dist/' . $file, $scripts_dependencies, $theme->get( 'Version' ), true ); // CSS - wp_register_style( 'theme-style', get_stylesheet_uri(), [], $version ); + \wp_register_style( 'theme-style', \get_stylesheet_uri(), [], $theme->get( 'Version' ) ); } /** @@ -97,7 +97,8 @@ public function enqueue_styles(): void { * @author Nicolas Juen */ public function stylesheet_uri( string $stylesheet_uri ): string { - if ( $this->is_minified() ) { + if ( ! defined( 'SCRIPT_DEBUG' ) || SCRIPT_DEBUG === false ) { + $file = $this->get_min_file( 'css' ); if ( ! empty( $file ) && file_exists( \get_theme_file_path( '/dist/' . $file ) ) ) { return \get_theme_file_uri( '/dist/' . $file ); @@ -167,21 +168,11 @@ public function get_min_file( string $type ): string { return $file; } - /** - * Check if we are on minified environment. - * - * @return bool - * @author Nicolas JUEN - */ - private function is_minified(): bool { - return ( ! defined( 'SCRIPT_DEBUG' ) || SCRIPT_DEBUG === false ); - } - /** * Change login CSS URL * @return string */ public function login_stylesheet_uri(): string { - return $this->is_minified() ? 'dist/' . $this->get_min_file( 'login' ) : 'dist/login.css'; + return ( ! defined( 'SCRIPT_DEBUG' ) || SCRIPT_DEBUG === false ) ? 'dist/' . $this->get_min_file( 'login' ) : 'dist/login.css'; } } diff --git a/phpcs.xml b/phpcs.xml index d3a05a26..10ed28a3 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -14,6 +14,7 @@ dist/ src/ scripts/ + tests/ diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 00000000..2c91f844 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,14 @@ + + + + + functions.php + inc + + + + + tests + + + diff --git a/psalm.xml b/psalm.xml index a1814797..44c2e5b6 100644 --- a/psalm.xml +++ b/psalm.xml @@ -13,6 +13,7 @@ + diff --git a/tests/FrameworkTest.php b/tests/FrameworkTest.php new file mode 100644 index 00000000..f1ab22b3 --- /dev/null +++ b/tests/FrameworkTest.php @@ -0,0 +1,37 @@ +assertFalse( Framework::get_container()->get_service( 'not-a-service' ) ); + } + + public function testSameContainer() { + $container = Framework::get_container(); + + $this->assertSame( $container, Framework::get_container() ); + } + + public function testServiceSet() { + Framework::register_service( Acf::class ); + + $this->assertNotEmpty( Framework::get_container()->get_service( Acf::class ) ); + } +} diff --git a/tests/Helpers/Formatting/EscapeTest.php b/tests/Helpers/Formatting/EscapeTest.php new file mode 100644 index 00000000..82617434 --- /dev/null +++ b/tests/Helpers/Formatting/EscapeTest.php @@ -0,0 +1,40 @@ +assertSame( 'ok', $value ); + + $value = escape_attribute_value( 'ok', 'test_escape' ); + $this->assertSame( 'esc_ok', $value ); + } + public function testContent() { + $value = escape_content_value( 'ok', '' ); + $this->assertSame( 'ok', $value ); + + $value = escape_content_value( 'ok', 'test_escape' ); + $this->assertSame( 'esc_ok', $value ); + } +} + diff --git a/tests/Helpers/Formatting/ImageTest.php b/tests/Helpers/Formatting/ImageTest.php new file mode 100644 index 00000000..4a691329 --- /dev/null +++ b/tests/Helpers/Formatting/ImageTest.php @@ -0,0 +1,55 @@ + '', + ] + ); + + $this->assertSame( '', get_the_image( 0, [] ) ); + } + + public function testGetImageEmpty() { + WP_Mock::userFunction( 'wp_get_attachment_image', [ + 'return' => '', + ] + ); + + $this->assertSame( '', get_the_image( 10, [ 'size' => '', 'data-location' => '' ] ) ); + } + + public function testImageBeforeAfter() { + WP_Mock::userFunction( 'wp_get_attachment_image', [ + 'return' => '', + ] + ); + + $this->assertSame( 'b', get_the_image( 10, [], [ 'before' => 'b' ] ) ); + $this->assertSame( 'a', get_the_image( 10, [], [ 'after' => 'a' ] ) ); + $this->assertSame( 'ba', get_the_image( 10, [], [ 'after' => 'a', 'before' => 'b' ] ) ); + } +} + diff --git a/tests/Helpers/Formatting/LinkTest.php b/tests/Helpers/Formatting/LinkTest.php new file mode 100644 index 00000000..9cc5ccea --- /dev/null +++ b/tests/Helpers/Formatting/LinkTest.php @@ -0,0 +1,202 @@ +assertSame( '', get_the_link( [] ) ); + } + + public function testGetTheLinkTargetBlank() { + + // Auto noopener + $this->assertSame( + 'New window', + get_the_link( + [ + 'href' => 'https://localhost.dev', + 'target' => '_blank', + 'title' => 'TITLE LINK', + ] + ) + ); + + // self + $this->assertSame( + '', + get_the_link( + [ + 'href' => 'https://localhost.dev', + 'target' => '_self', + ] + ) + ); + + // self title + $this->assertSame( + '', + get_the_link( + [ + 'href' => 'https://localhost.dev', + 'target' => '_self', + 'title' => 'TITLE LINK', + ] + ) + ); + + // Custom attribute + $this->assertSame( + '', + get_the_link( + [ + 'href' => 'https://localhost.dev', + 'data-seo' => 'ok', + ] + ) + ); + $this->assertSame( + '', + get_the_link( + [ + 'href' => 'https://localhost.dev', + 'empty-data' => null, + ] + ) + ); + + // Before/after + $this->assertSame( + 'b', + get_the_link( + [ + 'href' => 'https://localhost.dev', + ], + [ + 'before' => 'b', + ] + ) + ); + $this->assertSame( + 'a', + get_the_link( + [ + 'href' => 'https://localhost.dev', + ], + [ + 'after' => 'a', + ] + ) + ); + $this->assertSame( + 'ba', + get_the_link( + [ + 'href' => 'https://localhost.dev', + ], + [ + 'after' => 'a', + 'before' => 'b', + ] + ) + ); + + $this->assertSame( + 'Content', + get_the_link( + [ + 'href' => 'https://localhost.dev', + ], + [ + 'content' => 'Content', + ] + ) + ); + + $this->assertSame( + 'Content', + get_the_link( + [ + 'href' => 'https://localhost.dev', + 'title' => 'TITLE', + ], + [ + 'content' => 'Content', + ] + ) + ); + } + + public function testGetAcfLinkEmptyURLOrTitle() { + $this->assertSame( '', get_acf_link( [] ) ); + $this->assertSame( '', get_acf_link( [ 'field' => [ 'url' => 'ok' ] ] ) ); + $this->assertSame( '', get_acf_link( [ 'field' => [ 'title' => 'ok' ] ] ) ); + } + + public function testGetAcfLinkWithAttributes() { + $this->assertSame( + 'New windowTitle', + get_acf_link( + [ + 'field' => [ + 'title' => 'Title', + 'url' => 'https://localhost.dev', + 'target' => '_blank', + ], + ] + ) + ); + + $this->assertSame( + 'Title', + get_acf_link( + [ + 'field' => [ + 'title' => 'Title', + 'url' => 'https://localhost.dev', + 'target' => '', + ], + ] + ) + ); + + $this->assertSame( + 'CONTENT', + get_acf_link( + [ + 'field' => [ + 'title' => 'Title', + 'url' => 'https://localhost.dev', + 'target' => '', + ], + ], + [ + 'content' => 'CONTENT', + ] + ) + ); + } +} + diff --git a/tests/Helpers/Formatting/TextTest.php b/tests/Helpers/Formatting/TextTest.php new file mode 100644 index 00000000..1d8d4263 --- /dev/null +++ b/tests/Helpers/Formatting/TextTest.php @@ -0,0 +1,140 @@ +assertEmpty( $test ); + + ob_start(); + the_text( '' ); + $buffer = ob_get_clean(); + $this->assertSame( $test, $buffer ); + } + + public function testBeforeAfter() { + $val = get_the_text( 'val', [ 'before' => 'b' ] ); + $val2 = get_the_text( 'val', [ 'after' => 'a' ] ); + $val3 = get_the_text( 'val', [ 'before' => 'b', 'after' => 'a' ] ); + + ob_start(); + the_text( 'val', [ 'before' => 'b' ] ); + $buffer = ob_get_clean(); + + ob_start(); + the_text( 'val', [ 'after' => 'a' ] ); + $buffer2 = ob_get_clean(); + + ob_start(); + the_text( 'val', [ 'before' => 'b', 'after' => 'a' ] ); + $buffer3 = ob_get_clean(); + + // Test returns + $this->assertSame( 'bval', $val ); + $this->assertSame( 'vala', $val2 ); + $this->assertSame( 'bvala', $val3 ); + + // Test Buffer and generated the same + $this->assertSame( $val, $buffer ); + $this->assertSame( $val2, $buffer2 ); + $this->assertSame( $val3, $buffer3 ); + } + + public function testEscape() { + + + $this->assertSame( 'esc_val', get_the_text( 'val', [ + 'before' => '', + 'after' => '', + 'escape' => 'test_escape', + ] ) ); + $this->assertSame( 'besc_val', get_the_text( 'val', [ + 'before' => 'b', + 'after' => '', + 'escape' => 'test_escape', + ] ) ); + $this->assertSame( 'esc_vala', get_the_text( 'val', [ + 'before' => '', + 'after' => 'a', + 'escape' => 'test_escape', + ] ) ); + $this->assertSame( 'besc_vala', get_the_text( 'val', [ + 'before' => 'b', + 'after' => 'a', + 'escape' => 'test_escape', + ] ) ); + } + + public function testFilterSettings() { + + WP_Mock::onFilter( 'bea_theme_framework_text_settings' )->with( + [ + 'before' => '', + 'after' => '', + 'escape' => 'test_escape', + ], + 'val' + )->reply( + [ + 'before' => 'b', + 'after' => 'a', + 'escape' => 'esc_html', + ] + ); + + $this->assertSame( + 'bvala', + get_the_text( + 'val', + [ + 'before' => 'b', + 'after' => 'a', + 'escape' => 'esc_html', + ] + ) + ); + } + + public function testFilterValue() { + + WP_Mock::onFilter( 'bea_theme_framework_text_value' )->with( + 'esc_val', + [ + 'before' => '', + 'after' => '', + 'escape' => 'test_escape', + ] + )->reply( 'filtered' ); + + $this->assertSame( + 'filtered', + get_the_text( + 'val', + [ + 'before' => '', + 'after' => '', + 'escape' => 'test_escape', + ] + ) + ); + } +} + diff --git a/tests/Services/AcfTest.php b/tests/Services/AcfTest.php new file mode 100644 index 00000000..a5f602ae --- /dev/null +++ b/tests/Services/AcfTest.php @@ -0,0 +1,117 @@ +assertEquals( 'acf', $acf->get_service_name() ); + } + + public function testWarning() { + $acf = new Acf(); + + WP_Mock::userFunction( 'wp_die', [ + 'times' => 1, + ] ); + + WP_Mock::userFunction( 'esc_url', [ + 'times' => 1, + ] ); + + WP_Mock::userFunction( 'wp_login_url', [ + 'times' => 1, + ] ); + $acf->warning(); + + // Test we do not launch the functions on existing get_field function + WP_Mock::userFunction( 'get_field' ); + $acf->warning(); + } + + public function testGetSetFiles() { + $acf = new Acf(); + + $acf->register_files( [ 'myfile' ] ); + $this->assertSame( [ 'myfile' => 'myfile' ], $acf->get_files() ); + + $acf->register_files( [ 'myfile', '' ] ); + $this->assertSame( [ 'myfile' => 'myfile' ], $acf->get_files() ); + + $acf->register_files( [ 'myfile' ] ); + $this->assertSame( [ 'myfile' => 'myfile' ], $acf->get_files() ); + } + + public function testRegisterOptionPage() { + $acf = new Acf(); + + // Function not existing + $this->assertFalse( $acf->acf_add_options_page( [] ) ); + + WP_Mock::userFunction( 'acf_add_options_page', [ 'return' => 'ok' ] ); + $this->assertSame( 'ok', $acf->acf_add_options_page( [ 'menu_slug' => 'ok' ] ) ); + + // Exception is ok + $this->expectException( InvalidArgumentException::class ); + $acf->acf_add_options_page( [] ); + + } + + public function testRegisterOptionSubPage() { + $acf = new Acf(); + + // Function not existing + $this->assertFalse( $acf->acf_add_options_sub_page( [] ) ); + + WP_Mock::userFunction( 'acf_add_options_sub_page', [ 'return' => 'ok' ] ); + $this->assertSame( 'ok', $acf->acf_add_options_sub_page( [ 'menu_slug' => 'ok' ] ) ); + + // Exception is ok + $this->expectException( InvalidArgumentException::class ); + $acf->acf_add_options_sub_page( [] ); + } + + public function testPath() { + $acf = new Acf(); + + // Function not existing + $acf->set_path( 'test/path' ); + } + + public function testInitAcf() { + $acf = new Acf(); + + // Function not existing + $this->assertNull( $acf->init_acf() ); + + WP_Mock::userFunction( 'get_theme_file_path', [ + 'return_in_order' => [ + __DIR__ . '/../data/', + __DIR__ . '/../data/myfile.php', + __DIR__ . '/../data/myfile.php', + __DIR__ . '/../data/myfile2.php', + __DIR__ . '/../data/myfile3.php', + ], + 'times' => 5, + ] ); + + $acf->register_files( [ 'myfile', 'myfile2', 'myfile3' ] ); + $acf->init_acf(); + } + +} diff --git a/tests/Services/AssetsTest.php b/tests/Services/AssetsTest.php new file mode 100644 index 00000000..a05ec408 --- /dev/null +++ b/tests/Services/AssetsTest.php @@ -0,0 +1,211 @@ +assertEquals( 'assets', $assets->get_service_name() ); + } + + public function testStyleSheetURIWithScriptDebugAndNoFiles() { + $assets = new Assets(); + + define( 'SCRIPT_DEBUG', true ); + + WP_Mock::userFunction( 'get_theme_file_path', [ + 'times' => 1, + 'return' => 'ok.css', + 'args' => [ '/dist/app.css' ], + ] ); + + $this->assertSame( 'ok.css', $assets->stylesheet_uri( 'ok.css' ) ); + } + + public function testStyleSheetURIWithScriptDebugAndFiles() { + $assets = new Assets(); + + define( 'SCRIPT_DEBUG', true ); + + $assets_file = __DIR__ . '/../data/assets/app.css'; + + WP_Mock::userFunction( + 'get_theme_file_path', + [ + 'times' => 1, + 'return' => $assets_file, + 'args' => [ + '/dist/app.css', + ], + ] + ); + WP_Mock::userFunction( + 'get_theme_file_uri', + [ + 'times' => 1, + 'args' => [ + '/dist/app.css', + ], + 'return' => 'https://localhost.dev/data/assets/app.css', + ] + ); + + $this->assertSame( 'https://localhost.dev/data/assets/app.css', $assets->stylesheet_uri( 'ok.css' ) ); + } + + public function testStyleSheetURIWithOutScriptDebugAndNoFiles() { + $assets = new Assets(); + + define( 'SCRIPT_DEBUG', false ); + + WP_Mock::passthruFunction( 'get_theme_file_path', [ 'times' => 2 ] ); + + $this->assertSame( 'ok.css', $assets->stylesheet_uri( 'ok.css' ) ); + } + + public function testGetMinFileEmpty() { + $assets = new Assets(); + + $this->assertSame( '', $assets->get_min_file( '' ) ); + } + + public function testGetMinFileAssetsExistsAndEmpty() { + $assets = new Assets(); + $assets_file = __DIR__ . '/../data/assets/assets-empty.json'; + + WP_Mock::userFunction( 'get_theme_file_path', [ 'args' => '/dist/assets.json', 'return' => $assets_file ] ); + + $this->assertSame( '', $assets->get_min_file( 'css' ) ); + } + + public function testGetMinFileAssetsExistsNotEmptyNonExistingType() { + $assets = new Assets(); + $assets_file = __DIR__ . '/../data/assets/assets.json'; + + WP_Mock::userFunction( 'get_theme_file_path', [ 'args' => '/dist/assets.json', 'return' => $assets_file ] ); + + $this->assertSame( '', $assets->get_min_file( 'non-existing' ) ); + } + + public function testGetMinFileAssetsExistsNotEmptyExistingType() { + $assets = new Assets(); + $assets_file = __DIR__ . '/../data/assets/assets.json'; + + WP_Mock::userFunction( 'get_theme_file_path', [ 'args' => '/dist/assets.json', 'return' => $assets_file ] ); + + // Existing + $this->assertSame( 'app.min.css', $assets->get_min_file( 'css' ) ); + $this->assertSame( 'app.min.js', $assets->get_min_file( 'js' ) ); + $this->assertSame( 'editor.min.css', $assets->get_min_file( 'editor.css' ) ); + $this->assertSame( 'editor.min.js', $assets->get_min_file( 'editor.js' ) ); + $this->assertSame( 'login.min.css', $assets->get_min_file( 'login' ) ); + + // Custom + $this->assertSame( 'custom.min.css', $assets->get_min_file( 'custom.css' ) ); + + // Non existing + $this->assertSame( '', $assets->get_min_file( 'custom.min.css' ) ); + } + + public function testGetLoginStyleSheet() { + $assets = new Assets(); + $assets_file = __DIR__ . '/../data/assets/assets.json'; + + WP_Mock::userFunction( 'get_theme_file_path', [ 'args' => '/dist/assets.json', 'return' => $assets_file ] ); + + // Existing + $this->assertSame( 'dist/login.min.css', $assets->login_stylesheet_uri() ); + } + + public function testGetLoginStyleSheetDebug() { + $assets = new Assets(); + $assets_file = __DIR__ . '/../data/assets/assets.json'; + define( 'SCRIPT_DEBUG', true ); + + WP_Mock::userFunction( 'get_theme_file_path', [ 'args' => '/dist/assets.json', 'return' => $assets_file ] ); + + // Existing + $this->assertSame( 'dist/login.css', $assets->login_stylesheet_uri() ); + } + + public function testRegisterFilesAdmin() { + $assets = new Assets(); + + WP_Mock::userFunction( 'is_admin', [ 'return' => true, 'times' => 1 ] ); + WP_Mock::passthruFunction( 'wp_get_theme', [ 'times' => 0 ] ); + + $this->assertNull( $assets->register_assets() ); + } + + public function testRegisterFiles() { + $assets = new Assets(); + $container = Framework::get_container(); + $theme_mock = $this->getMockBuilder( stdclass::class )->addMethods( [ 'get' ] )->getMock(); + $assets->register( $container ); + + WP_Mock::userFunction( + 'is_admin', + [ + 'return' => false, + 'times' => 1, + ] + ); + WP_Mock::userFunction( + 'wp_get_theme', + [ + 'times' => 1, + 'return' => $theme_mock, + ] + ); + WP_Mock::passthruFunction( 'wp_register_script', [ 'times' => 2 ] ); + WP_Mock::passthruFunction( 'wp_register_style', [ 'times' => 1 ] ); + WP_Mock::passthruFunction( 'get_theme_file_path', [ 'times' => 1 ] ); + WP_Mock::passthruFunction( 'get_theme_file_uri' ); + WP_Mock::userFunction( 'get_stylesheet_uri', [ 'return' => false ] ); + + // Check the version is called + $theme_mock->expects( $this->atLeastOnce() )->method( 'get' ); + + $this->assertNull( $assets->register_assets() ); + } + + public function testCheckFiltersAdded() { + $assets = new Assets(); + + // Check filters + WP_Mock::expectFilterAdded( 'stylesheet_uri', [ $assets, 'stylesheet_uri' ] ); + WP_Mock::expectFilterAdded( 'wp_login_page_theme_css', [ $assets, 'login_stylesheet_uri' ] ); + + // Check Action + WP_Mock::expectActionAdded( 'wp', [ $assets, 'register_assets' ] ); + WP_Mock::expectActionAdded( 'wp_enqueue_scripts', [ $assets, 'enqueue_scripts' ] ); + WP_Mock::expectActionAdded( 'wp_print_styles', [ $assets, 'enqueue_styles' ] ); + + $assets->boot( Framework::get_container() ); + } +} diff --git a/tests/Services/SvgTest.php b/tests/Services/SvgTest.php new file mode 100644 index 00000000..a151c125 --- /dev/null +++ b/tests/Services/SvgTest.php @@ -0,0 +1,86 @@ +assertEquals( 'svg', $svg->get_service_name() ); + } + + public function testTags() { + $svg = new Svg(); + $this->assertIsArray( $svg->allow_svg_tag( [] ) ); + $this->assertArrayHasKey( 'path', $svg->allow_svg_tag( [] ) ); + $this->assertArrayHasKey( 'svg', $svg->allow_svg_tag( [] ) ); + $this->assertArrayHasKey( 'use', $svg->allow_svg_tag( [] ) ); + } + + public function testRegister() { + $svg = new Svg(); + $container = $this->createStub( Service_Container::class ); + + WP_Mock::expectFilterAdded( 'wp_kses_allowed_html', [ $svg, 'allow_svg_tag' ] ); + + $svg->register( $container ); + } + + public function testEmptyIcon() { + $svg = new Svg(); + $this->assertEmpty( $svg->get_the_icon('') ); + } + + public function testGetIcon() { + $svg = new Svg(); + WP_Mock::passthruFunction( 'sanitize_html_class' ); + WP_Mock::userFunction( 'get_theme_file_uri', [ + 'return' => 'test.example.fr', + ] ); + + $this->assertSame( + '', + $svg->get_the_icon( 'test' ) + ); + } + public function testTheIcon() { + $svg = new Svg(); + WP_Mock::passthruFunction( 'sanitize_html_class' ); + WP_Mock::userFunction( 'get_theme_file_uri', [ + 'return' => 'test.example.fr', + ] ); + + ob_start(); + $this->AssertNull( $svg->the_icon( 'test' ) ); + $this->AssertNull( $svg->the_icon( 'test', [ 'class1', 'class2' ] ) ); + ob_end_clean(); + } + + public function testGetIconWithClass() { + $svg = new Svg(); + WP_Mock::passthruFunction( 'sanitize_html_class' ); + + WP_Mock::userFunction( 'get_theme_file_uri', [ + 'return' => 'test.example.fr', + ] ); + + $this->assertSame( + '', + $svg->get_the_icon( 'test', [ 'class2', 'class3' ] ) + ); + } +} diff --git a/tests/Tools/AssetsTest.php b/tests/Tools/AssetsTest.php new file mode 100644 index 00000000..cde1f4e8 --- /dev/null +++ b/tests/Tools/AssetsTest.php @@ -0,0 +1,88 @@ + 1 ] ); + WP_Mock::passthruFunction( + 'wp_register_script', + [ + 'times' => 1, + 'args' => [ + 'handle', + 'src', + [], + false, + false, + ], + ] + ); + + $assets = new Assets(); + $assets->register_script( 'handle', 'src' ); + } + + public function testEnqueueScript() { + WP_Mock::passthruFunction( + 'wp_enqueue_script', + [ + 'times' => 1, + 'args' => [ + 'handle', + ], + ] + ); + + $assets = new Assets(); + $assets->enqueue_script( 'handle' ); + } + + public function testRegisterStyle() { + WP_Mock::passthruFunction( 'get_theme_file_uri', [ 'times' => 1 ] ); + WP_Mock::passthruFunction( + 'wp_register_style', + [ + 'times' => 1, + 'args' => [ + 'handle', + 'src', + [], + false, + 'all', + ], + ] + ); + + $assets = new Assets(); + $assets->register_style( 'handle', 'src' ); + } + + public function testEnqueueStyle() { + WP_Mock::passthruFunction( + 'wp_enqueue_style', + [ + 'times' => 1, + 'args' => [ + 'handle', + ], + ] + ); + + $assets = new Assets(); + $assets->enqueue_style( 'handle' ); + } +} diff --git a/tests/Tools/Body_Class_Test.php b/tests/Tools/Body_Class_Test.php new file mode 100644 index 00000000..307f7100 --- /dev/null +++ b/tests/Tools/Body_Class_Test.php @@ -0,0 +1,56 @@ +add( 'test' ); + $this->assertEquals( [ 'test' ], $body_class->body_class( [] ) ); + + } + + public function testRemove() { + $body_class = new Body_Class(); + + $body_class->add( 'test' ); + $body_class->remove( 'test' ); + $this->assertEquals( [], $body_class->body_class( [] ) ); + } + + public function testAddRemoveWithInitialData() { + $body_class = new Body_Class(); + + $body_class->add( 'test' ); + $body_class->remove( 'test' ); + $this->assertEquals( [ 'leaveme' ], $body_class->body_class( [ 'leaveme' ] ) ); + } + + public function testName() { + $body_class = new Body_Class(); + self::assertEquals( 'body-class', $body_class->get_service_name() ); + } + + public function testBoot() { + $body_class = new Body_Class(); + $container = $this->createStub( Service_Container::class ); + + WP_Mock::expectFilterAdded( 'body_class', [ $body_class, 'body_class' ] ); + + $body_class->boot( $container ); + } +} diff --git a/tests/Tools/Template_Parts_Test.php b/tests/Tools/Template_Parts_Test.php new file mode 100644 index 00000000..fa679a02 --- /dev/null +++ b/tests/Tools/Template_Parts_Test.php @@ -0,0 +1,59 @@ +assertTrue( $template->add_var( 'slug', 'key', 'value' ) ); + } + + public function testGet() { + $template = new Template_Parts(); + + $this->assertNull( $template->get_var( 'slug', 'key' ) ); + + $template->add_var( 'slug', 'key', 'value' ); + + $this->assertSame( 'value', $template->get_var( 'slug', 'key' ) ); + } + + public function testGetOtherslug() { + $template = new Template_Parts(); + + $template->add_var( 'slug', 'key', 'value' ); + + $this->assertEmpty( $template->get_var( 'slug2', 'key' ) ); + } + + public function testGetVars() { + $template = new Template_Parts(); + + $template->add_var( 'slug', 'key', 'value' ); + $template->add_var( 'slug', 'key2', 'value3' ); + $template->add_var( 'slug3', 'key', 'value3' ); + + $this->assertSame( [ 'key' => 'value', 'key2' => 'value3' ], $template->get_vars( 'slug' ) ); + $this->assertNull( $template->get_vars( 'slug2' ) ); + $this->assertSame( 'value3', $template->get_var( 'slug3', 'key' ) ); + } + + public function testName() { + $template = new Template_Parts(); + self::assertEquals( 'template-parts', $template->get_service_name() ); + } + +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 00000000..d1b42513 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,14 @@ +