Skip to content

Tutorial 2: Creating your first page

Natalia Djohari edited this page Mar 6, 2019 · 3 revisions

For the purpose of this exercise we'll create a new page called "Demo".

Test Driven Development

The principles of Test Driven Development are straightforward:

  • Write a failing test
  • Write just enough code to make the test pass
    • YAGNI - You Ain't Going To Need It
  • Refactor
  • Write the next failing test
  • Rinse and repeat

Write failing test

Open client/js/pages/homePage/homePage.spec.js

Add the following test above the test for #rightButtonEvent:

describe('#faceButtonEvent', () => {
  it('should take the user to the demo page', () => {
    const props = {
      navigate: () => { },
    };

    const page = new HomePage(props);
    spyOn(page, 'navigate');

    page.faceButtonEvent();
    expect(page.navigate).toHaveBeenCalledWith('demo');
  });
});

Run the tests with ./go test:dev. This will continually run the tests as you make changes to your code.

This test should fail with an output similar to the following:

FAIL  client/js/pages/homePage/homePage.spec.js
  ● HomePage › #faceButtonEvent › goes to demo page

    expect(spy).toHaveBeenCalledWith(expected)

    Expected spy to have been called with:
      ["demo"]
    But it was not called.

      at Object.<anonymous> (client/js/pages/homePage/homePage.spec.js:58:29)
          at new Promise (<anonymous>)
          at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:160:7)

Get the test to pass

To get this test passing we need to ensure that when a faceButtonEvent from the homepage occurs that navigate is being called with ‘demo’.

The first step is to add the faceButtonEvent() function in the homePage.js file, that parses ‘demo’.

  faceButtonEvent() {
    this.navigate('demo');
  }

This gives the face button from the home page some logic and will make our test pass.

Create the page

...first, write the test

We want our Demo page to contain the text "This is a demo", so we're going to start by writing a test for that.

In the client/js/pages folder, create a new folder demoPage. This is where all the files related to the demo page will exist. Create a new file called demoPage.spec.js.

Add the following test.

const DemoPage = require('../../src/js/pages/demoPage/demoPage');

describe('The Demo Page', () => {
  let watchFace;
  beforeEach(() => {
    document.body.innerHTML = `<div id='watch-face' style='height: 100px; width: 100px;'></div>`;
    watchFace = document.getElementById('watch-face');
  });

  describe('#render', () => {
    it('should contain the correct text', () => {
      const page = new DemoPage();
      expect(page.render()).toContain('This is a demo');
    });
  });
});

Check your test runner. If it is not running, you can start it by executing ./go test:dev.

We expect our new test to fail along lines something like this:

 FAIL  client/js/pages/demoPage/demoPage.spec.js
  ● Test suite failed to run

    Cannot find module '../../src/js/pages/demoPage/demoPage' from 'demoPage.spec.js'

    > 1 | const DemoPage = require('../../src/js/pages/demoPage/demoPage');
      2 | 
      3 | let page;
      4 | 

Almost every page starts the same way.

...now make the test pass

create the javascript file

First create a new file called demoPage.js inside client/src/js/pages/demoPage

The new page will be extending the basePage.js so we will need to require that at the top, and then use extend it in the class declaration.

const BasePage = require('watch-framework').BasePage;

class DemoPage extends BasePage {
  template = require('./demoPage.hbs');
}

module.exports = DemoPage;

...now create the content file

All of our pages require a template property that contains the imported handlebars file which holds html content. The content of the template file can be returned by calling the template method.

We will create the handlebars file we are importing in the demoPage.js. Create a new file called demoPage.hbs inside client/src/pages/demoPage and add this line:

<p>This is a demo</p>

To add content to a page, you must edit the handlebars file.

If you'd like to learn a little more about handlebars (.hbs) you can read more here

Link the page

So we have our new page demoPage.js and we have our faceButtonEvent() in homePage.js which is trying to navigate there, to link these together we need to require our demoPage in our routes.js file.

Write a test first!

open up watch_edition/client/pages/routes.spec.js

and add the following

const routes = require('../src/js/routes');

describe('routes', () => {
  it('all routes should exist', () => {
    expect(routes['/']).toBeDefined();
    expect(routes['contacts']).toBeDefined();
    expect(routes['team']).toBeDefined();
    expect(routes['404']).toBeDefined();
    expect(routes['demo']).toBeDefined();
  });
});

Run the test...

then go to routes.js and add this!

const HomePage = require('./pages/homePage/homePage');
const ContactsPage = require('./pages/contactsPage/contactsPage');
const TeamPage = require('./pages/teamPage/teamPage');
const FourOhFour = require('./pages/404Page/404Page');
const DemoPage = require('./pages/demoPage/demoPage');

module.exports = {
 '/': HomePage,
 'contacts': ContactsPage,
 'team': TeamPage,
 '404': FourOhFour,
 'demo': DemoPage
};

Time to check it out

Now go to your app's home page and click on the face button.

You should arrive at a new page that displays

This is a demo

And the tests should pass 💯 🥇 👯 🍡

If the above is true, congratulations, you've made your first page! 🎉🎉🎉🎉