6d) Language Reference

Descriptors

A lot of steps take the descriptor format to specify an element: <element> "<locator>" <number>

elementType of element, see the Possible elements page.
locator

Locator is a SAHI identifier (like id, full class specification, text). This means that also regular expressions and indexers can be used.

For more information see the SAHI documentation and the CWB examples.

numberIn case of multiple matches, the how manieth element. Number starts at 1 to identify the first match. If no number is given, then 1 is assumed.

Custom elements can easily be defined using an ElementHandler implementation, see CWB for developers.

Some examples of steps using the descriptor format:

* i click on link "Some link"
* i should see link 1
* i should not see link "Some link" 2
* heading "myheading" in div "group" should contain "sometext"

Form elements and labels

Form elements can often be identified by their label.  If no form element can be found matching the descriptor directly, then CTF will search for a label matching the descriptor, and for the element with the same id as the for attribute of the label.

In practice, this means form elements can often be identified using the visual label text instead of the id or name attribute of the DOM element.

Deprecated CWB steps

Sometimes steps can be deprecated, this would only happen if these steps turn out to be unreliable in their behaviour.  Deprecated steps will be removed from CTF shortly after they become deprecated.  As soon as they are deprecated however, they will always fail so as to force you to change the test implementation.

If you really do not want your tests to fail on deprecated steps, you can set the deprecated.allowed property to true in the ctf.properties file. Do be aware that with one of the next updates the deprecated step might be removed completely, in which case there is no way around fixing your tests.

Standard CWB steps

There are often multiple ways to formulate the same step.  Purpose is to improve readability in scenarios. There are always i centric statements and more generic statements.  Depending on the style of the scenario and the keyword at the front a different formulation can be used.

For a more detailed list of steps that is always up-to-date, see the feature examples.

Given/And

SyntaxAction

i am on "<url>"

i go to "<url>"

Will navigate the browser to the url specified.
that <el statement>Will execute the el statement and expects a boolean True.

i switch to popup "<windowName>"

i switch to window "<windowName>"

switch to popup "<windowName>"

switch to window "<windowName>"

Will switch the browser context to the window/popup with the specified name. All following statements will be executed against that window until a clear step is executed.

For SAHI to be able to work with other popups and windows (and possibly also iframes),

i clear the popup

clear the popup

Will move the browser back to the main browser window (without closing the other one).

In the step definition popup can always be replaced with window.

i close popup "<windowName>"

close popup "<windowName>"

Closes the window with the given name. In case the browser is currently scoped to that window, it will switch back to the main window.

In the step definition popup can always be replaced with window.

i close the popup

close the popup

 

Closes the current window but only if it is a different window created by javascript. Will switch the browser back to the main window.

In the step definition popup can always be replaced with window.

When/And

SyntaxAction
i go to <url>Will navigate the browser to the url specified.
i follow <link>Will follow the link (anchor element) specified.

i go back <value> page

i go back <value> pages

Will use the browser history to go back a number of pages

i click on <descriptor>

i click on <descriptor> in <descriptor>

Will click on the element specified by the descriptor.

i double click on <descriptor>

i double click on <descriptor> in <descriptor>

Will double click on the element specified by the descriptor.

i right click on <descriptor>

i right click on <descriptor> in <descriptor>

Will right click on the element specified by the descriptor

i fill in <descriptor> with <value>

i fill in <descriptor> in <descriptor> with <value>

Will fill in the field matching the descriptor. Only works for certain element types like textbox, tinymce...

In case the descriptor does not contain an element definition, then textbox is assumed.

These steps also take a multiline docstring as argument:

i fill in "body" with
  """
  line 1
  line 2
  """

i select "<value>" from <descriptor>

i select "<value>" from <descriptor> in <descriptor>

Will select a value from a dropdown matching the descriptor.

The element part of the first descriptor can be omitted and select will be assumed.

i choose <descriptor>

i choose <descriptor> in <descriptor>

Will check a checkbox or radiobutton matching the descriptor.

The element part of the first descriptor can be omitted and radio will be assumed.

i check <descriptor>

i check <descriptor> in <descriptor>

Will check a checkbox or radiobutton matching the descriptor. (only works when the checkbox has an id)

The element part of the first descriptor can be omitted and checkbox will be assumed. (only works when the checkbox has an id)

i uncheck <descriptor>

