@@ -101,6 +101,66 @@ describe('Form component', function () {
});
});
+ describe('when using controlled errors', function () {
+ let onValidateErrors;
+
+ beforeEach(function () {
+ onValidateErrors = stub();
+
+ ValidationFactoryMock.validators.defaultValidatorMock.validate = stub().returns('MOCK_ERROR');
+ ValidationFactoryMock.validators.customValidatorMock.validate = stub().returns('MOCK_ERROR_2');
+
+ renderForm({
+ errors: {first: 'MOCK_ERROR_CONTROLLED'},
+ onValidateErrors: onValidateErrors
+ });
+ });
+ afterEach(resetStubs);
+
+ it('should pass the errors to inputs', function () {
+ expect(fields[0].props.error).to.equal('MOCK_ERROR_CONTROLLED');
+ expect(fields[1].props.error).to.equal(undefined);
+ });
+
+ it('should prioritize prop error over state error', function () {
+ fields[1].props.onBlur();
+ expect(fields[1].props.error).to.equal(undefined);
+ });
+
+ it('should call onValidateErrors when state changes', function () {
+ fields[1].props.onBlur();
+ expect(onValidateErrors).to.have.been.calledWith({second: 'MOCK_ERROR_2'});
+
+ });
+
+ it('should still working if the error prop changes', function () {
+ function setErrorsOrRender(errors = {}) {
+ form = reRenderIntoDocument(
+
+ );
+ fields = TestUtils.scryRenderedComponentsWithType(form, Input);
+ }
+
+ setErrorsOrRender();
+ expect(fields[0].props.error).to.equal(undefined);
+ expect(fields[1].props.error).to.equal(undefined);
+
+ setErrorsOrRender({second: 'MOCK_ERROR_CONTROLLED_2'});
+ expect(fields[0].props.error).to.equal(undefined);
+ expect(fields[1].props.error).to.equal('MOCK_ERROR_CONTROLLED_2');
+
+ setErrorsOrRender({first: 'MOCK_ERROR_CONTROLLED', second: 'MOCK_ERROR_CONTROLLED_2'});
+ expect(fields[0].props.error).to.equal('MOCK_ERROR_CONTROLLED');
+ expect(fields[1].props.error).to.equal('MOCK_ERROR_CONTROLLED_2');
+ });
+ });
+
describe('when submitting the form', function () {
beforeEach(renderForm);
afterEach(resetStubs);
diff --git a/client/src/core-components/form.js b/client/src/core-components/form.js
index 33bb0710..530edca8 100644
--- a/client/src/core-components/form.js
+++ b/client/src/core-components/form.js
@@ -1,5 +1,4 @@
const React = require('react');
-const ReactDOM = require('react-dom');
const _ = require('lodash');
const {reactDFS, renderChildrenWithProps} = require('lib-core/react-dfs');
diff --git a/client/src/lib-app/__mocks__/api-call-mock.js b/client/src/lib-app/__mocks__/api-call-mock.js
new file mode 100644
index 00000000..3fcd2003
--- /dev/null
+++ b/client/src/lib-app/__mocks__/api-call-mock.js
@@ -0,0 +1,3 @@
+export default {
+ call: stub()
+};
\ No newline at end of file
diff --git a/client/src/lib-app/__mocks__/session-store-mock.js b/client/src/lib-app/__mocks__/session-store-mock.js
new file mode 100644
index 00000000..5ceed298
--- /dev/null
+++ b/client/src/lib-app/__mocks__/session-store-mock.js
@@ -0,0 +1,6 @@
+export default {
+ createSession: stub(),
+ getSessionData: stub().returns({}),
+ isLoggedIn: stub().returns(false),
+ closeSession: stub()
+};
\ No newline at end of file
diff --git a/client/src/lib-test/preprocessor.js b/client/src/lib-test/preprocessor.js
index 78afdb67..3af8576b 100644
--- a/client/src/lib-test/preprocessor.js
+++ b/client/src/lib-test/preprocessor.js
@@ -19,3 +19,14 @@ global.TestUtils = require('react-addons-test-utils');
global.requireUnit = function (path, mocks) {
return proxyquire(process.cwd() + '/src/' + path + '.js', mocks)
};
+global.reRenderIntoDocument = (function () {
+ let div;
+
+ return function (jsx) {
+ if (!div) {
+ div = document.createElement('div')
+ }
+
+ return ReactDOM.render(jsx, div);
+ }
+})();
diff --git a/client/src/lib-test/react-mock.js b/client/src/lib-test/react-mock.js
index ca0ea959..ec6091ab 100644
--- a/client/src/lib-test/react-mock.js
+++ b/client/src/lib-test/react-mock.js
@@ -4,7 +4,7 @@ const _ = require('lodash');
module.exports = function (options) {
return React.createClass(_.extend({
render() {
- return
;
+ return
{this.props.children}
;
}
}, options));
};
\ No newline at end of file
diff --git a/client/src/stores/__mocks__/common-store-mock.js b/client/src/stores/__mocks__/common-store-mock.js
new file mode 100644
index 00000000..1a488e3d
--- /dev/null
+++ b/client/src/stores/__mocks__/common-store-mock.js
@@ -0,0 +1,6 @@
+export default {
+ changeLanguage: stub(),
+ logged: stub(),
+ loggedOut: stub(),
+ listen: stub()
+};
\ No newline at end of file
diff --git a/client/src/stores/__mocks__/user-store-mock.js b/client/src/stores/__mocks__/user-store-mock.js
new file mode 100644
index 00000000..abba4ba6
--- /dev/null
+++ b/client/src/stores/__mocks__/user-store-mock.js
@@ -0,0 +1,6 @@
+export default {
+ loginUser: stub(),
+ logoutUser: stub(),
+ isLoggedIn: stub().returns(false),
+ listen: stub()
+};
\ No newline at end of file
diff --git a/client/src/stores/__tests__/user-store-test.js b/client/src/stores/__tests__/user-store-test.js
new file mode 100644
index 00000000..5ccc6790
--- /dev/null
+++ b/client/src/stores/__tests__/user-store-test.js
@@ -0,0 +1,105 @@
+// MOCKS
+const CommonActions = require('actions/__mocks__/common-actions-mock');
+const SessionStore = require('lib-app/__mocks__/session-store-mock');
+const API = require('lib-app/__mocks__/api-call-mock');
+const UserActions = {
+ checkLoginStatus: {listen: stub()},
+ login: {listen: stub()},
+ logout: {listen: stub()}
+};
+
+const UserStore = requireUnit('stores/user-store', {
+ 'actions/user-actions': UserActions,
+ 'actions/common-actions': CommonActions,
+ 'lib-app/session-store': SessionStore,
+ 'lib-app/api-call': API
+});
+
+describe('UserStore', function () {
+ describe('when login user', function () {
+ it('should call /user/login api path', function () {
+ let mockLoginData = {email: 'mock', password: 'mock'};
+
+ UserStore.loginUser(mockLoginData);
+ expect(API.call).to.have.been.calledWith({
+ path: 'user/login',
+ data: mockLoginData,
+ onSuccess: sinon.match.func,
+ onFail: sinon.match.func
+ });
+ });
+
+ it('should create session, trigger success event and inform common action when having a successful login', function () {
+ let mockLoginData = {email: 'mock', password: 'mock'};
+ let mockSuccessData = {
+ status: 'success',
+ data: {
+ userId: 12,
+ token: 'RANDOM_TOKEN'
+ }
+ };
+
+ spy(UserStore, 'trigger');
+ CommonActions.logged.reset();
+ SessionStore.createSession.reset();
+ API.call = ({onSuccess}) => {onSuccess(mockSuccessData)};
+
+ UserStore.loginUser(mockLoginData);
+
+ expect(SessionStore.createSession).to.have.been.calledWith(12, 'RANDOM_TOKEN');
+ expect(UserStore.trigger).to.have.been.calledWith('LOGIN_SUCCESS');
+ expect(CommonActions.logged).to.have.been.called;
+ UserStore.trigger.restore();
+ });
+
+ it('should trigger fail event if login fails', function () {
+ let mockLoginData = {email: 'mock', password: 'mock'};
+ let mockSuccessData = {
+ status: 'success',
+ data: {
+ userId: 12,
+ token: 'RANDOM_TOKEN'
+ }
+ };
+
+ spy(UserStore, 'trigger');
+ API.call = ({onFail}) => {onFail(mockSuccessData)};
+
+ UserStore.loginUser(mockLoginData);
+
+ expect(UserStore.trigger).to.have.been.calledWith('LOGIN_FAIL');
+ UserStore.trigger.restore();
+ });
+ });
+
+ describe('when login out', function () {
+
+ it('should call /user/logout api path', function () {
+ API.call = stub();
+
+ UserStore.logoutUser();
+ expect(API.call).to.have.been.calledWith({
+ path: 'user/logout',
+ onSuccess: sinon.match.func
+ });
+ });
+
+ it('should delete session, trigger LOGOUT event and inform common action of logout', function () {
+ API.call = ({onSuccess}) => {onSuccess()};
+ spy(UserStore, 'trigger');
+
+ UserStore.logoutUser();
+ expect(SessionStore.closeSession).to.have.been.called;
+ expect(UserStore.trigger).to.have.been.calledWith('LOGOUT');
+ expect(CommonActions.loggedOut).to.have.been.called;
+ UserStore.trigger.restore()
+ })
+ });
+
+ it ('should inform is the user is logged based on SessionStores\' info', function () {
+ SessionStore.isLoggedIn.returns(true);
+ expect(UserStore.isLoggedIn()).to.equal(true);
+ SessionStore.isLoggedIn.returns(false);
+ expect(UserStore.isLoggedIn()).to.equal(false);
+ });
+});
diff --git a/client/src/stores/common-store.js b/client/src/stores/common-store.js
index 9dcd271d..b4a82de7 100644
--- a/client/src/stores/common-store.js
+++ b/client/src/stores/common-store.js
@@ -23,10 +23,6 @@ let CommonStore = Reflux.createStore({
loggedOut() {
this.trigger('loggedOut');
- },
-
- isLogged() {
- return this.logged()
}
});
diff --git a/client/src/stores/user-store.js b/client/src/stores/user-store.js
index 61086059..93118c36 100644
--- a/client/src/stores/user-store.js
+++ b/client/src/stores/user-store.js
@@ -9,7 +9,6 @@ const UserStore = Reflux.createStore({
init() {
this.user = null;
- this.hasBeenChecked = false;
this.listenTo(UserActions.checkLoginStatus, this.checkLoginStatus);
this.listenTo(UserActions.login, this.loginUser);
@@ -46,7 +45,7 @@ const UserStore = Reflux.createStore({
CommonActions.logged();
},
- handleLoginFail(result) {
+ handleLoginFail() {
this.trigger('LOGIN_FAIL');
}
});