Automating a routine procedure in Windows 10 (Mostly interacting with the browser) - javascript

I'm trying to figure out if I can automate the following tasks,
Open the IE
Navigate to a site
Enter login and password
From the user page - Search XXX
Right click on the returned result
From the drop down menu Left click save
Save to a designated folder
I need to repeat this task for 500 times, what's the best way to go about it? I'm thinking of creating a VB Script but not sure if I can do all above with it..
I also found that this can be done in javascript as well? but I don't even know where to start from.
Can someone please give me the right direction? thanks,

1) Yes, you can do it with the Windows Script Host using VBScript or JScript (doesn't matter), using the InternetExplorer.Application COM object.
For details, check this thread: Vbscript for automated website login testing
See also the MSDN documentation about the IE object model: https://msdn.microsoft.com/en-us/library/ms970456.aspx
VBScript example by Francis MacDonald copied from the other thread:
Dim IE
Dim Helem
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = 1
IE.navigate "http://www.example.com"
Set Helem = IE.document.getElementByID("formUsername")
Helem.Value = "username" ' change this to yours
Set Helem = IE.document.getElementByID("formPassword")
Helem.Value = "password" ' change this to yours
Set Helem = IE.document.Forms(0)
Helem.Submit
Do While (IE.Busy)
WScript.Sleep 10
Loop
Dim someElement
Set someElement = IE.document.getElementByID("someElement")
If Len(someElement.innerText) > 0 Then
MsgBox "logged in"
End If
2) There is a tool designed specifically for this task which may help you further: Selenium.

Related

How can an image be saved with JavaScript for Automator (JXA) in macOS Preview application?

There is an image open in the Preview application, and it is unsaved.
I have tried this code, by building and running a standalone script in Script Editor:
var preview = Application('Preview')
var preview.documents[0].close({ saving: true, savingIn: '/Volumes/USB Drive/Untitled-Image.png' })
I see this in the logs
app = Application("Preview")
app.documents.at(0).Symbol.toPrimitive()
--> Error -1700: Can't convert types.
app.documents.at(0).Symbol.toPrimitive()
--> Error -1700: Can't convert types.
However, I'm not sure I'm reading the docs correctly, and I'm not sure how to further debug this code. A satisfactory alternative here would be to send a keystroke to save and click the Save button.
What can I do to persist the image in Preview to a file?
One can declare paths speculatively in JavaScript using Path('...'), and then use the save command to save the image to the file that will be created at that path:
Preview = Application('com.apple.Preview');
ImageFilepath = Path('/Users/CK/Pictures/Preview_SavedImage.jpg');
Preview.documents[0].save({ in: ImageFilepath });
This code worked for me.
var preview = Application('Preview')
var photo = preview.documents[0]
photo.close({ saving: 'yes', savingIn: Path("/Path/To Some/file_name.png") })
Upon execution, in the Replies log of Script Editor window, something slightly different from the question sample is logged.
app = Application("Preview")
app.close(app.documents.at(0), {savingIn:Path("/Path/To Some/file_name.png"), saving:"yes"})
I was able to figure this out by studying the scripting dictionary for macOS Mojave 10.14 as well as the Release Notes for JXA; there is a similar example under Passing Event Modifiers section of that.
From the Script Editor scripting dictionaries, this is the entry for the close method in the Standard Suite:
close method : Close a document.
close specifier : the document(s) or window(s) to close.
[saving: "yes"/‌"no"/‌"ask"] : Should changes be saved before closing?
[savingIn: File] : The file in which to save the document, if so.
Note the key differences between the working code here and the code in the question:
Specify a Path object when passing the savingIn option to close.
Specify a the saving option as one of "yes", "no", or "ask" (not true).
If you're new to JXA, Automator, and/or Script Editor for Mac, checkout the JXA Cookbook.
If this answer helps you, you're probably having a bad time, so best of luck!

Capture browser console logs with capybara