i uncheck <descriptor> in <descriptor>

Will uncheck a checkbox matching the descriptor. This does not work on radiobuttons as it is impossible to uncheck a radiobutton.

The element part of the first descriptor can be omitted and checkbox will be assumed.

i fill in the following:

i fill in the following in <descriptor>:

Allows you to specify a table of data entries for form filling. These steps should be followed by a table having the following structure:

| locator   | type      | value   |
| <locator> | <element> | <value> |

Example:

i fill in the following in div "registrationForm":
	| locator     | type     | value        |
    | firstname   | text     | my firstname |
    | /Naam/      | text     | my last name |

i press <descriptor>

i press <descriptor> in <descriptor>

Will press a button matching the locator and number (input type submit or button).

The element part of the first descriptor can be omitted and select will be assumed. In case there is an element specified, then this step does the same as a click.

i save <value> as "<variablename>"Will save the specified value as a variable with that name. The variable can then be used as ${variablename}.

i save <descriptor> as "<variablename>"

i save <descriptor> in <descriptor> as "<variablename>"

Saves a selected element as variable, so it can be used later on with an element specification. Especially useful to use as parent in case nesting of parents is required to select the right element.
i save variables:

Allows you to save several variables at once. This step should be followed by a table having the following structure:

| url.override  | http://host    |
| somethingElse | someOtherValue |
i execute <el statement>Will evaluate the el statement specified. Can be used to perform more complex actions by directly using the browser API. Only to be used if no other steps provides the functionality required.

 

Then/And

SyntaxAction

i should be on "<url>"

Will check if the browser is on the specified url.
pause

Will show a dialog and only continue execution when the OK button in the dialog is pressed.

Useful for pausing the feature and executing some manual actions in the browser.

wait for <number> ms

i wait for <number> ms

Will wait the number of milliseconds before going to the next step.

wait until <descriptor> is visible

i wait for <number> ms until <descriptor> is visible

i wait for <number> ms or until <descriptor> is visible

Will wait the specified number of milliseconds or until the specified element is visible, whichever comes first.

If the number of milliseconds is omitted, then the maximum wait time will be 10 seconds. If the maximum wait time is reached, this step will fail.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

wait until <descriptor> exists

i wait for <number> ms until <descriptor> exists

i wait for <number> ms or until <descriptor> exists

Will wait the specified number of milliseconds or until the specified element is found in the DOM, whichever comes first.

If the number of milliseconds is omitted, then the maximum wait time will be 10 seconds. If the maximum wait time is reached, this step will fail.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

wait until <descriptor> is not visible

i wait for <number> ms until <descriptor> is not visible

i wait for <number> ms or until <descriptor> is not visible

Will wait the specified number of milliseconds or until the specified element is not visible, whichever comes first.

If the number of milliseconds is omitted, then the maximum wait time will be 10 seconds. If the maximum wait time is reached, this step will fail.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

wait until <descriptor> does not exist

i wait for <number> ms until <descriptor> does not exist

i wait for <number> ms or until <descriptor> does not exist

Will wait the specified number of milliseconds or until the specified element is no longer found in the DOM, whichever comes first.

If the number of milliseconds is omitted, then the maximum wait time will be 10 seconds. If the maximum wait time is reached, this step will fail.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

highlight <descriptor>

i highlight <descriptor>

Will highlight the element for a very short while and will pause the execution (see pause step above).

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

focus on <descriptor>

i focus on <descriptor>

i put the focus on <descriptor>

Will put the browser focus on the element matching the descriptor.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

remove focus from <descriptor>

i remove focus from <descriptor>

Will remove the browser focus from the element matching the descriptor.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

The support for this seems to be very limited (SAHI and browser related), in most cases it is probably better to explicitly put the focus on a different element instead.

This does seem to be the only way to really trigger a focusout event.

i should see "<message>"

Will verify that the message is present in the page (body of the document); does not check actual visibility.

Avoid the use of this step, prefer using a specific step checking the visibility of an element or if an element contains a certain value.

This step is deprecated and will be removed in the future.

i should not see "<message>"

Will verify that the message is not present in the page (body of the document); does not check actual visibility.

Avoid the use of this step, prefer using a specific step checking the visibility of an element or if an element contains a certain value.

This step is deprecated and will be removed in the future.

i see <descriptor>

i should see <descriptor>

