I work on BDD infrastructure in c# using specflow, and ReportPortal. I am using scenario outline in order to automated the same flow, with several parameters, but I want to have a dynamic title in reportPortal. an example:
Scenario Outline: Perform a Test on car <car model>
Given I have the car"<car>"
When I expect that "<car>" has 4 wheels
Then I expect that the car will be able to move
This scenario doesn't work, since Gherkin doesnt support in scenario outline dynamic title. Is there a way where I can somehow influence the scenario title in the following code:
var currentFeature = FeatureContext.Current;
var currentScenario = ScenarioContext.Current;
var jsonRootElement = (JsonReportRootObject)currentFeature["JsonReport"];
var scenarioElement = new Element();
scenarioElement.keyword = "Scenario";
scenarioElement.line = 0;
scenarioElement.name = currentScenario.ScenarioInfo.Title;
scenarioElement.steps = new List<Step>();
https://github.com/reportportal/example-net-specflow/blob/master/src/Example.SpecFlow/Hooks/Hooks1.cs
You can subscribe on ReportPortalAddin.BeforeScenarioStarted event and modify e.StartTestItemRequest.Name property.
Related
I have Ilist to get all Offer from repository using entity framework core. Also I have service model OfferResponseModel which includes
OfferRequestModel as reference. I used mapster to bind entity model to service model. However it only set first child. Now I want to bind it manually. I created "offers" with the size of "Offer". When I try to use foreach loop, I cannot set "offers" child element.Because it has no elements. So, I can I solve this.
var offer = await _unitOfWork.Offers.GetAllOffer();
if (offer == null)
throw ServiceExceptions.OfferNotFound;
var results = new List<OfferResponseModel>(offer.Count);
results.ForEach(c => { c.Offer = new OfferRequestModel(); });
int i = 0;
foreach(var result in results)
{
result.Offer.User = Offer[i].User.Adapt<UserResponseModel>();
result.Offer.Responsible = Offer[i].Responsible.Adapt<EmployeeResponseModel>();
result.CreatedDate = Offer[i].CreatedDate;
result.ModifiedBy = Guid.Parse(Offer[i].UpdatedBy);
result.Active = Offer[i].Status;
result.Offer = Offer[i].Offer;
result.Offer.User.Company = Offer[i].Company.Adapt<CompanyModel>();
i++;
}
I created "offers" with the size of "Offer".
No, you created it with that capacity. It's still an empty list. It's not clear to me why you're trying to take this approach at all - it looks like you want one OfferResponseModel for each entry in offer, directly from that - which you can do with a single LINQ query. (I'm assuming that offer and Offer are equivalent here.)
var results = Offer.Select(o => new OfferResponseModel
{
Offer = new OfferRequestModel
{
User = o.User.Adapt<UserResponseModel>(),
Responsible = o.Responsible.Adapt<EmployeeResponseModel>()
},
CreatedDate = o.CreatedDate,
ModifiedBy = Guid.Parse(o.UpdatedBy),
Active = o.Status
}).ToList();
That doesn't set the Offer.User.Company in each entry, but your original code is odd as it sets the User and Responsible properties in the original Offer property, and then replaces the Offer with Offer[i].Offer. (Aside from anything else, I'd suggest trying to use the term "offer" less frequently - just changing the plural to "offers" would help.)
I suspect that with the approach I've outlined above, you'll be able to work out what you want and express it more clearly anyway. You definitely don't need to take the "multiple loops" approach of your original code.
One thing you have left out is the type of the offer variable that is referenced in the code. But I am thinking you need to do something along these lines:
if (offer == null)
throw ServiceExceptions.OfferNotFound;
var results = offer.Select(o => new OfferResponseModel
{
Offer = new OfferRequestModel
{
User = o.User.Adapt<UserResponseModel>(),
Responsible = o.Responsible.Adapt<EmployeeResponseModel>(),
...
}
}).ToList();
Select basically loops through any items in offer and "converts" them to other objects, in this case OfferResponseModel. So inside select you simply new up an OfferResponseModel and directly sets all the properties you need to set.
You need using System.Linq; for Select to be available.
Writing programm to Parse some data from one website using AngleSharp. Unfortunately I didn't find any documentation and it makes understanding realy hard.
How can I by using QuerySelectorAll get only link? I'm getting now just all things <a ...>...</a> with Name of article.
1. Name of artucle
The method I'm using now:
var items = document.QuerySelectorAll("a").Where(item => item.ClassName != null && item.ClassName.Contains("object-title-a text-truncate"));
In the previous example I also used ClassName.Contains("object-name"), but if we deal with table cells, there are no any class. As I understand to parse right element maybee I must use some info about parent also. So here is the question, how can I get this '4' value from tabble cell?
....<th class="strong">Room</th>
<td>4</td>....
Regarding your first question.
Here is an example that you can extract the link address.
This a Link of another Stackoveflow post that is related.
var source = #"<a href='http://kinnisvaraportaal-kv-ee.postimees.ee/muua-odra-tanaval-kesklinnas-valmiv-suur-ja-avar-k-2904668.html?nr=1&search_key=69ec78d9b1758eb34c58cf8088c96d10' class='object-title-a text-truncate'>1. Name of artucle</a>";
var parser = new HtmlParser();
var doc = parser.Parse(source);
var selector = "a";
var menuItems = doc.QuerySelectorAll(selector).OfType<IHtmlAnchorElement>();
foreach (var i in menuItems)
{
Console.WriteLine(i.Href);
}
For your Second question, you can check the example on the documention, here is the Link and below is the code sample:
// Setup the configuration to support document loading
var config = Configuration.Default.WithDefaultLoader();
// Load the names of all The Big Bang Theory episodes from Wikipedia
var address = "https://en.wikipedia.org/wiki/List_of_The_Big_Bang_Theory_episodes";
// Asynchronously get the document in a new context using the configuration
var document = await BrowsingContext.New(config).OpenAsync(address);
// This CSS selector gets the desired content
var cellSelector = "tr.vevent td:nth-child(3)";
// Perform the query to get all cells with the content
var cells = document.QuerySelectorAll(cellSelector);
// We are only interested in the text - select it with LINQ
var titles = cells.Select(m => m.TextContent);
I am trying to understand how to use anglesharp.
I made this code based on the example (https://github.com/AngleSharp/AngleSharp):
// Setup the configuration to support document loading
var config = Configuration.Default.WithDefaultLoader();
// Load the names of all The Big Bang Theory episodes from Wikipedia
var address = "http://store.scramblestuff.com/";
// Asynchronously get the document in a new context using the configuration
var document = await BrowsingContext.New(config).OpenAsync(address);
// This CSS selector gets the desired content
var menuSelector = "#storeleft a";
// Perform the query to get all cells with the content
var menuItems = document.QuerySelectorAll(menuSelector);
// We are only interested in the text - select it with LINQ
var titles = menuItems.Select(m => m.TextContent).ToList();
var output = string.Join("\n", titles);
Console.WriteLine(output);
This works as expected but now I want to access the Href property but I am unable to do this:
var links = menuItems.Select(m => m.Href).ToList();
When I look in the debugger I can see in results view that the HtmlAnchorElement enumerable object has a Href property but I am obviously not trying to access it right.
None of the examples in the documentation show a property being accessed so I guess it's something so simple that doesn't need to be shown but I am not seeing how to do it.
Can anyone show me how I should be accessing a html property with angle sharp?
edit:
This works when I cast it to the correct type
foreach (IHtmlAnchorElement menuLink in menuItems)
{
Console.WriteLine(menuLink.Href.ToString());
}
How would I write that as a Linq statement like the titles variable?
Alternative to har07's answer:
var menuItems = document.QuerySelectorAll(menuSelector).OfType<IHtmlAnchorElement>();
You can cast to IHtmlAnchorElement as follow :
var links = menuItems.Select(m => ((IHtmlAnchorElement)m).Href).ToList();
or using Cast<IHtmlAnchorElement>() :
var links = menuItems.Cast<IHtmlAnchorElement>()
.Select(m => m.Href)
.ToList();
im a bit late to this topic, but you can use
string link = menuItem.GetAttribute("href");
or this if its a list of items
List<string> menuItems = LinkList.Select(item => item.GetAttribute("href")) .ToList();
Thanks to Dave Bennett, I have a great Neo4j query that provides the results I need. I need to get this to work in Neo4JClient. Here's my working Neo4j query:
`// Composite Tile with related users
match (t:Tile{summary:"Test 1"})<-[:ASSIGNED_TO]-(u:User)
with {summary: t.summary,
id: t.id,
sprint_id: t.sprint_id,
size: t.size,
percent_done: t.percent_done,
color: t.color_id,
description: t.description,
queue_id: t.queue_id,
swimlane_id: t.swimlane_id,
icons: t.icons,
order: t.order,
assignees: collect(u)} as tile
RETURN collect(tile) as tiles`
Visual Studio and/or Neo4jClient is not very happy with my attempt:
var compositeTile = client.Cypher
.Match("(t:Tile)<-[:ASSIGNED_TO]-(u:User)")
.Where((Tile t)=> t.summary == tile.summary)
.With( {
summary: t.summary,
id: t.id,
sprint_id: t.sprint_id,
size: t.size,
percent_done: tile.percent_done,
color: t.color,
description: t.description,
queue_id: t.queue_id,
swimlane_id: t.swimlane_id,
icons: t.icons,
Order: t.order,
assignees: collect(u)
} as tile)
.return collect(tile) as tiles;
It just throws lots of red squiggly lines, I suspect because I'm not formatting the .with statement correctly. I haven't been able to find an example, so I'm asking here. How do I do this correctly in Neo4jClient?
So, two answers to your question - the first is that the .With statement takes a string as a parameter, so you just need to wrap your text with " (or #" if you want to keep the formatting). The second answer is more of a problem for you though:
It's not possible to do what you're trying to do with Neo4jClient - at the moment it doesn't allow you to create anonymous types. It's not able to deserialize the content. I thought it might be a quick fix, but it seems like it would be more involved. So, what we're looking at here is a change of the query.
I presume you have a class called Tile with the properties you're after. So I would change the query to something like this:
client.Cypher
.Match("(t:Tile)<-[:ASSIGNED_TO]-(u:User)")
.Where((Tile t) => t.summary == tile.summary)
.Return((t,u) => new {
Tile = t.As<Tile>(),
User = u.CollectAs<User>()
});
Which will give you a C# anonymous type with a Tile and an IEnumerable<Node<User>> elements, obviously you want the Users in your Tile, so you can then parse the result:
var tiles = new List<Tile>();
foreach (var result in results)
{
var tile = result.Tile;
foreach (var user in result.Users)
tile.users.Add(user.Data);
tiles.Add(tile);
}
One thing you might find is that you need to initialize the Users collection, so either add Users = new List<User>() to your Tile constructor, or just before parsing the data.
Let's say I have a table called Couriers in my database and an Entity Framework class also called Couriers (DbContext.Couriers), with this example data:
Id: 1. Name: UPS
Id: 2. Name: DHL
I have extended this class with two subclasess CourierUPS and CourierDHL, and both two have a new method called PrintSticker(), which is different in UPS and DHL (each company needs a different sticker format).
I also have a view with a combo to select between UPS or DHL and a button that calls the PrintSticker method of the selected Courier.
Well, the problem is that I can create the object with an IF statement (if selectedCourier = "UPS" create new CourierUPS elseif selectedCourier = "DLH" create new CourierDHL... it's just pseudo code), but it is not a good way, because if I want to create FedEx courier in the future, I will need to change that IF statement, so I think I will become a mess.
What I want to achieve is a way to dinamycally obtain this:
C#
CourierUPS courier = new CourierUPS;
VB.NET
Dim courier as CourierUPS = new CourierUPS
The questions are:
1) Is there a simple way to save the name of the class in the table (CourierUPS, CourierDHL, etc.), and use it the code to create the new objects?
2) Is there a simple way to dynamically construct the name of the class, attaching the name of the courier (DHL or UPS) to the "Courier" word? Courier + UPS = CourierUPS, so our code will use that class.
Both C# or VB.NET solutions would be appreciatted.
Thank you
And option that you can try is to create a factory dictionary for creating each type.
Start out with this:
var factory = new Dictionary<string, Func<Courier>>()
{
{ "UPS", () => new CourierUPS() },
{ "DHL", () => new CourierDHL() },
};
Now you can create either the "UPS" or "DHL" courier like this:
var courier = factory["UPS"].Invoke();
But, if you now want to configure a new courier you can pass your dictionary into a method that can add in "FedEx", and you can add it like so:
factory["FedEx"] = () => new CourierFedEx();
Now you can do this back in your main code:
var courier = factory["FedEx"].Invoke();
It's basic, but it works.