Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Boost: Add e2e tests to Page Cache #36501

Merged
merged 20 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/files/e2e-tests/e2e-matrix.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ const projects = [
suite: '',
buildGroup: 'jetpack-boost',
},
{
project: 'Jetpack Boost - Page Cache',
path: 'projects/plugins/boost/tests/e2e',
testArgs: [ 'specs/page-cache', '--retries=1' ],
targets: [ 'plugins/boost' ],
suite: '',
buildGroup: 'jetpack-boost',
},
{
project: 'Jetpack Boost - Concatenate JS/CSS',
path: 'projects/plugins/boost/tests/e2e',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const Meta = () => {

return (
pageCache && (
<div className={ styles.wrapper }>
<div className={ styles.wrapper } data-testid="page-cache-meta">
<div className={ styles.head }>
<div className={ styles.summary }>{ getSummary() }</div>
<div className={ styles.actions }>
Expand Down
21 changes: 20 additions & 1 deletion projects/plugins/boost/app/lib/class-cli.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

use Automattic\Jetpack_Boost\Data_Sync\Getting_Started_Entry;
use Automattic\Jetpack_Boost\Jetpack_Boost;
use Automattic\Jetpack_Boost\Modules\Optimizations\Page_Cache\Garbage_Collection;
use Automattic\Jetpack_Boost\Modules\Optimizations\Page_Cache\Page_Cache_Setup;
use Automattic\Jetpack_Boost\Modules\Optimizations\Page_Cache\Pre_WordPress\Boost_Cache_Settings;

/**
* Control your local Jetpack Boost installation.
Expand All @@ -24,7 +27,7 @@ class CLI {
*/
private $jetpack_boost;

const MAKE_E2E_TESTS_WORK_MODULES = array( 'critical_css', 'render_blocking_js', 'minify_js', 'minify_css', 'image_cdn', 'image_guide' );
const MAKE_E2E_TESTS_WORK_MODULES = array( 'critical_css', 'render_blocking_js', 'page_cache', 'minify_js', 'minify_css', 'image_cdn', 'image_guide' );

/**
* CLI constructor.
Expand Down Expand Up @@ -113,6 +116,22 @@ public function getting_started( $args ) {
private function set_module_status( $module_slug, $status ) {
( new Status( $module_slug ) )->update( $status );

if ( $module_slug === 'page_cache' && $status ) {
$setup_result = Page_Cache_Setup::run_setup();
if ( is_wp_error( $setup_result ) ) {
\WP_CLI::error(
sprintf(
/* translators: %s refers to the error code */
__( 'Setup: %s', 'jetpack-boost' ),
$setup_result->get_error_code()
)
);
}

Garbage_Collection::activate();
Boost_Cache_Settings::get_instance()->set( array( 'enabled' => true ) );
}

$status_label = $status ? __( 'activated', 'jetpack-boost' ) : __( 'deactivated', 'jetpack-boost' );

/* translators: The %1$s refers to the module slug, %2$s refers to the module state (either activated or deactivated)*/
Expand Down
4 changes: 4 additions & 0 deletions projects/plugins/boost/changelog/add-more-e2e-tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: added

Add end to end tests for modules.
1 change: 1 addition & 0 deletions projects/plugins/boost/tests/e2e/lib/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as JetpackBoostPage } from './wp-admin/JetpackBoostPage.js';
export { default as PermalinksPage } from './wp-admin/PermalinksPage.js';
export { default as FirstPostPage } from './frontend/FirstPostPage.js';
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,21 @@ export default class JetpackBoostPage extends WpPage {
return this.waitForElementToBeVisible( selector );
}

async isThePageCacheMetaInformationVisible() {
const selector = '[data-testid="page-cache-meta"]';
return this.page.isVisible( selector );
}

async waitForPageCacheMetaInfoVisibility() {
const selector = '[data-testid="page-cache-meta"]';
return this.waitForElementToBeVisible( selector, 3 * 60 * 1000 );
}

