Skip to content
This repository was archived by the owner on Sep 1, 2022. It is now read-only.

Working with forms

Cezary Piątek edited this page Aug 27, 2017 · 10 revisions

Interaction with form

In order to interact with form, first you have to get form reference using GetForm method passing a form id attribute value as an argument. After that you can access fields using SetFieldValue and GetFieldValue methods as follows.

var loginForm = browserAdapter.GetForm("AuthenticationForm");
loginForm.SetFieldValue("Login", "John Doe");
loginForm.SetFieldValue("Password", "secret123");
loginForm.ClickOnElementWithText("Sign in");

To provide more user oriented approach, there are also a methods to access form's fields based on label text.

var loginForm = browserAdapter.GetForm("RegistrationForm");
loginForm.SetFieldValueByLabel("First name", "John");
loginForm.SetFieldValueByLabel("Last name", "Doe");
loginForm.ClickOnElementWithText("Register");

This mechanism assumes that your form's labels have properly set the 'for' attributes.

Support for ASP.NET MVC

In ASP.NET MVC each form is associated with given ViewModel (or DTO). To interact with form in a strongly typed manner you have to get form reference using GetForm method. Sample interaction with form can be performed as follows:

var loginForm = browserAdapter.GetForm<LoginUserDTO>(AuthenticationUIElementsIds.AuthenticationForm);
loginForm.SetFieldValue(x => x.Login, "John Doe");
loginForm.SetFieldValue(x => x.Password, "secret123");
loginForm.ClickOnElementWithText("Sign in");

Where LoginUserDTO is a model connected with your form. AuthenticationUIElementsIds.AuthenticationForm const holds string with form id.

Handling different types of form inputs

In order to handle different types of form inputs MvcForms introduces notion of Input Adapters. Each type of input has its own input adapter. Input adapter is nothing more than implementation of IFormInputAdapter interface.

public interface IFormInputAdapter
{
	bool CanHandle(IWebElement webElement);
	void SetValue(IWebElement webElement, string value);
	string GetValue(IWebElement webElement);
	bool SupportSetRetry();
}

MvcForms provides out of the box the following input adapters:

  • TextFormInputAdapter
  • SelectFormInputAdapter
  • RadioFormInputAdapter
  • CheckboxFormInputAdapter
  • FileFormInputAdapter
  • HiddenFormInputAdapter

If you have custom types of inputs on your page you can create your own input adapter to handle this type of input. You have to create a class that implements IFormInputAdapter interface with custom logic corresponding to your input type and register your input adapter. In order to register your input adapter you have to add an instance of your input adapter into InputAdapters collection in BrowserAdapterConfig

var browserAdapterConfig = new BrowserAdapterConfig()
{
    InputAdapters = new List<IFormInputAdapter>()
    {
        new CustomInputAdapter(),
        new TextFormInputAdapter(),
        new SelectFormInputAdapter(),
        new CheckboxFormInputAdapter(),
        new RadioFormInputAdapter(),
        new FileFormInputAdapter(),
        new HiddenFormInputAdapter()
    };
};

using (var browserAdapter = BrowserAdapter.Create(browserAdapterConfig))
{
	//Here you can perform your tests with custom input adapter
}

Set Retries

Sometimes Selenium fails trying to set field value. To mitigate this non-deterministic failures MvcForms tries to detect that situation and retries setting field value. To be able to do that input adapter must meet the following requirements:

  • Return true value from SupportSetRetry() method
  • Provide full implementation of GetValue(IWebElement webElement) method (should return the same value as received in SetValue(IWebElement webElement, string value) method.

By default MvcForms tries to set field value three times. If it fails it throws UnableToSetFieldValueException. You can change the number of attemps by setting NumberOfInputSetRetries property on BrowserAdapterConfig (0 means that there will be no retries and the exception will not be thrown if it fails)

Wait for field value change

In order to wait for field value change use FieldValueWatcher

//Start observing field value
var amountGrossWatcher = sampleForm.GetFieldValueWatcher(x => x.AmountGross);

//Interact with page
sampleForm.SetFieldValue(x => x.AmountNett, "23000", AfterFieldValueSet.Blur);

//Wait until field 'AmountGross' change
amountGrossWatcher.WaitForValueChange();

You can also use the following shorthand version:

sampleForm.AffectValueWith(x => x.AmountGross, () => sampleForm.SetFieldValue(x => x.AmountNett, "23000", AfterFieldValueSet.Blur));