Automating windows SaveAs dialog using FlaUI - wpf

I am at my wits end, trying to automate our tests for the Windows SaveAs-dialog.
The thing is that the automation code works on some machines but not all.
It works on my local box and a few other, but we need to make it work on all our test machines. Something is different but what I can see sofar is
Same windows version
Same dotnet --info
The test code I have tried to make work is something like
...
var app = FlaUI.Core.Application.Launch("FlaUISaveDialog.exe");
using (var automation = new UIA3Automation())
{
var window = app.GetMainWindow(automation);
var button1 = window.FindFirstDescendant(cf => cf.ByAutomationId("ClickIt"))?.AsButton();
button1?.Patterns.Invoke.PatternOrDefault.Invoke();
Thread.Sleep(2400); // Wait for window to appear!
var dialog = window.FindFirstDescendant(cf => cf.ByControlType(ControlType.Window));
Thread.Sleep(1000);
var fileNameTextBox = dialog.FindFirstDescendant(e => e.ByAutomationId("1001"));
fileNameTextBox.Focus();
fileNameTextBox.Patterns.Value.Pattern.SetValue(resultFile);
Thread.Sleep(2400);
//FlaUI.Core.Input.Keyboard.Press(VirtualKeyShort.RETURN);
var save = dialog.FindFirstChild(e => e.ByAutomationId("1").And(e.ByControlType(ControlType.Button)));
save.Focus();
var mousePoint = new Point(save.BoundingRectangle.X + save.BoundingRectangle.Width/2, save.BoundingRectangle.Y + save.BoundingRectangle.Height/2);
FlaUI.Core.Input.Keyboard.Press(VirtualKeyShort.RETURN);
//FlaUI.Core.Input.Mouse.Click(mousePoint);
//save.Patterns.Invoke.Pattern.Invoke();
Thread.Sleep(2400); // Wait for file save to complete
Assert.IsTrue(File.Exists(resultFile));
}

After another day going at this, I found that it seems to be the "SetValue" pattern that looks like it works, but doesn't change the Dialogs actual filename.
But moving the mouse,clicking and typing like below actually works:
var fileNameTextBox = dialog.FindFirstDescendant(e => e.ByAutomationId("1001"));
var mousePoint = new Point(fileNameTextBox.BoundingRectangle.X + fileNameTextBox.BoundingRectangle.Width/2, fileNameTextBox.BoundingRectangle.Y + fileNameTextBox.BoundingRectangle.Height/2);
Thread.Sleep(1000);
FlaUI.Core.Input.Mouse.MoveTo(mousePoint);
FlaUI.Core.Input.Mouse.Click(mousePoint);
Thread.Sleep(1000);
FlaUI.Core.Input.Keyboard.TypeSimultaneously(VirtualKeyShort.CONTROL, VirtualKeyShort.KEY_A);
Thread.Sleep(1000);
FlaUI.Core.Input.Keyboard.Type(resultFile);
Thread.Sleep(1000);
FlaUI.Core.Input.Keyboard.Press(VirtualKeyShort.RETURN);
Edit #2: I seems that it is the Windows Explorer option "View File name extensions" that affects the automation behavior of the "SaveFileDialog". If we turn on "View file name extensions" the "SetValue" pattern starts working. Turn the setting off and the "SetValue" stops working! Unexpected, to say the least!

Related

Quartz.net Manually trigger job from Web API

