Am i able to automate custom controls like below
[TestMethod] |
public void LocalSilverlightTest() |
{ |
Manager.LaunchNewBrowser(BrowserType.InternetExplorer); |
ActiveBrowser.NavigateTo("http://localhost:1031/SampleSilverlightAppTestPage.aspx"); |
SilverlightApp app = ActiveBrowser.SilverlightApps()[0]; |
Assert.IsNotNull(app); |
SampleSilverlightApp.MyCustomControl ctrl = app.Find.ByName<SampleSilverlightApp.MyCustomControl>("myCustomControl"); |
Button btn = myCustomControl.Find.ByName<Button>("btnLogin"); |
btn.User.Click(); |
} |
My Custom Control
public partial class MyCustomControl : UserControl |
{ |
public MyCustomControl() |
{ |
InitializeComponent(); |
} |
private void btnLogin_Click(object sender, RoutedEventArgs e) |
{ |
MessageBox.Show("Custom Control"); |
} |
} |
28 Answers, 1 is accepted
With a few modifications to your sample source code I think we can make it work the way you intended:
[TestMethod]
public
void
LocalSilverlightTest()
{
Manager.LaunchNewBrowser(BrowserType.InternetExplorer);
ActiveBrowser.NavigateTo(
"http://localhost:1031/SampleSilverlightAppTestPage.aspx"
);
SilverlightApp app = ActiveBrowser.SilverlightApps()[0];
Assert.IsNotNull(app);
FrameworkElement myCustomControl = app.Find.ByName(
"myCustomControl"
);
Button btn = myCustomControl.Find.ByName<Button>(
"btnLogin"
);
btn.User.Click();
}
Or another much more complicated approach is to write your own wrapper class for accessing your custom control. If you wish to explore this avenue let me know and I'll try to get you started.
Kind regards,
Cody
the Telerik team
Thanks for your replay.
But this is not the one i really needed. I will explain my need.
I will be having a dependency property IsBusy/IsLoading in the Custom User Control.
So whenever i call a WCF service i make this property to true and when the service returns the result i will make it false.
So the requirement is that i should be able to access the IsBusy/IsLoading property of the custom control in the test case for wait condition.
Will the wrapper class do this for me? Any way i would like to know about wrapper class implimentation.
Also is there any code samples for the same online?
Thanks
Kiran
Sure you can fetch the value of any public property attached to a FrameworkElement using code like this:
bool isLoading = (bool)myCustomControl.GetProperty(new AutomationProperty(
"IsLoading"
, typeof(bool)));
You need to know what type the property returns in order to correctly typecast it. You also need to know the exact name (including the correct case) of the property you want to access.
Hope that helps.
Greetings,
Cody
the Telerik team
Thanks a lot for the information.
I tried it and its working. But one question , then what is the need for the wrapper class you mensioned before?
Also how can i access a public propery inside the custom control like this?
Also can you provide a sample for the wrapper.
Thanks
Kiran
I'll address your questions individually:
- what is the need for the wrapper class you mensioned before? - Just to provide an object oriented method of accessing your custom control. Supports code reuse in a larger project instead of having to sprinkle FrameworkElement.<method> etc. throughout your test. Using a wrapper can make your test easier to read and follow later on by yourself or another QA engineer.
- how can i access a public propery inside the custom control like this? - Perhaps I'm missing the point of your question. Didn't we just do that with the myCustomControl.GetProperty method call you just told me is working for you? Am I not understanding your question correctly?
- Also can you provide a sample for the wrapper? - I am sorry we don't have a wrapper sample to publish at this time. They really aren't very hard (if you're used to writing code that is) and are highly customized for each control. Just create your own class and start defining methods to manipulate and get properties of your control.
All the best,
Cody
the Telerik team
Can you provide some code snippets for the wrapper for custom controls.
It really needed coz i have some third pary controls and also some custom lookup controls in my Project.
Thanks in advanced....
I started this thread long back and no one gave a good answer for how to create wrapper for custom controls.
After spending lot of time finally i reflected Telerik.WebAii.Controls.Xaml dll and found out how to create wrapper classes.
I am giving the code snippets also for this. May it help someone like me......
Hi Cody,
If u dont have a sample to show wrapper implimentation i can send u this project solution. Please share your email id.
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
ArtOfTest.WebAii.Silverlight.UI;
using
ArtOfTest.WebAii.Core;
namespace
ControlWrappers
{
public
class
UserLookup : Control
{
public
string
Text
{
get
{
return
this
.SearchTextBox.Text;
}
}
public
TextBox SearchTextBox
{
get
{
return
base
.Find.ByName<TextBox>(
"txtUserName"
);
}
}
public
Button SearchButton
{
get
{
return
base
.Find.ByName<Button>(
"btnLookup"
);
}
}
public
override
void
InitializeMappings(MappingsCollection mappings)
{
mappings.Add(
"UserLookup"
,
"UserLookup"
);
}
public
void
TypeText(
string
text)
{
this
.SearchTextBox.User.Click(MouseClickType.LeftDoubleClick);
this
.SearchTextBox.User.TypeText(text, 50,
false
);
base
.Application.Desktop.KeyBoard.KeyPress(System.Windows.Forms.Keys.Tab, 0);
}
public
void
Search()
{
SearchButton.User.Click();
}
public
void
Search(
string
searchText)
{
SearchTextBox.Text = searchText;
SearchButton.User.Click();
}
}
}
Custom User Control
<
UserControl
x:Class
=
"RadControlSample.UserLookup"
>
<
Grid
x:Name
=
"LayoutRoot"
Background
=
"White"
>
<
StackPanel
>
<
TextBlock
>User Name :</
TextBlock
>
<
TextBox
Name
=
"txtUserName"
></
TextBox
>
<
Button
Name
=
"btnLookup"
Content
=
"Look Up"
Click
=
"btnLookup_Click"
></
Button
>
</
StackPanel
>
</
Grid
>
</
UserControl
>
Test Case
using
System;
using
System.Text;
using
System.Collections.Generic;
using
System.Linq;
using
Microsoft.VisualStudio.TestTools.UnitTesting;
using
ArtOfTest.WebAii.TestTemplates;
using
ArtOfTest.WebAii.Core;
using
ArtOfTest.WebAii.Silverlight;
using
System.Threading;
using
ControlWrapper;
namespace
SilverlightTest
{
[TestClass]
public
class
SampleTest : BaseTest
{
SilverlightApp CurrentApplication;
public
SampleTest()
{
}
private
TestContext testContextInstance;
public
TestContext TestContext
{
get
{
return
testContextInstance;
}
set
{
testContextInstance = value;
}
}
//Use ClassInitialize to run code before running the first test in the class
[ClassInitialize()]
public
static
void
MyClassInitialize(TestContext testContext)
{
}
//Use ClassCleanup to run code after all tests in a class have run
[ClassCleanup()]
public
static
void
MyClassCleanup()
{
}
// Use TestInitialize to run code before running each test
[TestInitialize()]
public
void
MyTestInitialize()
{
Settings settings = GetSettings();
// Override the settings you want. For example:
settings.EnableSilverlight =
true
;
// Now call Initialize again with your updated settings object
Initialize(settings,
new
TestContextWriteLine(
this
.TestContext.WriteLine));
SetTestMethod(
this
, (
string
)TestContext.Properties[
"TestName"
]);
}
// Use TestCleanup to run code after each test has run
[TestCleanup()]
public
void
MyTestCleanup()
{
this
.CleanUp();
}
[TestMethod]
public
void
UserLooupControlWrapperTest()
{
LaunchApplication();
UserLookup userLookup = CurrentApplication.Find.ByName<UserLookup>(
"UserLookupCtrl"
);
userLookup.User.Click();
if
(userLookup !=
null
)
{
userLookup.Search(
"Kiran"
);
}
Thread.Sleep(10000);
}
private
SilverlightApp LaunchApplication()
{
Manager.LaunchNewBrowser(BrowserType.InternetExplorer);
ActiveBrowser.NavigateTo(
"http://localhost:1070/SampleSilverligtAppTestPage.aspx"
);
// Get an instance of the running Silverlight Application.
CurrentApplication = ActiveBrowser.SilverlightApps()[0];
return
CurrentApplication;
}
}
}
This looks great! I also noticed you submitted it to the Code Library. This will earn you Telerik points once reviewed. Thank you very much! I am sorry I didn't have a sample I could share with you.
Kind regards,
Cody
the Telerik team
Hi,
Im looking at automating the custom controls (either inherited from Telerik or Silverlight Toolkit). I am unable to get the instance of the control using the following code.
iButton b = app.Find.ByName("MyBtn").CastAs<
iButton
>();
b.Content = "My New Text";
Please provide your thoughts to resolve this.
I'm assuming that iButton is the class name of your custom button control that you are using in your Silverlight application? Unfortunately the framework doesn't work this way. The Silverlight controls that we have implemented are all wrapper classes that use methods of our framework for communicating with your Silverlight application in order to fetch the state and properties of the various controls.
The .CastAs function requires you to cast it to something that is derived from our ArtOfTest.WebAii.Silverlight.FrameworkElement class. You could possibly write your own wrapper class for accessing the properties of your iButton object that derives from our ArtOfTest.WebAii.Silverlight.FrameworkElement base class.
Best wishes,
Cody
the Telerik team
Could you please post or attach a sample code on wrapping a custom control so as to access its properties and methods.
Thanks,
Satish
Few posts back Kiran has created such wrapper for his UserLookup control.
Perhaps you can examine his approach and implemented it for you iButton control.
Nikolai
the Telerik team
I went through the sample by Kiran. The wrapper was built around TextBox and Button which are WebAii controls. My control is a custom control which is not inherited from WebAii. It is either derived from RadControls or Sivlerlight toolkit. Please let me know how to access the properties and methods of my custom controls with a code snippet.
Thanks.
>>My control is a custom control which is not inherited from WebAii
That is where our wrappers come in. You need a wrapper that inherits from the WebAii wrapper your custom control inherits respectively. For example if the custom control inherits from RadButton, your WebAii wrapper should extend the RadButton WebAii wrapper.
It really depends what property would you like to get and use in the wrapper. Is there a public property of the custom control in question which value you would like to get and expose in the wrapper? If so take a look at the AutomationProperty approach we used in the CodeLibrary. You can take a look at it here.
In general we recommend exposing wrapper properties and methods operating against the visual tree in Silverlight. This is what you actually see as part of the application.
Let us know if you have additional questions.
Sincerely yours,
Konstantin Petkov
the Telerik team
Thank you. I am now able to access the properties of my custom controls. I found ways to access the properties and methods but not events. Could you please let me know how to access the events of my custom controls?
Thanks,
Satish
I'm glad that helped.
No, I don't think we have anything concerning events access currently exposed. Can you please elaborate more on why you need that? What is the actual event of that custom control and how are you going to use that should you have access to that event?
Sincerely yours,
Konstantin Petkov
the Telerik team
Thanks for the immediate response. I am looking at subscribing to custom events which need not be triggered by an UI action. The custom events are raised when a property is changed. Hence to check if the event has been raised, I am looking for an API at WebAii.
Thanks,
Satish
Thank you for the additional info. I'm logging a feature request so that we can add support for tracking events on Silverlight control for future version of the framework.
Thanks for the feedback!
Kind regards,
Konstantin Petkov
the Telerik team
Hi,
I am looking for a way to fetch the value of a custom property in my custom control. The test fails in the line where the Automation Property is used to fetch my custom property. Can a custom property be tested using the AutomationProperty? If not please let me know the alternate way to check for the custom properties.
The following is the code snippet used for your refrence.
MyClass myClass = (MyClass)childElement.GetProperty(new AutomationProperty("MyProperty", typeof(MyClass)));
Please provide your thoughts to resolve this.
Thanks,
Satish
While you have the right approach, our framework can only handle simple return types being returned i.e. bool, int, string. It cannot handle complex types such as your "MyClass" type.
Greetings,Cody
Thanks much for the response. I believe that those interested can contribute to the WebAii features and development. Could you please let me know the procedure so that I can try my hand in the feature additions. Is it possible to get the source code of the WebAii framework?
Thanks,
Satish
We appreciate your interest and enthusiasm. I am sorry to have to report that our WebAii framework project is a closed project wholly owned and controlled by Telerik. We actually use it as the base for our WebUI Test Studio commercial products. Therefore we need to maintain strict control over it.
We very much appreciate your feedback on features and the API. Any recommendations or bug reports are appreciated.
Cody
Thanks for the response. Is there a possibility to get the source code of WebAii framework ? We would like to implement some features to be used in our project. The features (such as support for custom property and support for events) are already requested in this forum.
Thanks.
No I am sorry. The code to the framework is private and cannot be released because it contains some trade secrets.
Kind regards,Cody
Regarding to the lookup there is one tricky thing:
This way it works:
UserLookup userLookup = CurrentApplication.Find.ByName<UserLookup>("UserLookupCtrl");
This way it doesn't:
UserLookup userLookup = CurrentApplication.Find.ByType<UserLookup>();
It doesn't find any element
It's strange because it looks like mapping works only with named controls.
Could You please give a tip what to add to search correctly by type?
What is a "UserLookup"? It is not a standard type included with Test Studio. Does it come from your own custom class? If so did you override the XamlTag property like this?
public
class
UserLookup : FrameworkElement
{
public
override
string
XamlTag
{
get
{
return
"UserLookup"
;
}
}
}
Cody
the Telerik team
Test Studio Trainings
UserLookup was custom control (I took a name from previous posts in this topic :) ).
XamlTag is the property I was looking for, so thx for Your help :)
Excellent. We'll be here if you need further assistance.
Kind regards,Cody
the Telerik team
Test Studio Trainings