Watai tutorial: the DuckDuckGo example
======================================

Subject
-------

We’ll present a test for the [DuckDuckGo](https://duckduckgo.com) search engine. This engine is just like Google, except that it doesn’t [track you](http://dontbubble.us/), and that it has a nice disambiguation feature: the “Zero Click Info box”.

Let’s imagine we are engineers at DuckDuckGo, and we want to test if a Zero Click Info box is shown for an acronym: **“TTIP”**.

[[/tutorials/images/duckduckgo_search.png|align=center]]

Why are people around the world using this acronym? Are they talking about a chemical compound? Or about a US-EU free trade agreement negotiated in secret that [endangers environmental norms](http://ttip2014.eu/qa.html), [online freedoms](https://www.laquadrature.net/en/trans-atlantic-trade-talks-bound-to-harm-freedoms-online) and [health regulation](https://www.techdirt.com/articles/20140702/02592127754/phrma-wants-us-to-use-taftattip-to-stop-eu-releasing-basic-drug-safety-information.shtml)? The result page should help our users get a quick answer!

[[/tutorials/images/duckduckgo_zeroclickbox.png|align=center]]


Scenario
--------

Based on the above requirements, we can formalize the following testing scenario:

1. Go to `duckduckgo.com` (English version).
2. Type _“TTIP”_ in the search field.
3. Submit the search.
4. Ensure that the text _“Transatlantic Trade”_ is presented somewhere in the “meanings” header ribbon.


Testing suite files
-------------------

The test suite automating the above scenario is already available. [Download it](https://github.com/MattiSG/Watai/wiki/tutorials/Watai-DuckDuckGo-example.zip) and open it in your file browser.

[[/tutorials/images/duckduckgo_folderlisting.png|alt=Folder listing]]

We see a `config` file, two `Component` files, a `Scenario` and a `Fixture` file.
These are all the parts of a Watai test. Let’s examine them in more details.


Configuration
-------------

The [`config.js`](https://github.com/MattiSG/Watai/blob/master/example/DuckDuckGo/config.js) file exports a hash with two mandatory key-value pairs:

```javascript
// example/DuckDuckGo/config.js
module.exports = {
	baseURL: 'https://duckduckgo.com',
	browser: 'firefox'
}
```

* `baseURL`, that describes the URL at which the test should start.
* `browser`, that defines which browser should be used to run the test.

> It also contains an optional `driverCapabilities` hash, which can be used to specify [[advanced constraints|Configuration]].
> For example, if your Firefox browser is stored in an unusual location, specify its path now in the `firefox_binary` key of the `driverCapabilities` hash.


Components
----------

**Components** are defined in files ending in `Component.js`. They represent a graphical component of your webapp.

### Elements ###

DOM mapping is mandatory for your tests to have knowledge of the structure of the tested web page.

That’s exactly what a **component** provides: a mapping from DOM elements, identified through selectors, to testing-environment attributes.

Open the [`ZeroClickComponent.js`](https://github.com/MattiSG/Watai/blob/master/example/DuckDuckGo/ZeroClickComponent.js) file: it is a simple hash entry.

```javascript
// example/DuckDuckGo/ZeroClickComponent.js
meanings: '#zci-meanings'	// this is an element definition
```

And here is our header definition, as an **element**. It maps a _meaningful, testable name_ to a CSS selector describing how this element is retrievable in the DOM. We will now be able to retrieve the content of the Meanings section of the Zero Click Info box.

> Watai also offers [[other ways|Component#alternative-location-methods]] to select elements, such as XPath, for situations where a dynamic DOM is too complex for CSS selectors.


### Actions ###

Interface components in modern webapps are not only sets of elements. They can also offer complex actions to the user, triggered by basic interaction events such as clicks or keystrokes on said elements.

This is why a **component** is a bit more than a simple DOM map: it also abstracts action sequences and makes them callable directly through a meaningful name.

Open the [`SearchBarComponent.js`](https://github.com/MattiSG/Watai/blob/master/example/DuckDuckGo/SearchBarComponent.js) file: there are once again **elements**, but there’s also an **action** defined.

```javascript
// example/DuckDuckGo/SearchBarComponent.js
field:        'input[name=q]',            // this is an element
submitButton: '#search_button_homepage',  // this is an element too

searchFor: function searchFor(term) {     // this is an action
	return	this.setField(term)()
				.then(this.submit());
}
```

The `searchFor` key is a JavaScript function that takes a parameter and sequences two basic steps: typing the passed string in a field, and clicking a submit button.
With this **action**, we will be able to search for an ambiguous term, as our scenario needs.

> The `then` syntax is here because all action steps are sequenced as [promises](http://wiki.commonjs.org/wiki/Promises/A), an abstraction over asynchronous operations.
> Don't worry, you don't need to understand this in details at this point. You may come back to this later if you need to write complex actions.


Fixtures
--------

We then need to define what we want to search for, and what we expect to be presented with!

Open the [`ZeroClickFixture.js`](https://github.com/MattiSG/Watai/blob/master/example/DuckDuckGo/ZeroClickFixture.js) file: this is where we define such fixture.

```javascript
// example/DuckDuckGo/ZeroClickFixture.js
query = 'TTIP'
expandedAcronym = /Transatlantic Trade/
```

You can notice that we're inputting a specific string, but we only expect results to match a given RegExp rather than defining exactly what they will be. This improves the resilience of our tests.

Using **fixtures files** to store values is optional, but it is recommended as a way to decouple concerns even more.

In our example, if we wanted to test another ambiguous term, there’s no hesitation where to define it: simply open the fixture file, replace `TTIP` with the new term, and restart the test.


### Naming ###

A fixture file is pure JavaScript code, and has to end in `Fixture.js`.

All the variables defined inside will be made available to all **components** and **scenarios** in the same suite.

> You may have as many fixtures files as you like, so don't hesitate to have many small and well-named files.


Scenarios
---------

So, we have now defined all needed **elements**, **actions** and **fixtures** for our scenario. However, we have not yet defined how these pieces fit together, nor what we are going to check.

This is what a **scenario** is for. Let’s look at the [`1 - ZeroClickScenario.js`](https://github.com/MattiSG/Watai/blob/master/example/DuckDuckGo/1%20-%20ZeroClickScenario.js) file.

```javascript
// example/DuckDuckGo/1 - ZeroClickScenario.js
description: 'Looking up an ambiguous term should make a Zero Click Info box appear.',

steps: [
    SearchBarComponent.searchFor(query),
    {
        'ZeroClickComponent.meanings': expandedAcronym
    }
]
```


### Description ###

Just like a **component**, a **scenario** is series of hash entries, except that it has two mandatory keys.

To present what expected behavior you are testing exactly, you will have to associate a string to the `description` key.

> It is good practice to write a sentence with “should” as the main verb, so that failures and successes may both be meaningful.


### Scenario ###

The second expected key in a **scenario** is `steps`. Its value must be an array.

In our example, the first line is simply a call to the **action** we defined in the `SearchBarComponent`: we are going to `searchFor` the term we defined in the **fixture**: `query`.

You can define as many **steps** in a **scenario** as you want. A **step** can be, like here, an **action**, a custom function, or a **state definition**. All these steps will be executed in order, always waiting for the previous ones.


### State definitions ###

So, with **scenario steps**, we know how to define what our components are to execute. But we still don’t know how to actually check behavior!

Assertions in Watai are implicit. That is, you won’t have to `assert` anything (unless you want to): you’ll simply define an expected **state**, and the actual state of the current web page will be checked against it.

A **state definition** is simply a hash where keys reference some **elements**, and the corresponding values are matched against the values of the targeted DOM elements.

The only tricky thing is that you cannot have an _actual_ reference as a hash key, only its name. So, remember to quote keys when defining states.

> In the end, all files manipulated by Watai are JavaScript (possibly wrapped by automatically-added curly braces). The syntax is thus JavaScript, and that's why hash keys containing dots must be protected by quotes.


### Naming ###

A scenario file contains one **scenario**, and has to end in `Scenario.js`.

You may also have noticed the `1 - ` prefix of the **scenario** filename. Such indices are needed for Watai to determine dependencies. Currently, there is no support for complex dependencies, so your test suite has to be linear. To make that explicit, **scenario** filenames have to be prefixed with their index.

> Indices don't have to be continuous, i.e. you may have scenarios 1, 2, 3 and 5 without any harm.
> This also means you can quickly exclude a scenario from being evaluated by renaming it to something like `x4 - MyFourthScenario.js`.


Executing the suite
-------------------

To run a test suite, simply use `watai` and pass it the path to the folder that contains your config, components, scenarios and fixtures files.

_The following assumes you have Firefox installed. If not, [do it now](https://www.mozilla.org/firefox/). If you don’t want to, learn how to [[test with Chrome|Testing-with-Chrome]], for example._

	watai path/to/downloaded/example/DuckDuckGo

➥ If there’s any problem (did you start the Selenium server?), don’t despair and check the [[troubleshooting guide|Troubleshooting]], there should be an easy fix  :)


Conclusion
----------

This was a small test suite, but it was enough to see all parts of Watai, congratulations!

### Where to go next? ###

- You could try to create your own test suite, using the DuckDuckGo example and keeping the [other examples](https://github.com/MattiSG/Watai/tree/master/example/) nearby to see more complex uses.
- You could also try to [[run the example with Chrome|Testing-with-Chrome]].
- If you need more in-depth information about some parts of Watai, read the [[references|Home#writing-test-suites]].
- If you’re still not sure about Watai or where it should fit in your development process, check out the [[rationale|Rationale]].

- - - - - - -

> If something in this introduction could be improved, please do so, this is a wiki! All new users will thank you  :)
>
> If you think of introducing bigger changes, please [create an issue](https://github.com/MattiSG/Watai/issues/new) so we can discuss it.
