From 17538d0d5afcb73851afd01b35de3919aeef78c0 Mon Sep 17 00:00:00 2001 From: isabelrios Date: Tue, 31 Jan 2017 11:54:00 +0100 Subject: [PATCH] ui tests --- README.md | 6 ++ package.json | 7 +- tests/selenium/mainPage.js | 19 +++++ tests/selenium/test_login.js | 89 +++++++++++++++++++++ tests/selenium/views/accessors.js | 17 ++++ tests/selenium/views/login/accessors.js | 27 +++++++ tests/selenium/views/login/view.js | 36 +++++++++ tests/selenium/views/signed_in/accessors.js | 17 ++++ tests/selenium/views/signed_in/view.js | 18 +++++ tests/selenium/views/view.js | 8 ++ 10 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 tests/selenium/mainPage.js create mode 100644 tests/selenium/test_login.js create mode 100644 tests/selenium/views/accessors.js create mode 100644 tests/selenium/views/login/accessors.js create mode 100644 tests/selenium/views/login/view.js create mode 100644 tests/selenium/views/signed_in/accessors.js create mode 100644 tests/selenium/views/signed_in/view.js create mode 100644 tests/selenium/views/view.js diff --git a/README.md b/README.md index c00a6a0..079209b 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,9 @@ npm start ``` You browser should automatically open a tab at http://localhost:3000 + +## Running UI tests + +```shell +mocha tests/selenium/* +``` \ No newline at end of file diff --git a/package.json b/package.json index 884b588..ba8beab 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,12 @@ "url": "git@github.com:mozilla-sensorweb/sensorweb-admin-panel.git" }, "devDependencies": { - "react-scripts": "0.4.1" + "react-scripts": "0.4.1", + "chai": "^3.5.0", + "chromedriver": "^2.27.2", + "mocha": "^2.5.3", + "selenium-webdriver": "^3.0.1", + "wd": "^0.4.0" }, "dependencies": { "classnames": "^2.2.5", diff --git a/tests/selenium/mainPage.js b/tests/selenium/mainPage.js new file mode 100644 index 0000000..266d1c7 --- /dev/null +++ b/tests/selenium/mainPage.js @@ -0,0 +1,19 @@ +'use strict'; + +var LoginView = require('./views/login/view.js'); + +function MainPage(driver) { + this.driver = driver; +} + +MainPage.prototype = { + getLogInPage : function() { + return new LoginView(this.driver); + }, + + stop() { + return this.driver.quit(); + }, +}; + +module.exports = MainPage; diff --git a/tests/selenium/test_login.js b/tests/selenium/test_login.js new file mode 100644 index 0000000..bf155c4 --- /dev/null +++ b/tests/selenium/test_login.js @@ -0,0 +1,89 @@ +'use strict'; + +var assert = require('assert'); +var webdriver = require('selenium-webdriver'); +var chrome = require('selenium-webdriver/chrome'); +var path = require('chromedriver').path; + +const By = require('selenium-webdriver').By; +const until = webdriver.until; + +var service = new chrome.ServiceBuilder(path).build(); + chrome.setDefaultService(service); + +var HOST_URL = 'http://localhost:3000' + +describe( 'Show main page', function(done) { + + var mochaTimeOut = 30000; //ms + var driver; + + var MainPage = require('./mainPage'); + var mainPage; + var loginView; + var elements; + + + before(function() { + this.timeout(mochaTimeOut); + driver = new webdriver.Builder() + .withCapabilities(webdriver.Capabilities.chrome()) + .build(); + }); + + after(() => mainPage.stop()); + + beforeEach(function() { + driver.get(HOST_URL) + }); + + it('should be titled sensorweb', function () { + this.timeout(mochaTimeOut); + return driver.wait(webdriver.until.titleIs('SensorWeb'), 5000) + .then(function(value) { + return assert.equal(value, true); + }); + }); + + describe('Sign In', function() { + + beforeEach(function() { + elements = { + pwd: driver.findElement(webdriver.By.css('#app > div > div.jumbotron > div > div > form > div:nth-child(2) > input')), + signIn: driver.findElement(webdriver.By.css('button.btn.btn-primary.btn-lg')) + }; + mainPage = new MainPage(driver); + loginView = mainPage.getLogInPage(); + return loginView; + }); + + it('should have the rights fields', function() { + var types = { + pwd: 'password', + signIn: 'submit' + }; + var promises = Object.keys(elements).map(function(key) { + return elements[key].getAttribute('type') + .then(function(value) { + assert.equal(value, types[key]); + }); + }); + return Promise.all(promises); + }); + + it('should error if wrong password', function () { + return loginView.incorrectLogin('a') + .then((text) => { assert.equal(text, 'Unauthorized')}); + }); + + it('should error if empty password', function () { + return loginView.incorrectLogin('') + .then((text) => { assert.equal(text, 'Unauthorized')}); + }); + + it('should login if password is correct', function () { + // The password should be the one used in server -> dev.json file + return loginView.correctPassword('PasswordSet') + }); + }); +}); diff --git a/tests/selenium/views/accessors.js b/tests/selenium/views/accessors.js new file mode 100644 index 0000000..9f51cf1 --- /dev/null +++ b/tests/selenium/views/accessors.js @@ -0,0 +1,17 @@ +'use strict'; + +const until = require('selenium-webdriver').until; + + +function Accessors(driver) { + this.driver = driver; +} + +Accessors.prototype = { + waitForElement(locator) { + const element = this.driver.wait(until.elementLocated(locator)); + return this.driver.wait(until.elementIsEnabled(element)); + }, +}; + +module.exports = Accessors; diff --git a/tests/selenium/views/login/accessors.js b/tests/selenium/views/login/accessors.js new file mode 100644 index 0000000..567475b --- /dev/null +++ b/tests/selenium/views/login/accessors.js @@ -0,0 +1,27 @@ +'use strict'; + +const By = require('selenium-webdriver').By; +const Accessors = require('../accessors'); + + +function LoginAccessors() { + Accessors.apply(this, arguments); +} + +LoginAccessors.prototype = Object.assign({ + + get passwordField() { + return this.waitForElement(By.css('#app > div > div.jumbotron > div > div > form > div:nth-child(2) > input')); + }, + + get singInButton() { + return this.waitForElement(By.css('#app > div > div.jumbotron > div > div > form > div:nth-child(3) > button')); + }, + + get unauthorizedError() { + return this.waitForElement(By.css('#app > div > div.jumbotron > div > div > form > div.form-group.has-error > span')) + } + +}, Accessors.prototype); + +module.exports = LoginAccessors; diff --git a/tests/selenium/views/login/view.js b/tests/selenium/views/login/view.js new file mode 100644 index 0000000..7eac8d2 --- /dev/null +++ b/tests/selenium/views/login/view.js @@ -0,0 +1,36 @@ +'use strict'; + +const View = require('../view'); +const LoginAccessors = require('./accessors'); + + +function LoginView() { + [].push.call(arguments, LoginAccessors); + View.apply(this, arguments); + + this.accessors.passwordField; + this.accessors.singInButton; +} + +LoginView.prototype = Object.assign({ + + correctPassword(password) { + return this.accessors.passwordField.sendKeys(password) + .then(() => { this.accessors.singInButton.click() + .then(() => { + const SignedInView = require('../signed_in/view'); + return new SignedInView(this.driver); + }); + }); + }, + + incorrectLogin(password) { + return this.accessors.passwordField.sendKeys(password) + .then(()=>{ + return this.accessors.singInButton.click() + }).then(() => { return this.accessors.unauthorizedError.getText()}) + } + +}, View.prototype); + +module.exports = LoginView; diff --git a/tests/selenium/views/signed_in/accessors.js b/tests/selenium/views/signed_in/accessors.js new file mode 100644 index 0000000..b66955f --- /dev/null +++ b/tests/selenium/views/signed_in/accessors.js @@ -0,0 +1,17 @@ +'use strict'; + +const By = require('selenium-webdriver').By; +const Accessors = require('../accessors'); + + +function SignedInAccessors() { + Accessors.apply(this, arguments); +} + +SignedInAccessors.prototype = Object.assign({ + + //TBD + +}, Accessors.prototype); + +module.exports = SignedInAccessors; diff --git a/tests/selenium/views/signed_in/view.js b/tests/selenium/views/signed_in/view.js new file mode 100644 index 0000000..b13a320 --- /dev/null +++ b/tests/selenium/views/signed_in/view.js @@ -0,0 +1,18 @@ +'use strict'; + +const View = require('../view'); +const SignedInAccessors = require('./accessors'); + + +function SignedInView() { + [].push.call(arguments, SignedInAccessors); + View.apply(this, arguments); +} + +SignedInView.prototype = Object.assign({ + + // Functions for the SingedIn View TBD + +}, View.prototype); + +module.exports = SignedInView; diff --git a/tests/selenium/views/view.js b/tests/selenium/views/view.js new file mode 100644 index 0000000..2bd6405 --- /dev/null +++ b/tests/selenium/views/view.js @@ -0,0 +1,8 @@ +'use strict'; + +function View(driver, Accessors) { + this.driver = driver; + this.accessors = new Accessors(driver); +} + +module.exports = View;