async waitForPageCachePermalinksErrorVisibility() {
const selector = '[data-testid="module-page_cache"] >> text=Permalink settings must be updated';
return this.waitForElementToBeVisible( selector, 3 * 60 * 1000 );
}

async isConcatenateJsMetaVisible() {
const selector = '[data-testid="meta-minify_js_excludes"]';
return this.page.isVisible( selector );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import WpPage from 'jetpack-e2e-commons/pages/wp-page.js';
import { resolveSiteUrl } from 'jetpack-e2e-commons/helpers/utils-helper.js';

export default class PermalinksPage extends WpPage {
constructor( page ) {
const url = `${ resolveSiteUrl() }/wp-admin/options-permalink.php`;
super( page, { expectedSelectors: [ '.permalink-structure' ], url } );
}

async usePlainStructure() {
const selector = '[id="permalink-input-plain"]';
await this.page.click( selector );
await this.page.click( '[id="submit"]' );
await this.waitForLoad();
}

async useDayNameStructure() {
const selector = '[id="permalink-input-day-name"]';
await this.page.click( selector );
await this.page.click( '[id="submit"]' );
await this.waitForLoad();
}
}
5 changes: 3 additions & 2 deletions projects/plugins/boost/tests/e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
"clean": "rm -rf output",
"config:decrypt": "openssl enc -md sha1 -aes-256-cbc -d -pass env:CONFIG_KEY -in ./node_modules/jetpack-e2e-commons/config/encrypted.enc -out ./config/local.cjs",
"distclean": "rm -rf node_modules",
"env:up": "e2e-env start --activate-plugins boost",
"env:up": "e2e-env start --activate-plugins boost && pnpm run prepare:e2e",
"env:down": "e2e-env stop",
"env:reset": "e2e-env reset --activate-plugins boost",
"tunnel:up": "tunnel up",
"tunnel:reset": "tunnel reset",
"tunnel:down": "tunnel down",
"pretest:run": "pnpm run clean",
"test:run": ". ./node_modules/jetpack-e2e-commons/bin/app-password.sh && playwright install && NODE_CONFIG_DIR='./config' ALLURE_RESULTS_DIR=./output/allure-results NODE_PATH=\"$PWD/node_modules\" playwright test --config=./playwright.config.mjs"
"test:run": ". ./node_modules/jetpack-e2e-commons/bin/app-password.sh && playwright install && NODE_CONFIG_DIR='./config' ALLURE_RESULTS_DIR=./output/allure-results NODE_PATH=\"$PWD/node_modules\" playwright test --config=./playwright.config.mjs",
"prepare:e2e": "pnpm jetpack docker --type e2e --name t1 exec-silent -- chown -R www-data .htaccess wp-config.php wp-content"
},
"devDependencies": {
"@playwright/test": "1.39.0",
Expand Down
145 changes: 145 additions & 0 deletions projects/plugins/boost/tests/e2e/specs/page-cache/page-cache.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { test, expect } from 'jetpack-e2e-commons/fixtures/base-test.js';
import { boostPrerequisitesBuilder } from '../../lib/env/prerequisites.js';
import { JetpackBoostPage, PermalinksPage } from '../../lib/pages/index.js';
import { PostFrontendPage } from 'jetpack-e2e-commons/pages/index.js';
import { WPLoginPage } from 'jetpack-e2e-commons/pages/wp-admin/index.js';
import playwrightConfig from 'jetpack-e2e-commons/playwright.config.mjs';
import { resolveSiteUrl } from 'jetpack-e2e-commons/helpers/utils-helper.js';

test.describe( 'Cache module', () => {
let page;

test.beforeAll( async ( { browser } ) => {
page = await browser.newPage( playwrightConfig.use );
await boostPrerequisitesBuilder( page )
.withInactiveModules( [
'page_cache', // Make sure it's inactive.
] )
.withCleanEnv()
.withConnection( true )
.build();

// Page Cache needs a pretty permalink structure to work properly.
const permalinksPage = await PermalinksPage.visit( page );
await permalinksPage.useDayNameStructure();
} );

// Disabling the module before each test, because each test will decide if
// it needs the module enabled or not.
test.beforeEach( async () => {
await boostPrerequisitesBuilder( page ).withInactiveModules( [ 'page_cache' ] ).build();
} );

test.afterAll( async () => {
// Reset the environment for any other tests.
await boostPrerequisitesBuilder( page ).withCleanEnv().withConnection( true ).build();
await page.close();
} );

test( 'No Page Cache meta information should show on the admin when the module is inactive', async () => {
const jetpackBoostPage = await JetpackBoostPage.visit( page );
expect(
await jetpackBoostPage.isThePageCacheMetaInformationVisible(),
'Page Cache meta information should not be visible'
).toBeFalsy();
} );

// Make sure there's no cache header when module is disabled.
test( 'Page Cache header should not be present when module is inactive', async ( {
browser,
} ) => {
const newPage = await browser.newPage( playwrightConfig.use );
const postFrontPage = await PostFrontendPage.visit( newPage );
await postFrontPage.logout();

newPage.on( 'response', response => {
if ( response.url().replace( /\/$/, '' ) !== resolveSiteUrl().replace( /\/$/, '' ) ) {
return;
}

expect(
response.headers().hasOwnProperty( 'X-Jetpack-Boost-Cache'.toLowerCase() ),
'Page Cache header should not be present'
).toBeFalsy();
} );

await PostFrontendPage.visit( newPage );

await newPage.close();
} );

// Make sure there's an error message when trying to enable Page Cache with plain permalinks.
test( 'Enabling Page Cache should show error notice when plain permalinks are enabled', async () => {
const loginPage = await WPLoginPage.visit( page );
await loginPage.login();

const permalinksPage = await PermalinksPage.visit( page );
await permalinksPage.usePlainStructure();

const jetpackBoostPage = await JetpackBoostPage.visit( page );
await jetpackBoostPage.toggleModule( 'page_cache' );
expect(
await jetpackBoostPage.waitForPageCachePermalinksErrorVisibility(),
'Page Cache should show permalink error message when using plain permalink structure'
).toBeTruthy();
} );

// Make sure Page Cache meta is visible when module is active.
test( 'Page Cache meta information should show on the admin when the module is active', async () => {
const permalinksPage = await PermalinksPage.visit( page );
await permalinksPage.useDayNameStructure();

// Activate the module.
const jetpackBoostPage = await JetpackBoostPage.visit( page );
await jetpackBoostPage.toggleModule( 'page_cache' );

expect(
await jetpackBoostPage.waitForPageCacheMetaInfoVisibility(),
'Page Cache meta information should be visible'
).toBeTruthy();
} );

// Make sure there's a cache header when module is enabled.
test( 'Page Cache header should be present when module is active', async ( { browser } ) => {
await boostPrerequisitesBuilder( page ).withActiveModules( [ 'page_cache' ] ).build();

const newPage = await browser.newPage( playwrightConfig.use );
const postFrontPage = await PostFrontendPage.visit( newPage );
await postFrontPage.logout();

let totalVisits = 0;

newPage.on( 'response', response => {
if ( response.url().replace( /\/$/, '' ) !== resolveSiteUrl().replace( /\/$/, '' ) ) {
return;
}

totalVisits++;

const responseHeaders = response.headers();
const cacheHeaderName = 'X-Jetpack-Boost-Cache'.toLowerCase();

// First visit should always be a miss.
if ( totalVisits === 1 ) {
expect(
responseHeaders.hasOwnProperty( cacheHeaderName ) &&
responseHeaders[ cacheHeaderName ] === 'miss',
'Page Cache header should be set to miss on first visit.'
).toBeTruthy();
} else {
expect(
responseHeaders.hasOwnProperty( cacheHeaderName ) &&
responseHeaders[ cacheHeaderName ] === 'hit',
'Page Cache header should be set to hit on second visit.'
).toBeTruthy();
}
} );

await PostFrontendPage.visit( newPage );

// Visit again to make sure the cache is hit.
await PostFrontendPage.visit( newPage );

await newPage.close();
} );
} );
Loading