I realize this has sort of been asked before but I want to get a clear confirmation.
I have a Windows Service running the Quartz.Net Scheduler. Jobs and Triggers have been created.
We will have an angular web client that will at times, need to fire jobs manually.
So in a Web API Controller, I have code like this:
var properties = new NameValueCollection
{
["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
["quartz.jobStore.useProperties"] = "true",
["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz",
["quartz.jobStore.dataSource"] = "myDS",
["quartz.jobStore.tablePrefix"] = "QRTZ_",
["quartz.dataSource.NAME.provider"] = "SqlServer",
["quartz.dataSource.NAME.connectionString"] = "Server=localhost;Database=QuartzScheduler;Uid=blahuser;Pwd=blahpwd",
["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz"
};
var sched = new StdSchedulerFactory(properties).GetScheduler().Result;
var jobKey = new JobKey("DailyJob1130EST", "DailyGroup");
var jobDataMap = new JobDataMap();
jobDataMap.Add("listIds", "33333");
sched.TriggerJob(jobKey, jobDataMap);
The Job Name and Group do exist in the database.
I was hoping that the call to TriggerJob would cause the Scheduler I have running in my windows service, to fire the job. But it doesn't. Nothing happens, not even an error.
BTW, I don't want to use remoting since it requires the full .NET Framework and the help docs say that it is considered unsafe.
If TriggerJob doesn't work, I guess to run a job manually I'd have to add a new trigger to the scheduler to run once, or something???
There may be other ways, but one way that I was able to successfully do it was:
var sched = await new StdSchedulerFactory(properties).GetScheduler();
var jobKey = new JobKey("DailyJob1130EST", "DailyGroup");
var jobDataMap = new JobDataMap();
jobDataMap.Add("listIds", rInt.ToString());
var trig = TriggerBuilder.Create()
.WithIdentity("RunNowTrigger")
.StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(5)))
.WithDescription("Run Now Trigger")
.Build();
sched.TriggerJob(jobKey, jobDataMap);
Note: "properties" were my NameValueCollection config information, which I omitted from the sample code. It was nothing out of the ordinary. It just setup the jobStore, dataSource, serializer.type and threadPool.type settings.

Handling multiple windows in IE and Chrome browsers

In the below code,
//Element clicked in parent window
driver.findElement(By.id("ID")).click();
//Once after clicking the ID, system takes the user to a different tab in chrome and launches an external link
//In IE the same external link will launch in a new browser which is different from chrome behavior
Iterator<String> browsers = driver.getWindowHandles().iterator();
while(browsers.hasNext()){
driver.switchTo().window(browsers.next());
//Element to be clickable in the child window or external site
driver.findElement(By.xpath(".//button")).click();
Can anyone help me out how can we handle the scenario,i want something which works both in IE and chrome. Currently the above code works in chrome but not in IE as the external link opens in a new browser. I am not able to handle the scenario
Try the below method for IE:
Java:
DesiredCapabilities cap = DesiredCapabilities.internetExplorer();
cap.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS,true);
cap.setCapability(InternetExplorerDriver.IGNORE_ZOOM_SETTING,true);
cap.setCapability(InternetExplorerDriver.UNEXPECTED_ALERT_BEHAVIOR,"accept");
cap.setCapability(InternetExplorerDriver.REQUIRE_WINDOW_FOCUS,true);
cap.setCapability(InternetExplorerDriver.INITIAL_BROWSER_URL,"");
WebDriver dr = new InternetExplorerDriver(cap);
C#:
var options = new InternetExplorerOptions();
options.IntroduceInstabilityByIgnoringProtectedModeSettings = true;
options.EnsureCleanSession = true;
options.IgnoreZoomLevel = true;
options.UnhandledPromptBehavior = UnhandledPromptBehavior.Accept;
options.RequireWindowFocus = true;
options.InitialBrowserUrl = "";
string iedriver = TestContext.DataRow["IEDRIVER"].ToString();
dr = new InternetExplorerDriver(iedriver,options);

WPF native windows 10 toasts

Using .NET WPF and Windows 10, is there a way to push a local toast notification onto the action center using c#? I've only seen people making custom dialogs for that but there must be a way to do it through the os.
You can use a NotifyIcon from System.Windows.Forms namespace like this:
class Test
{
private readonly NotifyIcon _notifyIcon;
public Test()
{
_notifyIcon = new NotifyIcon();
// Extracts your app's icon and uses it as notify icon
_notifyIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
// Hides the icon when the notification is closed
_notifyIcon.BalloonTipClosed += (s, e) => _notifyIcon.Visible = false;
}
public void ShowNotification()
{
_notifyIcon.Visible = true;
// Shows a notification with specified message and title
_notifyIcon.ShowBalloonTip(3000, "Title", "Message", ToolTipIcon.Info);
}
}
This should work since .NET Framework 1.1. Refer to this MSDN page for parameters of ShowBalloonTip.
As I found out, the first parameter of ShowBalloonTip (in my example that would be 3000 milliseconds) is generously ignored. Comments are appreciated ;)
I know this is an old post but I thought this might help someone that stumbles on this as I did when attempting to get Toast Notifications to work on Win 10.
This seems to be good outline to follow -
Send a local toast notification from desktop C# apps
I used that link along with this great blog post- Pop a Toast Notification in WPF using Win 10 APIs
to get my WPF app working on Win10. This is a much better solution vs the "old school" notify icon because you can add buttons to complete specific actions within your toasts even after the notification has entered the action center.
Note- the first link mentions "If you are using WiX" but it's really a requirement. You must create and install your Wix setup project before you Toasts will work. As the appUserModelId for your app needs to be registered first. The second link does not mention this unless you read my comments within it.
TIP- Once your app is installed you can verify the AppUserModelId by running this command on the run line shell:appsfolder . Make sure you are in the details view, next click View , Choose Details and ensure AppUserModeId is checked. Compare your AppUserModelId against other installed apps.
Here's a snipit of code that I used. One thing two note here, I did not install the "Notifications library" mentioned in step 7 of the first link because I prefer to use the raw XML.
private const String APP_ID = "YourCompanyName.YourAppName";
public static void CreateToast()
{
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(
ToastTemplateType.ToastImageAndText02);
// Fill in the text elements
XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
stringElements[0].AppendChild(toastXml.CreateTextNode("This is my title!!!!!!!!!!"));
stringElements[1].AppendChild(toastXml.CreateTextNode("This is my message!!!!!!!!!!!!"));
// Specify the absolute path to an image
string filePath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + #"\Your Path To File\Your Image Name.png";
XmlNodeList imageElements = toastXml.GetElementsByTagName("image");
imageElements[0].Attributes.GetNamedItem("src").NodeValue = filePath;
// Change default audio if desired - ref - https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-audio
XmlElement audio = toastXml.CreateElement("audio");
//audio.SetAttribute("src", "ms-winsoundevent:Notification.Reminder");
//audio.SetAttribute("src", "ms-winsoundevent:Notification.IM");
//audio.SetAttribute("src", "ms-winsoundevent:Notification.Mail"); // sounds like default
//audio.SetAttribute("src", "ms-winsoundevent:Notification.Looping.Call7");
audio.SetAttribute("src", "ms-winsoundevent:Notification.Looping.Call2");
//audio.SetAttribute("loop", "false");
// Add the audio element
toastXml.DocumentElement.AppendChild(audio);
XmlElement actions = toastXml.CreateElement("actions");
toastXml.DocumentElement.AppendChild(actions);
// Create a simple button to display on the toast
XmlElement action = toastXml.CreateElement("action");
actions.AppendChild(action);
action.SetAttribute("content", "Show details");
action.SetAttribute("arguments", "viewdetails");
// Create the toast
ToastNotification toast = new ToastNotification(toastXml);
// Show the toast. Be sure to specify the AppUserModelId
// on your application's shortcut!
ToastNotificationManager.CreateToastNotifier(APP_ID).Show(toast);
}
UPDATE
This seems to be working fine on windows 10
https://msdn.microsoft.com/library/windows/apps/windows.ui.notifications.toastnotificationmanager.aspx
you will need to add these nugets
Install-Package WindowsAPICodePack-Core
Install-Package WindowsAPICodePack-Shell
Add reference to:
C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Windows.winmd
And
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETCore\v4.5\System.Runtime.WindowsRuntime.dll
And use the following code:
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04);
// Fill in the text elements
XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
for (int i = 0; i < stringElements.Length; i++)
{
stringElements[i].AppendChild(toastXml.CreateTextNode("Line " + i));
}
// Specify the absolute path to an image
string imagePath = "file:///" + Path.GetFullPath("toastImageAndText.png");
XmlNodeList imageElements = toastXml.GetElementsByTagName("image");
ToastNotification toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier("Toast Sample").Show(toast);
The original code can be found here: https://www.michaelcrump.net/pop-toast-notification-in-wpf/
I managed to gain access to the working API for windows 8 and 10 by referencing
Windows.winmd:
C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral
This exposes Windows.UI.Notifications.
You can have a look at this post for creating a COM server that is needed in order to have notifications persisted in the AC with Win32 apps https://blogs.msdn.microsoft.com/tiles_and_toasts/2015/10/16/quickstart-handling-toast-activations-from-win32-apps-in-windows-10/.
A working sample can be found at https://github.com/WindowsNotifications/desktop-toasts