<descriptor> is visible

<descriptor> should be visible

Checks that a given element is visible.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

In rare cases this check fails even though the element is visible. It has been known to fail with table cells.

<descriptor> exists

<descriptor> should exist

Checks that a given element is present in the DOM.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

i do not see <descriptor>

i should not see <descriptor>

<descriptor> is not visible

<descriptor> should not be visible

Checks that a given element is not visible. This performs the sahi check (javascript/css visibility).

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

<descriptor> does not exist

<descriptor> should not exist

Checks that a given element is not present in the DOM.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

the following elements are visible:

the following elements should be visible:

the following elements in <descriptor> are visible:

the following elements in <descriptor> should be visible:

This statement should be followed by a table structure of the following form:

| locator   | type      | value   |
| <locator> | <element> | <value> |

This step verifies that all elements in the table are visible. Variation: the keyword elements can also be replaced with fields.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

the following elements exist:

the following elements should exist:

the following elements in <descriptor> exist:

the following elements in <descriptor> should exist:

This statement should be followed by a table structure of the following form:

| locator   | type      | value   |
| <locator> | <element> | <value> |

This step verifies that all elements in the table exist in the DOM.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

the following elements are not visible:

the following elements should not be visible:

the following elements in <descriptor> are not visible:

the following elements in <descriptor> should not be visible:

This statement should be followed by a table structure of the following form:

| locator   | type      | value   |
| <locator> | <element> | <value> |

This step verifies that none of the elements in the table are visible. Variation: the keyword elements can also be replaced with fields.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

the following elements do not exist:

the following elements should not exist:

the following elements in <descriptor> do not exist:

the following elements in <descriptor> should not exist:

This statement should be followed by a table structure of the following form:

| locator   | type      | value   |
| <locator> | <element> | <value> |

This step verifies that none of the elements in the table exist in the DOM.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

 

the <field> field should contain <value>

Will verify that the text type input field value is equal to the value specified.

Prefer using the more general step <descriptor> should contain <value>.

<descriptor> should contain "<value>"

<descriptor> contains "<value>"

 

Verifies that the given element contains the value anywhere in its text.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

There are multiple variants on this statement:

equals, should equal, isChecks for full equality.
starts with, should start withChecks the text starts with the given value.
ends with, should end withChecks the text ends with the given value.
matches, should matchChecks the text matches the regular expression specified by the value.

<descriptor> should not contain <value>

<descriptor> does not contain <value>

Verifies that the given element does not contain the value anywhere in its text.

The descriptor can always be replaced with a parent version: <descriptor> in <descriptor>.

There are multiple variants on this statement:

does not equal, should not equal, is notChecks the text does not equal the given value.
does not start with, should not start withChecks the text does not start with the given value.
does not end with, should not end withChecks the text does not end with the given value.
does not match, should not matchChecks the text does not match the regular expression specified by the value.

the element values contain:

the element values should contain:

the element values in <descriptor> contain:

the element values in <descriptor> should contain:

This statement should be followed by a table structure of the following form:

| locator   | type      | value   |
| <locator> | <element> | <value> |

This step verifies that all elements in the table contain the value anywhere in their text.

There are also multiple variants on this statement:

The keyword element can be substituted with field. The action (contain/should contain) can be substituted with:

equal, are, should be, should equalChecks the text equals the given value.
start with, should start withChecks the text starts with the given value.
end with, should end withChecks the text ends with the given value.
match, should matchChecks the text matches the regular expression specified by the value.

the element values do not contain:

the element values should not contain:

the element values in <descriptor> do not contain:

the element values in <descriptor> should not contain:

This statement should be followed by a table structure of the following form:

| locator   | type      | value   |
| <locator> | <element> | <value> |

This step verifies that no element in the table contains the value anywhere in its text.

There are also multiple variants on this statement:

The keyword element can be substituted with field. The action (do not contain/should not contain) can be substituted with:

do not equal, are not, should not be, should not equalChecks the text does not equal the given value.
do not start with, should not start withChecks the text does not start with the given value.
do not end with, should not end withChecks the text does not end with the given value.
do not match, should not matchChecks the text does not match the regular expression specified by the value.

<value> should be selected in <descriptor>

<value> should be selected in <descriptor> in <descriptor>

Will verify a value is selected in a specified dropdown.

