diff --git a/.env-template b/.env-template new file mode 100644 index 00000000..593923ec --- /dev/null +++ b/.env-template @@ -0,0 +1,2 @@ +ONION_SAUCELABS_USER=ascribe +ONION_SAUCELABS_APIKEY= diff --git a/.eslintrc b/.eslintrc index 0ce24daa..5751f3ad 100644 --- a/.eslintrc +++ b/.eslintrc @@ -3,7 +3,6 @@ "env": { "browser": true, "es6": true, - "mocha": true }, "rules": { "new-cap": [2, {newIsCap: true, capIsNew: false}], diff --git a/.gitignore b/.gitignore index 30c9eae9..f5bf11e8 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ node_modules/* build .DS_Store +.env diff --git a/package.json b/package.json index efe9648e..b2bbd68c 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "babel-jest": "^5.2.0", "chai": "^3.4.1", "chai-as-promised": "^5.1.0", + "dotenv": "^1.2.0", "jest-cli": "^0.4.0", "mocha": "^2.3.4", "wd": "^0.4.0" diff --git a/tests/.eslintrc b/tests/.eslintrc new file mode 100644 index 00000000..64f8d90a --- /dev/null +++ b/tests/.eslintrc @@ -0,0 +1,36 @@ +{ + "parser": "babel-eslint", + "env": { + "mocha": true, + "node": true + }, + "rules": { + "new-cap": [2, {newIsCap: true, capIsNew: false}], + "quotes": [2, "single"], + "eol-last": [0], + "no-mixed-requires": [0], + "no-underscore-dangle": [0], + "global-strict": [2, "always"], + "no-trailing-spaces": [2, { skipBlankLines: true }], + "no-console": 0, + "camelcase": [2, {"properties": "never"}], + }, + "globals": {}, + "plugins": [], + "ecmaFeatures": { + "modules": 1, + "arrowFunctions", + "classes": 1, + "blockBindings": 1, + "defaultParams": 1, + "destructuring": 1, + "objectLiteralComputedProperties": 1, + "objectLiteralDuplicateProperties": 0, + "objectLiteralShorthandMethods": 1, + "objectLiteralShorthandProperties": 1, + "restParams": 1, + "spread": 1, + "superInFunctions": 1, + "templateStrings": 1 + } +} diff --git a/tests/README.md b/tests/README.md index dfa6f8cf..458ba4cc 100644 --- a/tests/README.md +++ b/tests/README.md @@ -6,6 +6,7 @@ and how we are doing it. # How it works (bird's-eye view) + You will notice that the setup is a bit convoluted. This section will explain you why. Testing single functions in JavaScript is not that hard (if you don't need to interact with the DOM), and can be easily achieved using frameworks @@ -27,12 +28,17 @@ browsers) to run our tests. ## Components and tools +Right now we are just running the test locally, so no Continuous Integration™. + The components involved are: - **[Selenium WebDriver](https://www.npmjs.com/package/wd)**: it's a library that can control a browser. You can use the **WebDriver** to load new URLs, click around, fill out forms, submit forms etc. It's basically a way to control remotely a browser. There are other implementations in Python, PHP, - Java, etc. + Java, etc. Also, a **WebDriver** can be initialized with a list of [desired + capabilities](https://code.google.com/p/selenium/wiki/DesiredCapabilities) + describing which features (like the platform, browser name and version) you + want to use to run your tests. - **[Selenium Grid](https://github.com/SeleniumHQ/selenium/wiki/Grid2)**: it's the controller for the cluster of machines/devices that can run browsers. @@ -46,7 +52,66 @@ The components involved are: cluster to run your tests on over 700 combinations of browsers/operating systems. (They do other things, check out their websites). + - **[SauceConnect](https://wiki.saucelabs.com/display/DOCS/Setting+Up+Sauce+Connect)**: + it allows Saucelabs to connect to your `localhost` to test the app. (There + is also a [Node.js wrapper](https://www.npmjs.com/package/sauce-connect), so + you can use it programmatically within your code for tests). + + +On the JavaScript side, we use: + - [Mocha](https://mochajs.org/): a test framework running on Node.js. + + - [chai](http://chaijs.com/): a BDD/TDD assertion library for node that can be + paired with any javascript testing framework. + + - [chaiAsPromised](https://github.com/domenic/chai-as-promised/): an extension + for Chai with a fluent language for asserting facts about promises. The + extension is actually quite cool, we can do assertions on promises without + writing callbacks but just chaining operators. Check out their `README` on + GitHub to see an example. + + - [dotenv](https://github.com/motdotla/dotenv): a super nice package to loads + environment variables from `.env` into `process.env`. + ## Anatomy of a test -A test is a `.js` file. We use [Mocha](https://mochajs.org/) and [Should](https://shouldjs.github.io/). +```javascript +'use strict'; + +require('dotenv').load(); + +const wd = require('wd'); +const chai = require('chai'); +const chaiAsPromised = require('chai-as-promised'); +chai.use(chaiAsPromised); +chai.should(); +``` + + +```javascript +describe('Login logs users in', function() { + let browser; + + before(function() { + browser = wd.promiseChainRemote('ondemand.saucelabs.com', 80, + process.env.ONION_SAUCELABS_USER || 'ascribe', + process.env.ONION_SAUCELABS_APIKEY || 'b072b4f2-6302-42f6-a25d-47162666ca66'); + + return browser.init({ browserName: 'chrome' }); + }); + + beforeEach(function() { + return browser.get('http://www.ascribe.ninja/app/login'); + }); + + after(function() { + return browser.quit(); + }); + + it('should contain "Log in" in the title', function() { + return browser.title().should.become('Log in'); + }); + +}); +``` diff --git a/tests/test-login.js b/tests/test-login.js index 07c3d1d7..249a26c2 100644 --- a/tests/test-login.js +++ b/tests/test-login.js @@ -1,8 +1,10 @@ 'use strict'; +require('dotenv').load(); + const wd = require('wd'); -const chai = require("chai"); -const chaiAsPromised = require("chai-as-promised"); +const chai = require('chai'); +const chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); chai.should(); @@ -12,10 +14,10 @@ describe('Login logs users in', function() { before(function() { browser = wd.promiseChainRemote('ondemand.saucelabs.com', 80, - process.env.ONION_SAUCELABS_USER || 'ascribe', - process.env.ONION_SAUCELABS_APIKEY || 'b072b4f2-6302-42f6-a25d-47162666ca66') + process.env.ONION_SAUCELABS_USER, + process.env.ONION_SAUCELABS_APIKEY); - return browser.init({ browserName: 'chrome' }); + return browser.init({ browserName: 'chrome' }); }); beforeEach(function() {