Add e2e tests for notice templates (#44612)

* Add e2e tests for notice templates

* Add changelog entry

* Minor refactor

* Remove child theme zip files

* Generate child theme zip files on the fly
This commit is contained in:
Niels Lange 2024-02-27 13:46:31 +01:00 committed by GitHub
parent 7ad4ef8e4d
commit a668cf942e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 622 additions and 1 deletions

3
.gitignore vendored
View File

@ -37,6 +37,9 @@ npm-debug.log
*.swp
*.zip
# Allow theme *.zip files for testing purposes
!plugins/woocommerce-blocks/tests/e2e/bin/themes/*.zip
# Built packages
build/
build-module/

View File

@ -0,0 +1,3 @@
<!-- wp:shortcode -->
[woocommerce_cart]
<!-- /wp:shortcode -->

View File

@ -0,0 +1,3 @@
<!-- wp:shortcode -->
[woocommerce_checkout]
<!-- /wp:shortcode -->

View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
wp wc shop_coupon create --code=TESTCOUPON --amount=10 --discount_type=fixed_cart --user=1

View File

@ -74,5 +74,25 @@ post_id=$(wp post create \
${script_dir}/mini-cart.html
)
post_id=$(wp post create \
--porcelain \
--menu_order=8 \
--post_type=page \
--post_status=publish \
--post_author=1 \
--post_title='Cart Shortcode' \
${script_dir}/cart-shortcode.html
)
post_id=$(wp post create \
--porcelain \
--menu_order=8 \
--post_type=page \
--post_status=publish \
--post_author=1 \
--post_title='Checkout Shortcode' \
${script_dir}/checkout-shortcode.html
)
# Create renaming WooCommerce pages using tool
wp wc tool run install_pages --user=1

View File

@ -0,0 +1,15 @@
#!/usr/bin/env bash
# Get the directory of the current script.
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# The theme dir is two levels up from where this script is running.
themes_dir="$script_dir/../../themes"
# Delete the child themes if they already exist.
wp theme delete storefront-child
wp theme delete twentytwentyfour-child
# Install the child themes.
wp theme install "$themes_dir/storefront-child.zip"
wp theme install "$themes_dir/twentytwentyfour-child.zip"

View File

@ -6,5 +6,26 @@ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
head_dir=$(cd "$(dirname "$script_dir")" && cd ../../.. && pwd)
relative_path=${script_dir#$head_dir/}
# Generate the child themes zip files before running the tests.
# By doing so, we ensure that the zip files are up-to-date.
themes_dir="$script_dir/themes"
themes=("storefront-child" "twentytwentyfour-child")
for theme in "${themes[@]}"; do
# Define the path to the theme directory and the zip file.
theme_dir="$themes_dir/$theme"
zip_file="$themes_dir/$theme.zip"
# Check if the zip file exists. If it does, delete it.
if [ -f "$zip_file" ]; then
echo "Deleting existing zip file for $theme."
rm "$zip_file"
fi
# Navigate to the themes directory to ensure the zip contains only the theme folder name.
# Then, create a fresh zip file.
echo "Creating zip file for $theme."
(cd "$themes_dir" && zip -r "$zip_file" "$theme" -x "*.git*" -x "*node_modules*")
done
# Run the main script in the container for better performance.
wp-env run tests-cli -- bash wp-content/plugins/woocommerce/blocks-bin/playwright/scripts/index.sh

View File

@ -0,0 +1,4 @@
/*
Theme Name: Storefront Child
Template: storefront
*/

View File

@ -0,0 +1,34 @@
<?php
/**
* Show error messages
*
* This template can be overridden by copying it to yourtheme/woocommerce/notices/error.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see https://woo.com/document/template-structure/
* @package WooCommerce\Templates
* @version 3.9.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! $notices ) {
return;
}
?>
<ul class="woocommerce-error" role="alert">
<?php foreach ( $notices as $notice ) : ?>
<li<?php echo wc_get_notice_data_attr( $notice ); ?>>
CLASSIC ERROR NOTICE - <?php echo wc_kses_notice( $notice['notice'] ); ?>
</li>
<?php endforeach; ?>
</ul>

View File

@ -0,0 +1,32 @@
<?php
/**
* Show messages
*
* This template can be overridden by copying it to yourtheme/woocommerce/notices/notice.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see https://woo.com/document/template-structure/
* @package WooCommerce\Templates
* @version 3.9.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! $notices ) {
return;
}
?>
<?php foreach ( $notices as $notice ) : ?>
<div class="woocommerce-info"<?php echo wc_get_notice_data_attr( $notice ); ?>>
CLASSIC INFO NOTICE - <?php echo wc_kses_notice( $notice['notice'] ); ?>
</div>
<?php endforeach; ?>

View File

@ -0,0 +1,32 @@
<?php
/**
* Show messages
*
* This template can be overridden by copying it to yourtheme/woocommerce/notices/success.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see https://woo.com/document/template-structure/
* @package WooCommerce\Templates
* @version 3.9.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! $notices ) {
return;
}
?>
<?php foreach ( $notices as $notice ) : ?>
<div class="woocommerce-message"<?php echo wc_get_notice_data_attr( $notice ); ?> role="alert">
CLASSIC SUCCESS NOTICE - <?php echo wc_kses_notice( $notice['notice'] ); ?>
</div>
<?php endforeach; ?>

View File

@ -0,0 +1,4 @@
/*
Theme Name: Twenty Twenty-Four Child
Template: twentytwentyfour
*/

View File

@ -0,0 +1,51 @@
<?php
/**
* Show error messages
*
* This template can be overridden by copying it to yourtheme/woocommerce/notices/error.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see https://docs.woocommerce.com/document/template-structure/
* @package WooCommerce\Templates
* @version 8.5.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( empty( $notices ) || ! is_array( $notices ) ) {
return;
}
$multiple = count( $notices ) > 1;
?>
<div class="wc-block-components-notice-banner is-error" role="alert" <?php echo $multiple ? '' : wc_get_notice_data_attr( $notices[0] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
<path d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-6h-2v6zm0-8h2V7h-2v2z"></path>
</svg>
<div class="wc-block-components-notice-banner__content">
<?php if ( $multiple ) { ?>
<p class="wc-block-components-notice-banner__summary"><?php esc_html_e( 'The following problems were found:', 'woocommerce' ); ?></p>
<ul>
<?php foreach ( $notices as $notice ) : ?>
<li<?php echo wc_get_notice_data_attr( $notice ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
BLOCK ERROR NOTICE - <?php echo wc_kses_notice( $notice['notice'] ); ?>
</li>
<?php endforeach; ?>
</ul>
<?php
} else {
echo 'BLOCK ERROR NOTICE - ' . wc_kses_notice( $notices[0]['notice'] );
}
?>
</div>
</div>
<?php

View File

@ -0,0 +1,37 @@
<?php
/**
* Show info messages
*
* This template can be overridden by copying it to yourtheme/woocommerce/notices/notice.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see https://docs.woocommerce.com/document/template-structure/
* @package WooCommerce\Templates
* @version 8.5.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! $notices ) {
return;
}
?>
<?php foreach ( $notices as $notice ) : ?>
<div class="wc-block-components-notice-banner is-info"<?php echo wc_get_notice_data_attr( $notice ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> role="alert">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
<path d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-6h-2v6zm0-8h2V7h-2v2z"></path>
</svg>
<div class="wc-block-components-notice-banner__content">
BLOCK INFO NOTICE - <?php echo wc_kses_notice( $notice['notice'] ); ?>
</div>
</div>
<?php endforeach; ?>

View File

@ -0,0 +1,37 @@
<?php
/**
* Show success messages
*
* This template can be overridden by copying it to yourtheme/woocommerce/notices/success.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* @see https://docs.woocommerce.com/document/template-structure/
* @package WooCommerce\Templates
* @version 8.5.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! $notices ) {
return;
}
?>
<?php foreach ( $notices as $notice ) : ?>
<div class="wc-block-components-notice-banner is-success"<?php echo wc_get_notice_data_attr( $notice ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> role="alert">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
<path d="M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"></path>
</svg>
<div class="wc-block-components-notice-banner__content">
BLOCK SUCCESS NOTICE - <?php echo wc_kses_notice( $notice['notice'] ); ?>
</div>
</div>
<?php endforeach; ?>

View File

@ -0,0 +1,154 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import {
cli,
BLOCK_THEME_SLUG,
BLOCK_CHILD_THEME_SLUG,
} from '@woocommerce/e2e-utils';
/**
* Internal dependencies
*/
import { CheckoutPage } from '../checkout/checkout.page';
import { REGULAR_PRICED_PRODUCT_NAME } from '../checkout/constants';
const test = base.extend< { checkoutPageObject: CheckoutPage } >( {
checkoutPageObject: async ( { page }, use ) => {
const pageObject = new CheckoutPage( {
page,
} );
await use( pageObject );
},
} );
test.describe( 'Shopper → Block Notice Templates', () => {
test.beforeEach( async ( { wpCliUtils, frontendUtils } ) => {
const cartShortcodeID = await wpCliUtils.getPostIDByTitle(
'Cart Shortcode'
);
await cli(
`npm run wp-env run tests-cli -- wp option update woocommerce_cart_page_id ${ cartShortcodeID }`
);
await frontendUtils.emptyCart();
await frontendUtils.goToShop();
await frontendUtils.addToCart( REGULAR_PRICED_PRODUCT_NAME );
} );
test.afterEach( async ( { wpCliUtils, frontendUtils } ) => {
const cartID = await wpCliUtils.getPostIDByTitle( 'Cart Shortcode' );
await cli(
`npm run wp-env run tests-cli -- wp option update woocommerce_cart_page_id ${ cartID }`
);
await frontendUtils.emptyCart();
} );
test( 'default templates are visible', async ( {
frontendUtils,
page,
} ) => {
await frontendUtils.goToCartShortcode();
await page.getByPlaceholder( 'Coupon code' ).fill( 'testcoupon' );
await page.getByRole( 'button', { name: 'Apply coupon' } ).click();
await expect(
page.getByText( 'Coupon code applied successfully.', {
exact: true,
} )
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .wc-block-components-notice-banner.is-success
await expect(
page.locator( '.wc-block-components-notice-banner.is-success' )
).toBeVisible();
await page.reload();
await page.getByPlaceholder( 'Coupon code' ).fill( 'testcoupon' );
await page.getByRole( 'button', { name: 'Apply coupon' } ).click();
await expect(
page.getByText( 'Coupon code already applied!', {
exact: true,
} )
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .wc-block-components-notice-banner.is-error
await expect(
page.locator( '.wc-block-components-notice-banner.is-error' )
).toBeVisible();
await page.getByLabel( 'Remove Polo from cart' ).click();
await expect(
page.getByText( 'Your cart is currently empty.', {
exact: true,
} )
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .wc-block-components-notice-banner.is-success
await expect(
page.locator( '.wc-block-components-notice-banner.is-success' )
).toBeVisible();
} );
test( 'custom templates are visible', async ( { frontendUtils, page } ) => {
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_CHILD_THEME_SLUG }`
);
await frontendUtils.goToCartShortcode();
await page.getByPlaceholder( 'Coupon code' ).fill( 'testcoupon' );
await page.getByRole( 'button', { name: 'Apply coupon' } ).click();
await expect(
page.getByText(
'BLOCK SUCCESS NOTICE - Coupon code applied successfully.'
)
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .wc-block-components-notice-banner.is-success
await expect(
page.locator( '.wc-block-components-notice-banner.is-success' )
).toBeVisible();
await page.reload();
await page.getByPlaceholder( 'Coupon code' ).fill( 'testcoupon' );
await page.getByRole( 'button', { name: 'Apply coupon' } ).click();
await expect(
page.getByText(
'BLOCK ERROR NOTICE - Coupon code already applied!'
)
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .wc-block-components-notice-banner.is-error
await expect(
page.locator( '.wc-block-components-notice-banner.is-error' )
).toBeVisible();
await page.getByLabel( 'Remove Polo from cart' ).click();
await expect(
page.getByText(
'BLOCK INFO NOTICE Your cart is currently empty.'
)
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .wc-block-components-notice-banner.is-success
await expect(
page.locator( '.wc-block-components-notice-banner.is-success' )
).toBeVisible();
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ BLOCK_THEME_SLUG }`
);
} );
} );

View File

@ -0,0 +1,151 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import {
cli,
CLASSIC_THEME_SLUG,
CLASSIC_CHILD_THEME_SLUG,
} from '@woocommerce/e2e-utils';
/**
* Internal dependencies
*/
import { CheckoutPage } from '../checkout/checkout.page';
import { REGULAR_PRICED_PRODUCT_NAME } from '../checkout/constants';
const test = base.extend< { checkoutPageObject: CheckoutPage } >( {
checkoutPageObject: async ( { page }, use ) => {
const pageObject = new CheckoutPage( {
page,
} );
await use( pageObject );
},
} );
test.describe( 'Shopper → Classic Notice Templates', () => {
test.beforeEach( async ( { wpCliUtils, frontendUtils } ) => {
const cartShortcodeID = await wpCliUtils.getPostIDByTitle(
'Cart Shortcode'
);
await cli(
`npm run wp-env run tests-cli -- wp option update woocommerce_cart_page_id ${ cartShortcodeID }`
);
await frontendUtils.emptyCart();
await frontendUtils.goToShop();
await frontendUtils.addToCart( REGULAR_PRICED_PRODUCT_NAME );
} );
test.afterEach( async ( { wpCliUtils, frontendUtils } ) => {
const cartID = await wpCliUtils.getPostIDByTitle( 'Cart Shortcode' );
await cli(
`npm run wp-env run tests-cli -- wp option update woocommerce_cart_page_id ${ cartID }`
);
await frontendUtils.emptyCart();
} );
test( 'default templates are visible', async ( {
frontendUtils,
page,
} ) => {
await frontendUtils.goToCartShortcode();
await page.getByPlaceholder( 'Coupon code' ).fill( 'testcoupon' );
await page.getByRole( 'button', { name: 'Apply coupon' } ).click();
await expect(
page.getByText( 'Coupon code applied successfully.', {
exact: true,
} )
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .woocommerce-notices-wrapper .woocommerce-message
await expect(
page.locator( '.woocommerce-notices-wrapper .woocommerce-message' )
).toBeVisible();
await page.reload();
await page.getByPlaceholder( 'Coupon code' ).fill( 'testcoupon' );
await page.getByRole( 'button', { name: 'Apply coupon' } ).click();
await expect(
page.getByText( 'Coupon code already applied!', { exact: true } )
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .woocommerce-notices-wrapper .woocommerce-message
await expect(
page.locator( '.woocommerce-notices-wrapper .woocommerce-error' )
).toBeVisible();
await page.getByLabel( 'Remove Polo from cart' ).click();
await expect(
page.getByText( 'Your cart is currently empty.', { exact: true } )
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .woocommerce-notices-wrapper .woocommerce-info
await expect(
page.locator( '.woocommerce-notices-wrapper .woocommerce-info' )
).toBeVisible();
} );
test( 'custom templates are visible', async ( { frontendUtils, page } ) => {
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ CLASSIC_CHILD_THEME_SLUG }`
);
await frontendUtils.goToCartShortcode();
await page.getByPlaceholder( 'Coupon code' ).fill( 'testcoupon' );
await page.getByRole( 'button', { name: 'Apply coupon' } ).click();
await expect(
page.getByText(
'CLASSIC SUCCESS NOTICE - Coupon code applied successfully.'
)
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .woocommerce-notices-wrapper .woocommerce-message
await expect(
page.locator( '.woocommerce-notices-wrapper .woocommerce-message' )
).toBeVisible();
await page.reload();
await page.getByPlaceholder( 'Coupon code' ).fill( 'testcoupon' );
await page.getByRole( 'button', { name: 'Apply coupon' } ).click();
await expect(
page.getByText(
'CLASSIC ERROR NOTICE - Coupon code already applied!'
)
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .woocommerce-notices-wrapper .woocommerce-message
await expect(
page.locator( '.woocommerce-notices-wrapper .woocommerce-error' )
).toBeVisible();
await page.getByLabel( 'Remove Polo from cart' ).click();
await expect(
page.getByText(
'CLASSIC INFO NOTICE - Your cart is currently empty.'
)
).toBeVisible();
// We're explicitly checking for the following CSS classes here:
// .woocommerce-notices-wrapper .woocommerce-info
await expect(
page.locator( '.woocommerce-notices-wrapper .woocommerce-info' )
).toBeVisible();
await cli(
`npm run wp-env run tests-cli -- wp theme activate ${ CLASSIC_THEME_SLUG }`
);
} );
} );

View File

@ -7,8 +7,10 @@ export const BLOCK_THEME_WITH_TEMPLATES_SLUG = 'theme-with-woo-templates';
export const BLOCK_THEME_WITH_TEMPLATES_NAME = 'Theme with Woo Templates';
export const BLOCK_THEME_SLUG = 'twentytwentyfour';
export const BLOCK_THEME_NAME = 'Twenty Twenty-Four';
export const BLOCK_CHILD_THEME_SLUG = `${ BLOCK_THEME_SLUG }-child`;
export const CLASSIC_THEME_SLUG = 'storefront';
export const CLASSIC_THEME_NAME = 'Storefront';
export const CLASSIC_CHILD_THEME_SLUG = `${ CLASSIC_THEME_SLUG }-child`;
export const BASE_URL = 'http://localhost:8889';
export const WP_ARTIFACTS_PATH =

View File

@ -56,6 +56,12 @@ export class FrontendUtils {
} );
}
async goToCartShortcode() {
await this.page.goto( '/cart-shortcode', {
waitUntil: 'commit',
} );
}
async goToMiniCart() {
await this.page.goto( '/mini-cart', {
waitUntil: 'domcontentloaded',

View File

@ -0,0 +1,5 @@
Significance: patch
Type: dev
Comment: This PR only adds e2e tests for teh notice templates. Therefore, a changelog entry is not needed.

View File

@ -26,6 +26,7 @@ if ( ! $notices ) {
$multiple = count( $notices ) > 1;
?>
<div class="wc-block-components-notice-banner is-error" role="alert" <?php echo $multiple ? '' : wc_get_notice_data_attr( $notices[0] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
<path d="M12 3.2c-4.8 0-8.8 3.9-8.8 8.8 0 4.8 3.9 8.8 8.8 8.8 4.8 0 8.8-3.9 8.8-8.8 0-4.8-4-8.8-8.8-8.8zm0 16c-4 0-7.2-3.3-7.2-7.2C4.8 8 8 4.8 12 4.8s7.2 3.3 7.2 7.2c0 4-3.2 7.2-7.2 7.2zM11 17h2v-6h-2v6zm0-8h2V7h-2v2z"></path>

View File

@ -24,6 +24,7 @@ if ( ! $notices ) {
}
?>
<ul class="woocommerce-error" role="alert">
<?php foreach ( $notices as $notice ) : ?>
<li<?php echo wc_get_notice_data_attr( $notice ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>

View File

@ -16,7 +16,7 @@
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
exit;
}
if ( ! $notices ) {

View File

@ -18,9 +18,11 @@
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! $notices ) {
return;
}
?>
<?php foreach ( $notices as $notice ) : ?>