@ -2,11 +2,12 @@ require "rails_helper"
RSpec . describe UsersController , type : :request do
let ( :user ) { FactoryBot . create ( :user ) }
let ( :unauthorised _user ) { FactoryBot . create ( :user ) }
let ( :other _user ) { FactoryBot . create ( :user ) }
let ( :headers ) { { " Accept " = > " text/html " } }
let ( :page ) { Capybara :: Node :: Simple . new ( response . body ) }
let ( :new_value ) { " new test name " }
let ( :params ) { { id : user . id , user : { name : new_value } } }
let ( :new_name ) { " new test name " }
let ( :new_email ) { " new@example.com " }
let ( :params ) { { id : user . id , user : { name : new_name } } }
let ( :notify_client ) { instance_double ( Notifications :: Client ) }
let ( :devise_notify_mailer ) { DeviseNotifyMailer . new }
@ -56,7 +57,7 @@ RSpec.describe UsersController, type: :request do
context " when the reset token is valid " do
let ( :params ) do
{
id : user . id , user : { password : new_valu e , password_confirmation : " something_else " }
id : user . id , user : { password : new_nam e , password_confirmation : " something_else " }
}
end
@ -78,8 +79,8 @@ RSpec.describe UsersController, type: :request do
{
id : user . id ,
user : {
password : new_valu e ,
password_confirmation : new_valu e ,
password : new_nam e ,
password_confirmation : new_nam e ,
reset_password_token : raw ,
} ,
}
@ -109,6 +110,7 @@ RSpec.describe UsersController, type: :request do
end
end
context " when user is signed in as a data provider " do
describe " # show " do
context " when the current user matches the user ID " do
before do
@ -124,7 +126,7 @@ RSpec.describe UsersController, type: :request do
context " when the current user does not matches the user ID " do
before do
sign_in user
get " /users/ #{ unauthorised _user. id } " , headers : headers , params : { }
get " /users/ #{ other _user. id } " , headers : headers , params : { }
end
it " returns not found 404 " do
@ -152,7 +154,7 @@ RSpec.describe UsersController, type: :request do
context " when the current user does not matches the user ID " do
before do
sign_in user
get " /users/ #{ unauthorised _user. id } /edit " , headers : headers , params : { }
get " /users/ #{ other _user. id } /edit " , headers : headers , params : { }
end
it " returns not found 404 " do
@ -180,7 +182,7 @@ RSpec.describe UsersController, type: :request do
context " when the current user does not matches the user ID " do
before do
sign_in user
get " /users/ #{ unauthorised _user. id } /edit " , headers : headers , params : { }
get " /users/ #{ other _user. id } /edit " , headers : headers , params : { }
end
it " returns not found 404 " do
@ -198,7 +200,7 @@ RSpec.describe UsersController, type: :request do
it " updates the user " do
user . reload
expect ( user . name ) . to eq ( new_valu e )
expect ( user . name ) . to eq ( new_nam e )
end
it " tracks who updated the record " do
@ -207,6 +209,16 @@ RSpec.describe UsersController, type: :request do
expect ( whodunnit_actor ) . to be_a ( User )
expect ( whodunnit_actor . id ) . to eq ( user . id )
end
context " when user changes email and dpo " do
let ( :params ) { { id : user . id , user : { name : new_name , email : new_email , is_dpo : " true " } } }
it " allows changing email and dpo " do
user . reload
expect ( user . email ) . to eq ( new_email )
expect ( user . is_data_protection_officer? ) . to be true
end
end
end
context " when the update fails to persist " do
@ -223,22 +235,183 @@ RSpec.describe UsersController, type: :request do
end
context " when the current user does not matches the user ID " do
let ( :params ) { { id : unauthorised_user . id , user : { name : new_value } } }
let ( :params ) { { id : other_user . id , user : { name : new_name } } }
before do
sign_in user
patch " /users/ #{ other_user . id } " , headers : headers , params : params
end
it " returns not found 404 " do
expect ( response ) . to have_http_status ( :not_found )
end
end
context " when we update the user password " do
let ( :params ) do
{
id : user . id , user : { password : new_name , password_confirmation : " something_else " }
}
end
before do
sign_in user
patch " /users/ #{ user . id } " , headers : headers , params : params
end
it " shows an error if passwords don't match " do
expect ( response ) . to have_http_status ( :unprocessable_entity )
expect ( page ) . to have_selector ( " # error-summary-title " )
end
end
end
end
context " when user is signed in as a data coordinator " do
let ( :user ) { FactoryBot . create ( :user , :data_coordinator ) }
let ( :other_user ) { FactoryBot . create ( :user , organisation : user . organisation ) }
describe " # show " do
context " when the current user matches the user ID " do
before do
sign_in user
get " /users/ #{ user . id } " , headers : headers , params : { }
end
it " show the user details " do
expect ( page ) . to have_content ( " Your account " )
end
end
context " when the current user does not matches the user ID " do
before do
sign_in user
get " /users/ #{ other_user . id } " , headers : headers , params : { }
end
context " when the user is part of the same organisation as the current user " do
it " returns 200 " do
expect ( response ) . to have_http_status ( :ok )
end
it " shows the user details page " do
expect ( page ) . to have_content ( " #{ other_user . name } ’s account " )
end
end
context " when the user is not part of the same organisation as the current user " do
let ( :other_user ) { FactoryBot . create ( :user ) }
it " returns not found 404 " do
expect ( response ) . to have_http_status ( :not_found )
end
it " shows the 404 view " do
expect ( page ) . to have_content ( " Page not found " )
end
end
end
end
describe " # edit " do
context " when the current user matches the user ID " do
before do
sign_in user
get " /users/ #{ user . id } /edit " , headers : headers , params : { }
end
it " show the edit personal details page " do
expect ( page ) . to have_content ( " Change your personal details " )
end
end
context " when the current user does not matches the user ID " do
before do
sign_in user
get " /users/ #{ other_user . id } /edit " , headers : headers , params : { }
end
context " when the user is part of the same organisation as the current user " do
it " returns 200 " do
expect ( response ) . to have_http_status ( :ok )
end
it " shows the user details page " do
expect ( page ) . to have_content ( " Change #{ other_user . name } ’s personal details " )
end
end
context " when the user is not part of the same organisation as the current user " do
let ( :other_user ) { FactoryBot . create ( :user ) }
it " returns not found 404 " do
expect ( response ) . to have_http_status ( :not_found )
end
end
end
end
describe " # edit_password " do
context " when the current user matches the user ID " do
before do
sign_in user
patch " /users/ #{ unauthorised_user . id } " , headers : headers , params : params
get " /users/ #{ user . id } /password/edit " , headers : headers , params : { }
end
it " shows the edit password page " do
expect ( page ) . to have_content ( " Change your password " )
end
it " shows the password requirements hint " do
expect ( page ) . to have_css ( " # user-password-hint " )
end
end
context " when the current user does not matches the user ID " do
before do
sign_in user
get " /users/ #{ other_user . id } /password/edit " , headers : headers , params : { }
end
it " returns not found 404 " do
expect ( response ) . to have_http_status ( :not_found )
end
end
end
describe " # update " do
context " when the current user matches the user ID " do
before do
sign_in user
patch " /users/ #{ user . id } " , headers : headers , params : params
end
it " updates the user " do
user . reload
expect ( user . name ) . to eq ( new_name )
end
it " tracks who updated the record " do
user . reload
whodunnit_actor = user . versions . last . actor
expect ( whodunnit_actor ) . to be_a ( User )
expect ( whodunnit_actor . id ) . to eq ( user . id )
end
context " when user changes email and dpo " do
let ( :params ) { { id : user . id , user : { name : new_name , email : new_email , is_dpo : " true " } } }
it " allows changing email and dpo " do
user . reload
expect ( user . email ) . to eq ( new_email )
expect ( user . is_data_protection_officer? ) . to be true
end
end
context " when we update the user password " do
let ( :params ) do
{
id : user . id , user : { password : new_value , password_confirmation : " something_else " }
id : user . id , user : { password : new_nam e , password_confirmation : " something_else " }
}
end
@ -254,6 +427,91 @@ RSpec.describe UsersController, type: :request do
end
end
context " when the current user does not matches the user ID " do
before do
sign_in user
end
context " when the user is part of the same organisation as the current user " do
it " updates the user " do
expect { patch " /users/ #{ other_user . id } " , headers : headers , params : params }
. to change { other_user . reload . name } . from ( other_user . name ) . to ( new_name )
end
it " tracks who updated the record " do
expect { patch " /users/ #{ other_user . id } " , headers : headers , params : params }
. to change { other_user . reload . versions . last . actor & . id } . from ( nil ) . to ( user . id )
end
context " when user changes email and dpo " do
let ( :params ) { { id : other_user . id , user : { name : new_name , email : new_email , is_dpo : " true " } } }
it " allows changing email and dpo " do
patch " /users/ #{ other_user . id } " , headers : headers , params : params
other_user . reload
expect ( other_user . email ) . to eq ( new_email )
expect ( other_user . is_data_protection_officer? ) . to be true
end
end
it " does not bypass sign in for the coordinator " do
patch " /users/ #{ other_user . id } " , headers : headers , params : params
follow_redirect!
expect ( page ) . to have_content ( " #{ other_user . reload . name } ’s account " )
expect ( page ) . to have_content ( other_user . reload . email . to_s )
end
context " when we try to update the user password " do
let ( :params ) do
{
id : user . id , user : { password : new_name , password_confirmation : new_name , name : " new name " }
}
end
it " does not update the password " do
expect { patch " /users/ #{ other_user . id } " , headers : headers , params : params }
. not_to change ( other_user , :encrypted_password )
end
it " does update other values " do
expect { patch " /users/ #{ other_user . id } " , headers : headers , params : params }
. to change { other_user . reload . name } . from ( " Danny Rojas " ) . to ( " new name " )
end
end
end
context " when the current user does not matches the user ID " do
context " when the user is not part of the same organisation as the current user " do
let ( :other_user ) { FactoryBot . create ( :user ) }
let ( :params ) { { id : other_user . id , user : { name : new_name } } }
before do
sign_in user
patch " /users/ #{ other_user . id } " , headers : headers , params : params
end
it " returns not found 404 " do
expect ( response ) . to have_http_status ( :not_found )
end
end
end
end
context " when the update fails to persist " do
before do
sign_in user
allow ( User ) . to receive ( :find_by ) . and_return ( user )
allow ( user ) . to receive ( :update ) . and_return ( false )
patch " /users/ #{ user . id } " , headers : headers , params : params
end
it " show an error " do
expect ( response ) . to have_http_status ( :unprocessable_entity )
end
end
end
end
describe " # create " do
let ( :params ) do
{