You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by be...@apache.org on 2015/04/22 18:05:59 UTC
fauxton commit: updated refs/heads/master to 410d2c7
Repository: couchdb-fauxton
Updated Branches:
refs/heads/master 422cb92c6 -> 410d2c772
Updating Auth module to use React
Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/410d2c77
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/410d2c77
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/410d2c77
Branch: refs/heads/master
Commit: 410d2c7729533a9bb0873a14ab72bc7a590b738e
Parents: 422cb92
Author: Ben Keen <be...@gmail.com>
Authored: Thu Apr 16 16:14:27 2015 -0700
Committer: Ben Keen <be...@gmail.com>
Committed: Wed Apr 22 09:04:41 2015 -0700
----------------------------------------------------------------------
app/addons/auth/actions.js | 117 ++++++++
app/addons/auth/actiontypes.js | 23 ++
app/addons/auth/components.react.jsx | 287 +++++++++++++++++++
app/addons/auth/resources.js | 172 -----------
app/addons/auth/routes.js | 46 +--
app/addons/auth/stores.js | 171 +++++++++++
app/addons/auth/templates/change_password.html | 29 --
app/addons/auth/templates/create_admin.html | 37 ---
app/addons/auth/templates/login.html | 26 --
app/addons/auth/templates/nav_dropdown.html | 24 --
.../auth/test/auth.componentsSpec.react.jsx | 128 +++++++++
app/addons/auth/test/auth.storesSpec.js | 148 ++++++++++
app/core/routeObject.js | 11 +-
app/core/tests/routeObjectSpec.js | 10 +-
14 files changed, 914 insertions(+), 315 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/actions.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/actions.js b/app/addons/auth/actions.js
new file mode 100644
index 0000000..ab3f50e
--- /dev/null
+++ b/app/addons/auth/actions.js
@@ -0,0 +1,117 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+ 'api',
+ 'addons/auth/actiontypes'
+],
+function (FauxtonAPI, ActionTypes) {
+
+
+ var errorHandler = function (xhr, type, msg) {
+ msg = xhr;
+ if (arguments.length === 3) {
+ msg = xhr.responseJSON.reason;
+ }
+
+ FauxtonAPI.addNotification({
+ msg: msg,
+ type: 'error'
+ });
+ };
+
+
+ return {
+
+ login: function (username, password, urlBack) {
+ var promise = FauxtonAPI.session.login(username, password);
+
+ promise.then(function () {
+ FauxtonAPI.addNotification({ msg: FauxtonAPI.session.messages.loggedIn });
+ if (urlBack) {
+ return FauxtonAPI.navigate(urlBack);
+ }
+ FauxtonAPI.navigate('/');
+ });
+ promise.fail(errorHandler);
+ },
+
+ changePassword: function (password, passwordConfirm) {
+ var promise = FauxtonAPI.session.changePassword(password, passwordConfirm);
+
+ promise.done(function () {
+ FauxtonAPI.addNotification({ msg: FauxtonAPI.session.messages.changePassword });
+ FauxtonAPI.dispatch({ type: ActionTypes.AUTH_CLEAR_CHANGE_PWD_FIELDS });
+ });
+
+ promise.fail(errorHandler);
+ },
+
+ updateChangePasswordField: function (value) {
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CHANGE_PWD_FIELD,
+ value: value
+ });
+ },
+
+ updateChangePasswordConfirmField: function (value) {
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CHANGE_PWD_CONFIRM_FIELD,
+ value: value
+ });
+ },
+
+ createAdmin: function (username, password, loginAfter) {
+ var promise = FauxtonAPI.session.createAdmin(username, password, loginAfter);
+
+ promise.then(function () {
+ FauxtonAPI.addNotification({ msg: FauxtonAPI.session.messages.adminCreated });
+ if (loginAfter) {
+ FauxtonAPI.navigate('/');
+ } else {
+ FauxtonAPI.dispatch({ type: ActionTypes.AUTH_CLEAR_CREATE_ADMIN_FIELDS });
+ }
+ });
+
+ promise.fail(function (xhr, type, msg) {
+ msg = xhr;
+ if (arguments.length === 3) {
+ console.log("here...", xhr.responseJSON);
+ msg = xhr.responseJSON.reason;
+ }
+ errorHandler(FauxtonAPI.session.messages.adminCreationFailedPrefix + ' ' + msg);
+ });
+ },
+
+ updateCreateAdminUsername: function (value) {
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CREATE_ADMIN_USERNAME_FIELD,
+ value: value
+ });
+ },
+
+ updateCreateAdminPassword: function (value) {
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CREATE_ADMIN_PWD_FIELD,
+ value: value
+ });
+ },
+
+ selectPage: function (page) {
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_SELECT_PAGE,
+ page: page
+ });
+ }
+
+ };
+
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/actiontypes.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/actiontypes.js b/app/addons/auth/actiontypes.js
new file mode 100644
index 0000000..29ce9bf
--- /dev/null
+++ b/app/addons/auth/actiontypes.js
@@ -0,0 +1,23 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([], function () {
+ return {
+ AUTH_CLEAR_CHANGE_PWD_FIELDS: 'AUTH_CLEAR_CHANGE_PWD_FIELDS',
+ AUTH_UPDATE_CHANGE_PWD_FIELD: 'AUTH_UPDATE_CHANGE_PWD_FIELD',
+ AUTH_UPDATE_CHANGE_PWD_CONFIRM_FIELD: 'AUTH_UPDATE_CHANGE_PWD_CONFIRM_FIELD',
+ AUTH_CLEAR_CREATE_ADMIN_FIELDS: 'AUTH_CLEAR_CREATE_ADMIN_FIELDS',
+ AUTH_UPDATE_CREATE_ADMIN_USERNAME_FIELD: 'AUTH_UPDATE_CREATE_ADMIN_USERNAME_FIELD',
+ AUTH_UPDATE_CREATE_ADMIN_PWD_FIELD: 'AUTH_UPDATE_CREATE_ADMIN_PWD_FIELD',
+ AUTH_SELECT_PAGE: 'AUTH_SELECT_PAGE'
+ };
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/auth/components.react.jsx b/app/addons/auth/components.react.jsx
new file mode 100644
index 0000000..5fd5c4c
--- /dev/null
+++ b/app/addons/auth/components.react.jsx
@@ -0,0 +1,287 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+ 'app',
+ 'api',
+ 'react',
+ 'addons/auth/stores',
+ 'addons/auth/actions'
+], function (app, FauxtonAPI, React, AuthStores, AuthActions) {
+
+ var changePasswordStore = AuthStores.changePasswordStore;
+ var createAdminStore = AuthStores.createAdminStore;
+ var createAdminSidebarStore = AuthStores.createAdminSidebarStore;
+
+
+ var LoginForm = React.createClass({
+ propTypes: {
+ urlBack: React.PropTypes.string.isRequired
+ },
+
+ getInitialState: function () {
+ return {
+ username: '',
+ password: ''
+ };
+ },
+
+ getDefaultProps: function () {
+ return {
+ urlBack: ''
+ };
+ },
+
+ onInputChange: function (e) {
+ var change = (e.target.name === 'name') ? { username: e.target.value } : { password: e.target.value };
+ this.setState(change);
+ },
+
+ login: function (e) {
+ e.preventDefault();
+ AuthActions.login(this.state.username, this.state.password, this.props.urlBack);
+ },
+
+ componentDidMount: function () {
+ this.refs.username.getDOMNode().focus();
+ },
+
+ render: function () {
+ return (
+ <div className="row-fluid">
+ <div className="span12">
+ <form id="login" onSubmit={this.login}>
+ <p className="help-block">
+ Login with your username and password
+ </p>
+ <input id="username" type="text" name="name" ref="username" placeholder="Username" size="24"
+ onChange={this.onInputChange} value={this.state.username} />
+ <br/>
+ <input id="password" type="password" name="password" placeholder="Password" size="24"
+ onChange={this.onInputChange} value={this.state.password} />
+ <br/>
+ <button id="submit" className="btn" type="submit">Login</button>
+ </form>
+ </div>
+ </div>
+ );
+ }
+ });
+
+
+ var ChangePasswordForm = React.createClass({
+ getInitialState: function () {
+ return this.getStoreState();
+ },
+
+ getStoreState: function () {
+ return {
+ password: changePasswordStore.getChangePassword(),
+ passwordConfirm: changePasswordStore.getChangePasswordConfirm()
+ };
+ },
+
+ onChange: function () {
+ this.setState(this.getStoreState());
+ },
+
+ onChangePassword: function (e) {
+ AuthActions.updateChangePasswordField(e.target.value);
+ },
+
+ onChangePasswordConfirm: function (e) {
+ AuthActions.updateChangePasswordConfirmField(e.target.value);
+ },
+
+ componentDidMount: function () {
+ this.refs.password.getDOMNode().focus();
+ changePasswordStore.on('change', this.onChange, this);
+ },
+
+ componentWillUnmount: function () {
+ changePasswordStore.off('change', this.onChange);
+ },
+
+ changePassword: function (e) {
+ e.preventDefault();
+ AuthActions.changePassword(this.state.password, this.state.passwordConfirm);
+ },
+
+ render: function () {
+ return (
+ <div className="auth-page">
+ <h3>Change Password</h3>
+
+ <form id="change-password" onSubmit={this.changePassword}>
+ <p>
+ Enter your new password.
+ </p>
+
+ <input id="password" type="password" ref="password" name="password" placeholder="Password"
+ size="24" onChange={this.onChangePassword} value={this.state.password} />
+ <br />
+ <input id="password-confirm" type="password" name="password_confirm" placeholder= "Verify Password"
+ size="24" onChange={this.onChangePasswordConfirm} value={this.state.passwordConfirm} />
+
+ <br />
+ <p>
+ <button type="submit" className="btn btn-primary">Change</button>
+ </p>
+ </form>
+ </div>
+ );
+ }
+ });
+
+
+ var CreateAdminForm = React.createClass({
+ propTypes: {
+ loginAfter: React.PropTypes.bool.isRequired
+ },
+
+ getInitialState: function () {
+ return this.getStoreState();
+ },
+
+ getStoreState: function () {
+ return {
+ username: createAdminStore.getUsername(),
+ password: createAdminStore.getPassword()
+ };
+ },
+
+ onChange: function () {
+ this.setState(this.getStoreState());
+ },
+
+ getDefaultProps: function () {
+ return {
+ loginAfter: ''
+ };
+ },
+
+ onChangeUsername: function (e) {
+ AuthActions.updateCreateAdminUsername(e.target.value);
+ },
+
+ onChangePassword: function (e) {
+ AuthActions.updateCreateAdminPassword(e.target.value);
+ },
+
+ componentDidMount: function () {
+ this.refs.username.getDOMNode().focus();
+ createAdminStore.on('change', this.onChange, this);
+ },
+
+ componentWillUnmount: function () {
+ createAdminStore.off('change', this.onChange);
+ },
+
+ createAdmin: function (e) {
+ e.preventDefault();
+ AuthActions.createAdmin(this.state.username, this.state.password, this.props.loginAfter);
+ },
+
+ render: function () {
+ return (
+ <div className="auth-page">
+ <h3>Create Admins</h3>
+
+ <p>
+ Before a server admin is configured, all clients have admin privileges. This is fine when
+ HTTP access is restricted to trusted users. <strong>If end-users will be accessing this
+ CouchDB, you must create an admin account to prevent accidental (or malicious) data
+ loss.</strong>
+ </p>
+ <p>
+ Server admins can create and destroy databases, install and update _design documents, run
+ the test suite, and edit all aspects of CouchDB configuration.
+ </p>
+
+ <form id="create-admin-form" onSubmit={this.createAdmin}>
+ <input id="username" type="text" ref="username" name="name" placeholder="Username" size="24"
+ onChange={this.onChangeUsername} />
+ <br/>
+ <input id="password" type="password" name="password" placeholder= "Password" size="24"
+ onChange={this.onChangePassword} />
+ <p>
+ Non-admin users have read and write access to all databases, which
+ are controlled by validation functions. CouchDB can be configured to block all
+ access to anonymous users.
+ </p>
+ <button type="submit" id="create-admin" className="btn btn-primary">Create Admin</button>
+ </form>
+ </div>
+ );
+ }
+ });
+
+
+ var CreateAdminSidebar = React.createClass({
+ getInitialState: function () {
+ return this.getStoreState();
+ },
+
+ getStoreState: function () {
+ return {
+ selectedPage: createAdminSidebarStore.getSelectedPage()
+ };
+ },
+
+ onChange: function () {
+ this.setState(this.getStoreState());
+ },
+
+ componentDidMount: function () {
+ createAdminSidebarStore.on('change', this.onChange, this);
+ },
+
+ componentWillUnmount: function () {
+ createAdminSidebarStore.off('change', this.onChange);
+ },
+
+ selectPage: function (e) {
+ var newPage = e.target.href.split('#')[1];
+ AuthActions.selectPage(newPage);
+ },
+
+ render: function () {
+ var user = FauxtonAPI.session.user();
+ var userName = _.isNull(user) ? '' : FauxtonAPI.session.user().name;
+
+ return (
+ <div className="sidenav">
+ <header className="row-fluid">
+ <h3>{userName}</h3>
+ </header>
+ <ul className="nav nav-list" onClick={this.selectPage}>
+ <li className={this.state.selectedPage === 'changePassword' ? 'active' : ''} data-page="changePassword">
+ <a href="#changePassword">Change Password</a>
+ </li>
+ <li className={this.state.selectedPage === 'addAdmin' ? 'active' : ''} data-page="addAdmin">
+ <a href="#addAdmin">Create Admins</a>
+ </li>
+ </ul>
+ </div>
+ );
+ }
+ });
+
+ return {
+ LoginForm: LoginForm,
+ ChangePasswordForm: ChangePasswordForm,
+ CreateAdminForm: CreateAdminForm,
+ CreateAdminSidebar: CreateAdminSidebar
+ };
+
+
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/resources.js b/app/addons/auth/resources.js
index 3b6d295..c3deed7 100644
--- a/app/addons/auth/resources.js
+++ b/app/addons/auth/resources.js
@@ -20,17 +20,6 @@ function (app, FauxtonAPI, CouchdbSession) {
var Auth = new FauxtonAPI.addon();
- var errorHandler = function (xhr, type, msg) {
- msg = xhr;
- if (arguments.length === 3) {
- msg = xhr.responseJSON.reason;
- }
-
- FauxtonAPI.addNotification({
- msg: msg,
- type: 'error'
- });
- };
var Admin = Backbone.Model.extend({
url: function () {
@@ -214,167 +203,6 @@ function (app, FauxtonAPI, CouchdbSession) {
}
});
- Auth.CreateAdminView = FauxtonAPI.View.extend({
- template: 'addons/auth/templates/create_admin',
- className: "auth-page",
-
- initialize: function (options) {
- options = options || {};
- this.login_after = options.login_after === false ? false : true;
- },
-
- events: {
- "submit #create-admin-form": "createAdmin"
- },
-
- createAdmin: function (event) {
- event.preventDefault();
-
- var that = this,
- username = this.$('#username').val(),
- password = this.$('#password').val();
-
- var promise = this.model.createAdmin(username, password, this.login_after);
-
- promise.then(function () {
- FauxtonAPI.addNotification({
- msg: FauxtonAPI.session.messages.adminCreated,
- });
-
- if (that.login_after) {
- FauxtonAPI.navigate('/');
- } else {
- that.$('#username').val('');
- that.$('#password').val('');
- }
- });
-
- promise.fail(function (xhr, type, msg) {
- msg = xhr;
- if (arguments.length === 3) {
- msg = xhr.responseJSON.reason;
- }
- msg = FauxtonAPI.session.messages.adminCreationFailedPrefix + ' ' + msg;
- errorHandler(msg);
- });
- },
-
- afterRender: function () {
- $("#username").focus();
- }
- });
-
- Auth.LoginView = FauxtonAPI.View.extend({
- template: 'addons/auth/templates/login',
- className: "row-fluid",
- initialize: function (options) {
- this.urlBack = options.urlBack || "";
- },
-
- events: {
- "submit #login": "login"
- },
-
- login: function (event) {
- event.preventDefault();
-
- var username = this.$('#username').val(),
- password = this.$('#password').val(),
- urlBack = this.urlBack,
- promise = this.model.login(username, password);
-
- promise.then(function () {
- FauxtonAPI.addNotification({msg: FauxtonAPI.session.messages.loggedIn });
-
- if (urlBack) {
- return FauxtonAPI.navigate(urlBack);
- }
-
- FauxtonAPI.navigate('/');
- });
-
- promise.fail(errorHandler);
- },
-
- afterRender: function () {
- $("#username").focus();
- }
- });
-
- Auth.ChangePassword = FauxtonAPI.View.extend({
- template: 'addons/auth/templates/change_password',
- className: "auth-page",
-
- events: {
- "submit #change-password": "changePassword"
- },
-
- changePassword: function (event) {
- event.preventDefault();
-
- var that = this,
- new_password = this.$('#password').val(),
- password_confirm = this.$('#password-confirm').val();
-
- var promise = this.model.changePassword(new_password, password_confirm);
-
- promise.done(function () {
- FauxtonAPI.addNotification({msg: FauxtonAPI.session.messages.changePassword});
- that.$('#password').val('');
- that.$('#password-confirm').val('');
- });
-
- promise.fail(errorHandler);
- },
-
- afterRender: function () {
- $("#password").focus();
- }
- });
-
- Auth.NavDropDown = FauxtonAPI.View.extend({
- template: 'addons/auth/templates/nav_dropdown',
-
- beforeRender: function () {
- this.listenTo(this.model, 'change', this.render);
- },
-
- setTab: function (selectedTab) {
- this.selectedTab = selectedTab;
- this.$('.active').removeClass('active');
- var $tab = this.$('a[data-select="' + selectedTab + '"]');
- $tab.parent().addClass('active');
- },
-
- afterRender: function () {
- if (this.selectedTab) {
- this.setTab(this.selectedTab);
- }
- },
-
- serialize: function () {
- return {
- admin_party: this.model.isAdminParty(),
- user: this.model.user()
- };
- }
- });
-
- Auth.NoAccessView = FauxtonAPI.View.extend({
- template: "addons/auth/templates/noAccess",
- className: "row-fluid",
-
- initialize: function (options) {
- this.urlBack = options.urlBack || "";
- },
-
- serialize: function () {
- return {
- urlBack: this.urlBack,
- user: FauxtonAPI.session.user()
- };
- }
- });
return Auth;
});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/routes.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/routes.js b/app/addons/auth/routes.js
index b6ea57d..2632773 100644
--- a/app/addons/auth/routes.js
+++ b/app/addons/auth/routes.js
@@ -13,11 +13,14 @@
define([
"app",
"api",
- "addons/auth/resources"
+ 'addons/auth/resources',
+ 'addons/auth/actions',
+ 'addons/auth/components.react'
],
-function (app, FauxtonAPI, Auth) {
- var authRouteObject = FauxtonAPI.RouteObject.extend({
+function (app, FauxtonAPI, Auth, AuthActions, Components) {
+
+ var AuthRouteObject = FauxtonAPI.RouteObject.extend({
layout: 'one_pane',
routes: {
@@ -28,33 +31,31 @@ function (app, FauxtonAPI, Auth) {
},
login: function () {
- var urlBack = app.getParams().urlback;
- this.crumbs = [{name: 'Login', link:"#"}];
- this.setView('#dashboard-content', new Auth.LoginView({
- model: FauxtonAPI.session,
- urlBack: urlBack
- }));
+ this.crumbs = [{ name: 'Login', link: "#" }];
+
+ this.setComponent('#dashboard-content', Components.LoginForm, { urlBack: app.getParams().urlback });
},
logout: function () {
- FauxtonAPI.addNotification({msg: 'You have been logged out.'});
+ FauxtonAPI.addNotification({ msg: 'You have been logged out.' });
FauxtonAPI.session.logout().then(function () {
FauxtonAPI.navigate('/');
});
},
changePassword: function () {
- this.crumbs = [{name: 'Change Password', link:"#"}];
- this.setView('#dashboard-content', new Auth.ChangePassword({model: FauxtonAPI.session}));
+ this.crumbs = [{name: 'Change Password', link: "#" }];
+ this.setComponent('#dashboard-content', Components.ChangePasswordForm);
},
createAdmin: function () {
this.crumbs = [{name: 'Create Admin', link:"#"}];
- this.setView('#dashboard-content', new Auth.CreateAdminView({model: FauxtonAPI.session}));
+ this.setComponent('#dashboard-content', Components.CreateAdminForm, { loginAfter: true });
}
});
- var userRouteObject = FauxtonAPI.RouteObject.extend({
+
+ var UserRouteObject = FauxtonAPI.RouteObject.extend({
layout: 'with_sidebar',
routes: {
@@ -63,32 +64,33 @@ function (app, FauxtonAPI, Auth) {
roles: ['fx_loggedIn']
},
'addAdmin': {
- roles: ['_admin'],
- route: 'addAdmin'
+ route: 'addAdmin',
+ roles: ['_admin']
}
},
+
selectedHeader: function () {
return FauxtonAPI.session.user().name;
},
initialize: function () {
- this.navDrop = this.setView('#sidebar-content', new Auth.NavDropDown({model: FauxtonAPI.session}));
+ this.setComponent('#sidebar-content', Components.CreateAdminSidebar);
},
changePassword: function () {
- this.navDrop.setTab('change-password');
- this.setView('#dashboard-content', new Auth.ChangePassword({model: FauxtonAPI.session}));
+ AuthActions.selectPage('changePassword');
+ this.setComponent('#dashboard-content', Components.ChangePasswordForm);
},
addAdmin: function () {
- this.navDrop.setTab('add-admin');
- this.setView('#dashboard-content', new Auth.CreateAdminView({login_after: false, model: FauxtonAPI.session}));
+ AuthActions.selectPage('addAdmin');
+ this.setComponent('#dashboard-content', Components.CreateAdminForm, { loginAfter: false });
},
crumbs: [{name: 'User Management', link: '#'}]
});
- Auth.RouteObjects = [authRouteObject, userRouteObject];
+ Auth.RouteObjects = [AuthRouteObject, UserRouteObject];
return Auth;
});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/stores.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/stores.js b/app/addons/auth/stores.js
new file mode 100644
index 0000000..5327574
--- /dev/null
+++ b/app/addons/auth/stores.js
@@ -0,0 +1,171 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+ 'app',
+ 'api',
+ 'addons/auth/actiontypes'
+], function (app, FauxtonAPI, ActionTypes) {
+
+
+ // Not thrilled with this. The sole purpose of these next two stores is because the Create Admin + Change Password
+ // forms need to clear after a successful post. Since those events occur in actions.js, we need a way to tell the
+ // component to update + clear the fields. That's why all this code exists.
+
+ var ChangePasswordStore = FauxtonAPI.Store.extend({
+ initialize: function () {
+ this.reset();
+ },
+
+ reset: function () {
+ this._changePassword = '';
+ this._changePasswordConfirm = '';
+ },
+
+ getChangePassword: function () {
+ return this._changePassword;
+ },
+
+ getChangePasswordConfirm: function () {
+ return this._changePasswordConfirm;
+ },
+
+ setChangePassword: function (val) {
+ this._changePassword = val;
+ },
+
+ setChangePasswordConfirm: function (val) {
+ this._changePasswordConfirm = val;
+ },
+
+ dispatch: function (action) {
+ switch (action.type) {
+
+ case ActionTypes.AUTH_CLEAR_CHANGE_PWD_FIELDS:
+ this.reset();
+ this.triggerChange();
+ break;
+
+ case ActionTypes.AUTH_UPDATE_CHANGE_PWD_FIELD:
+ this.setChangePassword(action.value);
+ this.triggerChange();
+ break;
+
+ case ActionTypes.AUTH_UPDATE_CHANGE_PWD_CONFIRM_FIELD:
+ this.setChangePasswordConfirm(action.value);
+ this.triggerChange();
+ break;
+
+ default:
+ return;
+ }
+ }
+ });
+
+ var changePasswordStore = new ChangePasswordStore();
+ changePasswordStore.dispatchToken = FauxtonAPI.dispatcher.register(changePasswordStore.dispatch.bind(changePasswordStore));
+
+
+ var CreateAdminStore = FauxtonAPI.Store.extend({
+ initialize: function () {
+ this.reset();
+ },
+
+ reset: function () {
+ this._username = '';
+ this._password = '';
+ },
+
+ getUsername: function () {
+ return this._username;
+ },
+
+ getPassword: function () {
+ return this._password;
+ },
+
+ setUsername: function (val) {
+ this._username = val;
+ },
+
+ setPassword: function (val) {
+ this._password = val;
+ },
+
+ dispatch: function (action) {
+ switch (action.type) {
+ case ActionTypes.AUTH_CLEAR_CREATE_ADMIN_FIELDS:
+ this.reset();
+ this.triggerChange();
+ break;
+
+ case ActionTypes.AUTH_UPDATE_CREATE_ADMIN_USERNAME_FIELD:
+ this.setUsername(action.value);
+ this.triggerChange();
+ break;
+
+ case ActionTypes.AUTH_UPDATE_CREATE_ADMIN_PWD_FIELD:
+ this.setPassword(action.value);
+ this.triggerChange();
+ break;
+
+ default:
+ return;
+ }
+ }
+ });
+
+ var createAdminStore = new CreateAdminStore();
+ createAdminStore.dispatchToken = FauxtonAPI.dispatcher.register(createAdminStore.dispatch.bind(createAdminStore));
+
+
+ var CreateAdminSidebarStore = FauxtonAPI.Store.extend({
+ initialize: function () {
+ this.reset();
+ },
+
+ reset: function () {
+ this._selectedPage = 'changePassword';
+ },
+
+ getSelectedPage: function () {
+ return this._selectedPage;
+ },
+
+ setSelectedPage: function (val) {
+ this._selectedPage = val;
+ },
+
+ dispatch: function (action) {
+ switch (action.type) {
+ case ActionTypes.AUTH_SELECT_PAGE:
+ this.setSelectedPage(action.page);
+ this.triggerChange();
+ break;
+
+ default:
+ return;
+ }
+ }
+ });
+
+ var createAdminSidebarStore = new CreateAdminSidebarStore();
+ createAdminSidebarStore.dispatchToken = FauxtonAPI.dispatcher.register(createAdminSidebarStore.dispatch.bind(createAdminSidebarStore));
+
+
+ return {
+ changePasswordStore: changePasswordStore,
+ createAdminStore: createAdminStore,
+ createAdminSidebarStore: createAdminSidebarStore
+ };
+
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/templates/change_password.html
----------------------------------------------------------------------
diff --git a/app/addons/auth/templates/change_password.html b/app/addons/auth/templates/change_password.html
deleted file mode 100644
index 8879866..0000000
--- a/app/addons/auth/templates/change_password.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<%/*
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
-*/%>
-
-<h3>Change Password</h3>
-
-<form id="change-password">
- <p>
- Enter your new password.
- </p>
- <input id="password" type="password" name="password" placeholder="Password" size="24">
- <br/>
- <input id="password-confirm" type="password" name="password_confirm" placeholder= "Verify Password" size="24">
- <br/>
-
- <p>
- <button type="submit" class="btn btn-primary">Change</button>
- </p>
-</form>
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/templates/create_admin.html
----------------------------------------------------------------------
diff --git a/app/addons/auth/templates/create_admin.html b/app/addons/auth/templates/create_admin.html
deleted file mode 100644
index 9da8fa9..0000000
--- a/app/addons/auth/templates/create_admin.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<%/*
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
-*/%>
-
-<h3>Create Admins</h3>
-
-<p>
- Before a server admin is configured, all clients have admin privileges. This is fine when
- HTTP access is restricted to trusted users. <strong>If end-users will be accessing this
- CouchDB, you must create an admin account to prevent accidental (or malicious) data
- loss.</strong>
-</p>
-<p>
- Server admins can create and destroy databases, install and update _design documents, run
- the test suite, and edit all aspects of CouchDB configuration.
-</p>
-
-<form id="create-admin-form">
- <input id="username" type="text" name="name" placeholder="Username" size="24">
- <br/>
- <input id="password" type="password" name="password" placeholder= "Password" size="24">
- <p>Non-admin users have read and write access to all databases, which
- are controlled by validation functions. CouchDB can be configured to block all
- access to anonymous users.
- </p>
- <button type="submit" href="#" id="create-admin" class="btn btn-primary">Create Admin</button>
-</form>
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/templates/login.html
----------------------------------------------------------------------
diff --git a/app/addons/auth/templates/login.html b/app/addons/auth/templates/login.html
deleted file mode 100644
index d5bc6d7..0000000
--- a/app/addons/auth/templates/login.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
--->
-<div class="span12">
- <form id="login">
- <p class="help-block">
- Login with your username and password
- </p>
- <input id="username" type="text" name="name" placeholder="Username" size="24" />
- <br/>
- <input id="password" type="password" name="password" placeholder="Password" size="24" />
- <br/>
- <button id="submit" class="btn" type="submit">Login</button>
- </form>
-</div>
-
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/templates/nav_dropdown.html
----------------------------------------------------------------------
diff --git a/app/addons/auth/templates/nav_dropdown.html b/app/addons/auth/templates/nav_dropdown.html
deleted file mode 100644
index 44acf10..0000000
--- a/app/addons/auth/templates/nav_dropdown.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<%/*
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy of
-the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-License for the specific language governing permissions and limitations under
-the License.
-*/%>
-
-<div class="sidenav">
-<header class="row-fluid">
- <h3><%- user.name %></h3>
-</header>
-
-<ul class="nav nav-list">
- <li class="active" ><a data-select="change-password" id="user-change-password" href="#changePassword"> Change Password </a></li>
- <li ><a data-select="add-admin" href="#addAdmin"> Create Admins </a></li>
-</ul>
-</div>
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/test/auth.componentsSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/auth/test/auth.componentsSpec.react.jsx b/app/addons/auth/test/auth.componentsSpec.react.jsx
new file mode 100644
index 0000000..cdafb83
--- /dev/null
+++ b/app/addons/auth/test/auth.componentsSpec.react.jsx
@@ -0,0 +1,128 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+ 'api',
+ 'react',
+ 'testUtils',
+ 'addons/auth/components.react',
+ 'addons/auth/stores',
+ 'addons/auth/actions'
+], function (FauxtonAPI, React, testUtils, Components, Stores, Actions) {
+ var assert = testUtils.assert;
+
+ var TestUtils = React.addons.TestUtils;
+ var createAdminSidebarStore = Stores.createAdminSidebarStore;
+
+
+ describe('Auth -- Components', function () {
+
+ describe('LoginForm', function () {
+ var container, loginForm;
+
+ beforeEach(function () {
+ container = document.createElement('div');
+ loginForm = TestUtils.renderIntoDocument(<Components.LoginForm />, container);
+ });
+
+ afterEach(function () {
+ React.unmountComponentAtNode(container);
+ });
+
+ it('should trigger login event when form submitted', function () {
+ var spy = sinon.spy(Actions, 'login');
+ TestUtils.Simulate.submit($(loginForm.getDOMNode()).find('#login')[0]);
+ assert.ok(spy.calledOnce);
+ });
+ });
+
+ describe('ChangePasswordForm', function () {
+ var container, changePasswordForm;
+
+ beforeEach(function () {
+ container = document.createElement('div');
+ changePasswordForm = TestUtils.renderIntoDocument(<Components.ChangePasswordForm />, container);
+ });
+
+ afterEach(function () {
+ React.unmountComponentAtNode(container);
+ });
+
+ it('should call action to update password on field change', function () {
+ var spy = sinon.spy(Actions, 'updateChangePasswordField');
+ TestUtils.Simulate.change($(changePasswordForm.getDOMNode()).find('#password')[0], { target: { value: 'bobsyouruncle' }});
+ assert.ok(spy.calledOnce);
+ });
+
+ it('should call action to update password confirm on field change', function () {
+ var spy = sinon.spy(Actions, 'updateChangePasswordConfirmField');
+ TestUtils.Simulate.change($(changePasswordForm.getDOMNode()).find('#password-confirm')[0], { target: { value: 'hotdiggity' }});
+ assert.ok(spy.calledOnce);
+ });
+
+ it('should call action to submit form', function () {
+ var spy = sinon.spy(Actions, 'changePassword');
+ TestUtils.Simulate.submit($(changePasswordForm.getDOMNode()).find('#change-password')[0]);
+ assert.ok(spy.calledOnce);
+ });
+ });
+
+ describe('CreateAdminForm', function () {
+ var container, createAdminForm;
+
+ beforeEach(function () {
+ container = document.createElement('div');
+ createAdminForm = TestUtils.renderIntoDocument(<Components.CreateAdminForm loginAfter={false} />, container);
+ });
+
+ afterEach(function () {
+ React.unmountComponentAtNode(container);
+ });
+
+ it('should call action to update username on field change', function () {
+ var spy = sinon.spy(Actions, 'updateCreateAdminUsername');
+ TestUtils.Simulate.change($(createAdminForm.getDOMNode()).find('#username')[0], { target: { value: 'catsmeow' }});
+ assert.ok(spy.calledOnce);
+ });
+
+ it('should call action to update password confirm on field change', function () {
+ var spy = sinon.spy(Actions, 'updateCreateAdminPassword');
+ TestUtils.Simulate.change($(createAdminForm.getDOMNode()).find('#password')[0], { target: { value: 'topnotch' }});
+ assert.ok(spy.calledOnce);
+ });
+ });
+
+ describe('CreateAdminSidebar', function () {
+ var container, createAdminSidebar;
+
+ beforeEach(function () {
+ createAdminSidebarStore.reset();
+ container = document.createElement('div');
+ createAdminSidebar = TestUtils.renderIntoDocument(<Components.CreateAdminSidebar />, container);
+ });
+
+ afterEach(function () {
+ React.unmountComponentAtNode(container);
+ });
+
+ it('confirm the default selected nav item is the change pwd page', function () {
+ assert.equal($(createAdminSidebar.getDOMNode()).find('.active').find('a').attr('href'), '#changePassword');
+ });
+
+ it('confirm clicking a sidebar nav item selects it in the DOM', function () {
+ TestUtils.Simulate.click($(createAdminSidebar.getDOMNode()).find('li[data-page="addAdmin"]').find('a')[0]);
+ assert.equal($(createAdminSidebar.getDOMNode()).find('.active').find('a').attr('href'), '#addAdmin');
+ });
+ });
+
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/addons/auth/test/auth.storesSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/auth/test/auth.storesSpec.js b/app/addons/auth/test/auth.storesSpec.js
new file mode 100644
index 0000000..fd98147
--- /dev/null
+++ b/app/addons/auth/test/auth.storesSpec.js
@@ -0,0 +1,148 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+define([
+ 'api',
+ 'react',
+ 'testUtils',
+ 'addons/auth/actiontypes',
+ 'addons/auth/stores'
+], function (FauxtonAPI, React, testUtils, ActionTypes, Stores) {
+ var assert = testUtils.assert;
+
+ var changePasswordStore = Stores.changePasswordStore;
+ var createAdminStore = Stores.createAdminStore;
+ var createAdminSidebarStore = Stores.createAdminSidebarStore;
+
+ describe('Auth Stores', function () {
+
+ describe('ChangePasswordStore', function () {
+
+ it('get / set change password updates store', function () {
+ // check empty by default
+ assert.equal(changePasswordStore.getChangePassword(), '');
+
+ var newPassword = 'lets-rick-roll-mocha';
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CHANGE_PWD_FIELD,
+ value: newPassword
+ });
+ assert.equal(changePasswordStore.getChangePassword(), newPassword);
+ });
+
+ it('clearing change password clears in store', function () {
+ var newPassword = 'never-gonna-give-you-up';
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CHANGE_PWD_FIELD,
+ value: newPassword
+ });
+ assert.equal(changePasswordStore.getChangePassword(), newPassword);
+
+ FauxtonAPI.dispatch({ type: ActionTypes.AUTH_CLEAR_CHANGE_PWD_FIELDS });
+ assert.equal(changePasswordStore.getChangePassword(), '');
+ });
+
+ it('get / set change confirm password updates store', function () {
+ // check empty by default
+ assert.equal(changePasswordStore.getChangePasswordConfirm(), '');
+
+ // check getPassword works
+ var newPassword = 'never-gonna-let-you-down';
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CHANGE_PWD_CONFIRM_FIELD,
+ value: newPassword
+ });
+ assert.equal(changePasswordStore.getChangePasswordConfirm(), newPassword);
+ });
+
+ it('clearing change confirm password clears in store', function () {
+ var newPassword = 'never-gonna-run-around-and-desert-you';
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CHANGE_PWD_CONFIRM_FIELD,
+ value: newPassword
+ });
+ assert.equal(changePasswordStore.getChangePasswordConfirm(), newPassword);
+
+ FauxtonAPI.dispatch({ type: ActionTypes.AUTH_CLEAR_CHANGE_PWD_FIELDS });
+ assert.equal(changePasswordStore.getChangePasswordConfirm(), '');
+ });
+ });
+
+
+ describe('CreateAdminStore', function () {
+
+ it('get / set username updates store', function () {
+ assert.equal(createAdminStore.getUsername(), '');
+
+ var newUsername = 'never-gonna-make-you-cry';
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CREATE_ADMIN_USERNAME_FIELD,
+ value: newUsername
+ });
+ assert.equal(createAdminStore.getUsername(), newUsername);
+ });
+
+ it('clearing username clears in store', function () {
+ var newUsername = 'never-gonna-say-goodbye';
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CREATE_ADMIN_USERNAME_FIELD,
+ value: newUsername
+ });
+ assert.equal(createAdminStore.getUsername(), newUsername);
+
+ FauxtonAPI.dispatch({ type: ActionTypes.AUTH_CLEAR_CREATE_ADMIN_FIELDS });
+ assert.equal(createAdminStore.getUsername(), '');
+ });
+
+ it('get / set password updates store', function () {
+ // check empty by default
+ assert.equal(createAdminStore.getPassword(), '');
+
+ // check getPassword works
+ var newPassword = 'never-gonna-tell-a-lie-and-hurt-you';
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CREATE_ADMIN_PWD_FIELD,
+ value: newPassword
+ });
+ assert.equal(createAdminStore.getPassword(), newPassword);
+ });
+
+ it('clearing change confirm password clears in store', function () {
+ var newPassword = 'mocha-please-consider-yourself-rickrolled';
+ FauxtonAPI.dispatch({
+ type: ActionTypes.AUTH_UPDATE_CREATE_ADMIN_PWD_FIELD,
+ value: newPassword
+ });
+ assert.equal(createAdminStore.getPassword(), newPassword);
+
+ FauxtonAPI.dispatch({ type: ActionTypes.AUTH_CLEAR_CREATE_ADMIN_FIELDS });
+ assert.equal(createAdminStore.getPassword(), '');
+ });
+ });
+
+
+ describe('CreateAdminSidebarStore', function () {
+ var defaultPage = 'changePassword';
+ it('has correct default selected page', function () {
+ assert.equal(createAdminSidebarStore.getSelectedPage(), defaultPage);
+ });
+
+ it('selecting a page updates the selected page in store', function () {
+ var newPage = 'addAdmin';
+ FauxtonAPI.dispatch({ type: ActionTypes.AUTH_SELECT_PAGE, page: newPage });
+ assert.equal(createAdminSidebarStore.getSelectedPage(), newPage);
+ });
+ });
+
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/core/routeObject.js
----------------------------------------------------------------------
diff --git a/app/core/routeObject.js b/app/core/routeObject.js
index 0af072a..818f4eb 100644
--- a/app/core/routeObject.js
+++ b/app/core/routeObject.js
@@ -132,8 +132,8 @@ function (FauxtonAPI, React, Backbone) {
},
renderReactComponents: function () {
- _.each(this.reactComponents, function (component, selector) {
- React.render(React.createElement(component, null), $(selector)[0]);
+ _.each(this.reactComponents, function (componentInfo, selector) {
+ React.render(React.createElement(componentInfo.component, componentInfo.props), $(selector)[0]);
});
},
@@ -245,10 +245,13 @@ function (FauxtonAPI, React, Backbone) {
return view;
},
- setComponent: function (selector, component) {
+ setComponent: function (selector, component, props) {
this.removeView(selector);
this.removeComponent(selector);
- this.reactComponents[selector] = component;
+ this.reactComponents[selector] = {
+ component: component,
+ props: props || null
+ };
},
removeComponent: function (selector) {
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/410d2c77/app/core/tests/routeObjectSpec.js
----------------------------------------------------------------------
diff --git a/app/core/tests/routeObjectSpec.js b/app/core/tests/routeObjectSpec.js
index e267f65..fbac6b6 100644
--- a/app/core/tests/routeObjectSpec.js
+++ b/app/core/tests/routeObjectSpec.js
@@ -178,7 +178,15 @@ define([
var fakeSelector = '.fake-selector';
testRouteObject.setComponent(fakeSelector, fakeReactComponent);
- assert.deepEqual(fakeReactComponent, testRouteObject.reactComponents[fakeSelector]);
+ assert.deepEqual(fakeReactComponent, testRouteObject.reactComponents[fakeSelector].component);
+ });
+
+ it('sets props for the selector', function () {
+ var fakeReactComponent = React.createElement('div');
+ var fakeSelector = '.fake-selector';
+
+ testRouteObject.setComponent(fakeSelector, fakeReactComponent, {foo: 'bar baromat'});
+ assert.deepEqual(fakeReactComponent, testRouteObject.reactComponents[fakeSelector].component);
});
});