I have a web application hosted on http://localhost/MyWebApplication. And I am using Coded UI as a tool to perform UI Automation on the application
I have to carry out concurrency kind of scenaios where in two different admin users (say user1 & user2) login to http://localhost/MyWebApplication. When user1 performs any operation like edit or delete the same should be reflected on data for user2
To achieve this, I am logging into MyWebAppliction on IE browser as user1 & Chrome browser as user2. And I am able to launch and login to IE & Chrome as user1 & user2 respectively.
Now after I perform some edit, delete operation on user1 in IE, I need to go back & check if it is reflected in user2 in chrome. And I need to do Vise-versa as well (i.e Chrome to IE)
To switch between the browsers, I have writtent below method to bring the required browser (IE or chrome) to foreground
using System.Runtime.InteropServices;
using System.Diagnostics;
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
public void SwitchBrowserForMyWebApp(string browserName)
{
System.Diagnostics.Process[] p = System.Diagnostics.Process.GetProcessesByName(browserName).Where(x => x.MainWindowTitle.Contains("My Web Application")).ToArray();
if (p.Length > 0)
{
SetForegroundWindow(p[0].MainWindowHandle); // bring the desired browser to the front
}
// ========== Till here it works fine & brings the required browser to the front.
BrowserWindow curWindow;
if (browserName == "iexplore")
{
BrowserWindow.CurrentBrowser = "IE";
}
else
{
BrowserWindow.CurrentBrowser = browserName;
Process browserProcess = p[0];
BrowserWindow bwp = BrowserWindow.FromProcess(p[0]); // Here it gives null exception - Object not set to instance of an object
//BrowserWindow.Locate("My Web Application - Google Chrome");
}
}
Problem I am facing here is, If i bring IE to foreground, then I am able to access controls and perform edit or update
But if I bring chrome to foreground, then I am unable to access any of the controls on chrome.
I tried setting CurrentBrowser as "Chrome", used BrowserWindow.Locate("My Web Application - Google Chrome"), Also used BrowserWindow.FromProcess(p[0]);
Not able to find what is the issue. I am using IE 11 & Chrome version: 47.0.2526.111 m
Can any one let me know if I am missing anything. Or any work around to resolve this issue
Thanks in Advance
I haven't tried this, but Setting the "CurrentBrowser" Property does not switch browsers. This property has to be set before you call the Browser.Launch() Method to initialize the browser driver u use. It's defaulted to IE. U will have to use two different Browser Instance and use the one need. May be something like this,
public static BrowserWindow CurrentBrowser= null, Chrome = null, IE = null;
IE = BrowserWindow.Launch(new Uri("http:\\urAppURLHere.COM"));
BrowserWindow.CurrentBrowser = "Chrome"
Chrome = BrowserWindow.Launch(new Uri("http:\\urAppURLHere.COM"));
CurrentBrowser = GetMeTheBrowserIWant("Chrome");
public static BrowserWindow GetMeTheBrowserIWant(string BrowserType)
{
if(BrowserType.ToUpper().Equals("CHROME")
{
return Chrome;
}
if(BrowserType.ToUpper().Equals("IE")
{
return IE;
}
}
You are Switching the Browser, but the Test Object u identified is still instantiated with Chrome.
You will have to re identify the Test Object using IE Again.
Something like,
GmailLogOnButton = new HtmlControl(GetMeTheBrowserIWant("IE"));
GmailLogOnButton.SearchProperties.Add(HtmlControl.PropertyNames.Id, "signIn");
Coded Ui framework is not developed considering Concurrent execution of Same Steps. So when you try concurrency tests, u will end up doing additional steps.
You, may also consider using Threading, but it may create difficulties in how u sync your tests!!
Related
For starters I used navigator.hid.requestDevice without any filters. So I can see which devices are available before adding a custom filter, but my device doesn't show up in the HID browser device picker.
However, in the chrome device log chrome://device-log/ I can see connection/disconnection events for the device with both HID and USB labels:
I don't think this device is on the block list, so I'm not really sure why it's not showing up as an option when requesting HID devices. It shows up in Windows in the Device Manager under HID category as well.
If I use navigator.usb then the device does show up when requested, but when opened the device gets a Security Error, which possibly means it needs WinUSB driver. It's a HID USB device and works with libs outside of WebHID and WebUSB.
Any reasons it's not showing up?
Edit 1:
My device showed up in chrome://usb-internals/ where I see that it says HID is blocked by WebUSB. Not sure how to solve this yet.
Edit 2:
Using Chrome Canary and the devtools console provided a debug message when using the HID Device picker: Chooser dialog is not displaying a device blocked by the HID blocklist: vendorId=7992, productId=258, name='TEST', serial=''
Looking at the HID blocklist https://github.com/WICG/webhid/blob/main/blocklist.txt I still don't see an issue with the vendor id or product id. The usage page and usage don't match either, but the debug message doesn't mention those, so it's hard to say the exact reason.
Edit 3:
With chrome canary 103.0.5034.0 the new output gives this reason this device is blocked:
Chooser dialog is not displaying a device blocked by the HID blocklist: vendorId=7992, productId=258, name='TEST', serial='', numberOfCollections=1, numberOfProtectedInputReports=0, numberOfProtectedOutputReports=0, numberOfProtectedFeatureReports=0
If you're seeing it in the browser picker when you don't define any filters, it means this device is not blocklisted indeed.
I'd recommend you grab information such as vendorId and productId from https://nondebug.github.io/webhid-explorer/ for instance. After you connect your device, check out vendorId and productId info and use them as filters:
const filters = [{ vendorId: 0x1234, productId: 0x5678 }];
const [device] = await navigator.hid.requestDevice({ filters });
More generally, https://web.dev/hid/ is a great resource to get started with WebHID.
Edit 1
If you're not seeing your device in the browser picker when you don't have any filters but see "HID device added" in about:device-log, it means the browser picker is hiding it (either because it has a top-level collection with a FIDO usage or is blocklisted (https://github.com/WICG/webhid/blob/main/blocklist.txt). See Chromium source code at chrome/browser/ui/hid/hid_chooser_controller.cc:
bool HidChooserController::DisplayDevice(
const device::mojom::HidDeviceInfo& device) const {
// Check if `device` has a top-level collection with a FIDO usage. FIDO
// devices may be displayed if the origin is privileged or the blocklist is
// disabled.
const bool has_fido_collection =
base::Contains(device.collections, device::mojom::kPageFido,
[](const auto& c) { return c->usage->usage_page; });
if (has_fido_collection) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableHidBlocklist) ||
(chooser_context_ &&
chooser_context_->IsFidoAllowedForOrigin(origin_))) {
return FilterMatchesAny(device) && !IsExcluded(device);
}
VLOG(1) << "Not displaying a FIDO HID device.";
return false;
}
if (!device::HidBlocklist::IsDeviceExcluded(device))
return FilterMatchesAny(device) && !IsExcluded(device);
VLOG(1) << "Not displaying a device blocked by the HID blocklist.";
return false;
}
Edit 2
Note that it is possible your device is blocklisted if it doesn't have any collection. See HidBlocklist::IsDeviceExcluded() source code. Is that the case?
By the way, it is possible to disable the HID blocklist by running Chrome with a special flag:
$ chrome --disable-hid-blocklist
See Run Chromium with flags page.
I want to give an extra thanks to François Beaufort for pointing me in the right direction and adding debug logs to Chrome Canary specifically for WebHID testing.
The issue was that WebHID saw the number of input and output reports both as 0 and blocked the device from appearing in the HID device picker. Again, the device I was using works natively on Windows, so this issue was hidden until working with WebHID.
The exact issue was in the HID descriptor of the device firmware in the input & output sections of the HID descriptor. While I can't share the whole descriptor the input and output sections look as follows for the fix:
0x81, 0x00, // INPUT (Data, Var, Abs)
...
...
...
0x91, 0x01, // OUTPUT (Data, Var, Abs)
The first values 0x81 and 0x91 were correct, but the 2nd values needed to be changed to the above values to work. Once the firmware was modified the device immediately displayed using the WebHID device picker. Communication is working fine with WebHID now and the device still works natively on Windows as well.
I am implementing an appium test on remote android driver, with chrome browser for loading urls.
Some of the Urls are pdfs, and chrome asks to store those files. and appears that chrome doesnt have access to filesystem to store those files, which results in a dialog like below.
Please help me pass that dialog without any manual inputs.
Upon clicking continue, it will load actual permissions dialog from Android.
Here is my code initialize appium capabilities
DesiredCapabilities caps = DesiredCapabilities.android();
caps.setCapability("appiumVersion", "1.9.1");
caps.setCapability("deviceName","Samsung Galaxy S9 Plus HD GoogleAPI Emulator");
caps.setCapability("deviceOrientation", "portrait");
caps.setCapability("browserName", "Chrome");
caps.setCapability("platformVersion", "8.1");
caps.setCapability("platformName","Android");
caps.setCapability("autoAcceptAlerts", true);
caps.setCapability("autoGrantPermissions", true);
caps.setCapability("chromedriverArgs", "--allow-file-access-from-files");
caps.setCapability("maxDuration", 10000);
and this is the snippet I use to load a Url
driver.navigate().to("http://kmmc.in/wp-content/uploads/2014/01/lesson2.pdf");
autoGrantPermission also doesnt work in this case because chrome is already installed. Appium team has already rejected this issue -
https://github.com/appium/appium/issues/10008
Please help!
Indeed I had very hard time finding out the solution, but eventually I found a workaround.
The best workaround would have been reinstalling the chrome package. I tried that, but I could not start chrome after reinstalling it, as I had no access to shell, and chromedriver complained. So I left that track.
I tried getting hold of adb command or mobile:changePermissions but for that you need to use server flag --relaxed-security while starting the server, and saucelabs doesnt provide any handy interface to start the server with this flag.
The last resort, I found a solution here - https://stackoverflow.com/a/51241899/4675277 . But just that was not sufficient, because it helped me fix chrome alert, but later on it popped up with another alert with allow and deny, for which another solution in the same question helped me. So this is the code I eventually used -
driver.navigate().to("http://kmmc.in/wp-content/uploads/2014/01/lesson2.pdf");
String webContext = ((AndroidDriver)driver).getContext();
Set<String> contexts = ((AndroidDriver)driver).getContextHandles();
for (String context: contexts){
if (context.contains("NATIVE_APP")){
((AndroidDriver)driver).context(context);
break;
}
}
driver.findElement(By.id("android:id/button1")).click();
contexts = ((AndroidDriver)driver).getContextHandles();
for (String context: contexts){
if (context.contains("NATIVE_APP")){
((AndroidDriver)driver).context(context);
break;
}
}
driver.findElement(By.id("com.android.packageinstaller:id/permission_allow_button")).click();
((AndroidDriver)driver).context(webContext);
This helps allow all permissions required.
I have a UI test which involves the dismissal of a system-generated UIAlertController. This alert asks the user for the permission to access the device's calendar. The objective of the test is the behaviour after a tap on the OK button:
1 let app = XCUIApplication()
...
// this code was basically generated by the recording feature of XCode 7
2 app.alerts.elementBoundByIndex(0).collectionViews.buttons["OK"].tap()
Now, instead of clicking the OK button, line 2 makes the simulator tap onto the first button which happens to be the Cancel button...
Additionally, I found out that the testing framework does not accurately recognize the appearing alert. So if I check the current count of alerts I always get 0:
// ...tap...
let count = app.alerts.count // == 0
This also happens if I use an NSPredicate for the condition and wait for several seconds.
Is it possible that UI tests do not work reliably with system-generated alerts? I am using XCode 7.0.1.
Xcode 7.1 has finally fixed the issue with system alerts. There are, however, two small gotchas.
First, you need to set up a "UI Interuption Handler" before presenting the alert. This is our way of telling the framework how to handle an alert when it appears.
Second, after presenting the alert you must interact with the interface. Simply tapping the app works just fine, but is required.
addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in
alert.buttons["Allow"].tap()
return true
}
app.buttons["Request Location"].tap()
app.tap() // need to interact with the app for the handler to fire
The "Location Dialog" is just a string to help the developer identify which handler was accessed, it is not specific to the type of alert. I believe that returning true from the handler marks it as "complete", which means it won't be called again.
I managed to dismiss access prompt for contacts like this:
let alert = app.alerts["\u{201c}******\u{201d} Would Like to Access Your Contacts"].collectionViews.buttons["OK"]
if alert.exists
{
alert.tap()
}
Replace asterisks with your app's name. It might work the same for calendar.
This is what I ended up using to get the prompt to appear and then allow access to Contacts:
func allowAccessToContacts(textFieldsName: String)
{
let app = XCUIApplication()
let textField = app.textFields[textFieldsName]
textField.tap()
textField.typeText("aaa")
let alert = app.alerts["\u{201c}******\u{201d} Would Like to Access Your Contacts"].collectionViews.buttons["OK"]
if alert.exists
{
alert.tap()
}
textField.typeText("\u{8}\u{8}\u{8}")
}
I'm working with the tvOS beta 3 and trying to do some basic debugging on the tvml/tvjs side of things.
Messages logged via console.log(...) in my js files don't appear in the main Xcode output window.
Is there somewhere else I can find these messages or a setting which needs to be configured?
You should actually use the debug console in Safari. (The developer forum suggests you use Safari 9 and upgrade to El Capitan, both of which I have so haven't been able to test with inferior version)
Open Safari > Develop menu > Simulator
Your app name should appear here once and from there you can use the console.
Give it a few seconds to appear, it's not always instantaneous.
You must give a name to the Bundle Identifier in General/Identity (com.yourcompany.appname) to appear the app in the developers tool.
If you are developing a hybrid application (TVML/TVJS + Swift) with TVMLKitchen you can implement a logging function in Swift and use it in the TVJS code. For my projects I use the following code:
Kitchen.appController.evaluateInJavaScriptContext({context in
let printInJS : #convention(block) (NSString!) -> Void = {
(string : NSString!) -> Void in
print("Log: \(string)\n")
}
context.setObject(unsafeBitCast(printInJS, AnyObject.self), forKeyedSubscript: "printInJS")
})
I am trying to write a chrome.app that is able to open and close chrome.app windows on both displays of a system that is configured with two monitors. When launched, the chrome application establishes a socket connection with a native application running on the same computer, I also open a hidden window via chrome.app.window.create to keep the chrome application up and running. The native application then reads a configuration file and then sends a series of ‘openBrowser’ commands to the chrome application via the socket.
When the chrome application receives an ‘openBrowser’ command, the chrome application makes a call to the chrome API method chrome.app.window.create, passing the create parameters AND a callback function. A code snippet is below:
NPMBrowserManager.prototype.openBrowser = function (browserId,htmlFile,browserBounds,hidden,grabFocus)
{
var browserManager = this;
var createParameters = {};
createParameters.bounds = browserBounds;
createParameters.hidden = hidden;
chrome.app.window.create(htmlFile,createParameters,function(appWindow)
{
// Check to see if I got a non-undefined appWindow.
if(appWindow !== null)
{
browserManager.browsers.push({"browserId":browserId,"window":appWindow});
console.info("NPMBrowserManager.openBrowser: Added browser, id =" + browserId + ", count =" + browserManager.browsers.length);
}
});
}
Unfortunately, the ‘appWindow’, parameter passed in the create callback is always undefined. I suspect it has something to do with the fact that the method openBrowser is itself being called by another method that processes commands received from the native application. However, the window opens exactly here and when I want to to, I just can’t seem to cache away any information about the new window that can be used later to close or move the window.
I want to be able to cache away the appWindow so that I can close or modify the created window later on in the workflow.
As a side note, I’ve noticed that appWindow is NOT undefined if I call the openBrowser method from within the callback that is associated with the chrome.app.runtime.onLaunched event. I suspect it has something to do with the current script context. I was not able to find any chrome.app documentation that goes into any detail about the chrome app architecture.
I would GREATLY appreciate it if anyone out there can explain to me how I can get the appWindow of the window that is created in the chrome.app.window.create method. By the way, I have also tried calling chrome.app.window.current to no avail… Very frustrating!!!
I’d also be interested in any documentation that might exist. I am aware of developer.chrome.com, but could not find much documentation other than reference documentation.
Thanks for the help!
Jim