2015-12-07 00:24:06 +03:00
/* jshint expr:true */
2017-05-29 21:50:03 +03:00
import ctrlOrCmd from 'ghost-admin/utils/ctrl-or-cmd' ;
2015-12-07 00:24:06 +03:00
import destroyApp from '../helpers/destroy-app' ;
2017-04-05 20:45:35 +03:00
import moment from 'moment' ;
2017-05-29 21:50:03 +03:00
import startApp from '../helpers/start-app' ;
import testSelector from 'ember-test-selectors' ;
import { Response } from 'ember-cli-mirage' ;
import { afterEach , beforeEach , describe , it } from 'mocha' ;
import { authenticateSession , invalidateSession } from '../helpers/ember-simple-auth' ;
import { enableGhostOAuth } from '../helpers/configuration' ;
import { errorOverride , errorReset } from '../helpers/adapter-error' ;
import { expect } from 'chai' ;
2015-12-07 00:24:06 +03:00
describe ( 'Acceptance: Team' , function ( ) {
let application ;
beforeEach ( function ( ) {
application = startApp ( ) ;
} ) ;
afterEach ( function ( ) {
destroyApp ( application ) ;
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'redirects to signin when not authenticated' , async function ( ) {
2015-12-07 00:24:06 +03:00
invalidateSession ( application ) ;
2017-04-24 15:29:48 +03:00
await visit ( '/team' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( currentURL ( ) ) . to . equal ( '/signin' ) ;
2015-12-07 00:24:06 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'redirects correctly when authenticated as author' , async function ( ) {
2016-04-08 18:00:16 +03:00
let role = server . create ( 'role' , { name : 'Author' } ) ;
2016-11-14 16:16:51 +03:00
server . create ( 'user' , { roles : [ role ] , slug : 'test-user' } ) ;
2015-12-07 00:24:06 +03:00
server . create ( 'user' , { slug : 'no-access' } ) ;
authenticateSession ( application ) ;
2017-04-24 15:29:48 +03:00
await visit ( '/team/no-access' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( currentURL ( ) , 'currentURL' ) . to . equal ( '/team/test-user' ) ;
2015-12-07 00:24:06 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'redirects correctly when authenticated as editor' , async function ( ) {
2016-04-08 18:00:16 +03:00
let role = server . create ( 'role' , { name : 'Editor' } ) ;
2016-11-14 16:16:51 +03:00
server . create ( 'user' , { roles : [ role ] , slug : 'test-user' } ) ;
2015-12-07 00:24:06 +03:00
server . create ( 'user' , { slug : 'no-access' } ) ;
authenticateSession ( application ) ;
2017-04-24 15:29:48 +03:00
await visit ( '/team/no-access' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( currentURL ( ) , 'currentURL' ) . to . equal ( '/team' ) ;
2015-12-07 00:24:06 +03:00
} ) ;
2016-09-26 19:03:53 +03:00
describe ( 'when logged in as admin' , function ( ) {
2017-03-08 21:21:35 +03:00
let admin , adminRole , suspendedUser ;
2016-06-14 14:46:24 +03:00
2015-12-07 00:24:06 +03:00
beforeEach ( function ( ) {
2017-01-02 21:50:36 +03:00
server . loadFixtures ( 'roles' ) ;
adminRole = server . schema . roles . find ( 1 ) ;
2015-12-07 00:24:06 +03:00
2017-01-02 21:50:36 +03:00
admin = server . create ( 'user' , { email : 'admin@example.com' , roles : [ adminRole ] } ) ;
2015-12-07 00:24:06 +03:00
2017-02-27 16:11:39 +03:00
// add an expired invite
server . create ( 'invite' , { expires : moment . utc ( ) . subtract ( 1 , 'day' ) . valueOf ( ) } ) ;
2017-03-08 21:21:35 +03:00
// add a suspended user
suspendedUser = server . create ( 'user' , { email : 'suspended@example.com' , roles : [ adminRole ] , status : 'inactive' } ) ;
2015-12-07 00:24:06 +03:00
return authenticateSession ( application ) ;
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'it renders and navigates correctly' , async function ( ) {
2017-03-08 21:21:35 +03:00
let user1 = server . create ( 'user' ) ;
2016-04-08 18:00:16 +03:00
let user2 = server . create ( 'user' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
await visit ( '/team' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
// doesn't do any redirecting
expect ( currentURL ( ) , 'currentURL' ) . to . equal ( '/team' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
// it has correct page title
expect ( document . title , 'page title' ) . to . equal ( 'Team - Test Blog' ) ;
// it shows active users in active section
expect (
find ( ` ${ testSelector ( 'active-users' ) } ${ testSelector ( 'user-id' ) } ` ) . length ,
'number of active users'
) . to . equal ( 3 ) ;
expect (
find ( ` ${ testSelector ( 'active-users' ) } ${ testSelector ( 'user-id' , user1 . id ) } ` )
) . to . exist ;
expect (
find ( ` ${ testSelector ( 'active-users' ) } ${ testSelector ( 'user-id' , user2 . id ) } ` )
) . to . exist ;
expect (
find ( ` ${ testSelector ( 'active-users' ) } ${ testSelector ( 'user-id' , admin . id ) } ` )
) . to . exist ;
// it shows suspended users in suspended section
expect (
find ( ` ${ testSelector ( 'suspended-users' ) } ${ testSelector ( 'user-id' ) } ` ) . length ,
'number of suspended users'
) . to . equal ( 1 ) ;
expect (
find ( ` ${ testSelector ( 'suspended-users' ) } ${ testSelector ( 'user-id' , suspendedUser . id ) } ` )
) . to . exist ;
await click ( testSelector ( 'user-id' , user2 . id ) ) ;
// url is correct
expect ( currentURL ( ) , 'url after clicking user' ) . to . equal ( ` /team/ ${ user2 . slug } ` ) ;
// title is correct
expect ( document . title , 'title after clicking user' ) . to . equal ( 'Team - User - Test Blog' ) ;
// view title should exist and be linkable and active
2017-05-30 16:23:38 +03:00
expect (
find ( ` ${ testSelector ( 'screen-title' ) } a[href="/ghost/team"] ` ) . hasClass ( 'active' ) ,
'has linkable url back to team main page'
) . to . be . true ;
2017-04-24 15:29:48 +03:00
2017-05-30 16:23:38 +03:00
await click ( ` ${ testSelector ( 'screen-title' ) } a ` ) ;
2017-04-24 15:29:48 +03:00
// url should be /team again
expect ( currentURL ( ) , 'url after clicking back' ) . to . equal ( '/team' ) ;
2015-12-07 00:24:06 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'can manage invites' , async function ( ) {
await visit ( '/team' ) ;
// invite user button exists
expect (
find ( '.view-actions .gh-btn-green' ) . text ( ) . trim ( ) ,
'invite people button text'
) . to . equal ( 'Invite People' ) ;
// existing users are listed
expect (
find ( testSelector ( 'user-id' ) ) . length ,
'initial number of active users'
) . to . equal ( 2 ) ;
expect (
find ( testSelector ( 'user-id' , '1' ) ) . find ( testSelector ( 'role-name' ) ) . text ( ) . trim ( ) ,
'active user\'s role label'
) . to . equal ( 'Administrator' ) ;
// existing invites are shown
expect (
find ( testSelector ( 'invite-id' ) ) . length ,
'initial number of invited users'
) . to . equal ( 1 ) ;
expect (
find ( testSelector ( 'invite-id' , '1' ) ) . find ( testSelector ( 'invite-description' ) ) . text ( ) ,
'expired invite description'
) . to . match ( /expired/ ) ;
2017-02-27 16:11:39 +03:00
// remove expired invite
2017-04-24 15:29:48 +03:00
await click ( ` ${ testSelector ( 'invite-id' , '1' ) } ${ testSelector ( 'revoke-button' ) } ` ) ;
2017-02-27 16:11:39 +03:00
2017-04-24 15:29:48 +03:00
expect (
find ( testSelector ( 'invite-id' ) ) . length ,
'initial number of invited users'
) . to . equal ( 0 ) ;
2016-09-26 19:03:53 +03:00
// click the invite people button
2017-04-24 15:29:48 +03:00
await click ( '.view-actions .gh-btn-green' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
let roleOptions = find ( '.fullscreen-modal select[name="role"] option' ) ;
2016-09-26 19:03:53 +03:00
2017-04-24 15:29:48 +03:00
function checkOwnerExists ( ) {
for ( let i in roleOptions ) {
if ( roleOptions [ i ] . tagName === 'option' && roleOptions [ i ] . text === 'Owner' ) {
return true ;
2015-12-07 00:24:06 +03:00
}
2016-09-26 19:03:53 +03:00
}
2017-04-24 15:29:48 +03:00
return false ;
}
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
function checkSelectedIsAuthor ( ) {
for ( let i in roleOptions ) {
if ( roleOptions [ i ] . selected ) {
return roleOptions [ i ] . text === 'Author' ;
2015-12-07 00:24:06 +03:00
}
2016-09-26 19:03:53 +03:00
}
2017-04-24 15:29:48 +03:00
return false ;
}
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
// modal is displayed
expect (
find ( '.fullscreen-modal h1' ) . text ( ) . trim ( ) ,
'correct modal is displayed'
) . to . equal ( 'Invite a New User' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
// number of roles is correct
expect (
find ( '.fullscreen-modal select[name="role"] option' ) . length ,
'number of selectable roles'
) . to . equal ( 3 ) ;
2016-09-26 19:03:53 +03:00
2017-04-24 15:29:48 +03:00
expect ( checkOwnerExists ( ) , 'owner role isn\'t available' ) . to . be . false ;
expect ( checkSelectedIsAuthor ( ) , 'author role is selected initially' ) . to . be . true ;
2015-12-07 00:24:06 +03:00
2016-09-26 19:03:53 +03:00
// submit valid invite form
2017-04-24 15:29:48 +03:00
await fillIn ( '.fullscreen-modal input[name="email"]' , 'invite1@example.com' ) ;
await click ( '.fullscreen-modal .gh-btn-green' ) ;
// modal closes
expect (
find ( '.fullscreen-modal' ) . length ,
'number of modals after sending invite'
) . to . equal ( 0 ) ;
// invite is displayed, has correct e-mail + role
expect (
find ( testSelector ( 'invite-id' ) ) . length ,
'number of invites after first invite'
) . to . equal ( 1 ) ;
expect (
find ( testSelector ( 'invite-id' , '2' ) ) . find ( testSelector ( 'email' ) ) . text ( ) . trim ( ) ,
'displayed email of first invite'
) . to . equal ( 'invite1@example.com' ) ;
expect (
find ( testSelector ( 'invite-id' , '2' ) ) . find ( testSelector ( 'role-name' ) ) . text ( ) . trim ( ) ,
'displayed role of first invite'
) . to . equal ( 'Author' ) ;
expect (
find ( testSelector ( 'invite-id' , '2' ) ) . find ( testSelector ( 'invite-description' ) ) . text ( ) ,
'new invite description'
) . to . match ( /expires/ ) ;
// number of users is unchanged
expect (
find ( testSelector ( 'user-id' ) ) . length ,
'number of active users after first invite'
) . to . equal ( 2 ) ;
2015-12-07 00:24:06 +03:00
2016-09-26 19:03:53 +03:00
// submit new invite with different role
2017-04-24 15:29:48 +03:00
await click ( '.view-actions .gh-btn-green' ) ;
await fillIn ( '.fullscreen-modal input[name="email"]' , 'invite2@example.com' ) ;
await fillIn ( '.fullscreen-modal select[name="role"]' , '2' ) ;
await click ( '.fullscreen-modal .gh-btn-green' ) ;
// number of invites increases
expect (
find ( testSelector ( 'invite-id' ) ) . length ,
'number of invites after second invite'
) . to . equal ( 2 ) ;
// invite has correct e-mail + role
expect (
find ( testSelector ( 'invite-id' , '3' ) ) . find ( testSelector ( 'email' ) ) . text ( ) . trim ( ) ,
'displayed email of second invite'
) . to . equal ( 'invite2@example.com' ) ;
expect (
find ( testSelector ( 'invite-id' , '3' ) ) . find ( testSelector ( 'role-name' ) ) . text ( ) . trim ( ) ,
'displayed role of second invite'
) . to . equal ( 'Editor' ) ;
2015-12-07 00:24:06 +03:00
2016-09-26 19:03:53 +03:00
// submit invite form with existing user
2017-04-24 15:29:48 +03:00
await click ( '.view-actions .gh-btn-green' ) ;
await fillIn ( '.fullscreen-modal input[name="email"]' , 'admin@example.com' ) ;
await click ( '.fullscreen-modal .gh-btn-green' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
// validation message is displayed
expect (
find ( '.fullscreen-modal .error .response' ) . text ( ) . trim ( ) ,
'inviting existing user error'
) . to . equal ( 'A user with that email address already exists.' ) ;
2015-12-07 00:24:06 +03:00
2016-09-26 19:03:53 +03:00
// submit invite form with existing invite
2017-04-24 15:29:48 +03:00
await fillIn ( '.fullscreen-modal input[name="email"]' , 'invite1@example.com' ) ;
await click ( '.fullscreen-modal .gh-btn-green' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
// validation message is displayed
expect (
find ( '.fullscreen-modal .error .response' ) . text ( ) . trim ( ) ,
'inviting invited user error'
) . to . equal ( 'A user with that email address was already invited.' ) ;
2015-11-18 13:50:48 +03:00
2016-09-26 19:03:53 +03:00
// submit invite form with an invalid email
2017-04-24 15:29:48 +03:00
await fillIn ( '.fullscreen-modal input[name="email"]' , 'test' ) ;
await click ( '.fullscreen-modal .gh-btn-green' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
// validation message is displayed
expect (
find ( '.fullscreen-modal .error .response' ) . text ( ) . trim ( ) ,
'inviting invalid email error'
) . to . equal ( 'Invalid Email.' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
await click ( '.fullscreen-modal a.close' ) ;
2016-09-26 19:03:53 +03:00
// revoke latest invite
2017-04-24 15:29:48 +03:00
await click ( ` ${ testSelector ( 'invite-id' , '3' ) } ${ testSelector ( 'revoke-button' ) } ` ) ;
// number of invites decreases
expect (
find ( testSelector ( 'invite-id' ) ) . length ,
'number of invites after revoke'
) . to . equal ( 1 ) ;
// notification is displayed
expect (
find ( '.gh-notification' ) . text ( ) . trim ( ) ,
'notifications contain revoke'
) . to . match ( /Invitation revoked\. \(invite2@example\.com\)/ ) ;
// correct invite is removed
expect (
find ( testSelector ( 'invite-id' ) ) . find ( testSelector ( 'email' ) ) . text ( ) . trim ( ) ,
'displayed email of remaining invite'
) . to . equal ( 'invite1@example.com' ) ;
2016-09-26 19:03:53 +03:00
// add another invite to test ordering on resend
2017-04-24 15:29:48 +03:00
await click ( '.view-actions .gh-btn-green' ) ;
await fillIn ( '.fullscreen-modal input[name="email"]' , 'invite3@example.com' ) ;
await click ( '.fullscreen-modal .gh-btn-green' ) ;
2016-09-26 19:03:53 +03:00
2017-04-24 15:29:48 +03:00
// new invite should be last in the list
expect (
find ( ` ${ testSelector ( 'invite-id' ) } :last ` ) . find ( testSelector ( 'email' ) ) . text ( ) . trim ( ) ,
'last invite email in list'
) . to . equal ( 'invite3@example.com' ) ;
2016-09-26 19:03:53 +03:00
// resend first invite
2017-04-24 15:29:48 +03:00
await click ( ` ${ testSelector ( 'invite-id' , '2' ) } ${ testSelector ( 'resend-button' ) } ` ) ;
2016-09-26 19:03:53 +03:00
2017-04-24 15:29:48 +03:00
// notification is displayed
expect (
find ( '.gh-notification' ) . text ( ) . trim ( ) ,
'notifications contain resend'
) . to . match ( /Invitation resent! \(invite1@example\.com\)/ ) ;
2016-09-26 19:03:53 +03:00
2017-04-24 15:29:48 +03:00
// first invite is still at the top
expect (
find ( ` ${ testSelector ( 'invite-id' ) } :first-of-type ` ) . find ( testSelector ( 'email' ) ) . text ( ) . trim ( ) ,
'first invite email in list'
) . to . equal ( 'invite1@example.com' ) ;
2016-09-26 19:03:53 +03:00
// regression test: can revoke a resent invite
2017-04-24 15:29:48 +03:00
await click ( ` ${ testSelector ( 'invite-id' ) } :first-of-type ${ testSelector ( 'resend-button' ) } ` ) ;
await click ( ` ${ testSelector ( 'invite-id' ) } :first-of-type ${ testSelector ( 'revoke-button' ) } ` ) ;
// number of invites decreases
expect (
find ( testSelector ( 'invite-id' ) ) . length ,
'number of invites after resend/revoke'
) . to . equal ( 1 ) ;
// notification is displayed
expect (
find ( '.gh-notification' ) . text ( ) . trim ( ) ,
'notifications contain revoke after resend/revoke'
) . to . match ( /Invitation revoked\. \(invite1@example\.com\)/ ) ;
2015-12-07 00:24:06 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'can manage suspended users' , async function ( ) {
await visit ( '/team' ) ;
await click ( testSelector ( 'user-id' , suspendedUser . id ) ) ;
2017-03-08 21:21:35 +03:00
2017-04-24 15:29:48 +03:00
expect ( testSelector ( 'suspended-badge' ) ) . to . exist ;
2017-03-08 21:21:35 +03:00
2017-04-24 15:29:48 +03:00
await click ( testSelector ( 'user-actions' ) ) ;
await click ( testSelector ( 'unsuspend-button' ) ) ;
await click ( testSelector ( 'modal-confirm' ) ) ;
2017-03-08 21:21:35 +03:00
// NOTE: there seems to be a timing issue with this test - pausing
// here confirms that the badge is removed but the andThen is firing
// before the page is updated
// andThen(() => {
// expect(testSelector('suspended-badge')).to.not.exist;
// });
2017-04-24 15:29:48 +03:00
await click ( testSelector ( 'team-link' ) ) ;
2017-03-08 21:21:35 +03:00
2017-04-24 15:29:48 +03:00
// suspendedUser is now in active list
expect (
find ( ` ${ testSelector ( 'active-users' ) } ${ testSelector ( 'user-id' , suspendedUser . id ) } ` )
) . to . exist ;
2017-03-08 21:21:35 +03:00
2017-04-24 15:29:48 +03:00
// no suspended users
expect (
find ( ` ${ testSelector ( 'suspended-users' ) } ${ testSelector ( 'user-id' ) } ` ) . length
) . to . equal ( 0 ) ;
2017-03-08 21:21:35 +03:00
2017-04-24 15:29:48 +03:00
await click ( testSelector ( 'user-id' , suspendedUser . id ) ) ;
2017-03-08 21:21:35 +03:00
2017-04-24 15:29:48 +03:00
await click ( testSelector ( 'user-actions' ) ) ;
await click ( testSelector ( 'suspend-button' ) ) ;
await click ( testSelector ( 'modal-confirm' ) ) ;
2017-03-08 21:21:35 +03:00
2017-04-24 15:29:48 +03:00
expect ( testSelector ( 'suspended-badge' ) ) . to . exist ;
2017-03-08 21:21:35 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'can delete users' , async function ( ) {
2016-08-24 16:26:29 +03:00
let user1 = server . create ( 'user' ) ;
let user2 = server . create ( 'user' ) ;
2017-01-02 21:50:36 +03:00
let post = server . create ( 'post' ) ;
user2 . posts = [ post ] ;
2016-08-24 16:26:29 +03:00
2017-04-24 15:29:48 +03:00
await visit ( '/team' ) ;
await click ( testSelector ( 'user-id' , user1 . id ) ) ;
2016-08-24 16:26:29 +03:00
// user deletion displays modal
2017-04-24 15:29:48 +03:00
await click ( 'button.delete' ) ;
expect (
find ( '.fullscreen-modal .modal-content:contains("delete this user")' ) . length ,
'user deletion modal displayed after button click'
) . to . equal ( 1 ) ;
// user has no posts so no warning about post deletion
expect (
find ( '.fullscreen-modal .modal-content:contains("is the author of")' ) . length ,
'deleting user with no posts has no post count'
) . to . equal ( 0 ) ;
2016-08-24 16:26:29 +03:00
// cancelling user deletion closes modal
2017-04-24 15:29:48 +03:00
await click ( '.fullscreen-modal button:contains("Cancel")' ) ;
expect (
find ( '.fullscreen-modal' ) . length === 0 ,
'delete user modal is closed when cancelling'
) . to . be . true ;
2016-08-24 16:26:29 +03:00
// deleting a user with posts
2017-04-24 15:29:48 +03:00
await visit ( '/team' ) ;
await click ( testSelector ( 'user-id' , user2 . id ) ) ;
await click ( 'button.delete' ) ;
// user has posts so should warn about post deletion
expect (
find ( '.fullscreen-modal .modal-content:contains("is the author of 1 post")' ) . length ,
'deleting user with posts has post count'
) . to . equal ( 1 ) ;
await click ( '.fullscreen-modal button:contains("Delete")' ) ;
// redirected to team page
expect ( currentURL ( ) ) . to . equal ( '/team' ) ;
// deleted user is not in list
expect (
find ( testSelector ( 'user-id' , user2 . id ) ) . length ,
'deleted user is not in user list after deletion'
) . to . equal ( 0 ) ;
2016-08-24 16:26:29 +03:00
} ) ;
2015-12-07 00:24:06 +03:00
describe ( 'existing user' , function ( ) {
let user ;
beforeEach ( function ( ) {
2016-06-14 14:46:24 +03:00
user = server . create ( 'user' , {
2016-05-17 21:14:14 +03:00
slug : 'test-1' ,
name : 'Test User' ,
facebook : 'test' ,
twitter : '@test'
} ) ;
2015-12-07 00:24:06 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'input fields reset and validate correctly' , async function ( ) {
2015-12-07 00:24:06 +03:00
// test user name
2017-04-24 15:29:48 +03:00
await visit ( '/team/test-1' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( currentURL ( ) , 'currentURL' ) . to . equal ( '/team/test-1' ) ;
2017-05-17 15:24:31 +03:00
expect ( find ( '.user-details-bottom .first-form-group input.user-name' ) . val ( ) , 'current user name' ) . to . equal ( 'Test User' ) ;
2015-12-07 00:24:06 +03:00
2017-05-18 13:48:37 +03:00
expect ( find ( testSelector ( 'save-button' ) ) . text ( ) . trim ( ) , 'save button text' ) . to . equal ( 'Save' ) ;
2015-12-07 00:24:06 +03:00
// test empty user name
2017-05-17 15:24:31 +03:00
await fillIn ( '.user-details-bottom .first-form-group input.user-name' , '' ) ;
await triggerEvent ( '.user-details-bottom .first-form-group input.user-name' , 'blur' ) ;
2015-12-07 00:24:06 +03:00
2017-05-17 15:24:31 +03:00
expect ( find ( '.user-details-bottom .first-form-group' ) . hasClass ( 'error' ) , 'username input is in error state with blank input' ) . to . be . true ;
2015-12-07 00:24:06 +03:00
// test too long user name
2017-05-17 15:24:31 +03:00
await fillIn ( '.user-details-bottom .first-form-group input.user-name' , new Array ( 160 ) . join ( 'a' ) ) ;
await triggerEvent ( '.user-details-bottom .first-form-group input.user-name' , 'blur' ) ;
2015-12-07 00:24:06 +03:00
2017-05-17 15:24:31 +03:00
expect ( find ( '.user-details-bottom .first-form-group' ) . hasClass ( 'error' ) , 'username input is in error state with too long input' ) . to . be . true ;
2015-12-07 00:24:06 +03:00
// reset name field
2017-05-17 15:24:31 +03:00
await fillIn ( '.user-details-bottom .first-form-group input.user-name' , 'Test User' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '.user-details-bottom input[name="user"]' ) . val ( ) , 'slug value is default' ) . to . equal ( 'test-1' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '.user-details-bottom input[name="user"]' , '' ) ;
await triggerEvent ( '.user-details-bottom input[name="user"]' , 'blur' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '.user-details-bottom input[name="user"]' ) . val ( ) , 'slug value is reset to original upon empty string' ) . to . equal ( 'test-1' ) ;
2015-12-07 00:24:06 +03:00
2017-05-18 13:48:37 +03:00
// Save changes
await click ( testSelector ( 'save-button' ) ) ;
expect ( find ( testSelector ( 'save-button' ) ) . text ( ) . trim ( ) , 'save button text' ) . to . equal ( 'Saved' ) ;
// CMD-S shortcut works
await fillIn ( '.user-details-bottom input[name="user"]' , 'Test User' ) ;
await triggerEvent ( '.gh-app' , 'keydown' , {
keyCode : 83 , // s
metaKey : ctrlOrCmd === 'command' ,
ctrlKey : ctrlOrCmd === 'ctrl'
} ) ;
// we've already saved in this test so there's no on-screen indication
// that we've had another save, check the request was fired instead
let [ lastRequest ] = server . pretender . handledRequests . slice ( - 1 ) ;
let params = JSON . parse ( lastRequest . requestBody ) ;
expect ( params . users [ 0 ] . name ) . to . equal ( 'Test User' ) ;
2017-04-24 15:29:48 +03:00
await fillIn ( '.user-details-bottom input[name="user"]' , 'white space' ) ;
await triggerEvent ( '.user-details-bottom input[name="user"]' , 'blur' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '.user-details-bottom input[name="user"]' ) . val ( ) , 'slug value is correctly dasherized' ) . to . equal ( 'white-space' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '.user-details-bottom input[name="email"]' , 'thisisnotanemail' ) ;
await triggerEvent ( '.user-details-bottom input[name="email"]' , 'blur' ) ;
2015-12-07 00:24:06 +03:00
2017-05-17 15:24:31 +03:00
expect ( find ( '.user-details-bottom .form-group:nth-of-type(3)' ) . hasClass ( 'error' ) , 'email input should be in error state with invalid email' ) . to . be . true ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '.user-details-bottom input[name="email"]' , 'test@example.com' ) ;
await fillIn ( '#user-location' , new Array ( 160 ) . join ( 'a' ) ) ;
await triggerEvent ( '#user-location' , 'blur' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-location' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'location input should be in error state' ) . to . be . true ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-location' , '' ) ;
await fillIn ( '#user-website' , 'thisisntawebsite' ) ;
await triggerEvent ( '#user-website' , 'blur' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-website' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'website input should be in error state' ) . to . be . true ;
2015-12-07 00:24:06 +03:00
2016-05-16 21:16:40 +03:00
// Testing Facebook input
2016-05-17 21:14:14 +03:00
2017-04-24 15:29:48 +03:00
// displays initial value
expect ( find ( '#user-facebook' ) . val ( ) , 'initial facebook value' )
. to . equal ( 'https://www.facebook.com/test' ) ;
2016-05-17 21:14:14 +03:00
2017-04-24 15:29:48 +03:00
await triggerEvent ( '#user-facebook' , 'focus' ) ;
await triggerEvent ( '#user-facebook' , 'blur' ) ;
2016-05-17 21:14:14 +03:00
2017-04-24 15:29:48 +03:00
// regression test: we still have a value after the input is
// focused and then blurred without any changes
expect ( find ( '#user-facebook' ) . val ( ) , 'facebook value after blur with no change' )
. to . equal ( 'https://www.facebook.com/test' ) ;
2016-05-17 21:14:14 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-facebook' , '' ) ;
await fillIn ( '#user-facebook' , ')(*&%^%)' ) ;
await triggerEvent ( '#user-facebook' , 'blur' ) ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-facebook' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'facebook input should be in error state' ) . to . be . true ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-facebook' , '' ) ;
await fillIn ( '#user-facebook' , 'pages/)(*&%^%)' ) ;
await triggerEvent ( '#user-facebook' , 'blur' ) ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-facebook' ) . val ( ) ) . to . be . equal ( 'https://www.facebook.com/pages/)(*&%^%)' ) ;
expect ( find ( '#user-facebook' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'facebook input should be in error state' ) . to . be . false ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-facebook' , '' ) ;
await fillIn ( '#user-facebook' , 'testing' ) ;
await triggerEvent ( '#user-facebook' , 'blur' ) ;
2016-05-16 21:16:40 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-facebook' ) . val ( ) ) . to . be . equal ( 'https://www.facebook.com/testing' ) ;
expect ( find ( '#user-facebook' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'facebook input should be in error state' ) . to . be . false ;
2016-05-16 21:16:40 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-facebook' , '' ) ;
await fillIn ( '#user-facebook' , 'somewebsite.com/pages/some-facebook-page/857469375913?ref=ts' ) ;
await triggerEvent ( '#user-facebook' , 'blur' ) ;
2016-05-16 21:16:40 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-facebook' ) . val ( ) ) . to . be . equal ( 'https://www.facebook.com/pages/some-facebook-page/857469375913?ref=ts' ) ;
expect ( find ( '#user-facebook' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'facebook input should be in error state' ) . to . be . false ;
2016-05-16 21:16:40 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-facebook' , '' ) ;
await fillIn ( '#user-facebook' , 'test' ) ;
await triggerEvent ( '#user-facebook' , 'blur' ) ;
2016-03-03 11:52:27 +03:00
2017-05-15 21:26:34 +03:00
expect ( find ( '#user-facebook' ) . val ( ) ) . to . be . equal ( 'https://www.facebook.com/test' ) ;
expect ( find ( '#user-facebook' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'facebook input should be in error state' ) . to . be . false ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-facebook' , '' ) ;
await fillIn ( '#user-facebook' , 'http://twitter.com/testuser' ) ;
await triggerEvent ( '#user-facebook' , 'blur' ) ;
2016-05-16 21:16:40 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-facebook' ) . val ( ) ) . to . be . equal ( 'https://www.facebook.com/testuser' ) ;
expect ( find ( '#user-facebook' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'facebook input should be in error state' ) . to . be . false ;
2016-05-16 21:16:40 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-facebook' , '' ) ;
await fillIn ( '#user-facebook' , 'facebook.com/testing' ) ;
await triggerEvent ( '#user-facebook' , 'blur' ) ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-facebook' ) . val ( ) ) . to . be . equal ( 'https://www.facebook.com/testing' ) ;
expect ( find ( '#user-facebook' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'facebook input should be in error state' ) . to . be . false ;
2016-03-03 11:52:27 +03:00
2016-05-16 21:16:40 +03:00
// Testing Twitter input
2016-05-17 21:14:14 +03:00
2017-04-24 15:29:48 +03:00
// loads fixtures and performs transform
expect ( find ( '#user-twitter' ) . val ( ) , 'initial twitter value' )
. to . equal ( 'https://twitter.com/test' ) ;
2016-05-17 21:14:14 +03:00
2017-04-24 15:29:48 +03:00
await triggerEvent ( '#user-twitter' , 'focus' ) ;
await triggerEvent ( '#user-twitter' , 'blur' ) ;
2016-05-17 21:14:14 +03:00
2017-04-24 15:29:48 +03:00
// regression test: we still have a value after the input is
// focused and then blurred without any changes
expect ( find ( '#user-twitter' ) . val ( ) , 'twitter value after blur with no change' )
. to . equal ( 'https://twitter.com/test' ) ;
2016-05-17 21:14:14 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-twitter' , '' ) ;
await fillIn ( '#user-twitter' , ')(*&%^%)' ) ;
await triggerEvent ( '#user-twitter' , 'blur' ) ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-twitter' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'twitter input should be in error state' ) . to . be . true ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-twitter' , '' ) ;
await fillIn ( '#user-twitter' , 'name' ) ;
await triggerEvent ( '#user-twitter' , 'blur' ) ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-twitter' ) . val ( ) ) . to . be . equal ( 'https://twitter.com/name' ) ;
expect ( find ( '#user-twitter' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'twitter input should be in error state' ) . to . be . false ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-twitter' , '' ) ;
await fillIn ( '#user-twitter' , 'http://github.com/user' ) ;
await triggerEvent ( '#user-twitter' , 'blur' ) ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-twitter' ) . val ( ) ) . to . be . equal ( 'https://twitter.com/user' ) ;
expect ( find ( '#user-twitter' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'twitter input should be in error state' ) . to . be . false ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-twitter' , '' ) ;
await fillIn ( '#user-twitter' , 'twitter.com/user' ) ;
await triggerEvent ( '#user-twitter' , 'blur' ) ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-twitter' ) . val ( ) ) . to . be . equal ( 'https://twitter.com/user' ) ;
expect ( find ( '#user-twitter' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'twitter input should be in error state' ) . to . be . false ;
2016-03-03 11:52:27 +03:00
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-website' , '' ) ;
await fillIn ( '#user-bio' , new Array ( 210 ) . join ( 'a' ) ) ;
await triggerEvent ( '#user-bio' , 'blur' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
expect ( find ( '#user-bio' ) . closest ( '.form-group' ) . hasClass ( 'error' ) , 'bio input should be in error state' ) . to . be . true ;
2016-06-14 14:46:24 +03:00
// password reset ------
// button triggers validation
2017-04-24 15:29:48 +03:00
await click ( '.button-change-password' ) ;
expect (
find ( '#user-password-new' ) . closest ( '.form-group' ) . hasClass ( 'error' ) ,
'new password has error class when blank'
) . to . be . true ;
expect (
find ( '#user-password-new' ) . siblings ( '.response' ) . text ( ) ,
'new password error when blank'
) . to . match ( /can't be blank/ ) ;
2016-06-14 14:46:24 +03:00
// typing in inputs clears validation
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-password-new' , 'password' ) ;
await triggerEvent ( '#user-password-new' , 'input' ) ;
expect (
find ( '#user-password-new' ) . closest ( '.form-group' ) . hasClass ( 'error' ) ,
'password validation is visible after typing'
) . to . be . false ;
2016-06-14 14:46:24 +03:00
// enter key triggers action
2017-04-24 15:29:48 +03:00
await keyEvent ( '#user-password-new' , 'keyup' , 13 ) ;
expect (
find ( '#user-new-password-verification' ) . closest ( '.form-group' ) . hasClass ( 'error' ) ,
'confirm password has error class when it doesn\'t match'
) . to . be . true ;
expect (
find ( '#user-new-password-verification' ) . siblings ( '.response' ) . text ( ) ,
'confirm password error when it doesn\'t match'
) . to . match ( /do not match/ ) ;
2016-06-14 14:46:24 +03:00
// submits with correct details
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-new-password-verification' , 'password' ) ;
await click ( '.button-change-password' ) ;
// hits the endpoint
2017-05-18 13:48:37 +03:00
let [ newRequest ] = server . pretender . handledRequests . slice ( - 1 ) ;
params = JSON . parse ( newRequest . requestBody ) ;
2017-04-24 15:29:48 +03:00
2017-05-18 13:48:37 +03:00
expect ( newRequest . url , 'password request URL' )
2017-04-24 15:29:48 +03:00
. to . match ( /\/users\/password/ ) ;
// eslint-disable-next-line camelcase
expect ( params . password [ 0 ] . user _id ) . to . equal ( user . id . toString ( ) ) ;
expect ( params . password [ 0 ] . newPassword ) . to . equal ( 'password' ) ;
expect ( params . password [ 0 ] . ne2Password ) . to . equal ( 'password' ) ;
// clears the fields
expect (
find ( '#user-password-new' ) . val ( ) ,
'password field after submit'
) . to . be . blank ;
expect (
find ( '#user-new-password-verification' ) . val ( ) ,
'password verification field after submit'
) . to . be . blank ;
// displays a notification
expect (
find ( '.gh-notifications .gh-notification' ) . length ,
'password saved notification is displayed'
) . to . equal ( 1 ) ;
2016-06-14 14:46:24 +03:00
} ) ;
} ) ;
2016-09-30 14:43:40 +03:00
describe ( 'using Ghost OAuth' , function ( ) {
beforeEach ( function ( ) {
2016-10-28 16:07:50 +03:00
enableGhostOAuth ( server ) ;
2016-09-30 14:43:40 +03:00
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'doesn\'t show the password reset form' , async function ( ) {
await visit ( ` /team/ ${ admin . slug } ` ) ;
// ensure that the normal form is displayed so we don't get
// false positives
expect (
find ( 'input#user-slug' ) . length ,
'profile form is displayed'
) . to . equal ( 1 ) ;
// check that the password form is hidden
expect (
find ( '#password-reset' ) . length ,
'presence of password reset form'
) . to . equal ( 0 ) ;
expect (
find ( '#user-password-new' ) . length ,
'presence of new password field'
) . to . equal ( 0 ) ;
2016-09-30 14:43:40 +03:00
} ) ;
} ) ;
2016-06-14 14:46:24 +03:00
describe ( 'own user' , function ( ) {
2017-04-24 15:29:48 +03:00
it ( 'requires current password when changing password' , async function ( ) {
await visit ( ` /team/ ${ admin . slug } ` ) ;
2016-06-14 14:46:24 +03:00
// test the "old password" field is validated
2017-04-24 15:29:48 +03:00
await click ( '.button-change-password' ) ;
// old password has error
expect (
find ( '#user-password-old' ) . closest ( '.form-group' ) . hasClass ( 'error' ) ,
'old password has error class when blank'
) . to . be . true ;
expect (
find ( '#user-password-old' ) . siblings ( '.response' ) . text ( ) ,
'old password error when blank'
) . to . match ( /is required/ ) ;
// new password has error
expect (
find ( '#user-password-new' ) . closest ( '.form-group' ) . hasClass ( 'error' ) ,
'new password has error class when blank'
) . to . be . true ;
expect (
find ( '#user-password-new' ) . siblings ( '.response' ) . text ( ) ,
'new password error when blank'
) . to . match ( /can't be blank/ ) ;
2016-06-14 14:46:24 +03:00
// validation is cleared when typing
2017-04-24 15:29:48 +03:00
await fillIn ( '#user-password-old' , 'password' ) ;
await triggerEvent ( '#user-password-old' , 'input' ) ;
expect (
find ( '#user-password-old' ) . closest ( '.form-group' ) . hasClass ( 'error' ) ,
'old password validation is in error state after typing'
) . to . be . false ;
2015-12-07 00:24:06 +03:00
} ) ;
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'redirects to 404 when user does not exist' , async function ( ) {
2016-02-05 15:16:29 +03:00
server . get ( '/users/slug/unknown/' , function ( ) {
2017-01-02 21:50:36 +03:00
return new Response ( 404 , { 'Content-Type' : 'application/json' } , { errors : [ { message : 'User not found.' , errorType : 'NotFoundError' } ] } ) ;
2015-12-07 00:24:06 +03:00
} ) ;
2016-02-05 15:16:29 +03:00
errorOverride ( ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
await visit ( '/team/unknown' ) ;
2015-12-07 00:24:06 +03:00
2017-04-24 15:29:48 +03:00
errorReset ( ) ;
expect ( currentPath ( ) ) . to . equal ( 'error404' ) ;
expect ( currentURL ( ) ) . to . equal ( '/team/unknown' ) ;
2015-12-07 00:24:06 +03:00
} ) ;
} ) ;
2016-09-26 19:03:53 +03:00
describe ( 'when logged in as author' , function ( ) {
2016-11-14 16:16:51 +03:00
let adminRole , authorRole ;
2016-09-26 19:03:53 +03:00
beforeEach ( function ( ) {
adminRole = server . create ( 'role' , { name : 'Administrator' } ) ;
authorRole = server . create ( 'role' , { name : 'Author' } ) ;
2016-11-14 16:16:51 +03:00
server . create ( 'user' , { roles : [ authorRole ] } ) ;
2016-09-26 19:03:53 +03:00
server . get ( '/invites/' , function ( ) {
2017-01-02 21:50:36 +03:00
return new Response ( 403 , { } , {
2016-09-26 19:03:53 +03:00
errors : [ {
errorType : 'NoPermissionError' ,
message : 'You do not have permission to perform this action'
} ]
} ) ;
} ) ;
return authenticateSession ( application ) ;
} ) ;
2017-04-24 15:29:48 +03:00
it ( 'can access the team page' , async function ( ) {
2016-11-14 16:16:51 +03:00
server . create ( 'user' , { roles : [ adminRole ] } ) ;
server . create ( 'invite' , { roles : [ authorRole ] } ) ;
2016-09-26 19:03:53 +03:00
errorOverride ( ) ;
2017-04-24 15:29:48 +03:00
await visit ( '/team' ) ;
2016-09-26 19:03:53 +03:00
2017-04-24 15:29:48 +03:00
errorReset ( ) ;
expect ( currentPath ( ) ) . to . equal ( 'team.index' ) ;
expect ( find ( '.gh-alert' ) . length ) . to . equal ( 0 ) ;
2016-09-26 19:03:53 +03:00
} ) ;
} ) ;
2015-12-07 00:24:06 +03:00
} ) ;