How to test that login page of yours
Tags: testing, javascript, webdev, codequality
Published: 2018-08-06 21:48:59

---
title: How to test that login page of yours
published: true
description: Get past test anxiety with this tutorial on testing a login page, something we all have to do at some point in our lives.
tags: testing, javascript, webdev, codequality
cover_image: https://thepracticaldev.s3.amazonaws.com/i/9mpyh6lcs1l6cgjccg4t.jpg
---

"Yeah, I'd love to start testing, but I just don't for some reason".

I've heard this statement a lot, and have said it myself a few too many times. 

In fact, I wrote about it in a previous post:
{% link https://dev.to/klamping/why-youre-not-writing-ui-tests-5fdd %}

While there are plenty of tutorials out there on how to write a basic automated test, they don't seem to get people past that initial resistance.

They're just a too simple of examples to really apply in to a real website. Questions like "What should I be checking?" and "how do I organize this?" usually keep folks from moving forward.

So I had an idea: What if I put together a set of tests for devs so they get that first step out of the way?

What if someone could go to a site, answer a few prompts, and be given a set of tests to get them started?

I thought that'd be really cool!

# Identifying a starting point

In order to do this, I needed a common bit of functionality that almost all websites shared.

What's one thing almost all websites have? A login form.

So I threw together a landing page where people could sign up for updates, then I let the idea percolate a little (really, I was just too busy making the video tutorials to dedicate time to the idea). A few folks signed up, which was enough to show me that people were interested in the idea.

I finally got around to building out the functionality and put together the website [https://testyourlog.in](https://testyourlog.in)

![Test Your Login Homepage](https://images2.imgbox.com/c2/37/4siUIF7Y_o.png)

Go give it shot and let me know if it helps. I'd love to have your feedback.

If you want, you can just go to there and ignore the rest of this post.

But if you want to know the details, here's a full, in-depth tutorial on how to write tests for your login page.

# The "Test your Login" WebdriverIO Tutorial

## The Video Version

I did a YouTube live stream a while back, and if you prefer video format (like me), perhaps you'll fancy the video tutorial better than the text below. Or you can go with both!
{% youtube dl-YnA_njXo %}

## The Text Version

### Step 1: Install WebdriverIO

If you haven't messed around with [WebdriverIO](https://webdriver.io), I'll quickly explain that it's a functional test automation framework. It allows you to script out page actions to take in a browser, and validate that the actions had the desired affect.

There are lots of reasons I love WebdriverIO, but I cover them in another post:
{% link https://dev.to/klamping/how-webdriverio-makes-testing-worth-it %}

Before I get to installing WebdriverIO, you need to have a recent version NodeJS and be in an NPM package.

I won't cover the first item (it varies greatly by system and there are plenty of tutorials out there already), but if you aren't in an NPM package, you can quickly set one up by opening up a command prompt and running:

```sh
npm init -y
```

So long as you have those two things, you can install WebdriverIO by running [the normal NPM command for such things](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

```sh
npm i --save-dev webdriverio
```

### Running WebdriverIO

I used to recommend folks [add a command to their `package.json` scripts section](https://www.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/), but now I go with a much simpler solution, [npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b).

You can run the WebdriverIO CLI with just:

```sh
npx wdio
```

### Configuration

The first time you run that command, it will check for a `wdio.conf.js` file. 

Since we haven't created one yet, WebdriverIO is smart enough to figure that out and help us through the process. Here are the answers I chose:

- Where do you want to execute your tests? **On my local machine**
- Which framework do you want to use? **mocha**
- Shall I install the framework adapter for you? **Yes**
- Where are your test specs located? **./test/\*\*/*.js**
- Which reporter do you want to use?  **spec - https://github.com/webdriverio/wdio-spec-reporter**
- Shall I install the reporter library for you? **Yes**
- Do you want to add a service to your test setup?  **selenium-standalone - https://github.com/webdriverio/wdio-selenium-standalone-service**
- Shall I install the services for you? **Yes**
- Level of logging verbosity **silent**
- In which directory should screenshots gets saved if a command fails? **./errorShots/**
- What is the base url? **http://testyourlog.in/example**

![Console output when filling out the configurations](https://thepracticaldev.s3.amazonaws.com/i/jzu9jel85gc66vgrvwx7.gif)

You'll probably want to replace the test URL with whatever page you want to validate.

After that last question, WebdriverIO will install our dependencies and generate our configuration file. We still have a few more steps to go for our first test though.

### Folder & File set up

We told WebdriverIO that we've got our tests stored in the `test` folder. Go ahead and create that folder if you haven't already. Then, create a file called `login.js` and open it up in your favorite text editor. 

![Folder/File Overview](https://images2.imgbox.com/59/ce/ymjLbV1L_o.png)

WebdriverIO can be set up to use Mocha, which is what I did in my configuration answers earlier. This helps organize our tests and process the test results.

Mocha uses two functions, `describe` and `it`, to add hierarchy to test suites. If you're unfamiliar with them, [ check out the official docs](https://mochajs.org/#getting-started) and my take on them:
{% link https://dev.to/klamping/take-a-drive-with-webdriverio-and-mocha-14e %}

For our needs, we'll set up the following:

```js
describe('Login Page', function () {
  it('should let you log in', function () {
    // our tests will go here
  })
})
```

You do need both `describe` and `it`, as that's the hierarchy Mocha excepts. The `it` goes inside the `describe` block. Inside of the `it` block we'll put our tests.

## All set up and ready to dance

Okay, we've got WebdriverIO configured and our test file laid out. Let's write our first test.

We're checking out a basic "happy path" scenario: The user enters in valid credentials for an active account.

![Showing logging in](https://images2.imgbox.com/f2/ed/KPgmxGGw_o.gif)

There are four unique steps to this test:

1. Go to the login page
2. Enter valid credentials
4. Click submit
5. Validate we're logged in

Let's go through these one at a time.

### Going to the login page

The basic way to move to various pages in WebdriverIO is to use [the `url` command](http://webdriver.io/api/protocol/url.html). If you pass in text to it, WebdriverIO will tell the browser to that specific webpage.

You could pass in the entire URL of the page you want to test, but since we've already defined the domain we're testing on (see config generation above), all we have to pass in is the path. 

That looks like:

```
it('should let you log in', function () {
  browser.url('./');
})
```

The path you use will depend on where your login page lives. Maybe it's part of your homepage (like ours is). Maybe it's some complex URL that users have no hope of remembering.

Whatever it is, just use the right one :)

### Entering valid credentials

Now that we're on our login page with our login form, we need to enter our username/email and password.

The command we need to use for this is called ['setValue'](http://webdriver.io/api/action/setValue.html). It works by accepting [an element selector](http://webdriver.io/guide/usage/selectors.html) and a text value to insert in said element.

```
it('should let you log in', function () {
  browser.url('/');
  browser.setValue('input[name="email"]', 'valid@user.com');
  browser.setValue('input[name="password"]', 'hunter2');
})
```

For our element selectors, we use a combination of an HTML element and an HTML attribute. If you're not familiar with [selecting elements in WebdriverIO](http://blog.kevinlamping.com/selecting-elements-in-webdriverio/), you're definitely going to want to read up on it.

Again, update your selectors and credentials with what's right for your site. 

### Clicking Submit

Okay, we've gone to the login page and have entered our credentials. Let's finish logging in.

There is a 'submitForm' command, but it's been deprecated, so we'll just go with clicking the 'Login' button.

We can 'click' and element by using [the `click` command](http://webdriver.io/api/action/click.html). That just makes sense, right?

All we need to do beyond calling the command is pass in a selector defining what element we want to click. This will trigger Webdriver to simulate a mouse left click in the center of that element.

```
it('should let you log in', function () {
  browser.url('/');
  browser.setValue('input[name="email"]', 'valid@user.com');
  browser.setValue('input[name="password"]', 'hunter2');
  browser.click('.button=Login');
})
```

Woah, what is that `=login` selector?! Turns out, [you can select elements by the text those elements contain](http://webdriver.io/guide/usage/selectors.html#Element-with-certain-text). 

WebdriverIO is so cool.

### Validating we're logged in

If all has gone well, we should be logged in now. But how do we really know?

If we were to run our test, the login page would quickly flash by, and we may miss visually verifying things worked out as planned.

Instead, we're going to use 'assertions' to check the status for us.

The simplest way I know to explain assertions is to say that:

1. You give the computer some unknown value (like a variable)
2. You give the computer a known value (like the number 9)
3. You tell the computer to validate the relationship between those two values. Examples:
  - The variable should equal 9
  - The variable should not equal 9
  - The variable should be bigger than 9

If the value of the variable is 8, only the second assertion will pass (8 does not equal 9). 

Usually the variable is the result of some code function you want to test. Maybe you have a function that calculates the square of a number (called `calcSquare`).

Your assertions would be:

```
assert.equal(calcSquare(3), 9); // 9 == 9
assert.notEqual(calcSquare(2), 9); // 4 != 9
```

Both of those assertions will pass, assuming the `calcSquare` function is working correctly.

We can use assertions in many ways in WebdriverIO. For our current needs, we want to validate that the url of the page we're on is either:

- not the same as the login url
- the same as the url after logging in

The first is a more general test, and may result in a false positive (the test passes when it shouldn't) if the login takes you to a different page without logging you in (for example, a 'forgot your password' page).

The second option is a better one, but requires knowing the url of the page you get logged in to. 

Thankfully, I know that URL for my example. But just in case, I'll show you both assertions.

First, we need to get the URL of the page we're now on (Webdriver is smart enough to wait for the page to reload after submitting the login form). 

We get that url with [the `getUrl` command](http://webdriver.io/api/property/getUrl.html).

```
it('should let you log in', function () {
  browser.url('/');
  browser.setValue('input[name="email"]', 'valid@user.com');
  browser.setValue('input[name="password"]', 'hunter2');
  browser.click('.button=Login');
  
  const pageUrl = browser.getUrl();
})
```

We don't pass any value in to the `getUrl` command. We simply assign the result of it to a `pageUrl` constant. 

With it, we can now run our assertions:

```
it('should let you log in', function () {
  browser.url('/');
  browser.setValue('input[name="email"]', 'valid@user.com');
  browser.setValue('input[name="password"]', 'hunter2');
  browser.click('.button=Login');
  
  const pageUrl = browser.getUrl();
  assert.notEqual(pageUrl, 'http://testyourlog.in/example/');
  assert.equal(pageUrl, 'http://testyourlog.in/example/logged-in.html?email=valid%40user.com&password=hunter2');
})
```

I include both assertion types here, but you should really only need to include one.

Wait.

Where did this magical `assert` come from? 

Nowhere, yet!

Yes, I neglected to mention the minor detail of loading [Node's 'assert' library](https://nodejs.org/api/assert.html).

Thankfully that is pretty easy. Just shoot up to the top of your file and add:

```js
const assert = require('assert');
```

Now you're ready to party.

Here's the full script just for easier reference:

```
const assert = require('assert');

describe('Login Page', function () {
  it('should let you log in', function () {
    browser.url('/');
    browser.setValue('input[name="email"]', 'valid@user.com');
    browser.setValue('input[name="password"]', 'hunter2');
    browser.click('.button=Login');
  
    const pageUrl = browser.getUrl();
    assert.notEqual(pageUrl, 'http://testyourlog.in/example/');
    assert.equal(pageUrl, 'http://testyourlog.in/example/logged-in.html?email=valid%40user.com&password=hunter2');
  });
});
```

## Let's run our tests already!

We've got our test written and our assertions in place. Time to try it all out.

In a terminal window (or command prompt if you prefer to call it that), run your `npx wdio` command again.

If everything is set up correctly, you will see a Firefox browser momentarily pop up on your screen.

Hopefully your test completed and passed. 

![Console output of successful test passing](https://images2.imgbox.com/a1/66/hHtz0hmC_o.png)

## That's it for now

There's more to test on our login page and we'll also want to try out using Page Objects. But this is about all I can type on the subject for now (and probably all you have time to read).

[The official testyourlog.in generator](https://testyourlog.in/) includes visual regression testing, TravisCI integration and Page Object support, which are all advanced subjects.

I cover all these subjects out on [my free YouTube channel](https://www.youtube.com/user/medigerati/) and in [my special videos tutorials on WebdriverIO](https://learn.webdriver.io).

If you're interested in seeing the code that runs testyourlog.in, it's available via GitHub:
{% github klamping/testyourlog.in %}