Skip to content

Commit

Permalink
Boost: Add e2e tests to Page Cache (#36501)
Browse files Browse the repository at this point in the history
* Add test for Page Cache meta visibility when module is inactive

* Add test for Page Cache header when module is inactive

* Add test for Page cache meta visibility when module is active

* Add permalink tests for page cache

* add changelog

* Add cache header test

* Update boost CLI to support page cache

* Fix test

* Update GH actions to include page cache tests

* Fix page cache tests

* Update file permissions in docker to be writable

* Add pnpm script to make files used by page cache writable

* Revert permission changes

* Fix prepare script

* Update script

* Update page cache test to check header value as well
  • Loading branch information
dilirity authored Apr 5, 2024
1 parent 9339d2b commit 26f9122
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 4 deletions.
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();
} );
} );

0 comments on commit 26f9122

Please sign in to comment.