Is it possible to make the devtool status off when using Puppeteer? - google-chrome-devtools

is it possible to make the devtool status off when using Puppeteer?
because there are some websites that protect their pages from being inspected using devtool, so it can not be accessed using Puppeteer.
I opened this url https://jsbin.com/cecuzeb/edit?js,output to check devtool status
const browser = await puppeteer.launch({
headless: false,
devtools: false,
});
const page = await browser.newPage();
await page.goto('https://jsbin.com/cecuzeb/edit?js,output');
is there any way to make this status off?

The answer below is rather a theoretical version to prevent detection by normal dev tools detection using /./.toString method based on the provided jsbin link on main question.
Stop all intervals of page. Since most devtool detection libraries are simply running the interval check, we can stop them.
(function(w){w = w || window; var i = w.setInterval(function(){},100000); while(i>=0) { w.clearInterval(i--); }})(/*window*/);
Stop console.clear, if there are no console.clear running, then you won't have problem with the console getting cleared without your permission. Also stop printing "%c" or any other clearing characters.
console.clear = console.log = console.warn = console.error = () => {};

Related

Protractor file upload with Saucelabs (Chrome 90) redirected to "data:text/html,<html></html>" after upload, works locally but not on Saucelabs

I am using protractor for a Node.js application with Chrome, in one test case I have to upload image and then click add/update button. The test case is working perfectly on my machine, but on Saucelabs it cant interact with the button after the image is uploaded. If I don't upload image its able to find button and click on it but when using with image upload it doesn't.
I have printed the current URL after image upload and it shows
"data:text/html,", whereas in the Saucelabs video I can see previous page.
Approaches I have tried
Tried to print all available handles and it only prints 1 handle i.e.
"handles are [chrome 90.0 Windows 10 #01-1]
CDwindow-B29A329D03022E36745F1A844177FAA8"
Print Current URL "data:text/html,"
Code
const remote = require('selenium-webdriver/remote');
browser.driver.setFileDetector(new remote.FileDetector());
// absolute path resolution
const path = require('path');
const fileToUpload = './Test_Images/' + imageName;
const absolutePath = path.resolve(__dirname, fileToUpload);
console.log('path is ', absolutePath);
// Find the file input element
const fileElem = element(by.css('input[type="file"]'));
//upload image
await browser.sleep(2000);
fileElem.sendKeys(absolutePath);
console.log('\n Image Uploaded for report');
//print current url after image upload
const currentUrl = (await browser.getCurrentUrl()).toString();
console.log('\n Current URL', currentUrl);
await browser.sleep(2000);
//get all handles
browser.getAllWindowHandles().then(function (handles) {
for (const handle of handles) {
console.log('\n\nhandles are\n', handle.toString());
}});
//click on the submit button
await adminReportsPage.createReportButton.click();
console.log('Report Submit button Clicked ');
The reason why this fails is because a remote machine in the cloud, as with Sauce Labs, does not has access to your local file system and your local machine has.
I'm not 100% sure if Protractor has a workaround for this, but with a framework like for example WebdriverIO, you have the option to use a method like uploadFile. That method will only work on Chrome and will translate the file to a base64 string so you can upload it form your local machine to the remove machine.
A working example can be found here
Last but not least, keep in the back of your mind that Protractor is deprecated and with the upcoming release of Selenium 4 you can't use it anymore because it doesn't support W3C. Also check the Protractor repository for more information.
#wswebcreation I have found a solution, it worked by changing the
const fileElem = element(by.css('input[type="file"]'));
to
const fileElem = browser.driver.findElement(by.css('input[type="file"]'));

Puppeteer: Launch Chromium with "Preserve log" enabled