The element part of the first descriptor can be omitted and select will be assumed.

<descriptor> should be chosen

<descriptor> should be chosen in <descriptor>

Will verify a radiobutton is selected.

The element part of the first descriptor can be omitted and radio will be assumed.

<descriptor> should be checked

<descriptor> should be checked in <descriptor>

Will verify a checkbox is checked.

The element part of the first descriptor can be omitted and checkbox will be assumed.

<descriptor> should be unchecked

<descriptor> should be unchecked in <descriptor>

Will verify a checkbox is unchecked.

The element part of the first descriptor can be omitted and checkbox will be assumed.

ensure that <el statement>Will verify that the el statement evaluates to a boolean True.
ensure that <first> equals <second>Will verify that the outcome of first value (string, variable or el statement) equals the second.

ensure that <object> contains <property>

ensure that <object> contains <property> with <value>

ensure that <object> contains:

Checks that a certain object contains properties. This can be a variable that is previously declared, or the result of a REST call or anything else that translates into an object.

ensure that "#{myvariable}" contains "code"
ensure that "#{myvariable}" contains "code" with value "1234"
ensure that "#{myvariable}" contains:
| code |
ensure that "#{myvariable}" contains:
| code | 1234 |

<descriptor> should have attribute "<attributeName>"

<descriptor> has attribute "<attributeName>"

<descriptor> has the following attributes:

| <attributeName> |

<descriptor> should have the following attributes:

| <attributeName> |


Will verify a DOM attribute is present.

Make sure you use the Javascript/DOM name in case an attribute is not found but expected to be.

<descriptor> should not have attribute "<attributeName>"

<descriptor> does not have attribute "<attributeName>"

<descriptor> should not have the following attributes:

| <attributeName> |

<descriptor> does not have the following attributes:

| <attributeName> |

Will verify a DOM attribute is not present.

Make sure you use the Javascript/DOM name in case an attribute is not found but expected to be.

<descriptor> should have attribute "<attributeName>" with value "<value>"

<descriptor> has attribute "<attributeName>" with value "<value>"

<descriptor> has the following attributes:

| <attributeName> | <value> |

<descriptor> should have the following attributes:

| <attributeName> | <value> |


Will verify a DOM attribute has a specific value. An empty value will simply perform an existence check for that attribute.

Make sure you use the Javascript/DOM name in case an attribute is not found but expected to be.

<descriptor> should not have attribute "<attributeName>" with value "<value>"

<descriptor> does not have attribute "<attributeName>" with value "<value>"

<descriptor> does not have the following attributes:

| <attributeName> | <value> |

<descriptor> should not have the following attributes:

| <attributeName> | <value> |

Will verify a DOM attribute does not have a specific value. An empty value will simply perform an existence check for that attribute.

Make sure you use the Javascript/DOM name in case an attribute is not found but expected to be.

<descriptor> should have class "<className>"

<descriptor> has class "<className>"

Will verify the specified class names (seperated with a space) are present on the element.

The order of the class names does not matter and the element is allowed to have more classes than the ones specified.

 

<descriptor> should not have class "<className>"

<descriptor> does not have class "<className>"

Will verify that the element does not have all classes specified.

If multiple classes are specified (separated with a space), then this step will only fail if the element has all of those classes.

Checkbox, radio button and select

Form elements checkbox, radio and select can also be used with the table statements the element values should be or i fill in the following.  A radiobutton or checkbox can be verified using the checked value.

Example:

And the field values in div "registrationSection" should be:
    | locator                      | type     | value     |
    | birthdate_dd                 | select   | 16        |
    | /interessante aanbiedingen./ | checkbox | unchecked |
    | robinsonThirdParty           | checkbox | checked   |
    | Mevr.                        | radio    | checked   |

Working with popups and other windows

It is possible to work with other windows or popups opened by javascript from the original page.  To be able to access them they must have a unique name, you can then scope the browser to a specific window after which all steps will be executed against that window.  When finished, you should clear the window so the scope goes back to the original page.

When i switch to popup "Image browser"
Then i should see link "somelinkinthepopup"
And i clear the popup

Uploading files to a webpage

Working with files is a bit tricky and might not always work under all circumstances.  This is due to browser security restrictions and not much can be done about it.  However, in many cases it does work quite well.

Accessing file elements is done using either the file or file2 type descriptor.  The difference between the 2 is on how uploaded files are handled, this is due to how SAHI treats file uploads.

