I am trying to automate a scenario where I click on a button and its opens up a pdf document in new tab. When the test fails, a json object is displayed instead of the pdf document.
I use this code :
element(by.id('MyButton')).click().then(function () {
browser.getAllWindowHandles().then(function (handles) {
newWindowHandle = handles[1]; // this is your new window
browser.switchTo().window(newWindowHandle).then(function () {
var EC = protractor.ExpectedConditions;
// Waits for the element is not present on the dom.
browser.wait(EC.stalenessOf($('#formattedJson')), 5000);
});
});
});
I can open the new tab but when I dont know how to check the content (pdf or json object).
Some advices would be appreciated.
For instance I have the error :
Failed: Error while waiting for Protractor to sync with the page: "both angularJS testability and angular testability are undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details"
Thanks in advance.
;-)
Probably because the window that is rendering your pdf isn't an angular page. You can tell protractor not to wait for angular by using browser.waitForAngularEnabled(false). You should do this right before your call to switch window. Just remember to turn it back on when you close the window and switch back to your main app window. Check out this documentation for more info.
browser.getAllWindowHandles().then(function (handles) {
newWindowHandle = handles[1]; // this is your new window
browser.waitForAngularEnabled(false); //add this and it should work
browser.switchTo().window(newWindowHandle).then(function () {
var EC = protractor.ExpectedConditions;
// Waits for the element is not present on the dom.
browser.wait(EC.stalenessOf($('#formattedJson')), 5000);
});
}):
Related
I am trying to develop a simple web extension/addon under Safari, which is using the tabs onUpdated event. I used the Safari XCRUN converter: https://developer.apple.com/documentation/safariservices/safari_web_extensions/converting_a_web_extension_for_safari
What I am trying to do is :
Open new tab on Google Scholar with set prefs params, from "options.js" script (Options page code below)
Listen for this tab to be updated and ready (e.g. tab status is complete)
Then, inject a content script that will simulate the user click on save button (i.e. on GScholar page)
Then remove the listener, and wait 1,5s (for GS tab to reload and finish saving) in order to finally close this tab.
// Detect browser language
const gsUrl = currentBrowser.i18n.getUILanguage().includes("fr")
? GSCHOLAR_SET_PREFS_FR_URL
: GSCHOLAR_SET_PREFS_COM_URL;
// Listener to detect when the GS tab has finished loading
const gsTabListener = (tabId, changeInfo, tabInfo) => {
if (changeInfo.url && changeInfo.url.startsWith(GSCHOLAR_HOST)) {
currentBrowser.tabs.executeScript(
tabId,
{
code: `document.getElementsByName("save")[0].click();`,
},
() => {
currentBrowser.tabs.onUpdated.removeListener(gsTabListener);
setTimeout(() => currentBrowser.tabs.remove(tabId), 1500);
}
);
}
};
currentBrowser.tabs.onUpdated.addListener(gsTabListener); // Add tab listener
currentBrowser.tabs.create({
url: `${gsUrl}?inst=${gScholarInstIdList.join("&inst=")}&save=#2`,
active: false,
}); // Open GS tab according to browser language
The problem is that it works well on Chrome/Edge/Firefox (on MacOS), but not on Safari : the GS tab is opended but isn't closed and nothing happens :-/
PS:
It seems tabs onUpdated event is well supported on Safari according to MDN.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/onUpdated
I have also tried webNavigation onCompleted event, but same !
Developing on : MacBookAir under MacOS Monterey 12.4, Safari 15.4 (17613.2.7.18), XCode 13.3.1 (13E500a), extension is bundled with Webpack 5.68.0 (e.g. building all assets files).
I really don't see what I am doing wrong and why wouldn't this tab event be intercepted ?
Thanks for your feedback.
After debugging I finally sloved this by noticing that in fact the events were triggered, but missed because of the availability and values of parameters passed into callabck (changeInfo, details) depending on the browser we're on.
So I switched from onUpdated to webNavigation.onCompleted API, which is better suited to our need (tab page fully loaded) and whose parameter is simple and consistent across browsers :-)
const uiLanguage = currentBrowser.i18n.getUILanguage().includes("fr")
? "fr"
: "com"; // Detect browser language
const gsUrl = `${GSCHOLAR_SETTINGS_HOST}.${uiLanguage}`;
// Listener to detect when the GS tab has finished loading
const gsTabListener = (details) => {
if (details && details.url && details.tabId) {
if (details.url.startsWith(`${gsUrl}/scholar_settings?`)) {
currentBrowser.tabs.executeScript(details.tabId, {
code: `document.getElementsByName("save")[0].click();`,
});
} else if (details.url.startsWith(`${gsUrl}/scholar?`)) {
currentBrowser.webNavigation.onCompleted.removeListener(
gsTabListener
);
currentBrowser.tabs.remove(details.tabId);
}
}
};
currentBrowser.webNavigation.onCompleted.addListener(gsTabListener); // Add GS tab listener
currentBrowser.tabs.create({
url: `${gsUrl}/scholar_settings?inst=${gScholarInstIdList.join(
"&inst="
)}&save=#2`,
active: false,
}); // Open GS tab according to browser language
I'm trying to use testcafe to fill forms on a page.
When the form is filled, I'd like to be able to stop the test with the window still open so a human can review the form before clicking submit.
I can pause the test with t.debug() but this locks the page and shows the testcafe controls overlay at the bottom.
Is there a way I can remove this overlay and unlock the page?
I've tried using client functions to hide the element with javascript as follows:
test('test_1', async (t) => {
const hideOverlay = ClientFunction(function() {
const target = document.querySelector('#root-hammerhead-shadow-ui > div > div');
target.style.display = 'none';
return true;
})
await t.wait(5000);
setTimeout(async function() {
const res = await hideOverlay();
console.log('-------->', { res });
}, 6000);
await t.debug();
});
Since no code will be executed after debug is invoked, I thought I could use a settimeout to queue the call to the function that hides the overlay, so that it is queued and only executes after debug is called and the overlay is visible.
Didn't work though :( code didn't execute, got an unhandled promise rejection.
Could really use some help here, thanks :)
Yes, you can unlock the page by clicking the 'Unlock page' button in the footer as #VysakhMohan mentioned in the comment.
Please refer to the client-side debugging documentation for more details.
I have an AngularJS front-end that opens a Bootstrap Modal that has a button on it. When this button is clicked it calls a Web API method on the server that generates an OPEN XML Word Document as a stream and returns the file to the client. I have several files downloading successfully in IE where I see this:
However, for the file I'm trying to download with the open Modal I never see the above image. It's not the file itself because it downloads successfully when I try it without the open Modal. Also, I don't see any errors reported in IE Dev Tools. I don't think it's the code that generates the streams because the same code generates other files successfully. I also tried closing the Modal before downloading but that didn't work either. It's almost like the Modal is "blocking" the download.
Here is the Modal definition:
var isOUOModal;
var isSubmitItem = false;
var openSignificanceModal = function () {
return $modal.open({
scope: $scope,
templateUrl: './app/oa/significance_modal.html',
controller: SignificanceModalCtrl,
keyboard: false,
backdrop: 'static',
resolve: {
item: function () {
return $scope.item;
}
}
});
};
var SignificanceModalCtrl = function ($scope, $modalInstance, item, $window) {
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
I seem to be out of ideas at the moment so any assistance is much appreciated.
Thanks,
Pete
I was able to determine the cause of the problem here. It had to do with the way I was calling the Web API Method. I was using an AJAX JQuery GET call. Instead I had to do something like this:
var url = url;
window.location.href = url;
When I changed the way I was calling the Web API method I saw the stream returned to the client as expected.
I develop my first firefox extension. My usecase (already sucessfully implemented as a chrome extension):
Inject CSS of a specific page
Default load: contentscript-on.js
On Click icon (icon-on.png / icon-off.png) switch from contentscript-on.js to contentscript-off.js and backward
The contentscript-on.js already works on page load. I´ve searched a lot to find help or an example for my usecase. Any ideas?
Thank you very much!
main.js
var pageMod = require("sdk/page-mod");
var self = require("sdk/self");
pageMod.PageMod({
include: "https://app.example.de/dashboard",
contentScriptFile: [self.data.url("jquery-1.11.0.min.js"), self.data.url("contentscript-on.js")]
});
In my chrome extension, I use a background.js to toggle on / off and switch between the scripts
//toggle = true, because the contenscript-on.js is already loaded on initial loading of the page
var toggle = true;
chrome.browserAction.onClicked.addListener(function(tab) {
toggle = !toggle;
if(toggle){
//change the icon after pushed the icon to On
chrome.browserAction.setIcon({path: "icon-on.png", tabId:tab.id});
//start the content script to hide dashboard
chrome.tabs.executeScript({file:"contentscript-on.js"});
}
else{
//change the icon after pushed the icon to Off
chrome.browserAction.setIcon({path: "icon-off.png", tabId:tab.id});
//start the content script to hide dashboard
chrome.tabs.executeScript({file:"contentscript-off.js"});
}
});
Is there a similar way to this in firefox extensions?
The PageMod constructor has an optional onAttach property which passes a content worker to your function. This worker can be destroyed to remove the scripts from the page
var contentWorker; // Global (or greater scope) variable
// …
onAttach: function(worker) {
contentWorker = worker;
}
Then, in your click listener
var tab = contentWorker.tab;
contentWorker.destroy();
contentWorker = tab.attach( {
contentScriptFile: [self.data.url("jquery-1.11.0.min.js"), self.data.url("contentscript-off.js")]
});
Frankly, it would probably be easier just to attach both and toggle them somehow from within the content script code
As a side note, there's a new toggle button that you can can use that will have an activated/deactivated look that sounds like it would be good for your scenario.
I have made a plugin using the addon SDK. The plugin adds a button to the nav-bar, and when it is clicked it opens a new tab with some data from an internal indexeddb using code similar to this:
// main.js
tabs.open({
url: self.data.url('index.html'),
onReady: runScript
});
function runScript(tab) {
var worker = tab.attach({
contentScriptFile: [
self.data.url("script.js")]
});
}
Everything works fine, except for the scenario where the user quits Firefox and opens it again, that tab will be restored, but it will contain nothing because it hasn't been triggered by the addon button click. This is because the scripts on the page are loaded through the runScript function in main.js, which is not executed when the HTML file is loaded on a restart.
How can I get this tab to have the same behavior on page startup than on button clicking?
I think you'll have to reload the tab:
exports.main = function(options) {
if(options.reason==='startup') for (var i=tabs.length-1; i>=0; i--) {
var tab = tabs[i];
if (tab.url!==self.data.url('index.html')) continue;
tab.once('ready', runScript.bind(null, tab));
tab.reload();
/* If it can't reload the tab,
use tab.url = self.data.url('index.html'); */
}
// ...
}
This a bug I had reported it awhile ago on bugzilla here
I added your topic as an example.
So what you have to do for now, is onReady, you have to turn you body into html datauri and set the location of the tab to this contents.
For example on ready:
var htmlDataUri = 'data:text/html,' + encodeURIComponent(document.documentElement.innerHTML);
//end make htmldatauri
document.location = htmlDataUri;