Skip to content

Commit

Permalink
Merge pull request #14474 from newrelic/daily-release/Sep-5-2023-5_26
Browse files Browse the repository at this point in the history
daily-release/Sep-5-2023-5_26
  • Loading branch information
bradleycamacho authored Sep 5, 2023
2 parents 7ee55ae + 78695f6 commit 8e22bc0
Show file tree
Hide file tree
Showing 44 changed files with 1,943 additions and 274 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/webdriver.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: validate javascript functionality

on:
pull_request:
branches:
- main

env:
NODE_OPTIONS: '--max-old-space-size=4096'
CHOKIDAR_USEPOLLING: 1
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WEBDRIVER_ENV: main

jobs:
test:
name: webdriver test
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16

- name: Cache dependencies
id: yarn-cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: ${{ runner.os }}-node-modules-${{ hashFiles('**/yarn.lock') }}

- name: Install dependencies
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn install --frozen-lockfile

- uses: browser-actions/setup-chrome@latest
- run: chrome --version

- name: run webdriver on desktop
run: yarn webdriver-desktop

- name: run webdriver on mobile
run: yarn webdriver-mobile
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"@typescript-eslint/parser": "^5.10.0",
"add": "^2.0.6",
"adm-zip": "^0.5.1",
"assert": "^2.0.0",
"aws-sdk": "^2.827.0",
"babel-jest": "~27.4.6",
"babel-preset-gatsby": "^1.3.0",
Expand Down Expand Up @@ -138,6 +139,7 @@
"remark-parse": "8.0.3",
"remark-parse10": "npm:remark-parse@^10.0.1",
"remark-stringify": "^8.1.1",
"selenium-webdriver": "^4.12.0",
"simple-git": "^3.16.0",
"source-map-loader": "^3.0.1",
"sync-fetch": "^0.3.0",
Expand All @@ -157,6 +159,7 @@
"vfile": "^4.2.0",
"vfile-glob": "^1.0.0",
"vfile-reporter": "^6.0.1",
"webdriver-manager": "^12.1.9",
"yaml-loader": "^0.6.0",
"yarn": "^1.22.10"
},
Expand Down Expand Up @@ -213,7 +216,9 @@
"update-attribute-dictionary-json": "node scripts/actions/update-attribute-dictionary-json.mjs",
"validate-datasources": "node scripts/actions/check-datasource-ids.js",
"verify-install-page": "node scripts/verifyInstallPage.js",
"verify-mdx": "node scripts/verify_mdx.js"
"verify-mdx": "node scripts/verify_mdx.js",
"webdriver-desktop": "node scripts/actions/webdriver-desktop.mjs",
"webdriver-mobile": "node scripts/actions/webdriver-mobile.mjs"
},
"repository": {
"type": "git",
Expand Down
131 changes: 131 additions & 0 deletions scripts/actions/webdriver-desktop.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/* eslint-disable no-console */

/* this script is mostly mirrored in our scripted web browser
* synthetics check that runs on the production site.
* if you make updates, be sure to add them there as well.
* https://staging.onenr.io/037jbB4Akjy
*/

import assert from 'assert';
import { Builder, By, WebElement, until } from 'selenium-webdriver';
import { Options } from 'selenium-webdriver/chrome.js';

const options = new Options();
// options required for github action to run chromedriver properly
options.addArguments('no-sandbox');
options.addArguments('disable-dev-shm-usage');
options.addArguments('headless');

const TIMEOUT = 10000;

const waitForXPath = (xpath, timeout = TIMEOUT) =>
driver.wait(until.elementsLocated(By.xpath(xpath)), timeout);

const main = async () => {
// running on develop builds because the url is static
// github workflow triggers on PRs to main
const testUrl =
process.env.WEBDRIVER_ENV === 'main'
? 'https://docswebsitedevelop.gatsbyjs.io/'
: 'http://localhost:8000/';

await driver.get(testUrl + 'docs/mdx-test-page/');

// order here matters — some tests scroll the page
await collapserTest();
await searchTest();
await navTest();

await driver.get(testUrl);
await tileTest();

// this step isn't necessary in synthetics
await driver.quit();
};

const collapserTest = async () => {
const [firstCollapser, secondCollapser] = await waitForXPath(
'//h5[contains(@id, "collapser")]/ancestor::button'
);
const { y: initialTop } = await secondCollapser.getRect();
console.log('clicking first collapser');
await firstCollapser.click();
const { y: afterTop } = await secondCollapser.getRect();
assert.notEqual(
initialTop,
afterTop,
'clicking the first collapser did not change the position of the second collapser'
);
};

const navTest = async () => {
const releaseNotesXPath = '//div[@data-flip-id="Release notes"]';
const nextNodeXPath = `${releaseNotesXPath}/following-sibling::div[1]`;
const [releaseNotes] = await waitForXPath(releaseNotesXPath);
const [initialNextNode] = await waitForXPath(nextNodeXPath);
await driver.executeScript('arguments[0].scrollIntoView()', releaseNotes);
console.log('clicking Release Notes div');
await releaseNotes.click();
const [afterNextNode] = await waitForXPath(nextNodeXPath);
assert.notEqual(
initialNextNode,
afterNextNode,
'clicking Release Notes in the nav did not expand the Release Notes section'
);
};

const searchTest = async () => {
const [searchInput] = await waitForXPath('//aside//input');
console.log('clicking search input');
await searchInput.click();
const activeEl = await driver.executeScript('return document.activeElement');
assert(
WebElement.equals(activeEl, searchInput),
'clicking search input did not focus the page on the search input'
);
};

const tileTest = async () => {
const initialUrl = await driver.getCurrentUrl();
const [defaultViewTab] = await waitForXPath(
'//main//button[text()="Default view"]'
);
console.log('clicking Default view tab button');
await defaultViewTab.click();

// Added this xpath for the scroll function.
// for some reason, when running in headless mode the site
// header overlaps the tile we need to click
const [popularDocsSection] = await waitForXPath(
'//main//section//h3[text()="Popular docs"]'
);
const [firstDocTile] = await waitForXPath(
'//main//section//h3[text()="Popular docs"]/following::a'
);
// sometimes the cookie banner covers the doc tile so we need to scroll
await driver.executeScript(
'arguments[0].scrollIntoView()',
popularDocsSection
);
await firstDocTile.click();
await driver.wait(
until.stalenessOf(firstDocTile),
TIMEOUT,
'timed out waiting to navigate away from homepage'
);
// we can't check if the url equals the link href because of redirects,
// so we just have to make sure the URL has changed at all
const afterUrl = await driver.getCurrentUrl();
assert.notEqual(
initialUrl,
afterUrl,
`clicking homepage doc tile did not navigate as expected, URL did not change after clicking link`
);
};

const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();

main();
143 changes: 143 additions & 0 deletions scripts/actions/webdriver-mobile.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/* eslint-disable no-console */

/* this script is mostly mirrored in our scripted web browser
* synthetics check that runs on the production site.
* if you make updates, be sure to add them there as well.
* https://staging.onenr.io/0BoQDyBkDwy
*/

import assert from 'assert';
import { Builder, By, until } from 'selenium-webdriver';
import { Options } from 'selenium-webdriver/chrome.js';

const options = new Options().setMobileEmulation({
// uses mobile device names from chrome dev tools
deviceName: 'iPhone 12 Pro',
});
// options required for github action to run chromedriver properly
options.addArguments('no-sandbox');
options.addArguments('disable-dev-shm-usage');
options.addArguments('headless');

const TIMEOUT = 10000;

const waitForXPath = (xpath, timeout = TIMEOUT) =>
driver.wait(until.elementsLocated(By.xpath(xpath)), timeout);

const main = async () => {
// running on develop builds because the url is static
// github workflow triggers on PRs to main
const testUrl =
process.env.WEBDRIVER_ENV === 'main'
? 'https://docswebsitedevelop.gatsbyjs.io/'
: 'http://localhost:8000/';

await driver.get(testUrl + 'docs/mdx-test-page/');

// order here matters — some tests scroll the page
// `searchTest` opens the search modal, any tests on the same page
// that come afterwards would have to close the modal
await collapserTest();
await searchTest();

// there's no way to switch the homepage view on mobile with the UI so this is a bit of a hack
// in synthetics, this step is being done within the tileTest,
// but it's not registering in time here
await driver.executeScript(
"localStorage.setItem('docs-website/homepage-selected-view', 'default-view')"
);

await driver.get(testUrl);
await tileTest();
await navTest();

// this step isn't necessary in synthetics
await driver.quit();
};

const collapserTest = async () => {
const [firstCollapser, secondCollapser] = await waitForXPath(
'//h5[contains(@id, "collapser")]/ancestor::button'
);
const { y: initialTop } = await secondCollapser.getRect();
console.log('clicking first collapser');
await firstCollapser.click();
// sleep is required here on mobile to account for the click delay
await driver.sleep(500);
const { y: afterTop } = await secondCollapser.getRect();
assert.notEqual(
initialTop,
afterTop,
'clicking the first collapser did not change the position of the second collapser'
);
};

const navTest = async () => {
const releaseNotesXPath = '//div[@data-flip-id="Release notes"]';
const nextNodeXPath = `${releaseNotesXPath}/following-sibling::div[1]`;
const [hamburgerButton] = await waitForXPath(
'//header//button[contains(@aria-label, "Mobile")]'
);
await hamburgerButton.click();
await driver.sleep(500);
// nav on mobile is a new list, the desktop nav comes first in the DOM but is hidden
const [_desktopRN, releaseNotes] = await waitForXPath(releaseNotesXPath);
const [_desktopINN, initialNextNode] = await waitForXPath(nextNodeXPath);
await driver.executeScript('arguments[0].scrollIntoView()', releaseNotes);
console.log('clicking Release Notes div');
await releaseNotes.click();
const [_desktopANN, afterNextNode] = await waitForXPath(nextNodeXPath);
assert.notEqual(
initialNextNode,
afterNextNode,
'clicking Release Notes in the nav did not expand the Release Notes section'
);
};

const searchTest = async () => {
const [searchButton] = await waitForXPath('//a[contains(@href, "?q=")]');
console.log('clicking search button');
await searchButton.click();
// sleep is required here on mobile to account for the click delay
await driver.sleep(500);
const activeEl = await driver.executeScript('return document.activeElement');
assert.equal(
await activeEl.getTagName(),
'input',
'clicking search button did not focus the page on an input'
);
};

const tileTest = async () => {
const initialUrl = await driver.getCurrentUrl();
const [firstDocTile] = await waitForXPath(
'//main//section//h3[text()="Popular docs"]/following::a'
);
// sometimes the cookie banner covers the doc tile so we need to scroll
await driver.executeScript(
'arguments[0].scrollIntoView(false)',
firstDocTile
);
console.log('clicking doc tile');
await firstDocTile.click();
await driver.wait(
until.stalenessOf(firstDocTile),
TIMEOUT,
'timed out waiting to navigate away from homepage'
);
// we can't check if the url equals the link href because of redirects,
// so we just have to make sure the URL has changed at all
const afterUrl = await driver.getCurrentUrl();
assert.notEqual(
initialUrl,
afterUrl,
`clicking homepage doc tile did not navigate as expected, URL did not change after clicking link`
);
};

const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();

main();
Loading

0 comments on commit 8e22bc0

Please sign in to comment.