Path: blob/master/proxyServiceValidator.js
5154 views
// This file is solely used for the automatically run GitHub job, which checks to1// see if all HU LTS code is working properly (at least on an Ubuntu machine).23const axios = require('axios');4const puppeteer = require('puppeteer');56const testEndpoint = async (url) => {7try {8const response = await axios.get(url);9return response.status === 200;10} catch (error) {11console.error(`Error ${error.code} while testing ${url}:`, error.message);12return false;13}14};1516const generateUrl = async (omniboxId, urlPath, errorPrefix = 'failure') => {17// Wait for the document to load before getting the omnibox.18await new Promise((resolve) => {19const waitLonger = () => setTimeout(resolve, 5000);20if (document.readyState === 'complete') waitLonger();21else window.addEventListener('load', waitLonger);22});2324let omnibox = document.getElementById(omniboxId);25omnibox = omnibox && omnibox.querySelector('input[type=text]');2627if (omnibox) {28try {29// Send an artificial input to the omnibox. The omnibox will create30// a proxy URL and leave it as the input value in response.31omnibox.value = urlPath;32const generateInput = async () => {33await omnibox.dispatchEvent(34new KeyboardEvent('keydown', { code: 'Validator Test' })35);36};37/* Keep trying to send an input signal every second until it works.38* Implemented to account for a condition where the document has39* finished loading, but the event handler for DOMContentLoaded has40* not finished executing its script to listen for artificial inputs.41*/42await generateInput();43const inputInterval = setInterval(generateInput, 1000),44resolveHandler = (resolve) => () => {45clearInterval(inputInterval);46resolve(omnibox.value);47},48// Wait up to 40 seconds for the omnibox to finish updating.49loadUrl = new Promise((resolve) => {50if (omnibox.value !== urlPath) resolveHandler(resolve)();51else omnibox.addEventListener('change', resolveHandler(resolve));52}),53timeout = new Promise((resolve) => {54setTimeout(resolveHandler(resolve), 40000);55}),56// Return the proxy URL that the omnibox left here.57generatedUrl = await Promise.race([loadUrl, timeout]);58return generatedUrl !== urlPath ? generatedUrl : errorPrefix;59} catch (e) {60return errorPrefix + ': ' + e.message;61}62} else {63return errorPrefix + ': omnibox not defined';64}65};6667const testGeneratedUrl = async (url, headers) => {68try {69console.log('Testing generated URL:', url);7071const response = await axios.get(url, { headers });72console.log(`Response status for ${url}:`, response.status);73return response.status === 200;74} catch (error) {75console.error(`Error while testing generated URL ${url}:`, error.message);76return false;77}78};7980const testServerResponse = async () => {81const endpoints = [82'http://localhost:8080/',83'http://localhost:8080/test-404',84'http://localhost:8080/browsing',85'http://localhost:8080/physics',86'http://localhost:8080/networking',87'http://localhost:8080/documentation',88'http://localhost:8080/questions',89'http://localhost:8080/s',90'http://localhost:8080/credits',91'http://localhost:8080/terms',92'http://localhost:8080/books',93'http://localhost:8080/dictionary',94'http://localhost:8080/catalogue',95'http://localhost:8080/textbook',96'http://localhost:8080/math',97'http://localhost:8080/wiki',98'http://localhost:8080/software',99'http://localhost:8080/whiteboard',100'http://localhost:8080/notebook',101'http://localhost:8080/assets/js/card.js',102'http://localhost:8080/assets/js/common-1735118314.js',103'http://localhost:8080/assets/js/csel.js',104'http://localhost:8080/assets/js/register-sw.js',105'http://localhost:8080/assets/json/emu-nav.json',106'http://localhost:8080/assets/json/blacklist.json',107'http://localhost:8080/assets/json/emulib-nav.json',108'http://localhost:8080/assets/json/flash-nav.json',109'http://localhost:8080/assets/json/h5-nav.json',110'http://localhost:8080/assets/json/links.json',111'http://localhost:8080/gmt/index.js',112'http://localhost:8080/gmt/worker.js',113'http://localhost:8080/epoch/index.mjs',114'http://localhost:8080/worker/working.all.js',115'http://localhost:8080/worker/working.sw.js',116'http://localhost:8080/worker/working.sw-blacklist.js',117'http://localhost:8080/network/networking.bundle.js',118'http://localhost:8080/network/networking.sw.js',119'http://localhost:8080/network/networking.config.js',120'http://localhost:8080/network/workerware.js',121'http://localhost:8080/network/WWError.js',122];123124125const results = await Promise.all(endpoints.map(testEndpoint));126const allPassed = results.every((result) => result);127128if (allPassed) {129console.log('All endpoints responded with status code 200. Test passed.');130await testCommonJSOnPage();131} else {132console.error(133'One or more endpoints failed to respond with status code 200. Test failed.'134);135process.exitCode = 1;136}137};138139const testCommonJSOnPage = async () => {140const browser = await puppeteer.launch({141args: [142'--enable-features=NetworkService',143'--enable-features=ServiceWorker',144'--enable-features=InsecureOrigins',145],146headless: true,147ignoreHTTPSErrors: true,148});149const page = await browser.newPage();150151try {152const getHeaders = async () => {153const headers = {};154155headers['User-Agent'] = await page.evaluate(() => navigator.userAgent);156headers['Referer'] = await page.evaluate(() => window.location.href);157158return headers;159};160161const testRammerhead = async () => {162const omniboxId = 'pr-rh',163urlPath = 'example.com';164await page.goto('http://localhost:8080/physics');165const generatedUrl = await page.evaluate(generateUrl, omniboxId, urlPath);166const testResults = {};167testResults.rammerhead = generatedUrl;168169console.log('Rammerhead test results:', testResults);170171const headers = await getHeaders();172const rammerheadTestPassed =173testResults.rammerhead !== 'failure' &&174(await testGeneratedUrl(testResults.rammerhead, headers));175176console.log(177`Rammerhead test result: ${178rammerheadTestPassed ? 'success' : 'failure'179}`180);181182return rammerheadTestPassed;183};184185/*186187xx188xx xx189xxx xx190xxx xx191xxx xx192xxx xx193xx xx194xx xx195xx196xx197198199200201x x202203204205206207208xxxxxxxxxxxxxxx209xxxxxxxxxxxx xxxxx210xxxx xxx211xxx xxx212xxx xx213xx xx214xx xx215xxx x216xx x217xx xx218219*/220221const testUltraviolet = async () => {222const omniboxId = 'pr-uv',223errorPrefix = 'failure',224// For the hacky URL test further below, use the URL page's EXACT title.225website = Object.freeze({226path: 'example.com',227title: 'Example Domain',228});229await page.goto('http://localhost:8080/networking');230const generatedUrl = await page.evaluate(231generateUrl,232omniboxId,233website.path,234errorPrefix235);236237const testResults = await page.evaluate(238async (generatedUrl, pageTitle) => {239const results = [{}, {}];240241await new Promise((resolve) => {242const waitForDocument = () => {243const waitLonger = () => setTimeout(resolve, 5000);244if (document.readyState === 'complete') waitLonger();245else window.addEventListener('load', waitLonger);246},247// Wait until a service worker is registered before continuing.248// Also check again to make sure the document is loaded.249waitForWorker = async () => {250setTimeout(async () => {251(await navigator.serviceWorker.getRegistrations()).length > 0252? waitForDocument()253: waitForWorker();254}, 1000);255};256257waitForWorker();258});259260try {261results[0].ultraviolet = generatedUrl;262263// Test to see if the document title for example.com has loaded,264// by appending an IFrame to the document and grabbing its content.265const testGeneratedUrlHacky = async (url) => {266const exampleIFrame = document.createElement('iframe');267const waitForDocument = new Promise((resolve) => {268document.documentElement.appendChild(exampleIFrame);269exampleIFrame.addEventListener('load', () => {270resolve(271exampleIFrame.contentWindow.document.title === pageTitle272);273});274});275276// Give 10 seconds for the IFrame to load before manually checking.277const timeout = new Promise((resolve) => {278setTimeout(() => {279resolve(280exampleIFrame.contentWindow.document.title === pageTitle281);282}, 10000);283});284285exampleIFrame.src = url;286exampleIFrame.style.display = 'none';287return await Promise.race([waitForDocument, timeout]);288};289290results[1].uvTestPassed =291!!results[0].ultraviolet.indexOf(errorPrefix) &&292(await testGeneratedUrlHacky(results[0].ultraviolet));293} catch (e) {294results[0].ultraviolet = errorPrefix + ': ' + e.message;295}296297return results;298},299generatedUrl,300website.title,301errorPrefix302);303304console.log('Ultraviolet test results:', testResults[0]);305const uvTestPassed =306testResults[0].ultraviolet &&307testResults[0].ultraviolet !== 'failure' &&308testResults[1].uvTestPassed;309console.log(310'Ultraviolet test result:',311uvTestPassed ? 'success' : 'failure'312);313return uvTestPassed;314};315316// Run tests for Rammerhead and Ultraviolet.317await page.goto('http://localhost:8080/');318const rammerheadPassed = await testRammerhead();319const ultravioletPassed = await testUltraviolet();320321if (rammerheadPassed && ultravioletPassed) {322console.log('Both tests passed.');323process.exitCode = 0;324} else {325console.error('Tests failed.');326process.exitCode = 1;327}328} catch (error) {329console.error('Error in testCommonJSOnPage:', error.message);330process.exitCode = 1;331} finally {332await browser.close();333}334};335336testServerResponse();337338339