I need to capture the console logs (category: info) of a browser using Ruby & Capybara. Until now I have tried using driver.manage.logs.get(:browser) or (:client) but, using this, the result is not what I want. It gives out the interaction results between selenium and browser where I can see my javascript statements sent for execution, but the resulting output fails to get captured.
Whether or not logs are available when using selenium depends on what browser you are using with Selenium. If you were using Firefox you'd be out of luck since it doesn't support the log retrieval API, however since you're using Chrome they are accessible. The issue you're having is that, by default, only WARN or ERROR level logs are captured. You can change this in the driver registration through the loggingPrefs capability
Selenium 3
Capybara.register_driver :logging_selenium_chrome do |app|
caps = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs:{browser: 'ALL'})
browser_options = ::Selenium::WebDriver::Chrome::Options.new()
# browser_options.args << '--some_option' # add whatever browser args and other options you need (--headless, etc)
Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options, desired_capabilities: caps)
end
Selenium 4
Capybara.register_driver :logging_selenium_chrome do |app|
options = Selenium::WebDriver::Chrome::Options.new
options.add_option("goog:loggingPrefs", {browser: 'ALL'})
browser_options = ::Selenium::WebDriver::Chrome::Options.new()
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new(app,
capabilities: options,
browser: :chrome)
end
end
and then specify to use :logging_selenium_chrome as your driver
Capybara.javascript_driver = :logging_selenium_chrome # or however else you're specifying which driver to use
which should then allow you to get the logs in your tests with
page.driver.browser.manage.logs.get(:browser)
Thomas Walpole answer is correct but it seems that nowadays if you are using chrome as your driver you should use
Selenium::WebDriver::Remote::Capabilities.chrome( "goog:loggingPrefs": { browser: 'ALL' } )
Notice goog:loggingPrefs instead of loggingPrefs only with this solution i was able to get console.log printed in the log.
Took me a while and got it from here https://intellipaat.com/community/5478/getting-console-log-output-from-chrome-with-selenium-python-api-bindings after several frustrating attempts.
November 2022 update, use:
page.driver.browser.logs.get(:browser)
Not sure that this is what you want, but take a look at https://github.com/dbalatero/capybara-chromedriver-logger.
It helps me identify the problem with dynamic modules import(''). Works both locally and in Github Actions / Circle CI by displaying failed loads of assets (which i believe outputs as console.error).

Synchronization problems with automated testing Angular website with Selenium and testing issues with Internet Explorer.