unable to take screenshot of mouseover in selenium

I am trying to take screenshot of sub menu which happens on hovering in selenium using TakesScreenshot. But this is not working. Screenshot is taken but sub menu is not present in the image.
I have also tried using implicit wait after hover, but nothing worked.
Please suggest a method to capture screenshot of the sub menu.
contactUs.hoverHM();
screenshot = ((TakesScreenshot) PageFactoryBase.getSharedWebDriver()).getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png");
This did the trick for me. I am pretty sure it will work for you.
_driver = new FirefoxDriver();
_driver.Navigate().GoToUrl("http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_event_mouseover_mouseout");
_driver.SwitchTo().Frame(_driver.FindElement(By.Id("iframeResult")));
Actions builder = new Actions(_driver);
builder.MoveToElement(_driver.FindElement(By.TagName("p"))).Build().Perform();
var screenshot = ((ITakesScreenshot)_driver).GetScreenshot();
var filename = new StringBuilder("D:\\");
filename.Append(DateTime.Now.ToString("HH_mm_ss dd-MM-yyyy" + " "));
filename.Append("test");
filename.Append(".png");
screenshot.SaveAsFile(filename.ToString(), System.Drawing.Imaging.ImageFormat.Png);
After hovering mouse on the text, it turns yellow and below is the screen shot that I took.
Below is another approach where you can use 'Print screen' Key in your Test code and get the image from the clipboard in the system.
What is have done is used KeyEvent 'PRTSC' to get the Image into the system clipboard and then get the system clipboard to write it to a file. I hope it will also copy the mouseover.
Robot rob = new Robot();
rob.keyPress(KeyEvent.VK_PRINTSCREEN);
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable content = clip.getContents(null);
BufferedImage img = (BufferedImage)content.getTransferData(DataFlavor.imageFlavor);
ImageIO.write(img, "png", new File("D:\\test.png"));
I have tried the same scenario but for clickAndHold for hover skin. It worked for me with the help of Actions as below:
WebElement elm = driver.findElement(By.id("btn1"));
Actions builder = new Actions(driver);
Action act = builder.clickAndHold(elm).build();
act.perform();
try {
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("c:\\Img\\screenshot.png"));
} catch (IOException e) {
e.printStackTrace();
}
act = builder.release(elm).build();
act.perform();
You can instead replace clickAndHold with moveToElement Mouse hover the element. take the screenshot then release the element or move away from it.
Thanks everyone for answering on this thread.
I am able to take screenshot using robot as suggested by Vivek.
builder.moveToElement(getSharedWebDriver().findElement(By.xpath("//div[#class='brand section']/ul/li[#class='active hasflyout']"))).perform();
Robot robot = new Robot();
Point point;
point = getSharedWebDriver().findElement(By.xpath("//div[#class='brand section']/ul/li[#class='active hasflyout']")).getLocation();
int x = point.getX();
int y = point.getY();
robot.mouseMove(x,y);
In ideal case, either perform() or mouseMove() should be used. But somehow in my case, i had to use both the functions.

