Skip to content

Commit

Permalink
Merge pull request #64 from wp-media/test/57-beacon-script-captures-r…
Browse files Browse the repository at this point in the history
…ight-image-on-template

Closes #57: Test that beacon script captures right image on template
  • Loading branch information
Mai-Saad authored Apr 5, 2024
2 parents d81e89e + da3af62 commit 52a88c4
Show file tree
Hide file tree
Showing 9 changed files with 348 additions and 6 deletions.
81 changes: 79 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"test:delayjs:flatsome": "THEME=flatsome $npm_package_config_testCommand --tags @delayjs",
"test:delayjs:divi": "THEME=Divi $npm_package_config_testCommand --tags @delayjs",
"test:delayjs:astra": "THEME=astra $npm_package_config_testCommand --tags @delayjs",
"test:lcp": "$npm_package_config_testCommand --tags @lcp",
"test:test": "$npm_package_config_testCommand --tags @test",
"wp-env": "wp-env"
},
Expand Down Expand Up @@ -51,7 +52,9 @@
},
"homepage": "https://github.com/wp-media/wp-rocket-e2e#readme",
"dependencies": {
"@types/axios": "^0.14.0",
"@types/ssh2": "^1.11.13",
"axios": "^1.6.8",
"backstopjs": "^6.2.2",
"json-diff": "^1.0.6",
"node-ssh": "^13.1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/features/delay-js.feature
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Feature: No Regression with delayjs script udpate
And I save settings 'cache' 'mobileDeviceSeparateCache'
When theme is activated
And I log out
And visit page '' in mobile view
And I visit '' in mobile view
And expand mobile menu
And I click on link
Then page navigated to the new page 'about-us'
Expand Down
35 changes: 35 additions & 0 deletions src/features/lcp-beacon-script.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@lcp @setup
Feature: Beacon script captures the right images.

Background:
Given I am logged in
And plugin is installed 'new_release'
And plugin is activated

Scenario: Beacon captures expected images in desktop
When I log out
And I visit the following urls in 'desktop'
| path | atfs |
| lcp_bg_inline_template | /wp-content/rocket-test-data/images/lcp/testjpeg.jpeg |
| lcp_bg_samestyle_template | wp-content/rocket-test-data/images/lcp/testjpg.jpg |
| lcp_img_loadedbydynamicjs_template | http://www.google.com/intl/en_com/images/logo_plain.png |
| lcp_img_loadedbyjs_template | /test.png, https://new.rocketlabsqa.ovh/wp-content/rocket-test-data/images/istockphoto-1184692500-612x612.webp |
| lcp_with_space_after_title | /wp-content/rocket-test-data/images/test_inline2.jpeg |
| lcp_test_template | /wp-content/rocket-test-data/images/lipsum_logo.jpg |
| lcp_bg_responsive_webkit_template | /wp-content/rocket-test-data/image/test3.webp, /wp-content/rocket-test-data/images/lcp/testwebp.webp |
| lcp_regular_image_template | /test.png, /wp-content/rocket-test-data/images/test_inline2.jpeg, /wp-content/rocket-test-data/images/Przechwytywanie.PNG, /wp-content/rocket-test-data/images/file_example_JPG_100kB.jpg |
Then lcp and atf should be as expected in 'desktop'

Scenario: Beacon captures expected images in mobile
When I log out
And I visit the following urls in 'mobile'
| path | atfs |
| lcp_bg_inline_template | /wp-content/rocket-test-data/images/test_inline2.jpeg |
| lcp_bg_samestyle_template | https://new.rocketlabsqa.ovh/wp-content/rocket-test-data/images/lcp/testavif.avif |
| lcp_img_loadedbydynamicjs_template | http://www.google.com/intl/en_com/images/logo_plain.png |
| lcp_img_loadedbyjs_template | /test.png, https://new.rocketlabsqa.ovh/wp-content/rocket-test-data/images/istockphoto-1184692500-612x612.webp |
| lcp_with_space_after_title | https://new.rocketlabsqa.ovh/wp-content/rocket-test-data/images/test_inline2.jpeg |
| lcp_test_template | /wp-content/rocket-test-data/images/test_internal2.jpg, https://new.rocketlabsqa.ovh/wp-content/rocket-test-data/images/lipsum_logo.jpg |
| lcp_bg_responsive_webkit_template | https://rocketlabsqa.ovh/wp-content/rocket-test-data/images/fixtheissue.jpg |
| lcp_regular_image_template | /test.png, /wp-content/rocket-test-data/images/test_inline2.jpeg, /wp-content/rocket-test-data/images/lcp/testPng.png, /wp-content/rocket-test-data/images/Przechwytywanie.PNG, /wp-content/rocket-test-data/images/file_example_JPG_100kB.jpg, /wp-content/rocket-test-data/images/img_nature.jpg, /wp-content/rocket-test-data/images/mountain.webp |
Then lcp and atf should be as expected in 'mobile'
2 changes: 1 addition & 1 deletion src/support/steps/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ When('theme is activated', async function (this:ICustomWorld) {
/**
* Executes the step visit a page in mobile view.
*/
When('visit page {string} in mobile view', async function (this:ICustomWorld, page) {
When('I visit {string} in mobile view', async function (this:ICustomWorld, page) {
await this.page.setViewportSize({
width: 500,
height: 480,
Expand Down
130 changes: 130 additions & 0 deletions src/support/steps/lcp-beacon-script.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/**
* @fileoverview
* This module contains Cucumber step definitions using Playwright for deleting the WP Rocket plugin.
* It includes steps for confirming the deletion, navigating to the plugins page, deactivating the plugin,
* handling deactivation modal, initiating the deletion process, and asserting successful deletion.
*
* @requires {@link ../../common/custom-world}
* @requires {@link @playwright/test}
* @requires {@link @cucumber/cucumber}
*/
import { ICustomWorld } from "../../common/custom-world";
import { expect } from "@playwright/test";
import { Given, Then } from "@cucumber/cucumber";
import { LcpDataTable, LcpData, Row } from "../../../utils/types";
import axios from 'axios';
import { dbQuery, getWPTablePrefix } from "../../../utils/commands";
import { extractFromStdout } from "../../../utils/helpers";
import { WP_BASE_URL } from '../../../config/wp.config';

let data: LcpDataTable[],
truthy: boolean = true,
failMsg: string = "";

const [actual, expected]: [LcpData, LcpData] = [{}, {}];

/**
* Executes step to visit page based on the form factor(desktop/mobile) and get the LCP/ATF data from DB.
*/
Given('I visit the following urls in {string}', async function (this: ICustomWorld, formFactor: string, dataTable) {
let sql: string,
result: string,
resultFromStdout: Row[];

// Set page to be visited in mobile.
if ( formFactor === 'mobile' ) {
await this.page.setViewportSize({
width: 360,
height: 640,
});
}

data = dataTable.rows();

const tablePrefix: string = await getWPTablePrefix();

// Visit page.
for (const row of data) {
const url: string = `${WP_BASE_URL}/${row[0]}`;
await this.utils.visitPage(row[0]);
// Wait for 2 seconds before fetching from DB.
await this.page.waitForTimeout(2000);

// Get the LCP/ATF from the DB
sql = `SELECT lcp, viewport FROM ${tablePrefix}wpr_above_the_fold WHERE url LIKE "%${row[0]}%"`;
result = await dbQuery(sql);
resultFromStdout = await extractFromStdout(result);

// Populate the actual data.
actual[row[0]] = {
url: url,
lcp: resultFromStdout[0].lcp,
viewport: resultFromStdout[0].viewport
}
}
});

/**
* Executes the step to assert that LCP & ATF should be as expected.
*/
Then('lcp and atf should be as expected in {string}', async function (this: ICustomWorld, formFactor: string) {
let apiUrl: string;

// Get the LCP from the PSI
for (const row of data) {
const url: string = `${WP_BASE_URL}/${row[0]}`;
apiUrl = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${encodeURIComponent(url+'?nowprocket')}/&fields=lighthouseResult.audits&strategy=${formFactor}`;

try {
const response = await axios.get(apiUrl);
const data = response.data;
const lcp: string = data.lighthouseResult.audits['prioritize-lcp-image'] && data.lighthouseResult.audits['prioritize-lcp-image'].details ? data.lighthouseResult.audits['prioritize-lcp-image'].details.debugData.initiatorPath[0].url : '';

// Populate the expected data.
expected[row[0]] = {
url: url,
lcp: lcp,
viewport: row[1]
}
} catch (error) {
console.error(`Error fetching PageSpeed Insight for ${url}:`, error);
}
}

// Make assertions.
for (const key in actual) {
if (Object.hasOwnProperty.call(actual, key)) {
const [url, actualLcp, expectedLcp, actualViewport, expectedViewport] = [actual[key].url, actual[key].lcp, expected[key].lcp, actual[key].viewport, expected[key].viewport];

// Check if expected lcp is present in actual lcp.
if (!actualLcp.includes(expectedLcp)) {
truthy = false;
failMsg += `Expected LCP - ${expectedLcp} for ${url} is not present in actual - ${actualLcp}\n\n\n`;
}

// Cater for multiple expected viewport candidates.
if (expectedViewport.includes(',')) {
const viewports = expectedViewport.split(',').map(item => item.trim());

for (const viewport of viewports) {
if (!actualViewport.includes(viewport)) {
truthy = false;
failMsg += `Expected Viewport - ${viewport} for ${url} is not present in actual - ${actualViewport}\n\n\n`;
}
}
// Treat single viewport candidate.
} else{
if (!actualViewport.includes(expectedViewport)) {
truthy = false;
failMsg += `Expected Viewport - ${expectedViewport} for ${url} is not present in actual - ${actualViewport}\n\n\n`;
}
}
}
}

if ( failMsg !== '' ) {
console.log(failMsg);
}

expect(truthy, failMsg).toBeTruthy();
});
52 changes: 52 additions & 0 deletions utils/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,4 +317,56 @@ export async function generateUsers(users: Array<{name: string, email: string, r
})
}

/**
* Wraps a command with the appropriate prefix for SSH.
*
* @param {string} command - The command to be wrapped.
* @returns {string} - The wrapped command.
*/
function wrapSSHPrefix(command: string): string {
const cwd = getWPDir(configurations);

if(configurations.type === ServerType.external) {
return `ssh ${configurations.ssh.username}@${configurations.ssh.address} -i ${configurations.ssh.key} -t "cd ${cwd} && ${command}"`;
}
}

/**
* Performs a sql query using wp cli.
*
* @param {string} sql SQL Query.
* @return {Promise<string>} A Promise that resolves when the query is executed.
*/
export async function dbQuery(sql: string): Promise<string> {
sql = sql.replaceAll('"', '\\"');

const command = wrapSSHPrefix(`wp db query '${sql}'`);
const result = exec(command, { silent: true });

if (result.code === 1) {
return '';
}

return result.stdout;
}

/**
* Gets the WordPress Table Prefix.
*
* @return {Promise<string>} A Promise that resolves when the query is executed.
*/
export async function getWPTablePrefix(): Promise<string> {
const command = wrapSSHPrefix(`wp config get table_prefix`);
const result = exec(command, { silent: true });

if (result.code === 1) {
return '';
}

let tablePrefix: string = result.stdout;
tablePrefix = tablePrefix.replace(/\r?\n/g, "");

return tablePrefix;
}

export default wp;
Loading

0 comments on commit 52a88c4

Please sign in to comment.