I am building a testing framework, my objective is to test many websites that have similar pages with light difference between each other using this framework.
I have an issue where I want WebElements Selectors to be dynamic, which means that I want to pass the way I want to find the element as a parameter to FindElement method.
I am trying to build something like this:
public class WebComponent
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public IWebElement WebElement{get;set;}
public Accessor Accessor { get; set; }
public WebComponent()
{
Accessor = new Accessor();
}
}
public class Accessor
{
OpenQA.Selenium.By By { get; set; }
public string Value { get; set; }
}
And later in my code when I want to have instance of this class:
WebComponent component = new WebComponent();
component.ID = 1;
component.Name = "Logout Button";
component.Description = "The button to click when user wants to logout of website";
component.Accessor.By = By.Id;
component.Accessor.Value = "logout";
component.WebElement = Browser.Driver.FindElement(//missing code);
My question is how can I find the WebElement using component.Accessor, any advice or suggested edits will be much appreciated.
By.Id is a method group, you can't assign it to type OpenQA.Selenium.By. The assignment should be
component.Accessor.By = By.id("logout"); // or any other By and value.
And then you can locate the element using
component.WebElement = Browser.Driver.FindElement(component.Accessor.By);
Edit
To choose the locator and value dynamically you can do something like
private By chooseType(String locatorType, string value) {
switch(locatorType) {
case "id":
return By.id(value);
case "class":
return By.className(value);
//...
}
}
Related
Let's say we have a document like this
public class Event
{
public string Id { get; set; }
public EntityDescriptor Venue { get; set; }
// Other properties omitted for simplicity
}
public class EntityDescriptor
{
public string Id { get; set; }
public string Name { get; set; }
}
And an index like this
public class Events : AbstractIndexCreationTask<Event>
{
public Events()
{
Map = items => from e in items
select new
{
Venue_Id = e.Venue.Id,
Venue_Name = e.Venue.Name
};
}
}
When trying to sort on Event.Venue.Id
session.Query<Event, Events>().Take(10).OrderBy(e => e.Venue.Id).ToArray();
the sent request is
/indexes/Events?&pageSize=10&sort=__document_id&SortHint-__document_id=String
Is this by design or a bug?
PS: OrderBy(e => e.Venue.Name) works as expected (sort=Venue_Name).
It's not a bug. __document_id is the special known field containing the ID of the document. It's there regardless of whether you have an .Id property.
edit
I misread your question. This indeed appears to be a bug. I recommend you send a simple repro case to the Raven forum and let them know which RavenDB version you're using.
I want to use ReadAsAsync() in my mvc project with .net 4.0. The result comes as null.
If I enter the uri to address bar, the result in chrome as(tag names are changed):
<ns2:MyListResponse xmlns:ns2="blablabla">
<customerSessionId>xxcustomerSessionIdxx</customerSessionId>
<numberOfRecordsRequested>0</numberOfRecordsRequested>
<moreResultsAvailable>false</moreResultsAvailable>
<MyList size="1" activePropertyCount="1">
<MySummary order="0">
<id>1234</id>
<name>...</name>
.
.
</MySummary>
</MyList>
</ns2:MyListResponse>
If I use the statement in code :
using (var client = new HttpClient())
{
var response = client.GetAsync(apiUri).Result;
var message = response.Content.ReadAsStringAsync().Result;
var result1 = JsonConvert.DeserializeObject<MyListResponse>(message);
var result2 = response.Content.ReadAsAsync<MyListResponse>().Result;
}
the message comes in string format as "{\"MyListResponse\":{\"customerSessionId\"...}" which corresponds to a json object as:
{"MyListResponse":
{"customerSessionId":"xxcustomerSessionIdxx",
"numberOfRecordsRequested":0,
"moreResultsAvailable":false,
"MyList":
{"#size":"1",
"#activePropertyCount":"1",
"MySummary":
{"#order":"0",
"id":1234,
"name":"...",
.
.
}
}
}
}
and the properties of result1 and result2 came as null or default values. Class definitions are below. I want to read the content as an object but I couldn't. What do you advice to solve this? What am I doing wrong? Thanks in advance.
public class MySummary
{
public int #Order { get; set; }
public string Id { get; set; }
public string Name { get; set; }
.
.
}
public class MyList
{
public int #Size { get; set; }
public int #ActivePropertyCount { get; set; }
public MySummary MySummary{ get; set; }
}
public class MyListResponse
{
public string CustomerSessionId { get; set; }
public int NumberOfRecordsRequested { get; set; }
public bool MoreResultsAvailable { get; set; }
public MyList MyList { get; set; }
}
I defined a new class as:
public class ResponseWrapper
{
public MyListResponse MyListResponse { get; set; }
}
then I used this wrapper with,
var result1 = JsonConvert.DeserializeObject<ResponseWrapper>(message);
var result2 = response.Content.ReadAsAsync<ResponseWrapper>().Result;
then it worked. I need only MySummary object but I should write more classes to make it work.
After reading your solution I came up with one that doesn't need an extra class:
private static async Task<U> Execute<U>(HttpClient client, string path)
{
U output = default(U);
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
var jsonAsString = await response.Content.ReadAsStringAsync();
output = JsonConvert.DeserializeObject<U>(jsonAsString);
}
else
{
throw new ApplicationException(string.Format("Response message is not OK. Issues in action: {0}", path));
}
return output;
}
For the sake of future readers, I think the correct approach is using ReadAsAsync overload that takes IEnumerable<MediaTypeFormatter> and provide a formatter with the same settings used on the server for serialization. That should fix it.
It is possible to use at client ReadAsAsync with MyListResponse directly (in consequence without ResponseWrapper). To do this, you can define "BodyStyle = WebMessageBodyStyle.Bare" in the operation contract of "apiuri" in stead of "BodyStyle = WebMessageBodyStyle.Wrapped" (server side, i.e. service contract).
Current code in model:
[Display(Name = "E-mail")]
public string EMail { get; set; }
Desired code:
public string EMail { get; set; }
I would like to delegate the translation to a handler, something like this:
if(propertyName == "EMail") return "E-mail"
Based on my understanding of your question, I'm assuming that you are trying to implement localisation in your application.
If so, there are two options;
Resources
In .NET you can add Resource (.resx) files into your application to handle translation (one resx for each language). Then you can specify the Resource by specifying the ResourceType property of your Display attribute. For example;
public class Model
{
[Display(Name = "Email", ResourceType = typeof(Resources.Strings))]
public string Email { get; set; }
}
Custom attribute
Alternatively, if you are set on implementing this in a handler then you could implement a custom attribute, as demonstrated in this question.
Edit: Modified from the example in the above post.
If you add a new Resource file to your project - say Strings.resx and add "HelloWorld" as a field. You can then create a new attribute, such as LocalisedDisplayNameAttribute;
public class LocalisedDisplayNameAttribute : DisplayNameAttribute
{
public LocalisedDisplayNameAttribute(string resourceId)
: base(GetMessageFromResource(resourceId))
{
}
private static string GetMessageFromResource(string resourceId)
{
// "Strings" is the name of your resource file.
ResourceManager resourceManager = Strings.ResourceManager;
return resourceManager.GetString(resourceId);
}
}
You can then use it as follows;
public class Model
{
[LocalisedDisplayName("HelloWorld")]
public string Email { get; set; }
}
Let me know if I can help further,
Matt
I'm a complete noob to Fluent NHibernate, and I'm using the Query Object Pattern based on a recommendation. Which I'm also new to. I'll try to keep the code samples concise and helpful.
User class:
public class User {
public Guid ID { get; set; }
public string Name { get; set; }
}
Visibility:
public enum VisibilityType {
Anybody,
OwnersOnly,
Nobody
}
Car class:
public class Car {
public Guid ID { get; set; }
public VisibilityType Visibility { get; set; }
public ICollection<User> Owners { get; set; }
}
So I need to write a conditional restriction method for the query object. Return all cars that have VisibilityType.Public, but if a car has Visibility property value of VisibilityType.OwnersOnly, restrict the return to users who belong to that group.
Here's the current restriction method that I have working, but without the condition:
public class CarQueryObject
{
private User user { get; set; }
private const string OwnersProperty = "Owners";
private const string OwnersIDProperty = "Owners.ID";
public CarQueryObject RestrictToOwners()
{
// How do I add a conditional criteria here? Only restrict by owner
// if the QueryObject has VisibilityType.OwnersOnly? Note that it should
// *NOT* restrict VisibilityType.Anybody
CreateOwnersAlias();
Criteria.Add(Restrictions.Eq(OwnersIDProperty, user.Id));
return this;
}
public CarQueryObject JoinFetchOwned()
{
Criteria.SetFetchMode(OwnersProperty, FetchMode.Join);
return this;
}
public void CreateOwnersAlias()
{
Criteria.CreateAlias(OwnersProperty, OwnersProperty, JoinType.LeftOuterJoin);
JoinFetchOwned();
}
}
?_?
an idea to get shown cars
var carsShown = session.CreateCriteria<Car>()
.JoinAlias("Owner", "owner")
.Add(Expressions.Or(
Expression.Eq("Visibility", Visibility.Anybody),
Expression.Eq("Visibility", Visibility.OwnersOnly) && Expression.Eq("owner.Id", currentUser.Id)
))
.List<Car>();
My application has the following classes:
public class Widget {
public virtual int Id { get; set; }
public virtual WidgetType Type { get; set; }
public virtual string Parameters { get; set; }
}
public class WidgetType {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string ParametersAssembly { get; set; }
public virtual string ParametersClass { get; set; }
}
Now if i'd like to update the Parameters for a particular widget i would say something like:
// Get the widget
var widget = GetWidget(1);
// Create an instance of the type parameters class
var parameters = Activator.CreateInstance(Assembly.LoadFrom(Server.MapPath("~/bin/"
+ widget.Type.ParametersAssembly + ".dll")).GetType(widget.Type.ParametersClass));
... Code here to update the parameters
widget.Parameters = new XmlSerializer(parameters.GetType()).Serialize(parameters);
I have to do the reverse when i wish to get the parameters. You can imagine this becomes quite tedious. I was wondering if it was possibly to automatically do this?
I've been looking at the IUserType interface. I found an article which is kind of similar. However my problem is a little more complicated as my type changes based on the type of the widget.
I'd appreciate it if someone could let me know if this is possible and possibly how it could be achieved. Thanks
an easy way
public class Widget
{
public virtual int Id { get; set; }
public virtual WidgetType Type { get; set; }
private string _serializedParameters;
private virtual string SerializedParameters {
get
{
return new XmlSerializer(Parameters.GetType()).Serialize(Parameters);
}
set
{
_serializedParameters = value;
// code to deserialize the Parameters and set to Parameters
var ptype = Assembly.LoadFrom(Server.MapPath("~/bin/" + widget.Type.ParametersAssembly + ".dll")).GetType(widget.Type.ParametersClass);
Parameters = Activator.CreateInstance(ptype);
}
}
private object _parameters;
public virtual object Parameters
{
get
{
if (_parameters == null)
_parameters = Activator.CreateInstance(Assembly.LoadFrom(Server.MapPath("~/bin/" + widget.Type.ParametersAssembly + ".dll")).GetType(widget.Type.ParametersClass));
return _parameters;
}
set { _parameters = value; }
}
}
it can't be in the Parameters property because then you have to get -> alter -> set instead of get -> alter. But you are right that building the parameters object should go in the getter of Parameters because only there we can be sure to have the WidgetType loaded
it is essentially the same as a UserType except that we know that WidgetType is there