I am trying to write an automated test program for one of my website using Selenium WEbDriver. I am having some problems when doing the test on Internet Explorer. The website that I am trying to test is built in AngularJS. I will explain my problems in detail.
Here, is the code that waits until Angular has finished processing.
private static ExpectedCondition angularHasFinishedProcessing() {
return (ExpectedCondition<Boolean>) driver -> {
String hasAngularFinishedScript = "var callback = arguments[arguments.length - 1];\n" +
"var el = document.querySelector('html');\n" +
"if (!window.angular) {\n" +
" callback('false')\n" +
"}\n" +
"if (angular.getTestability) {\n" +
" angular.getTestability(el).whenStable(function(){callback('true')});\n" +
"} else {\n" +
" if (!angular.element(el).injector()) {\n" +
" callback('false')\n" +
" }\n" +
" var browser = angular.element(el).injector().get('$browser');\n" +
" browser.notifyWhenNoOutstandingRequests(function(){callback('true')});\n" +
"}";
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
assert javascriptExecutor != null;
String isProcessingFinished = javascriptExecutor.executeAsyncScript(hasAngularFinishedScript).toString();
return Boolean.valueOf(isProcessingFinished);
};
}
private void waitForAngular() {
WebDriverWait wait = new WebDriverWait(driver, 15, 100);
wait.until(angularHasFinishedProcessing());
}
And here is the code that instantiates WebDriver for Internet Explorer.
System.setProperty("webdriver.ie.driver",
new File("H:/libraries/webdrivers/IEDriverServer.exe").getAbsolutePath());
DesiredCapabilities d = DesiredCapabilities.internetExplorer();
// To bypasse the Protected Mode settings of IE
d.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
driver = new InternetExplorerDriver(d);
driver.manage().timeouts().setScriptTimeout(30, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.get("https://arandomangularjsapp.com"); // Let's suppose this
I had to bypass the Protected Mode settings (shown in above code) because I was constantly getting this Exception
Caused by: org.openqa.selenium.WebDriverException: Unexpected error launching Internet
Explorer. Protected Mode must be set to the same value (enabled or disabled) for all
zones. (WARNING: The server did not provide any stacktrace information)
though I made sure that protected mode was enabled and same values were set for all zones.
Now comes the real issue I am having. Look at this block of code,
waitForAngular();
WebElement el = driver.findElement(By.xpath("//div[#class='events-list__event-info' and #id='48040']" +
"//following-sibling::div[#class='events-list__event-buy']/a"));
if(driver.toString().toUpperCase().contains("INTERNETEXPLORER"))
el.sendKeys(Keys.ENTER);
else
el.click();
waitForAngular();
webElement = driver.findElement(By.xpath("(//div[#class='ticket u-cf ng-scope'])[1]//select"));
select = new Select(webElement);
select.selectByIndex(1);
My first question, the way I am trying to wait for Angular app to get ready by calling waitForAngular(), is it a good way? In my program I even had to use Thread.sleep() so many times in order to let elements to properly render before I could invoke actions on them. It would be great if you guys can suggest me a proper way to use Selenium WebDriver along with Angular App.
Now let's talk about my second issue. I had to completely disable Protected Mode from Internet Explorer's options in order to run the program. Otherwise, I would get this exception,
Caused by: org.openqa.selenium.JavascriptException: JavaScript error in async script. (WARNING: The server did not provide any stacktrace information)
I get this exception when trying to execute waitForAngular(). What could be causing this? Is there any way by which I could keep the Protected Mode enabled and still be able to execute that script inside angularHasFinishedProcessing() method?
Finally, my third problem is related to click action not being triggered. Forget about the previous issues for a second. I disabled IE's Protected Mode, so my program starts IE without throwing any exception. The program successfully finds the first element as shown in the code above. But, the click action is not triggered, browser thus doesn't navigate to next page, and the program fails to find the second element. As a workaround I even tried el.sendKeys(Keys.ENTER); but it didn't work.** So, am I having this problem because I bypassed/disabled Protected Mode? Or, is there something else that I am not being able to see?**
I run tests on IE, Opera, Chrome and Firefox and the problem seems to occur only in IE. Any sort of help, suggestions or guidelines are highly appreciated.
Thank You.

Make an AppJS project into a single exe

I have been reading online for days and I am unable to find a solution for this that I can get working.
I would like a single exe file that unpacks to temporary location when you run the file which can be shared and sent to people. Ideally I would like to hide my JavaScript files.
I just need 1 file that can be sent easily.
-Fasani
i don't know of any simple way to do this
but i had a similar problem a while ago and i created a VB.Net program to do this for me
First download portable 32bit version of node here : Node.exe
if you have visual studio installed create a new project then from the solution explorer go to your projects properties and add node.exe and your .js file as Resources.
then in the formload (if you don't want your program to have a ui) or in a buttons click event place these code:
Try
Dim tmpp = System.IO.Path.GetTempPath & "NodeTmp"
If (Not System.IO.Directory.Exists(tmpp)) Then System.IO.Directory.CreateDirectory(tmpp)
If Not System.IO.File.Exists(tmpp & "\tmp_node.exe") Then _
My.Computer.FileSystem.WriteAllBytes(tmpp & "\node.exe", My.Resources.node, False)
System.IO.File.WriteAllText(tmpp & "\jsfile.js", My.Resources.jsfile)
System.IO.File.WriteAllText(tmpp & "\batfile.bat", """" & tmpp & "\tmp_node.exe"" """ & tmpp & "\jsfile.js""")
Dim p As New Process()
p.StartInfo.FileName = "cmd.exe"
p.StartInfo.Arguments = "/C """ & tmpp & "\pz.bat"""
p.StartInfo.CreateNoWindow = True
p.StartInfo.UseShellExecute = False
p.Start()
'Timer1.start()
Catch ex As Exception
MsgBox("Error")
End Try
the above code creates a folder called NodeTmp in the C:\user{name}\appdata\local\Temp and extracts node.exe (from a file resorce called "node") in that folder then extracts jsfile.js (from a file resource called "jsfile") in the same folder then creates a .bat file and runs it
to Delete .js file after it is run (it is created and deleted in less then 1sec so it is kind of hidden from user):
create a timer called Timer1 and set its interval to something like 150ms and uncomment the line Timer1.start() from above code and put the following sub somewhere in code
Sub pz_cleanup() Handles Timer1.tick
Try
Dim tmpp = System.IO.Path.GetTempPath & "PZT"
System.IO.File.Delete(tmpp & "\pz.bat")
System.IO.File.Delete(tmpp & "\pz.js")
Timer1.stop()
Catch ex As Exception
End Try
End Sub
This is definitely not the best way to do this , but it worked for me , the only downside it had for me so far was its need for .net framework to be installed on other users computer which not all of them had it
if you want a cmd to open and show nodes output comment the line that sets CreateNoWindow to true
----- not part of answer but if you want to have a UI and put a close button there to so users don't have to end task node from taskmanager use this code:
Try
Dim pProcess() As Process = System.Diagnostics.Process.GetProcessesByName("tmp_node")
For Each p As Process In pProcess
p.Kill()
p.WaitForExit()
Next
Catch ex As Exception
MsgBox("Error")
Return True
End Try
hope this helps , you can do similar thing in other languages too if you are more comfortable with them then VB.Net

equivalent of browserField.displayContent() in javascript

I tried to create my own app for BlackBerry using BlackBerry workflow SDK and phonegap.
I have a web service which sends html code and I need to use this code in a new window. I tried
window.document.write('test'); But when I use the back button on the phone, the application just quits.
Resolution without html code but url :
//Invoke blackberry browser
var args = new blackberry.invoke.BrowserArguments(url);
blackberry.invoke.invoke(blackberry.invoke.APP_BROWSER, args);
BlackBerry WebWorks only has one window. You will need to work with that.
So, There are a couple ways you can do what I think you're looking to achieve.
1 - If you just need to show the new html and you dont care about the back button working you can just insert the html into the current page
document.querySelector("body").innerHTML = htmldata;
2 - If you need the back button to will need to save the htmlData to localStorage and change pages, then load the stored html.
localStorage.setItem("htmldata", htmlData);
window.location.href = "page2.html";
document.querySelector("body").innerHTML = localStorage.getItem("htmldata");;
EDIT
3 - Trap hardware key
blackberry.system.event.onHardwareKey(blackberry.system.event.KEY_BACK, handleBack);
function handleBack() {
alert("handle back button");
}

Categories