UNPKG

phantomjscloud

Version:

Official PhantomJs Cloud Client API Library for Node.js

740 lines (632 loc) 33.9 kB
import xlib = require( "xlib" ); import phantomjscloud = require( "./_index" ); import ioDatatypes = phantomjscloud.ioDatatypes; const __ = xlib.lolo; const log = __.log; const _ = xlib.lodash; const __verifyResponseStatus_defaultOptions = { contentStatusCode: 200, userResponseStatusCode: 200, backend: "chrome", doneDetail: "normal", contentType: "" }; /** does basic verification of the userResponse common among most tests */ function verifyResponseStatus( userResponse: ioDatatypes.IUserResponse, options: Partial<typeof __verifyResponseStatus_defaultOptions> = __verifyResponseStatus_defaultOptions ) { options = xlib.lodash.defaultsDeep( options, __verifyResponseStatus_defaultOptions ); const responseSummary = xlib.serialization.jsonX.inspectParse( userResponse ); log.assert( userResponse != null, "response null", { options, userResponse } ); log.assert( userResponse.statusCode === options.userResponseStatusCode, "responseStatusCode", userResponse.statusCode, { options, responseSummary } ); log.assert( userResponse.content.statusCode === options.contentStatusCode, "contentStatusCode", userResponse.content.statusCode, { options, responseSummary } ); log.assert( userResponse.meta.backend.platform.toLowerCase() === options.backend.toLowerCase(), "backend", userResponse.meta.backend, { options, responseSummary } ); if ( options.backend === "chrome" ) { log.assert( JSON.stringify( userResponse.content.doneDetail ).includes( options.doneDetail ), "doneDetail", userResponse.content.doneDetail, { options, responseSummary } ); } if ( options.contentType != null && options.contentType.length > 0 ) { log.assert( userResponse.content.headers[ "content-type" ].includes( options.contentType ), `content-type header not what expected. got ${ userResponse.content.headers[ "content-type" ] } but expect it to include "${ options.contentType }"` ); } log.assert( userResponse.meta.billing.creditCost > 0, "invalid creditCost" ); log.assert( userResponse.meta.billing.dailySubscriptionCreditsRemaining >= 0, "invalid dailySubscriptionCreditsRemaining" ); log.assert( userResponse.meta.billing.prepaidCreditsRemaining >= 0, "invalid prepaidCreditsRemaining" ); xlib.lodash.forEach( userResponse.pageResponses, ( pageResponse ) => { //log.assert( pageResponse.metrics.pageStatus === options.contentStatusCode.toString(), "pageResponse.metrics.pageStatus", pageResponse.metrics.pageStatus, { options, pageResponse: JSON.stringify( pageResponse ) } ); if ( options.backend === "chrome" ) { log.assert( JSON.stringify( pageResponse.doneDetail ).includes( options.doneDetail ), "pageResponse.doneDetail", pageResponse.doneDetail, { options, pageResponse: JSON.stringify( pageResponse ) } ); } } ); } /** helper to set all properties to null */ function _nullAllProperties( obj: any ) { _.forEach( obj, ( value, key ) => { if ( _.isObject( value ) ) { _nullAllProperties( value ); obj[ key ] = value; } else { obj[ key ] = null; } } ); } /** hack fix for mocha bug, unable to have a timeout for async tests */ function it2( testFcn: () => Promise<any> ) { const testName = xlib.reflection.getTypeName( testFcn ); return it( testName, async function () { const timeoutMs = this.timeout(); return xlib.promise.bluebird.resolve( testFcn.apply( this ) ).timeout( timeoutMs, new xlib.promise.bluebird.TimeoutError( `operation timed out. Max of ${ timeoutMs }ms exceeded` ) ); } ); } describe( __filename, function unitTests() { let browser: phantomjscloud.BrowserApi; this.timeout( 10000 ); //set default timeout for these pjsc tests this.beforeAll( function beforeAll() { const apiKey = xlib.environment.getEnvironmentVariable( "phantomjscloud_apikey" ); const endpointOrigin: string = // "http://localhost:80"; //used for UAT testing //"https://phantomjscloud.com"; //PROD (explicit) //"http://35.232.215.225"; //PREPROD undefined; //PROD (implicit, default) browser = new phantomjscloud.BrowserApi( { apiKey, endpointOrigin } ); } ); describe( "e2eDefaultBrowser", function e2eDefaultBrowser() { let test = it2( async function basicE2e() { const pageRequest: phantomjscloud.ioDatatypes.IPageRequest = { url: "https://localhost/examples/corpus/example.com.html", renderType: "html", backend: "chrome" }; const userResponse = await browser.requestSingle( pageRequest ); log.assert( userResponse.content.data.indexOf( "Example Domain" ) >= 0 ); } ); test.timeout( 20000 ); it2( async function htmlBasicPageRequest() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/corpus/example.com.html", renderType: "plainText", }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.data.includes( "Example Domain" ), "content verification failed", response.content.data ); } ); // ! production servers fulfill this too fast, so even 50ms ajax calls finish too rapidly for it to be waited on. // // it2( async function gracefulFailureExceedMaxWait() { // // const pageRequest: ioDatatypes.IPageRequest = { // // url: "http://localhost/examples/corpus/ajax-fast.html", // // renderType: "plainText", // // requestSettings: { // // maxWait: 3000, // // } // // }; // // const response = await browser.requestSingle( pageRequest ); // // verifyResponseStatus( response, { contentStatusCode: 408, doneDetail: "error:maxWait" } ); // // log.assert( response.content.data.includes( "this page will make ajax calls" ), "content verification failed", response.content.data ); // // } ); it2( async function contentInjection() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/helpers/requestdata", renderType: "plainText", content: "<html><h1>hello-world</h1></html>", }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.data.includes( "hello-world" ), "content verification failed", response.content.data ); } ); it2( async function redirectJs() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/helpers/requestdata", renderType: "plainText", content: "<html><script>window.location='https://localhost/examples/corpus/example.com.html';</script><h1>hello-world</h1></html>", }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.data.includes( "This domain is established to be used" ), "content verification failed", response.content.data ); } ); it2( async function doneWhenSelector() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/corpus/ajax.html", renderType: "plainText", requestSettings: { doneWhen: [ { text: `"statusCode":206`, statusCode: 202 }, { selector: "pre#fill-target", statusCode: 201 } ], }, }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { contentStatusCode: 201, doneDetail: "pre#fill-target" } ); log.assert( response.content.data.includes( "this page will make ajax calls" ), "content verification failed", response.content.data ); } ); it2( async function doneWhenDomReady() { // loads up an expensive page and renders as soon as possible, tossing out unneeded contents const pageRequest: ioDatatypes.IPageRequest = { url: "http://cnn.com", renderType: "plainText", requestSettings: { doneWhen: [ { event: "domReady" } ], ignoreImages: true, waitInterval: 0, resourceWait: 100, //disableJavascript:true, resourceModifier: [ { isBlacklisted: true, regex: ".*" }, { isBlacklisted: false, regex: ".*cnn.*" }, { isBlacklisted: true, category: "subFrameResource" }, { isBlacklisted: true, type: "stylesheet" }, { isBlacklisted: true, type: "image" }, { isBlacklisted: true, type: "media" }, { isBlacklisted: true, type: "texttrack" }, { isBlacklisted: true, type: "websocket" }, { isBlacklisted: true, type: "other" }, { isBlacklisted: true, type: "eventsource" }, { isBlacklisted: true, type: "fetch" }, { isBlacklisted: true, type: "font" }, { isBlacklisted: true, type: "manifest" }, //{ isBlacklisted: true, type: "xhr" } , ], } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { doneDetail: "domReady" } ); log.assert( response.content.data.includes( "Politics" ), "content verification failed", response.content.data ); } ).timeout( 15000 ); // ! prod is too fast for the ajax to delay rendering. so this forceFinish() test doesn't work. // it2( async function forceFinish() { // const pageRequest: ioDatatypes.IPageRequest = { // url: "http://localhost/examples/corpus/ajax-fast.html", // renderType: "plainText", // requestSettings: { waitInterval: 500 }, // renderSettings: { // viewport: { height: 20, width: 200 }, // }, // scripts: { domReady: [ "setInterval(function(){var lastY=window.scrollY;window.scrollBy(0,20);if(lastY===window.scrollY){window._pjscMeta.forceFinish=true;}},50);" ] }, // }; // const response = await browser.requestSingle( pageRequest ); // verifyResponseStatus( response, { contentStatusCode: 200, doneDetail: "forceFinish" } ); // log.assert( response.content.data.includes( "this page will make ajax calls" ), "content verification failed", response.content.data ); // } ); it2( async function htmlBasicUserRequest() { const userRequest: ioDatatypes.IUserRequest = { pages: [ { url: "http://localhost/examples/helpers/requestdata", renderType: "plainText", requestSettings: { maxWait: 5000, } } ], }; const response = await browser.requestSingle( userRequest ); verifyResponseStatus( response ); log.assert( response.content.data.includes( `"user-agent": "Mozilla` ), "content verification failed", response.content.data ); } ); it2( async function resourceModifier_changeUrl() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://www.highcharts.com/demo/pie-donut", renderType: "html", requestSettings: { resourceModifier: [ { regex: ".*highcharts.com.*", changeUrl: "$$protocol:$$port//en.wikipedia.org/wiki$$path" } ] } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { contentStatusCode: 404 } ); log.assert( response.content.data.includes( "<title>Demo/pie-donut - Wikipedia</title>" ), "content verification failed", response.content.data ); } ); it2( async function cookies_inject() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/corpus/example.com.html", renderType: "plainText", requestSettings: { cookies: [ { domain: "example.com", name: "myCookie1", value: "value1" }, { domain: "localhost", name: "myCookie2", value: "value2" } ] } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.pageResponses[ 0 ].cookies.length === 1, "cookie verification failed: cookie count", response.pageResponses[ 0 ].cookies.length ); log.assert( response.pageResponses[ 0 ].cookies[ 0 ].name === "myCookie2", "cookie verification failed: name" ); log.assert( response.pageResponses[ 0 ].cookies[ 0 ].value === "value2", "cookie verification failed: value" ); log.assert( response.content.data.includes( "Example Domain" ), "content verification failed", response.content.data ); } ); it2( async function cors_bypass_and_loadFinished_script() { const pageRequest: ioDatatypes.IPageRequest = { url: "https://news.ycombinator.com/", renderType: "html", backend: "chrome", requestSettings: { maxWait: 10000, disableSecureHeaders: true, }, scripts: { domReady: [ "http://localhost/examples/scripts/hilitor.js" ], loadFinished: [ "var myHilitor = new Hilitor(); myHilitor.apply('ask,who,jobs,new');" ] } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.data.includes( `<em class="hilitor"` ), "content verification failed", response.content.data ); } ); it2( async function translation() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/corpus/example.com.html", renderType: "plainText", requestSettings: { disableSecureHeaders: true, }, scripts: { pageNavigated: [ "http://localhost/examples/scripts/google-translate.js?targetLang=ko&hideUi=true" ] } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.data.indexOf( `예 도메인` ) === 0, "content verification failed", response.content.data ); } ); it2( async function redirect_with_scripts_also_verify_content_properties() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/corpus/redirect.html", renderType: "html", scripts: { domReady: [ "http://localhost/examples/scripts/hilitor.js" ], loadFinished: [ "var myHilitor = new Hilitor(); myHilitor.apply('simple,page,example,http');" ] } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.url === "http://localhost/examples/corpus/simple.html", "should have reddirected" ); log.assert( response.content.data.includes( `<em class="hilitor" style="background-color: rgb(255, 255, 102); font-style: inherit; color: rgb(0, 0, 0);">Simple</em> Html` ), "content verification failed, scripts did not exec properly", response.content.data ); log.assert( response.content.name === "localhost-examples-corpus-simple.html", "content name not set properly" ); log.assert( response.content.pageExecLastWaitedOn.includes( "waitInterval" ), "expected waitInterval to be last thing our page wated on finishing" ); log.assert( response.content.encoding === "utf8", "expect utf8 encoding for our html output" ); } ); it2( async function postBasic() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/helpers/requestdata", renderType: "html", urlSettings: { data: "my=postData", operation: "POST", }, }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.data.includes( `"my": "postData"` ), "content verification failed, post payload not found", response.content.data ); } ); it2( async function postJson_with_passThroughHeaders() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/helpers/requestdata", renderType: "plainText", outputAsJson: true, urlSettings: { operation: "POST", headers: { hello: "world", "Content-Type": "application/json" }, data: "{\"yourPostData\":123}", }, renderSettings: { passThroughHeaders: true, } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { contentType: "application/json" } ); log.assert( response.content.data.includes( `"yourPostData": 123` ), "content verification failed, post payload not found", response.content.data ); } ); it2( async function postUnicode() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/helpers/requestdata", renderType: "plainText", outputAsJson: false, urlSettings: { operation: "POST", // tslint:disable-next-line: max-line-length data: "{\"loans\":[{\"account_id\":\"49790094591\",\"account_name\":\"สินเชื่อรถยนต์ใหม่\",\"account_type\":\"CARLOAN\",\"customer_name\":\"นาย บีเอสซีบีคอนเนค คอนเนค นาย\",\"status\":\"ACTIVE\",\"scb_connect\":true,\"linked_date\":\"1537499724000\"},{\"account_id\":\"49790094606\",\"account_name\":\"สินเชื่อรถยนต์ใหม่\",\"account_type\":\"CARLOAN\",\"customer_name\":\"นาย บีเอสซีบีคอนเนค คอนเนค นาย\",\"status\":\"INACTIVE\",\"scb_connect\":true,\"linked_date\":\"1537499724000\"},{\"account_id\":\"49790094614\",\"account_name\":\"สินเชื่อรถยนต์ใหม่\",\"account_type\":\"CARLOAN\",\"customer_name\":\"นาย บีเอสซีบีคอนเนค คอนเนค นาย\",\"status\":\"ACTIVE\",\"scb_connect\":true,\"linked_date\":\"1537499724000\"},{\"account_id\":\"49790094648\",\"account_name\":\"สินเชื่อรถยนต์ใหม่\",\"account_type\":\"CARLOAN\",\"customer_name\":\"นาย บีเอสซีบีคอนเนค คอนเนค นาย\",\"status\":\"ACTIVE\",\"scb_connect\":true,\"linked_date\":\"1537499724000\"},{\"account_id\":\"49790094656\",\"account_name\":\"สินเชื่อรถยนต์ใหม่\",\"account_type\":\"CARLOAN\",\"customer_name\":\"นาย บีเอสซีบีคอนเนค คอนเนค นาย\",\"status\":\"ACTIVE\",\"scb_connect\":true,\"linked_date\":\"1537499724000\"}]}" }, }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.data.includes( `สินเชื่อรถยนต` ), "content verification failed, post payload not found", response.content.data ); } ); it2( async function scriptOutputDomElement() { const pageRequest: ioDatatypes.IPageRequest = { outputAsJson: false, url: "http://localhost/examples/corpus/example.com.html", renderType: "script", scripts: { domReady: [ "http://localhost/examples/scripts/jquery-3.3.1.min.js" ], loadFinished: [ "window._pjscMeta.scriptOutput={h1:$('h1').text()};" ] } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( _.isPlainObject( response.content.data ), "content verification failed, script output not as expected. expect a POJO", response.content.data ); const scriptOutput: { h1: string; } = response.content.data as any; log.assert( scriptOutput.h1 === "Example Domain", "content verification failed, script output h1 element not as expected. expect contents 'Example Domain'", response.content.data ); log.assert( response.content.name === "localhost-examples-corpus-example-com.json", "expect file extension to be JSON" ); } ); it2( async function selectorTest() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/corpus/news.ycombinator.com.html", renderType: "plainText", renderSettings: { selector: ".itemlist", }, }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.data.indexOf( "1." ) === 0, "content verification failed, expect first post 'index number' in beginning of content", response.content.data ); } ); it2( async function nullOptionalParameters() { const pageRequest = ioDatatypes.pageRequestDefaultsGet(); _nullAllProperties( pageRequest ); pageRequest.url = "http://localhost/examples/corpus/example.com.html"; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.encoding === "base64", `content verification failed, expect base64 image. instead got ${ response.content.encoding }` ); log.assert( response.content.name === "localhost-examples-corpus-example-com.jpeg", `content verification failed, expect jpeg name. instead got ${ response.content.name }` ); log.assert( response.content.size > 30000 && response.content.size < 60000, `content verification failed, expect about 40880 bytes. instead got ${ response.content.size }` ); } ); } ); //end describe("e2e tests"); describe( "user scenarios", function userScenarios() { /** suggested output of the pdfMake tests */ const pdfMakeOutputStart = "JVBERi0xLjMKJf////8KNSAwIG9iago8PAovVHlwZSAvUGFnZQ"; const pdfMakeOutputEnd = "Jvb3QgMiAwIFIKL0luZm8gNyAwIFIKPj4Kc3RhcnR4cmVmCjMwMzAKJSVFT0YK"; /** from email conversation with sean.colonello on 20181017, made script execution synchronous by default, to make this work same as webkit */ it2( async function chromePdfMake() { const pageRequest: ioDatatypes.IPageRequest = { url: null, backend: "chrome", outputAsJson: true, content: "", requestSettings: { maxWait: 6000, }, renderType: "script", scripts: { domReady: [], load: [], loadFinished: [ "http://localhost/examples/scripts/pdfmake-0.1.38.min.js", "http://localhost/examples/scripts/pdfmake-0.1.38.vfs_fonts.js", "_pjscMeta.manualWait=true; var dd={content:'Test'};var pdf=pdfMake.createPdf(dd);pdf.getBase64(function(enc){_pjscMeta.scriptOutput=enc;_pjscMeta.manualWait=false;});" ], } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.name === "localhost-blank.json" ); log.assert( response.content.size === 4466 ); log.assert( response.content.data.indexOf( pdfMakeOutputStart ) === 0 ); log.assert( response.content.data.indexOf( pdfMakeOutputEnd ) === response.content.data.length - pdfMakeOutputEnd.length ); log.assert( response.content.resourceSummary.complete === 3 ); log.assert( response.content.resourceSummary.failed === 0 ); log.assert( response.content.execErrors == null ); } ).timeout( 6000 ); /** from email conversation with sean.colonello on 20181017, * made script execution synchronous by default, this should thus fail because the scripts execute asynchronously * this request is identical to the one above in ```chromePdfMake()``` but this one specifies ```scriptSettings.async=true``` and thus should fail due to race conditions * */ it2( async function chromePdfMakeFailDueToAsync() { const pageRequest: ioDatatypes.IPageRequest = { url: null, backend: "chrome", outputAsJson: true, content: "", requestSettings: { maxWait: 6000, }, renderType: "script", scripts: { domReady: [], load: [], loadFinished: [ "http://localhost/examples/scripts/pdfmake-0.1.38.min.js", "http://localhost/examples/scripts/pdfmake-0.1.38.vfs_fonts.js", "_pjscMeta.manualWait=true; var dd={content:'Test'};var pdf=pdfMake.createPdf(dd);pdf.getBase64(function(enc){_pjscMeta.scriptOutput=enc;_pjscMeta.manualWait=false;});" ], }, scriptSettings: { async: true, }, }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { contentStatusCode: 424, doneDetail: "error:maxWait" } ); log.assert( response.content.name === "localhost-blank.json" ); log.assert( response.content.size === 2 ); log.assert( _.isPlainObject( response.content.data ) ); log.assert( _.isEmpty( response.content.data ) ); log.assert( response.content.resourceSummary.complete === 3 ); log.assert( response.content.resourceSummary.failed === 0 ); log.assert( response.content.execErrors.length === 2 ); log.assert( _.find( response.content.execErrors, ( execErr ) => execErr.message.includes( "pdfMake is not defined" ) ) != null, "could not find expected error message in content.execErrors" ); } ).timeout( 10000 ); /** from email conversation with sean.colonello on 20181017, this worked in webkit but not chrome */ it2( async function webkitPdfMake() { const pageRequest: ioDatatypes.IPageRequest = { url: null, backend: "webkit", outputAsJson: true, content: "", renderType: "script", scripts: { domReady: [], load: [], loadFinished: [ "http://localhost/examples/scripts/pdfmake-0.1.38.min.js", "http://localhost/examples/scripts/pdfmake-0.1.38.vfs_fonts.js", "_pjscMeta.manualWait=true; var dd={content:'Test'};var pdf=pdfMake.createPdf(dd);pdf.getBase64(function(enc){_pjscMeta.scriptOutput=enc;_pjscMeta.manualWait=false;});" ], } }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { backend: "phantomjs" } ); log.assert( response.content.name === "content.json" ); log.assert( response.content.size === 4466 ); log.assert( response.content.data.indexOf( pdfMakeOutputStart ) === 1 ); log.assert( response.content.data.indexOf( pdfMakeOutputEnd ) === response.content.data.length - 1 - pdfMakeOutputEnd.length ); } ); /** from email conversation with priceline around 20181017, they need to know when a page fails to load properly */ it2( async function pricelineBlankPageDetectableError() { const pageRequest: ioDatatypes.IPageRequest = { url: null, content: "http://localhost/examples/customer-tests/priceline-blank.html", "outputAsJson": true, "requestSettings": { "disableJavascript": true, "resourceWait": 500, "waitInterval": 500, //"resourceModifier": [ { "regex": ".*qaa.priceline.com.*", "changeUrl": "$$protocol://www.priceline.com$$path", } ], }, "renderSettings": { "pdfOptions": { "format": "onepage" } }, "renderType": "plainText", //"renderType": "jpeg", }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { contentStatusCode: 408 } ); //prod times out on this log.assert( response.content.name === "localhost-blank.text" ); log.assert( response.content.data.includes( "Complete Your Booking" ) );//"Hotels Cars Flights" ) ); log.assert( response.content.resourceSummary.failed > 0 ); } ).timeout( 40000 ); /** from email conversation with priceline around 20181017, they need to know when a page fails to load properly */ it2( async function pricelineBlankPageDetectableErrorViaTimeout() { const pageRequest: ioDatatypes.IPageRequest = { url: null, content: "http://localhost/examples/customer-tests/priceline-blank.html", "outputAsJson": true, "requestSettings": { "disableJavascript": true, "resourceWait": 500, "waitInterval": 500, maxWait: 10000 //"resourceModifier": [ { "regex": ".*qaa.priceline.com.*", "changeUrl": "$$protocol://www.priceline.com$$path", } ], }, "renderSettings": { "pdfOptions": { "format": "onepage" } }, "renderType": "plainText", //"renderType": "jpeg", }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { contentStatusCode: 408, doneDetail: "error:maxWait" } ); log.assert( response.content.name === "localhost-blank.text" ); log.assert( response.content.data.includes( "Complete Your Booking" ) );//"Hotels Cars Flights" ) ); log.assert( response.content.resourceSummary.late > 0 ); } ).timeout( 40000 ); /** from email conversation with priceline around 20181017, they need to know when a page fails to load properly */ it2( async function pricelineBlankPageFix() { const pageRequest: ioDatatypes.IPageRequest = { url: null, content: "http://localhost/examples/customer-tests/priceline-blank.html", "outputAsJson": true, "requestSettings": { "disableJavascript": true, "resourceWait": 500, "waitInterval": 500, "resourceModifier": [ { "regex": ".*qaa.priceline.com.*", "changeUrl": "$$protocol://www.priceline.com$$path", } ], }, "renderSettings": { "pdfOptions": { "format": "onepage" } }, "renderType": "plainText", //"renderType": "jpeg", }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response ); log.assert( response.content.name === "localhost-blank.text" ); log.assert( response.content.data.includes( "Complete Your Booking" ) ); log.assert( response.content.resourceSummary.failed === 0 ); } ).timeout( 10000 ); } ); //end describe userScenarios describe( "failureTests", function failureTests() { it2( async function invalidDomain() { let pageRequest: ioDatatypes.IPageRequest = { url: "https://www.exadsfakjalkjghlalkjrtiuibe.com", renderType: "plainText", }; try { const userResponse = await browser.requestSingle( pageRequest ); throw log.error( "should have failed...", { userResponse } ); } catch ( _err ) { if ( _err.response != null && _err.request && _err instanceof Error ) { const axiosErr = _err as xlib.net.axios.AxiosError; log.assert( axiosErr.response != null && axiosErr.response.status === 424, "expected error status 424", { axiosErr } ); } else { throw _err; } } } ).timeout( 20000 ); it2( async function invalidPort() { let pageRequest: ioDatatypes.IPageRequest = { url: "https://www.example.com:82728", renderType: "plainText", requestSettings: { maxWait: 3000 }, }; try { const userResponse = await browser.requestSingle( pageRequest ); log.error( "should have failed...", { userResponse } ); throw new Error( "the request should have failed due to invalid URL port" ); } catch ( _err ) { if ( _err.response != null && _err.request && _err instanceof Error ) { const axiosErr = _err as xlib.net.axios.AxiosError; log.assert( axiosErr.response != null && axiosErr.response.status === 424, "expected error status 424", { axiosErr } ); } else { throw _err; } } } ).timeout( 6000 ); it2( async function invalidUrl() { let pageRequest: ioDatatypes.IPageRequest = { url: "//example.com", }; try { const userResponse = await browser.requestSingle( pageRequest ); log.error( "should have failed...", { userResponse } ); throw new Error( "the request should have failed due to invalid URL" ); } catch ( _err ) { if ( _err.response != null && _err.request && _err instanceof Error ) { const axiosErr = _err as xlib.net.axios.AxiosError; log.assert( axiosErr.response != null && axiosErr.response.status === 400, "expected error status 400", { axiosErr } ); } else { throw _err; } } } ).timeout( 6000 ); it2( async function invalidUrlFile() { let pageRequest: ioDatatypes.IPageRequest = { url: "file://.", }; try { const userResponse = await browser.requestSingle( pageRequest ); log.error( "should have failed...", { userResponse } ); throw new Error( "the request should have failed due to invalid URL" ); } catch ( _err ) { if ( _err.response != null && _err.request && _err instanceof Error ) { const axiosErr = _err as xlib.net.axios.AxiosError; log.assert( axiosErr.response != null && axiosErr.response.status === 400, "expected error status 400", { axiosErr } ); } else { throw _err; } } } ).timeout( 6000 ); it2( async function allNullParameters() { let pageRequest = ioDatatypes.pageRequestDefaultsGet(); pageRequest.url = "http://localhost/examples/corpus/example.com.html"; _nullAllProperties( pageRequest ); try { const userResponse = await browser.requestSingle( pageRequest ); log.error( "should have failed...", { userResponse } ); throw new Error( "the request should have failed due to invalid URL" ); } catch ( _err ) { if ( _err.response != null && _err.request && _err instanceof Error ) { const axiosErr = _err as xlib.net.axios.AxiosError; log.assert( axiosErr.response != null && axiosErr.response.status === 400, "expected error status 400", { axiosErr } ); } else { throw _err; } } } ); it2( async function scriptFailureInjected() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/corpus/simple.html", backend: "chrome", outputAsJson: true, renderType: "script", scripts: { loadFinished: [ "throw new Error('boom');", ], }, }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { contentStatusCode: 424 } );//, doneDetail: "error:scripts.loadFinished" } ); } ).timeout( 6000 ); it2( async function scriptFailureLoad() { const pageRequest: ioDatatypes.IPageRequest = { url: "http://localhost/examples/corpus/simple.html", backend: "chrome", outputAsJson: true, renderType: "script", scripts: { domReady: [ "http://localhost/examples/scripts/does-not-exist.js", ], }, }; const response = await browser.requestSingle( pageRequest ); verifyResponseStatus( response, { contentStatusCode: 424 } );//, doneDetail: "error:scripts.domReady" } ); } ).timeout( 6000 ); } ); //end describe("failure tests"); } );//end describe(__filename);