From 67bcab2f5e388c5f8c8f12c0074559b3dfa00981 Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Tue, 10 May 2016 22:35:36 -0300 Subject: [PATCH] [Ivan Diaz] - Add initial ruby api testing setup [Ivan Diaz] - Add environment variables to PHP database configuration [Ivan Diaz] - Add mocha-chai-sinon unit testing architecture [Ivan Diaz] - Add frontend test to readme [Ivan Diaz] - FrontEnd - Update form/button unit testing [Ivan Diaz] - Remove warning dependencies [Ivan Diaz] - Remove bacon from requires Revert "[Ivan Diaz] - Remove bacon from requires" This reverts commit eb909b3c19e87d722076270216b8401d73ca9f9b. [Ivan Diaz] - FrontEnd - Remove gemfile.lock [Ivan Diaz] - FrontEnd - Remove bundle Remove abstract getProps [Ivan Diaz] - Debugging ruby libs global database variable [skip ci] [Ivan Diaz] - Use global database variable [Ivan Diaz] - Use value instead of id libs.rb edited online with Bitbucket [Ivan Diaz] - Add default mysql values, remove api comments --- README.md | 5 ++ client/package.json | 33 +++++------- .../core-components/__tests__/button-test.js | 19 +++---- .../core-components/__tests__/form-test.js | 52 +++++++++---------- client/src/core-components/button.js | 7 ++- client/src/lib-test/preprocessor.js | 20 +++++++ client/src/lib-test/react-mock.js | 9 ++++ server/api-test/.bundle/config | 2 - server/api-test/Gemfile | 2 - server/api-test/libs.rb | 21 ++++++-- server/api-test/scripts.rb | 11 ++++ server/api-test/user/login.rb | 24 +++++++++ server/api-test/user/signup.rb | 2 +- server/config.php | 6 +-- server/models/DataStore.php | 1 - 15 files changed, 136 insertions(+), 78 deletions(-) create mode 100644 client/src/lib-test/preprocessor.js create mode 100644 client/src/lib-test/react-mock.js delete mode 100644 server/api-test/.bundle/config create mode 100644 server/api-test/scripts.rb diff --git a/README.md b/README.md index e99c7bcf..2af3f06f 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,11 @@ OpenSupports v4.0 Now that `gulp dev` is running, the server is up as well and serving files from the `/build` directory. Any changes in the `/src` directory will be automatically processed by Gulp and the changes will be injected to any open browsers pointed at the proxy address. +#### Frontend Unit Testing +1. Do the steps described before +2. Install mocha "sudo npm install -g mocha" +3. Run `npm test` to run the tests + ### Getting up and running BACK-END (server folder) 1. Clone this repo diff --git a/client/package.json b/client/package.json index 97366c3e..07a0990f 100644 --- a/client/package.json +++ b/client/package.json @@ -13,13 +13,15 @@ "npm": "^2.1.x" }, "scripts": { - "test": "export NODE_PATH=src && jest" + "test": "export NODE_PATH=src && mocha src/lib-test/preprocessor.js --compilers js:babel-core/register --recursive src/**/__tests__/*-test.js" }, "devDependencies": { "babel-core": "^5.8.22", + "babel-register": "^6.7.2", "babelify": "^6.1.x", "browser-sync": "^2.7.13", "browserify": "^10.2.6", + "chai": "^3.5.0", "debowerify": "^1.3.1", "del": "^1.2.0", "express": "^4.13.1", @@ -38,10 +40,14 @@ "gulp-uglify": "^1.2.0", "gulp-util": "^3.0.6", "humps": "^0.6.0", - "jest-cli": "^0.5.10", "jquery-mockjax": "^2.1.0", + "jsdom": "^8.4.1", "morgan": "^1.6.1", + "proxyquire": "^1.7.4", + "react-addons-test-utils": "^15.0.1", "run-sequence": "^1.1.1", + "sinon": "^1.17.3", + "sinon-chai": "^2.8.0", "vinyl-source-stream": "^1.1.0", "watchify": "^3.2.x" }, @@ -51,28 +57,13 @@ "jquery": "^2.1.4", "lodash": "^3.10.0", "messageformat": "^0.2.2", - "react": "^0.14.6", + "react": "^15.0.1", "react-document-title": "^1.0.2", - "react-dom": "^0.14.6", + "react-dom": "^15.0.1", "react-google-recaptcha": "^0.5.2", "react-motion": "^0.3.0", - "react-router": "^2.0.0-rc5", - "reflux": "^0.2.9", + "react-router": "^2.4.0", + "reflux": "^0.4.1", "sessionstorage": "0.0.1" - }, - "jest": { - "scriptPreprocessor": "./preprocessor.js", - "testFileExtensions": [ - "es6", - "js" - ], - "moduleFileExtensions": [ - "js", - "json", - "es6" - ], - "unmockedModulePathPatterns": [ - "react" - ] } } diff --git a/client/src/core-components/__tests__/button-test.js b/client/src/core-components/__tests__/button-test.js index 4650ee06..d60d41e6 100644 --- a/client/src/core-components/__tests__/button-test.js +++ b/client/src/core-components/__tests__/button-test.js @@ -1,19 +1,14 @@ -jest.dontMock('../button.js'); +let Button = require('core-components/button'); -import React from 'react'; -import Button from '../button.js'; +describe('Button component', function () { -let TestUtils = React.addons.TestUtils; + it('should render children correctly', function () { -describe('Button', function () { - it('should render children', function () { let button = TestUtils.renderIntoDocument( - + ); - expect(button.getDOMNode().textContent).toEqual('testcontent'); + expect(ReactDOM.findDOMNode(button).textContent).to.eql('test content'); }); it('should add passed types to class', function () { @@ -26,11 +21,11 @@ describe('Button', function () { types.forEach(function (type) { let button = TestUtils.renderIntoDocument( ); - expect(button.getDOMNode().getAttribute('class')).toContain('button-' + type); + expect(ReactDOM.findDOMNode(button).getAttribute('class')).to.include('button-' + type); }); }); }); diff --git a/client/src/core-components/__tests__/form-test.js b/client/src/core-components/__tests__/form-test.js index 8e11ac6d..b98fd40d 100644 --- a/client/src/core-components/__tests__/form-test.js +++ b/client/src/core-components/__tests__/form-test.js @@ -1,26 +1,24 @@ -jest.dontMock('core-components/form.js'); -jest.dontMock('core-components/form.js'); +const Form = require('core-components/form'); +const Input = require('core-components/input'); -import React from 'react'; -import Form from 'core-components/form.js'; -import Input from 'core-components/input.js'; +describe('Form component', function () { + let form, inputs, onSubmit = stub(); -let TestUtils = React.addons.TestUtils; - -describe('Form', function () { - let results = TestUtils.renderIntoDocument( -
-
- - -
- -
- ); - let inputs = TestUtils.scryRenderedComponentsWithType(results, Input); + beforeEach(function () { + form = TestUtils.renderIntoDocument( +
+
+ + +
+ +
+ ); + inputs = TestUtils.scryRenderedComponentsWithType(form, Input); + }); it('should store input value in form state', function () { - expect(results.state.form).toEqual({ + expect(form.state.form).to.deep.equal({ first: 'value1', second: 'value2', third: 'value3' @@ -30,7 +28,7 @@ describe('Form', function () { it('should update form state if an input value changes', function () { inputs[0].props.onChange({ target: {value: 'value4'}}); - expect(results.state.form).toEqual({ + expect(form.state.form).to.deep.equal({ first: 'value4', second: 'value2', third: 'value3' @@ -38,7 +36,7 @@ describe('Form', function () { }); it('should update input value if state value changes', function () { - results.setState({ + form.setState({ form: { first: 'value6', second: 'value7', @@ -46,14 +44,14 @@ describe('Form', function () { } }); - expect(inputs[0].props.value).toEqual('value6'); - expect(inputs[1].props.value).toEqual('value7'); - expect(inputs[2].props.value).toEqual('value8'); + expect(inputs[0].props.value).to.equal('value6'); + expect(inputs[1].props.value).to.equal('value7'); + expect(inputs[2].props.value).to.equal('value8'); }); it('should call onSubmit callback when form is submitted', function () { - TestUtils.Simulate.submit(results.getDOMNode()); + TestUtils.Simulate.submit(ReactDOM.findDOMNode(form)); - expect(results.props.onSubmit).toBeCalledWith(results.state.form); + expect(form.props.onSubmit).to.have.been.calledWith(form.state.form); }); -}); \ No newline at end of file +}); diff --git a/client/src/core-components/button.js b/client/src/core-components/button.js index 0322eab7..c0ccec07 100644 --- a/client/src/core-components/button.js +++ b/client/src/core-components/button.js @@ -1,7 +1,6 @@ -import React from 'react'; -import classNames from 'classnames'; -import Router from 'react-router'; -import callback from 'lib-core/callback'; +var React = require('react'); +var classNames = require('classnames'); +var callback = require('lib-core/callback'); let Button = React.createClass({ diff --git a/client/src/lib-test/preprocessor.js b/client/src/lib-test/preprocessor.js new file mode 100644 index 00000000..a052d635 --- /dev/null +++ b/client/src/lib-test/preprocessor.js @@ -0,0 +1,20 @@ +var jsdom = require('jsdom').jsdom; + +global.document = jsdom(''); +global.window = document.defaultView; +global.navigator = { + userAgent: 'node.js' +}; +global.React = require('react'); +global.ReactDOM = require('react-dom'); +global.chai = require('chai'); +global.expect = chai.expect; +global.sinon = require('sinon'); +global.stub = sinon.stub; +global.proxyquire = require('proxyquire'); +global.ReactMock = require('lib-test/react-mock'); +chai.use(require('sinon-chai')); +global.TestUtils = require('react-addons-test-utils'); +global.requireUnit = function (path, mocks) { + return proxyquire(process.cwd() + '/src/' + path + '.js', mocks) +}; diff --git a/client/src/lib-test/react-mock.js b/client/src/lib-test/react-mock.js new file mode 100644 index 00000000..d8511872 --- /dev/null +++ b/client/src/lib-test/react-mock.js @@ -0,0 +1,9 @@ +const React = require('react'); + +module.exports = function () { + return React.createClass({ + render() { + return
; + } + }); +}; \ No newline at end of file diff --git a/server/api-test/.bundle/config b/server/api-test/.bundle/config deleted file mode 100644 index 3a3091eb..00000000 --- a/server/api-test/.bundle/config +++ /dev/null @@ -1,2 +0,0 @@ ---- -BUNDLE_NO_INSTALL: false diff --git a/server/api-test/Gemfile b/server/api-test/Gemfile index f1acdc46..a5cabf73 100644 --- a/server/api-test/Gemfile +++ b/server/api-test/Gemfile @@ -1,5 +1,3 @@ source "https://rubygems.org" gem 'mysql' gem 'bacon' -gem 'net/http' -gem 'uri' diff --git a/server/api-test/libs.rb b/server/api-test/libs.rb index a072a1f7..7472135a 100644 --- a/server/api-test/libs.rb +++ b/server/api-test/libs.rb @@ -6,11 +6,22 @@ def request(path, data) return JSON.parse(response.body) end -def getRow(table, id) - database = Mysql.new('localhost', 'root', '', 'os_dev') - queryResponse = database.query("select * from #{table} where id='#{id.to_s}'") +class Database + def initialize() + mysqlUser = ENV['MYSQL_USER'] || 'root'; + mysqlPass = ENV['MYSQL_PASSWORD'] || ''; + @connection = Mysql.new('localhost', mysqlUser , mysqlPass, 'development') + end - database.close + def close() + @connection.close + end - return queryResponse.fetch_hash + def getRow(table, value, field = 'id') + queryResponse = @connection.query("select * from #{table} where #{field}='#{value.to_s}'") + + return queryResponse.fetch_hash + end end + +$database = Database.new diff --git a/server/api-test/scripts.rb b/server/api-test/scripts.rb new file mode 100644 index 00000000..e7dccfb1 --- /dev/null +++ b/server/api-test/scripts.rb @@ -0,0 +1,11 @@ +class Scripts + def self.createUser(email = 'steve@jobs.com', password = 'custompassword') + response = request('/user/signup', { + 'email' => email, + 'password' => password + }) + + if response['status'] === 'fail' + raise "Could not create user" + end +end diff --git a/server/api-test/user/login.rb b/server/api-test/user/login.rb index e69de29b..61bb33ac 100644 --- a/server/api-test/user/login.rb +++ b/server/api-test/user/login.rb @@ -0,0 +1,24 @@ +describe '/user/login' do + before do + @loginEmail = 'login@os4.com' + @loginPass = 'loginpass' + + Scripts.createUser(@loginEmail, @loginPass) + end + + it 'should fail if password is incorrect' do + result = request('/user/login', { + email: @loginEmail, + pass: 'some_incorrect_password' + }) + + (result['status']).should.equal('fail') + end + + it 'should login correctly' do + + end + + it 'should fail if already logged in' do + + end diff --git a/server/api-test/user/signup.rb b/server/api-test/user/signup.rb index 5fdc5adc..5be05330 100644 --- a/server/api-test/user/signup.rb +++ b/server/api-test/user/signup.rb @@ -5,7 +5,7 @@ describe '/user/signup' do 'password' => 'custom' }) - userRow = getRow('users', response['data']['userId']) + userRow = $database.getRow('users', response['data']['userId']) (userRow['email']).should.equal('steve@jobs.com') end diff --git a/server/config.php b/server/config.php index 0fd6e678..323842f2 100644 --- a/server/config.php +++ b/server/config.php @@ -1,5 +1,5 @@