There is this handy feature in DevTools that you are able to preserve log (so it does not clear the content of the console nor the network tab etc. on page reloads / navigation).
At the moment my hand needs to be as fast as a lightning to click the checkbox during debugging if I don't want to miss a thing. I've already looked for corresponding chrome launch flags on peter.sh without a luck.
Is there a way to launch chromium with this feature enabled? Can it be applied with puppeteer?
My set up is so far:
const browser = await puppeteer.launch({ headless: false, devtools: true })
Edit
Thanks to the comment of #wOxxOm I was able to enable it, but the solution requires three additional dependencies on the project: puppeteer-extra, puppeteer-extra-plugin-user-preferences and puppeteer-extra-plugin-user-data-dir.
I would be interested in a solution without extra dependencies, exclusively in puppeteer.
user-preferences example:
const puppeteer = require('puppeteer-extra')
const ppUserPrefs = require('puppeteer-extra-plugin-user-preferences')
puppeteer.use(
ppUserPrefs({
userPrefs: {
devtools: {
preferences: {
'network_log.preserve-log': '"true"'
}
}
}
})
)
I've had some success without any extra packages:
Launch and close a Browser instance for the sole purpose of generating a new user data directory. Ideally you have provided your own path to it.
Locate the Preferences file (it's a JSON file), read it and write to devtools.preferences.
Relaunch a Browser (using the user data directory created in step 1)
Here's some code to get you started:
I've used the official puppeteer-core package so that I can use my local installation of Chrome which is why I provided the executablePath option. You don't need this if you use the full puppeteer package.
const pp = require('puppeteer-core');
const fs = require("fs");
const run = async () => {
const opts = { executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
, devtools: true
, userDataDir: "/tmp/pp-udd"
, args: ["--auto-open-devtools-for-tabs"]
};
// open & close to create the user data directory
let browser = await pp.launch(opts);
await browser.close();
// read & write Preferences
const prefs = JSON.parse(fs.readFileSync("/tmp/pp-udd/Default/Preferences"));
prefs.devtools.preferences['network_log.preserve-log'] = '"true"';
fs.writeFileSync("/tmp/pp-udd/Default/Preferences", JSON.stringify(prefs));
// relaunch with our own Preferences from our own user data directory
browser = await pp.launch(opts);
let page = await browser.newPage();
await page.goto("https://stackoverflow.com/q/63661366/1244884");
};
run();
And here's a screencast:
The first launch is the "launch & close" of step 1
Then there's the second launch that goes to this question ;) with the DevTools open and the "Preserve log" option checked right from the start.

Flutter - How check new verson with Firebase Remote Config

I try to check if my app has new version. If has new version shows a modal to force to update. I use the firebase remote config package.
The code looks
versionCheck(context) async {
PackageInfo info = await PackageInfo.fromPlatform();
RemoteConfig remoteConfig = await RemoteConfig.instance;
await remoteConfig.fetch();
await remoteConfig.activateFetched();
final currentBuildNumber = int.parse(info.buildNumber);
final requiredBuildNumber = remoteConfig
.getInt('android_app_version');
if (requiredBuildNumber > currentBuildNumber) {
versionDialog(context);
}
}
The problem: currentBuildNumber return the correct number, but the requiredBuildNumber always return '50', so the if conditional doesn´t work as expected. Something is wrong but don't i don't know what. What´s is the rigth way to do this?
If the app fetches so many times in a short period of time it the fetch calls are throttled. Because of the throttling limits, it is not possible for your app to immediately see changes in Remote Config values. Cached values will be used until the next fetch is allowed. The default cache expiration is 12 hours. This is done to optimize the network usage by Remote Config feature.
Keep in mind that this setting should be used for development only,
not for an app running in production. If you're just testing your app
with a small 10-person development team, you are unlikely to hit the
hourly service-side quota limits. But if you pushed your app out to
thousands of test users with a very low minimum fetch interval, your
app would probably hit this quota.

How to stop automatically closing browser when writing protractor test cases

I am new to writing test cases using protractor for non angular application. I wrote a sample test case.Here the browser closes automatically after running test case.How can I prevent this. Here is my code
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
});
I was also struggling with a similar issue where i had a test case flow where we were interacting with multiple application and when using Protractor the browser was closing after executing one conf.js file. Now when I looked into the previous response it was like adding delay which depends on how quick your next action i performed or it was hit or miss case. Even if we think from debugging perspective most of the user would be performing overnight runs and they would want to have browser active for couple of hours before they analyze the issue. So I started looking into the protractor base code and came across a generic solution which can circumvent this issue, independent of any browser. Currently the solution is specific to requirement that browser should not close after one conf.js file is executed, then could be improved if someone could add a config parameter asking the user whether they want to close the browser after their run.
The browser could be reused for future conf.js file run by using tag --seleniumSessionId in command line.
Solution:
Go to ..\AppData\Roaming\npm\node_modules\protractor\built where your
protractor is installed.
Open driverProvider.js file and go to function quitDriver
Replace return driver.quit() by return 0
As far as my current usage there seems to be no side effect of the code change, will update if I came across any other issue due to this change. Snapshot of code snippet below.
Thanks
Gleeson
Snapshot of code snippet:
Add browser.pause() at the end of your it function. Within the function itself.
I found Gleeson's solution is working, and that really helped me. The solution was...
Go to %APPDATA%Roaming\npm\node_modules\protractor\built\driverProviders\
Find driverProviders.js
Open it in notepad or any other text editor
Find and Replace return driver.Quit() to return 0
Save the file
Restart your tests after that.
I am using
node v8.12.0
npm v6.4.1
protractor v5.4.1
This solution will work, only if you installed npm or protractor globally; if you have installed your npm or protractor locally (in your folder) then, you have to go to your local protractor folder and do the same.
I suggest you to use browser.driver.sleep(500); before your click operation.
See this.
browser.driver.sleep(500);
element(by.css('your button')).click();
browser.driver.sleep(500);
Add a callback function in It block and the browser window doesn't close until you call it.
So perform the action that you need and place the callback at your convenience
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function(callback) {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
// Have all the logic you need
// Then invoke callback
callback();
});
});
The best way to make browser NOT to close for some time, Use browser.wait(). Inside the wait function write logic for checking either visibilityOf() or invisibilityOf() of an element, which is not visible or it will take time to become invisible on UI. In this case wait() keep on checking the logic until either condition met or timeout reached. You can increase the timeout if you want browser visible more time.
var EC=protractor.ExpectedConditions;
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
browser.wait(function(){
EC.invisibilityOf(submitBtnElm).call().then(function(isPresent){
if(isPresent){
return true;
}
});
},20000,'error message');
});
});
I'm sure there is a change triggered on your page by the button click. It might be something as subtle as a class change on an element or as obvious as a <p></p> element with the text "Saved" displayed. What I would do is, after the test, explicitly wait for this change.
[...]
return protractor.browser.wait(function() {
return element(by.cssContainingText('p', 'Saved')).isPresent();
}, 10000);
You could add such a wait mechanism to the afterEach() method of your spec file, so that your tests are separated even without the Protractor Angular implicit waits.
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
browser.pause(); // it should leave browser alive after test
});
browser.pause() should leave browser alive until you let it go.
#Edit Another approach is to set browser.ignoreSynchronization = true before browser.get(...). Protractor wouldn't wait for Angular loaded and you could use usual element(...) syntax.
Protractor will close browsers, that it created, so an approach that I am using is to start the browser via the webdriver-reuse-session npm package.
DISCLAIMER: I am the author of this package
It is a new package, so let me know if it solves your problem. I am using it with great success.

How do you make the Chrome Developer Tools only show your console.log?

It adds logs when plugins say something. It adds logs when it gets anything from the cache manifest. It logs HTTP information sometimes.
My 1 little log gets flooded by 10,000 logs I don't need or want.
Use only in development:
(function(){
var originalConsole = window.console;
window.console = {};
window.console.log = window.console.debug = window.console.error = function(){};
window.myLog = function() {
originalConsole.log.apply(originalConsole, arguments);
};
}());
This will save a local copy of the original window.console object.
It will change the original window.console object to use empty functions.
And finally it will define a global myLog function which will use the local copy of the original window.console to actually log stuff.
This way all the other code will use the useless console.log() and your code could use myLog().
on the Console tab select No info on the left Hand I have attached a screenshot here
You should update to the google chrome latest version