Scenario Outline generating incorrect step code - specflow

I have the following feature file
Feature: Employee_EditEmployeeFeature
Check Edit Employee Page
#Employee_EditEmployeeFeature
Scenario Outline: Verify invalid format field error displayed (Email Address)
Given I enter an invalid worker email address <EmailAddress>
When I click on the Employee Edit Save button
Then Check invalid format error displayed for worker Email Address field
Examples:
| EmailAddress |
| invalidaddress |
| invalid address#acme.com |
| invalidaddress#acme |
#Employee_EditEmployeeFeature
Scenario Outline: Verify invalid format field error displayed (Passport Number)
Given I enter invalid worker passport number <PassportNo>
When I click on the Employee Edit Save button
Then Check invalid format error displayed for worker passport field
Examples:
| PassportNo |
| 1234 |
| AS1234567 |
I get the following step code generated for the Given statements
[Given(#"I enter an invalid worker email address invalidaddress")]
public void GivenIEnterAnInvalidWorkerEmailAddressInvalidaddress()
{
ScenarioContext.Current.Pending();
}
[Given(#"I enter invalid worker passport number (.*)")]
public void GivenIEnterInvalidWorkerPassportNumber(int p0)
{
ScenarioContext.Current.Pending();
}
Because the email address step has been generated incorrectly e.g. with no parameter, when the test is run it fails with the following,
Test Name: VerifyInvalidFormatFieldErrorDisplayedEmailAddress_Invalidaddress
Result Message:
Assert.Inconclusive failed. No matching step definition found for one or more steps.
using System;
using TechTalk.SpecFlow;
namespace MyNamespace
{
[Binding]
public class StepDefinitions
{
[Given(#"I enter an invalid worker email address invalidaddress")]
public void GivenIEnterAnInvalidWorkerEmailAddressInvalidaddress()
{
ScenarioContext.Current.Pending();
}
I have trawled the internet and see other people have had this issue, and I have tried some of their solutions to no avail. Any advice as I cannot really move on until I can consistently generate correct step code for Scenario Outline features.

Probably did not recognized the VS integration the parameter correctly as you created it.
Simply change your binding to following:
[Given(#"I enter an invalid worker email address (.*)")]
public void GivenIEnterAnInvalidWorkerEmailAddress(string invalidEMailAddress)
{
ScenarioContext.Current.Pending();
}
See http://www.specflow.org/documentation/Step-Definitions/ for more information about step bindings.

First up, I do not use the Example tag, I do use tables in my tests.
The way I would do this is:
[Given(#"I enter an invalid worker email address invalidaddress")]
public void GivenIEnterAnInvalidWorkerEmailAddressInvalidaddress(Table table)
{
ScenarioContext.Current.Pending();
}
Then, create a new class file and call it whatever you want, I name it Paremeters.cs
In this class file, create a public string. For this example I would say:
public string EmailAddress { get; set; }
Now fill in your method for the table:
[Given(#"I enter an invalid worker email address invalidaddress")]
public void GivenIEnterAnInvalidWorkerEmailAddressInvalidaddress(Table table)
{
var parameters = table.CreateSet<Parameters>();
foreach (var parameter in parameters){
Define your action here what you want to do with each email address
}
}
Hope this helps :-)

After a long time searching, I discovered that we need to use double quotes.
Instead of:
<myParameter>
Use:
"<myParameter>"
Instead of:
When I have a name 'name'
Use:
When I have a "name"

I have encountered the same issue. If you want your steps to be generated correctly after you write down your feature file, on examples leave only the headers then generate your steps and you will see the change.
Your Feature:
#Employee_EditEmployeeFeature
Scenario Outline: Verify invalid format field error displayed (Email Address)
Given I enter an invalid worker email address <EmailAddress>
When I click on the Employee Edit Save button
Then Check invalid format error displayed for worker Email Address field
Examples:
| EmailAddress |
Your steps generated will look like this
[Given(#"I enter an invalid worker email address (.*)")]
public void GivenIEnterAnInvalidWorkerEmailAddress(string p0)
{
ScenarioContext.Current.Pending();
}
[When(#"I click on the Employee Edit Save button")]
public void WhenIClickOnTheEmployeeEditSaveButton()
{
ScenarioContext.Current.Pending();
}
[Then(#"Check invalid format error displayed for worker Email Address field")]
public void ThenCheckInvalidFormatErrorDisplayedForWorkerEmailAddressField()
{
ScenarioContext.Current.Pending();
}
After the steps are generated you can add your data rows.
Or just decorate your parameters with single quotes
Given I enter an invalid worker email address '<EmailAddress>'

Related

Jenkins form validation with objects as parameters

I'm building a plugin for Jenkins and I'm trying to validate my form (connection test method). This worked fine when all #QueryParameter were Strings.
Now I'm trying to send my form validation method an Object like this:
public FormValidation doTestConnection(
#QueryParameter("url") final String url,
#QueryParameter("timeout") final String timeout,
#QueryParameter("bypassProxy") final boolean bypassProxy,
#QueryParameter("deployerCredentialsConfig") final CredentialsConfig deployerCredentialsConfig,
#QueryParameter("resolverCredentialsConfig") final CredentialsConfig resolverCredentialsConfig
) throws ServletException {
In my global.jelly file I have this:
<f:validateButton
title="${%Test Connection}" progress="${%Testing...}"
method="testConnection"
with="url,timeout,bypassProxy,deployerCredentialsConfig,resolverCredentialsConfig"/>
My CredentialConfig class implements Serializable but I guess that is not enough becuase I'm getting this when clicking the "Test Connection" button:
java.lang.IllegalArgumentException: Failed to invoke public hudson.util.FormValidation
org.jfrog.hudson.MyBuilder$DescriptorImpl.doTestConnection(java.lang.String,java.lang.String,boolean,org.jfrog.hudson.CredentialsConfig,org.jfrog.hudson.CredentialsConfig) throws javax.servlet.ServletException
Jenkins has no good documentation for using objects inside of FormValidation calls.
Looking at the Jenkins documentation and the code behind <f:validateButton/>, I believe it's impossible have objects bind in validation logic.
The docs say (https://wiki.jenkins-ci.org/display/JENKINS/Jelly+form+controls):
The 'with' attribute specifies the input fields sent to the server for
the validation. They are matched against the field attribute or the
name attribute of other input controls. The values of the nearest
input fields above the are sent to the server, so
this means the button has to come after the input fields. Multiple
fields can be specified by using ','.
The code simply gets fields by the names - there is no "object assembly" (I believe it's only done during actual config submission).
https://github.com/jenkinsci/jenkins/blob/96ec7a267e0efba2ec99590c871db0940e35920f/war/src/main/webapp/scripts/hudson-behavior.js#L2856
I bumped into a similar problem. Looking at the code, it seems stapler tries to convert your parameter to the type you provided in the doCheck function declaration.
class HandlerImpl extends AnnotationHandler<QueryParameter> {
public Object parse(StaplerRequest request, QueryParameter a, Class type, String parameterName) throws ServletException {
String name = a.value();
if(name.length()==0) name=parameterName;
if(name==null)
throw new IllegalArgumentException("Parameter name unavailable neither in the code nor in annotation");
String value = request.getParameter(name);
if(a.required() && value==null)
throw new ServletException("Required Query parameter "+name+" is missing");
if(a.fixEmpty() && value!=null && value.length()==0)
value = null;
return convert(type,value); // <--- HERE
}
}
As a workaround, I changed the type to boolean, like so:
public FormValidation doTestConnection(
#QueryParameter("url") final String url,
#QueryParameter("timeout") final String timeout,
#QueryParameter("bypassProxy") final boolean bypassProxy,
#QueryParameter("deployerCredentialsConfig") final boolean deployerCredentialsConfig,
#QueryParameter("resolverCredentialsConfig") final boolean resolverCredentialsConfig
) throws ServletException {
This allows me to at least check if the variable is set. It might not be enough for your use case, though.

Custom validation of HttpPostedFileBase

I use MVC5. I've got some issue with file uploading using HttpPostedFileBase. I've got a form where I can can choose a file from my disk and type some information about it(in textbox). When I submit a form the controller action is called. In this action I open file and check if it has some specific data(related with data from textbox). So I do some validation here. I can't do it using JQuery - it's complex. The server side validation is the only option. Finally if validation fails I return model(with file) to the view but after that I've got validation error next to file field but file field is empty. I've read that's hard to return file to the view. I don't want to use ajax to upload file. I want to do it simple. If you got an article that can help, please share it with me.
How can I solve my problem?
I know you mentioned not using AJAX to do file upload, but I think this solution is a very simple one.
Using the following jQuery plugin (https://blueimp.github.io/jQuery-File-Upload/), you can automate that process and if there are any validation issues in your file, then you can return the following model with the error.
string errors = "Errors returned from complex logic";
if (!String.IsNullOrEmpty(errors))
{
// error response
status = new ViewDataUploadFilesResult()
{
name = Path.GetFileName(hpf.FileName),
size = hpf.ContentLength,
error = errors
};
}
Here is the class needed for the response that matches the jQuery file upload documentation: https://github.com/blueimp/jQuery-File-Upload/wiki/Setup
public class ViewDataUploadFilesResult
{
public string name { get; set; }
public int size { get; set; }
public string type { get; set; }
public string url { get; set; }
public string error { get; set; }
}
If I'm understanding correctly, since the file is already on the users computer, you only need to associate the file to the current file they're attempting to upload to returns errors. And to make it so they don't have to reselect the file to upload. I don't see any other reason to need to return the actual file to the user as they already have the file they're uploading.

Nancy and request validation

I have sample app in Nancy and have problem with request validation.
I am using FluentValidator with BindAndValidate extension. So for example i have model :
public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
And module with :
Post["/create-user"] = m => this.BindAndValidate<User>());
And there is problem, if client app call module with parameters Name:"foo,Age:"some-string",
then Nancy throw exception :
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Exception: some-string is not a valid value for Int32. ---> System.FormatException: Input string was not in a correct format.
Is here any workaround for exception by parameter ("property Age was not in correct format") ?
Thanks
The problem is that the bind fails so the validator never runs. You can tell nancy to ignore binding errors, but it doesn't do so gracefully (it basically stops binding on the first error). So then your validation step does run, but may complain about properties that were ok, but simply were not set by the binder.
You can get around this by providing your own BodyDeserializer that uses Newtonsoft's handling of errors so that the binding doesn't stop on the first error found. See Handle multiple binding errors from ModelBindingException in NancyFX when binding to JSON in Request.Body
Before binding you could try to check if Age is int, and if it is then to validation. Something like this:
int age;
bool isInt = int.TryParse(Request.Form("Age"), out age);
if (isInt)
{
this.BindAndValidate<User>();
}
Hope it helps.

Guid of created aggregate root in CQRS

Looking at this code from here:
[Serializable]
public class CreateClientCommand : Command
{
public string ClientName { get; private set; }
public string Street { get; private set; }
public string StreetNumber { get; private set; }
public string PostalCode { get; private set; }
public string City { get; private set; }
public string PhoneNumber { get; private set; }
public CreateClientCommand(Guid id, string clientName, string street, string streetNumber, string postalCode, string city, string phoneNumber) : base(id)
{
ClientName = clientName;
Street = street;
StreetNumber = streetNumber;
PostalCode = postalCode;
City = city;
PhoneNumber = phoneNumber;
}
}
The Guid here is just relevant for the command. It is not the Guid of the (potentially) created aggregate root. What is the best practice to obtain this Guid and how are any potential validation errors communicated back to the the code that puts a command on the bus? For example like this:
_bus.Publish(new CreateClientCommand(
Guid.NewGuid(),
_clientDetailsReport.ClientName,
_clientDetailsReport.Street,
_clientDetailsReport.StreetNumber,
_clientDetailsReport.PostalCode,
_clientDetailsReport.City,
_clientDetailsView.PhoneNumber));
_bus.Commit();
I understand that CQRS usually implements eventual consistency. This means that it might take a while before the client is actually created. Some MVC/CQRS code uses this approach:
[HttpPost]
public ActionResult Add(DiaryItemDto item)
{
ServiceLocator.CommandBus.Send(new CreateItemCommand(Guid.NewGuid(),item.Title,item.Description,-1,item.From,item.To));
return RedirectToAction("Index");
}
Obviously, the index page might show some grid containing the DiaryItems and the user might be able to see the latest created DiaryItem (potentiality after a while). Any feedback would be very much appreciated. Thanks.
Are you asking about the distinction between an ID for the command itself, versus the ID of the entity it might create? The former would typically be an infrastructure concern, found on something like a message envelope, buried in a RPC protocol, or the like. The latter would be part of your domain. (Though in many cases, it's nice to treat the ID of an entity as an infrastructure concern as well, since you might choose it for convenience in your persistence model.)
The easiest way to do this is to use the guid that you pass on the command as the actual aggregate Id and then you have it to hand and don't have to wait for it to be communicated back down on an event
Not sure why your command has an id it confuses things ( Yes some distributed systems use this but it should be a last resort). Most developers would see this as the id of the aggregate .
Generally just create the aggregate Id and send it with the command . After all the command is creating the Entity ..
Commands should in most cases be sync so you can throw errors back . With async commands you really should have a call back for success or failure ( and async should only be used where you really have the need it adds a lot of cost to the system ) .
You don't move to the next step ( if you need a next step ) until either
A) Its a system that deals with eventual consistency, a lot of business logic does do this. eg waiting for the exchange or a 3rd party to process something , then the work is waiting for that information . ( Ie the command creates an Order but the processing of the order eg OrderDetail may not be there yet and the order has a state of Order Processing)
B) You have success , timeout or failure response to command before continuing .

asp.net mvc validation must be a number custom error

I am new to asp.net and I have a problem. When the users insert in a editor for a decimal field something other than numbers, they get an error "Field name" is not a number. But I don't want them to receive this message I want them to receive another message. I have no problem with this with required and range validators.
Is there any way for me to do this?
I am not refering necessarily to changing the culture just displaying another message.
Thanks.
Hope I understand your, to change RangeValidator ErrorMessage just initialize ErrorMessage parameter:
[Range(0, 100, ErrorMessage = "Some another error message insert here!")]
[RegularExpression("\d", ErrorMessage = "!!!")]
public decimal DecimalField { get; set; }
This is the actual answer:
Create a class CustomClientDataTypeModelValidatorProvider. Copy the code from the MVC sources. Change the method MakeErrorString to output the appropiate message like this:
private static string MakeErrorString(string displayName)
{
return string.Format(
CultureInfo.CurrentCulture,
Core.Resources.Errors.EroareNuENr,
displayName);
}
I couldn't find a way not to copy the code just extend it as it uses this static method.
If anyone knows this please tell me.
Then, in global.asax, I wrote this:
var cdProvider = ModelValidatorProviders.Providers.SingleOrDefault(p => p.GetType().Equals(typeof(ClientDataTypeModelValidatorProvider)));
if(cdProvider != null)
{
ModelValidatorProviders.Providers.Remove(cdProvider);
ModelValidatorProviders.Providers.Add(
new CustomClientDataTypeModelValidatorProvider());
}
so that the flow would actually be routed to my class and not the class in the asp.net MVC dll
I got the idea from here:
Unfortunately this is is not a trivial task. However you can try the following hack...
Better to do this only on essential fields, as this is more code to maintain.
In the controller's action method
if(ModelState.IsValid)
{
// code
}
else
{
if (ModelState["YourField"].Errors.Count > 0)
{
ModelState["YourField"].Errors.Clear();
ModelState.AddModelError("YourField", "Your custom message here");
}
// code
}
You can set ResourceClassKey of ClientDataTypeModelValidatorProvider class to name of a global resource that contains FieldMustBeNumeric key to replace mvc validation error message of number with your custom message. Also key of date validation error message is FieldMustBeDate.
ClientDataTypeModelValidatorProvider.ResourceClassKey="MyResources"; // MyResource is my global resource
See here for more details on how to add the MyResources.resx file to your project:
The field must be a number. How to change this message to another language?
To change the error message you get after server side validation you need to change 'PropertyValueInvalid' key in your resource file and assign the resource file name to DefaultModelBinder.ResourceClassKey. See this question for details: localize default model validation in mvc 2
Look for solution at the end of this page:
http://jwwishart.wordpress.com/2010/03/22/custom-server-and-client-side-required-validator-in-mvc-2-using-jquery-validate/
I checked this in my MVC 3 RTM project and it works well.
... or use jQuery to change to message on the client.
A quick and simple hack for Customize RangeValidator ErrorMessage --"'Field name' is not a number"-- is using RegularExpression
[Range(0.5, 1000, ErrorMessage = "Amount should be in range {1} to {2}.")]
[DataType(DataType.Currency)]
[RegularExpression(#"\d", ErrorMessage = "Amount is not valid.")]
public decimal Amount{ get; set; }
You could implement your own custom validation attribute: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
It seems that since Para's answer MVC evolved and now the ClientDataTypeModelValidatorProvider accepts a ResourceClassKey property. It uses the FieldMustBeNumeric and FieldMustBeNumeric messages specified in your resource class.

Resources