Skip to content

Commit

Permalink
experimentation with playwright
Browse files Browse the repository at this point in the history
  • Loading branch information
vlkerag committed Jan 29, 2024
1 parent 89e3a6a commit b226a3b
Show file tree
Hide file tree
Showing 10 changed files with 1,716 additions and 2,299 deletions.
7 changes: 4 additions & 3 deletions monitoring/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
"dotenv": "^16.3.1",
"inquirer": "^8.2.6",
"playwright-aws-lambda": "^0.10.0",
"playwright-core": "^1.40.1",
"tslib": "^2.6.2",
"uuid": "^9.0.1"
"uuid": "^9.0.1",
"@guardian/consent-management-platform": "13.8.0",
"playwright-core": "^1.40.1"
},
"devDependencies": {
"@aws-sdk/client-lambda": "^3.490.0",
Expand All @@ -47,4 +48,4 @@
"overrides": {
"clone-deep": "4.0.1"
}
}
}
5 changes: 2 additions & 3 deletions monitoring/src/check-page/aus.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { checkTopAdHasLoaded, clickAcceptAllCookies } from '@guardian/consent-management-platform';
import type { Browser, BrowserContext, Page } from 'playwright-core';
import type { Config } from '../types';
import {
checkCMPIsNotVisible,
checkCMPIsOnPage,
checkCMPLoadingTimeAndVersion,
checkTopAdHasLoaded,
clickAcceptAllCookies,
loadPage,
log_info,
makeNewBrowser,
Expand Down Expand Up @@ -45,7 +44,7 @@ const checkPages = async (config: Config, url: string, nextUrl: string) => {
await loadPage(page, url);
await checkTopAdHasLoaded(page);

Check failure on line 45 in monitoring/src/check-page/aus.ts

View workflow job for this annotation

GitHub Actions / CI

Unsafe call of an `any` typed value
await checkCMPIsOnPage(page);
await clickAcceptAllCookies(config, page, 'Continue');
await clickAcceptAllCookies(page, 'Continue');

Check failure on line 47 in monitoring/src/check-page/aus.ts

View workflow job for this annotation

GitHub Actions / CI

Unsafe call of an `any` typed value
await checkCMPIsNotVisible(page);
await reloadPage(page);
await checkTopAdHasLoaded(page);

Check failure on line 50 in monitoring/src/check-page/aus.ts

View workflow job for this annotation

GitHub Actions / CI

Unsafe call of an `any` typed value
Expand Down
2 changes: 1 addition & 1 deletion monitoring/src/check-page/ccpa.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {checkTopAdHasLoaded} from '@guardian/consent-management-platform';
import type { Browser, BrowserContext, Page } from 'playwright-core';
import { ELEMENT_ID } from '../types';
import type { Config } from '../types';
import {
checkCMPIsNotVisible,
checkCMPIsOnPage,
checkCMPLoadingTimeAndVersion,
checkTopAdHasLoaded,
loadPage,
log_info,
makeNewBrowser,
Expand Down
70 changes: 1 addition & 69 deletions monitoring/src/check-page/common-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
PutMetricDataCommand
} from '@aws-sdk/client-cloudwatch';
import { launchChromium } from 'playwright-aws-lambda';
import type { Browser, BrowserContext, Page, Request } from 'playwright-core';
import type { Browser, BrowserContext, Page } from 'playwright-core';
import type { Config } from '../types';
import { ELEMENT_ID } from '../types';

Expand Down Expand Up @@ -73,24 +73,6 @@ export const makeNewPage = async (context: BrowserContext): Promise<Page> => {
return page;
};

/**
* This function waits for the page to load
* clicks the accept all button
*
* @param {Config} config
* @param {Page} page
* @param {string} textToPrintToConsole
*/
export const clickAcceptAllCookies = async (config: Config, page: Page, textToPrintToConsole: string) => {

log_info(`Clicking on "${textToPrintToConsole}" on CMP`);

const acceptAllButton = page.frameLocator(ELEMENT_ID.CMP_CONTAINER).locator(ELEMENT_ID.TCFV2_FIRST_LAYER_ACCEPT_ALL);
await acceptAllButton.click();

log_info(`Clicked on "${textToPrintToConsole}"`);
};

/**
* This function waits for the page to load
* clicks the manage cookies button to open the privacy settings panel
Expand Down Expand Up @@ -165,56 +147,6 @@ export const clickRejectAllSecondLayer = async (config: Config, page: Page) => {
log_info(`Clicking on reject all button: Complete`);
};

/**
* This function checks for interaction with GAM
* Using this after advice from Commercial to check that cookies were accepted as we otherwise do not interact with GAM
* This has to be adjusted if anything in the interaction with GAM changes or we stop using GAM
*
* @param {Page} page
* @return {*} {Promise<void>}
*/
export const checkTopAdHasLoaded = async (page: Page) => {
log_info(`Waiting for interaction with GAM: Start`);

const gamUrl = /https:\/\/securepubads.g.doubleclick.net\/gampad\/ads/;

const getEncodedParamsFromRequest = (
request: Request,
paramName: string,
): URLSearchParams | null => {
const url = new URL(request.url());
const param = url.searchParams.get(paramName);
if (!param) return null;
const paramDecoded = decodeURIComponent(param);
const searchParams = new URLSearchParams(paramDecoded);
return searchParams;
};

const assertOnSlotFromRequest = (request: Request, expectedSlot: string) => {
const isURL = request.url().match(gamUrl);
if (!isURL) return false;
const searchParams = getEncodedParamsFromRequest(request, 'prev_scp');
if (searchParams === null) return false;
const slot = searchParams.get('slot');
if (slot !== expectedSlot) return false;
return true;
};

const waitForGAMRequestForSlot = (page: Page, slotExpected: string) => {
return page.waitForRequest((request) =>
assertOnSlotFromRequest(request, slotExpected),
);
};

const gamRequestPromise = waitForGAMRequestForSlot(
page,
'top-above-nav',
);
await gamRequestPromise;

log_info(`Waiting for interaction with GAM: Complete`);
};

/**
* This function checks the ad is not on the page
* This checks that the top ad frame does not appear on the page
Expand Down
7 changes: 3 additions & 4 deletions monitoring/src/check-page/tcfv2.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { checkTopAdHasLoaded, clickAcceptAllCookies } from '@guardian/consent-management-platform';
import type { Browser, BrowserContext, Page } from 'playwright-core';
import type { Config } from '../types';
import {
Expand All @@ -6,10 +7,8 @@ import {
checkCMPLoadingTimeAndVersion,
checkPrivacySettingsPanelIsOpen,
checkTopAdDidNotLoad,
checkTopAdHasLoaded,
clearCookies,
clearLocalStorage,
clickAcceptAllCookies,
clickRejectAllSecondLayer,
clickSaveAndCloseSecondLayer,
loadPage,
Expand Down Expand Up @@ -45,7 +44,7 @@ const checkSubsequentPage = async (
]);
await reloadPage(page);
await checkTopAdDidNotLoad(page);
await clickAcceptAllCookies(config, page, "Yes I'm Happy");
await clickAcceptAllCookies( page, "Yes I'm Happy");

Check failure on line 47 in monitoring/src/check-page/tcfv2.ts

View workflow job for this annotation

GitHub Actions / CI

Unsafe call of an `any` typed value
await Promise.all([
checkCMPIsNotVisible(page),
checkTopAdHasLoaded(page),
Expand Down Expand Up @@ -126,7 +125,7 @@ export const firstLayerCheck = async function (

await checkTopAdDidNotLoad(page);

await clickAcceptAllCookies(config, page, "Yes I'm Happy");
await clickAcceptAllCookies( page, "Yes I'm Happy");

await checkCMPIsNotVisible(page);

Expand Down
11 changes: 8 additions & 3 deletions monitoring/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,11 @@
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b"
integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==

"@guardian/consent-management-platform@13.8.0":
version "13.8.0"
resolved "https://registry.yarnpkg.com/@guardian/consent-management-platform/-/consent-management-platform-13.8.0.tgz#60d1d319a2b438cdc8c6587ac20adf7b553815d3"
integrity sha512-J8YBXxpl/oGLmDGtjvkSwGmkaTJtnr/rxmYJAynaX0dkqopdDvG9REdbxMZBz3kugBpqHzhREzAk5Ut/uiyl8w==

"@guardian/eslint-config-typescript@^9.0.1":
version "9.0.1"
resolved "https://registry.yarnpkg.com/@guardian/eslint-config-typescript/-/eslint-config-typescript-9.0.1.tgz#42d63f6b4d0c0414d5a7a6a4da3b288fa53df709"
Expand Down Expand Up @@ -4725,9 +4730,9 @@ playwright-aws-lambda@^0.10.0:
lambdafs "^2.1.1"

playwright-core@^1.40.1:
version "1.40.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.40.1.tgz#442d15e86866a87d90d07af528e0afabe4c75c05"
integrity sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ==
version "1.41.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.41.1.tgz#9c152670010d9d6f970f34b68e3e935d3c487431"
integrity sha512-/KPO5DzXSMlxSX77wy+HihKGOunh3hqndhqeo/nMxfigiKzogn8kfL0ZBDu0L1RKgan5XHCPmn6zXd2NUJgjhg==

prelude-ls@^1.2.1:
version "1.2.1"
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,12 @@
"svelte": "~3.59.1",
"tslib": "^2.5.3",
"typescript": "~5.1.3",
"wait-for-expect": "^3"
"wait-for-expect": "^3",
"playwright-core": "^1.40.1"
},
"peerDependencies": {
"@guardian/libs": "^15.0.0"
}
"@guardian/libs": "^15.0.0",
"playwright-core": "^1.40.1"
},
"packageManager": "yarn@1.22.19"
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
import type { CMP, InitCMP, WillShowPrivacyMessage } from './types';
import { initVendorDataManager } from './vendorDataManager';

export {checkTopAdHasLoaded, clickAcceptAllCookies} from './testing/common-functions';

// Store some bits in the global scope for reuse, in case there's more
// than one instance of the CMP on the page in different scopes.
if (!isServerSide) {
Expand Down
78 changes: 78 additions & 0 deletions src/testing/common-functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { Page, Request } from 'playwright-core';

/**
* This function console logs an info message.
*
* @param {string} message
*/
const log_info = (message: string): void => {

Check warning on line 8 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
console.log(`(cmp monitoring) info: ${message}`);

Check warning on line 9 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
};


/**
* This function waits for the page to load
* clicks the accept all button
*
* @param {Page} page
* @param {string} textToPrintToConsole
*/
export const clickAcceptAllCookies = async (page: Page, textToPrintToConsole: string = "Accept All") => {

Check warning on line 20 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

Check warning on line 20 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function

log_info(`Clicking on "${textToPrintToConsole}" on CMP`);

Check warning on line 22 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

const acceptAllButton = page.frameLocator('[id*="sp_message_iframe"]').locator('button.sp_choice_type_ACCEPT_ALL');

Check warning on line 24 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
await acceptAllButton.click();

Check warning on line 25 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

log_info(`Clicked on "${textToPrintToConsole}"`);

Check warning on line 27 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
};

/**
* This function checks for interaction with GAM
* Using this after advice from Commercial to check that cookies were accepted as we otherwise do not interact with GAM
* This has to be adjusted if anything in the interaction with GAM changes or we stop using GAM
*
* @param {Page} page
* @return {*} {Promise<void>}
*/
export const checkTopAdHasLoaded = async (page: Page) => {

Check warning on line 38 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
log_info(`Waiting for interaction with GAM: Start`);

Check warning on line 39 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

const gamUrl = /https:\/\/securepubads.g.doubleclick.net\/gampad\/ads/;

Check warning on line 41 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

const getEncodedParamsFromRequest = (

Check warning on line 43 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
request: Request,
paramName: string,
): URLSearchParams | null => {
const url = new URL(request.url());

Check warning on line 47 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
const param = url.searchParams.get(paramName);

Check warning on line 48 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
if (!param) return null;

Check warning on line 49 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 49 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 49 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
const paramDecoded = decodeURIComponent(param);

Check warning on line 50 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
const searchParams = new URLSearchParams(paramDecoded);

Check warning on line 51 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
return searchParams;

Check warning on line 52 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
};

Check warning on line 53 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

const assertOnSlotFromRequest = (request: Request, expectedSlot: string) => {

Check warning on line 55 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
const isURL = request.url().match(gamUrl);

Check warning on line 56 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
if (!isURL) return false;

Check warning on line 57 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 57 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 57 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
const searchParams = getEncodedParamsFromRequest(request, 'prev_scp');

Check warning on line 58 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
if (searchParams === null) return false;

Check warning on line 59 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 59 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 59 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
const slot = searchParams.get('slot');

Check warning on line 60 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
if (slot !== expectedSlot) return false;

Check warning on line 61 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 61 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 61 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
return true;

Check warning on line 62 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
};

Check warning on line 63 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

const waitForGAMRequestForSlot = (page: Page, slotExpected: string) => {

Check warning on line 65 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
return page.waitForRequest((request) =>

Check warning on line 66 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
assertOnSlotFromRequest(request, slotExpected),

Check warning on line 67 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
);

Check warning on line 68 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
};

Check warning on line 69 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

const gamRequestPromise = waitForGAMRequestForSlot(
page,
'top-above-nav',
);

Check warning on line 74 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
await gamRequestPromise;

Check warning on line 75 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

log_info(`Waiting for interaction with GAM: Complete`);

Check warning on line 77 in src/testing/common-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
};
Loading

1 comment on commit b226a3b

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 83.17% 257/309
🟡 Branches 77.42% 96/124
🟢 Functions 81.82% 63/77
🟢 Lines 83.84% 249/297

Test suite run success

328 tests passing in 16 suites.

Report generated by 🧪jest coverage report action from b226a3b

Please sign in to comment.