Use fileif the form containing the input does not have any javascript validation on a file being selected before submitting the form.

Use file2: if the form does have javascript checks that require.

Because file2 actually modified the dom element from a regular file input type to a text input type, it is best to use file if that one works.

More details on how SAHI handles file uploads can be found in the SAHI documentation.

Selecting files to upload

Basically you can use any absolute path to specify the file to upload.  However, CTF provides a best practice: 

  • Put the files you want in the src/test/resources folder (preferably in a subdirectory eg. files).
  • Specify the file using a relative path /files/myfile.jpeg

Any relative path will be assumed to be a resource residing in the test resources folder.

Uploading under a different file name

It's possible to upload a file using a different name (for example a name unique for the current scenario).  You can do this by specifying the name as the first part of the value, followed by a :: (these can include whitespace for improved readability).

In this case CTF will make a copy of that file to the temp directory, and then upload that copy.

Examples of using file upload
* i fill in the following:
| type  | locator | value                                          |
| file  | File 1  | /files/test-file.jpeg                          |  # Will upload the file as test-file.jpeg - without javascript changes
| file2 | File 2  | #{id.scenario}-1.jpeg::/files/test-file.jpeg   |  # Will upload the file using the 2nd upload approach (will modify the dom)
| file2 | File 3  | #{id.scenario}-2.jpeg :: /files/test-file.jpeg |  # Will upload the same file again, but under a different name
* i press "Upload"

Regular expressions

A normal lookup will look for the exact text matching beginning to end, however in most places a Javascript style regular expression can be used for partial or case insensitive matching.

Valid lookups:

When i check "Some checkbox"
And i check "/Some/"
And i check "/SOME CHECK/i"

Element scoping

In many steps you can lookup an element using a descriptor, with an optional parent element (having its own descriptor).  The parent element is the scope of the lookup.

There is never more than a single parent specification allowed in a step.  It is however possible to nest parents by saving them to an intermediate variable and using the element or parent indicator.  An example explains best:

* i save div "somediv" as "some div"
* i save div "layout-box" in div "main-content" as "layout box"
* element "${layout box}" should be visible
* i should see div "view-content" in parent "${layout box}"
* i save list "main-block-items" in element "${layout box}" as "news items"
* i should see listItem 1 in element "${news items}"
* i should not see element "${some element that does not exist}"

Property & variable accessing

In most places where strings are used you can use the shorthand variable notation of ${variable}.  Variables can be mixed with text, the following would be a legal combination:

Given i am on "http://website.${subdomein}.foreach.be/user/${username}"

A variable can be created using the i save step.  When encountering a variable placeholder the script will first look for the saved value in the collection of local variables.  If not found it will then look for the key in the collection of properties.

Variables created during scenario execution and having a simple name (no spaces, dots or other punctuation), are also directly accessible using the EL syntax: #{variable}.  This allows you to save complex objects as variable, and access their properties directly in scripts.

Standard objects

The above is only for manually created variables and properties.  There are also a number of standard objects available.  

Note that you should use the EL script syntax (#{objectname}) to access the standard objects.

The following standard objects are available:

 Commonly used 
#{environment}Returns the value of the environment system property.
#{id.today}Returns a unique identifier for the date (date in format 2013-12-01).
#{id.testrun}Will return the same value in every scenario that is executed in the same test run.
#{id.scenario}Will return the same value in the same scenario and will guaranteed be different in another scenario.
#{id.next}Will return a guaranteed different value on every use.
#{id.nextNumber}Will return a guaranteed different value on every use, but will return it as a (larger) number.
#{date.X}Provides a set of date functions, see the 6d) Date values object.
Specialist objects
#{properties['key']}Will look for the key in the properties collection and will return empty if not found.
#{variables['key']}Will look for the key in the variables collection and will return empty if not found.
#{lookup('key')}

Will first look for key in the variables collection, if not found there will look for it in the properties.

Does the same as ${key}.

#{browser.textbox(...)}Allows direct use of the SAHI browser API.

EL Script

Avoid use of EL script except for more technical testing purposes.

EL statements are always prefixed with #{}.  They can be mixed with text, the following would be a legal combination of EL script elements and text:

Given i am on "http://website.#{environment}.foreach.be/user/#{lookup('username')}"