Mono winforms app fullscreen in Ubuntu?

Just wondering if there's a known way of getting a Mono System.Windows.Forms application to go fullscreen on Ubuntu/Gnome.
Mono is 2.4.2.3
Ubuntu is 9.10
Doing it on Windows requires a pinvoke, clearly not going to work here.
This is what I get setting window border to none, window position to centre, and state to maximised:
alt text http://dl.dropbox.com/u/116092/misc/permalink/joggler/screenshot01.png
Update.
Have also tried:
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
CTRL-F11
Text = string.Empty; // No caption
MaximizeBox = false;
MinimizeBox = false;
ControlBox = false;
FormBorderStyle = None;
WindowState = Maximized;
FormBorderStyle = FormBorderStyle.None;
Location = new Point(0, 0);
Size = Screen.PrimaryScreen.Bounds.Size;
All of which I end up with the same result.
I have come across a lead which involves a pinvoke involving _NET_WM_STATE_FULLSCREEN but that's as far as I've got with it. Any pointers on that would be appreciated.
_NET_WM_STATE_FULLSCREEN will just get rid of the borders. The GNOME panel will still appear.
According to the following post, the secret is to get rid of the minimum/maximum sizes so that the window manager does the resizing itself:
http://linux.derkeiler.com/Mailing-Lists/GNOME/2010-01/msg00035.html
Here is some documentation on the native spec:
http://standards.freedesktop.org/wm-spec/wm-spec-latest.html
http://www.x.org/docs/ICCCM/icccm.pdf
To talk directly to the X Window System you have to pinvoke into XLib. In order to send something like _NET_WM_STATE_FULLSCREEN you have to have a pointer to the window and also to the display.
I am not sure how to find the display but I can help with a pointer to the window. When running on X, the property Form.Handle should be a pointer to the X window.
Not sure what you mean by "Full Screen" - but I've written several Windows.Forms applications that take over the screen, and without a single PInvoke.
Here's how I configure my main form ...
Text = string.Empty; // No caption
MaximizeBox = false;
MinimizeBox = false;
ControlBox = false;
FormBorderStyle = None;
WindowState = Maximized;
Optionally,
TopMost = true;
Hope this helps.
You need to disable visual effects in ubuntu.
edit:
And make sure your form size is at least screen resolution without borders. If borders are on design time and you are removing them in code you will need something like 1030x796 for a 1024x768 display.
I have been suffered by this problem 2 days and finally i got the solution:
click the 1st icon on left tool bar and search compizconfig program. Go to preference-> unity and you will see there is a tick for unity plugin on the left side. Remove that tick and you will see the top menu bar disappeared.
Though this thread is very old but I still hope I can help anyone who gets this problem and seek for help.
Have you tried this?
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
Unfortunately I have no Ubuntu available right now, but I can see old patches for this in old mono versions...
It should be possible to display every app running inside gnome in fullscreen mode with the "CTRL+F11" hotkey.
Maybe you could try
System.Windows.Forms.SendKeys.Send();
but that is just a guess, I haven't got a Linux running atm to try this. But maybe this helps.
I can't test it at the moment, but have you tried a simple resize?
form.FormBorderStyle = FormBorderStyle.None
form.Location = Point(0, 0)
form.Size = Screen.PrimaryScreen.Bounds.Size
I have worked around this for now by setting the autohide property of the panel.
Not ideal because it depends on the user changing their environment to use my application, but better than nothing.
YMMV. http://fixunix.com/xwindows/91585-how-make-xlib-based-window-full-screen.html
The following worked:
(Inspiration was taken from here: https://bugzilla.xamarin.com/show_bug.cgi?id=40997)
1) sudo apt-get install wmctrl
2) In your code:
Form form = new MainWindow();
form.FormBorderStyle = FormBorderStyle.None;
form.WindowState = FormWindowState.Maximized;
form.Load += (s, e) => {
Process process = new Process {
StartInfo = new ProcessStartInfo {
FileName = "wmctrl",
Arguments = $"-r :ACTIVE: -b add,fullscreen",
CreateNoWindow = true
}
};
process.Start();
process.WaitForExit();
};
Application.Run(form);

Resources