Commit 9238c40c130fc613a0c3a9514472172370da8544

Authored by Rodrigo Souto
2 parents 582c3cb3 9b038076

Merge branch 'users-management'

app/controllers/admin/users_controller.rb
... ... @@ -4,12 +4,52 @@ class UsersController < AdminController
4 4  
5 5 protect 'manage_environment_users', :environment
6 6  
  7 + include UsersHelper
  8 +
7 9 def index
  10 + @filter = params[:filter]
  11 + scope = environment.people.no_templates
  12 + if @filter == 'admin_users'
  13 + scope = scope.admins
  14 + elsif @filter == 'activated_users'
  15 + scope = scope.activated
  16 + elsif @filter == 'deactivated_users'
  17 + scope = scope.deactivated
  18 + end
  19 + @q = params[:q]
  20 + @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results]
  21 + end
  22 +
  23 + def set_admin_role
  24 + person = environment.people.find(params[:id])
  25 + environment.add_admin(person)
  26 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  27 + end
  28 +
  29 + def reset_admin_role
  30 + person = environment.people.find(params[:id])
  31 + environment.remove_admin(person)
  32 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  33 + end
  34 +
  35 + def activate
  36 + person = environment.people.find(params[:id])
  37 + person.user.activate
  38 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  39 + end
  40 +
  41 + def deactivate
  42 + person = environment.people.find(params[:id])
  43 + person.user.deactivate
  44 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  45 + end
  46 +
  47 + def download
8 48 respond_to do |format|
9 49 format.html
10 50 format.xml do
11   - @users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person])
12   - send_data @users.to_xml(
  51 + users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person])
  52 + send_data users.to_xml(
13 53 :skip_types => true,
14 54 :only => %w[email login created_at updated_at],
15 55 :include => { :person => {:only => %w[name updated_at created_at address birth_date contact_phone identifier lat lng] } }),
... ... @@ -45,4 +85,10 @@ class UsersController < AdminController
45 85 end
46 86 end
47 87  
  88 + private
  89 +
  90 + def per_page
  91 + 10
  92 + end
  93 +
48 94 end
... ...
app/controllers/application_controller.rb
... ... @@ -174,7 +174,7 @@ class ApplicationController < ActionController::Base
174 174 end
175 175  
176 176 def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={})
177   - @plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) ||
  177 + plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) ||
178 178 fallback_find_by_contents(asset, scope, query, paginate_options, options)
179 179 end
180 180  
... ...
app/helpers/application_helper.rb
... ... @@ -1340,8 +1340,8 @@ module ApplicationHelper
1340 1340 @plugins.dispatch("content_remove_#{action.to_s}", @page).include?(true)
1341 1341 end
1342 1342  
1343   - def template_options(klass, field_name)
1344   - templates = klass.templates(environment)
  1343 + def template_options(kind, field_name)
  1344 + templates = environment.send(kind).templates
1345 1345 return '' if templates.count == 0
1346 1346 return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1
1347 1347  
... ...
app/helpers/users_helper.rb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +module UsersHelper
  2 +
  3 + FILTER_TRANSLATION = {
  4 + 'all_users' => _('All users'),
  5 + 'admin_users' => _('Admin users'),
  6 + 'activated_users' => _('Activated users'),
  7 + 'deactivated_users' => _('Deativated users'),
  8 + }
  9 +
  10 + def filter_selector(filter, float = 'right')
  11 + options = options_for_select(FILTER_TRANSLATION.map {|key, name| [name, key]}, :selected => filter)
  12 + url_params = url_for(params.merge(:filter => 'FILTER'))
  13 + onchange = "document.location.href = '#{url_params}'.replace('FILTER', this.value)"
  14 + select_field = select_tag(:filter, options, :onchange => onchange)
  15 + content_tag('div',
  16 + content_tag('strong', _('Filter')) + ': ' + select_field,
  17 + :class => "environment-users-customize-search"
  18 + )
  19 + end
  20 +
  21 + def filter_title(filter)
  22 + FILTER_TRANSLATION[filter]
  23 + end
  24 +
  25 +end
... ...
app/models/person.rb
... ... @@ -75,6 +75,10 @@ class Person < Profile
75 75 named_scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*'
76 76 named_scope :non_abusers, :joins => "LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'", :conditions => ["tasks.status != 3 OR tasks.id is NULL"], :select => "DISTINCT profiles.*"
77 77  
  78 + named_scope :admins, :joins => [:role_assignments => :role], :conditions => ['roles.key = ?', 'environment_administrator' ]
  79 + named_scope :activated, :joins => :user, :conditions => ['users.activation_code IS NULL AND users.activated_at IS NOT NULL']
  80 + named_scope :deactivated, :joins => :user, :conditions => ['NOT (users.activation_code IS NULL AND users.activated_at IS NOT NULL)']
  81 +
78 82 after_destroy do |person|
79 83 Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy }
80 84 end
... ...
app/models/profile.rb
... ... @@ -78,7 +78,8 @@ class Profile < ActiveRecord::Base
78 78 #FIXME: these will work only if the subclass is already loaded
79 79 named_scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
80 80 named_scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
81   - named_scope :templates, lambda { |environment| { :conditions => {:is_template => true, :environment_id => environment.id} } }
  81 + named_scope :templates, {:conditions => {:is_template => true}}
  82 + named_scope :no_templates, {:conditions => {:is_template => false}}
82 83  
83 84 def members
84 85 scopes = plugins.dispatch_scopes(:organization_members, self)
... ...
app/models/user.rb
... ... @@ -143,6 +143,21 @@ class User &lt; ActiveRecord::Base
143 143 end
144 144 end
145 145  
  146 + # Deactivates the user in the database.
  147 + def deactivate
  148 + return false unless self.person
  149 + self.activated_at = nil
  150 + self.person.visible = false
  151 + begin
  152 + self.person.save! && self.save!
  153 + rescue Exception => exception
  154 + logger.error(exception.to_s)
  155 + false
  156 + else
  157 + true
  158 + end
  159 + end
  160 +
146 161 def activated?
147 162 self.activation_code.nil? && !self.activated_at.nil?
148 163 end
... ...
app/views/account/_signup_form.rhtml
... ... @@ -101,7 +101,7 @@
101 101  
102 102 <%= @plugins.dispatch(:signup_extra_contents).collect { |content| instance_eval(&content) }.join("") %>
103 103  
104   - <%= template_options(Person, 'profile_data') %>
  104 + <%= template_options(:people, 'profile_data') %>
105 105  
106 106 <% unless @terms_of_use.blank? %>
107 107 <div id='terms-of-use-box' class='formfieldline'>
... ...
app/views/enterprise_registration/basic_information.rhtml
... ... @@ -34,7 +34,7 @@
34 34 <% end %>
35 35 <% end %>
36 36  
37   - <%= template_options(Enterprise, 'create_enterprise')%>
  37 + <%= template_options(:enterprises, 'create_enterprise')%>
38 38  
39 39 <% button_bar do %>
40 40 <%= submit_button('next', _('Next'), :cancel => {:profile => current_user.person.identifier, :action=>"enterprises", :controller=>"profile"}) %>
... ...
app/views/memberships/new_community.rhtml
... ... @@ -44,7 +44,7 @@
44 44 </div>
45 45 </div>
46 46  
47   - <%= template_options(Community, 'community')%>
  47 + <%= template_options(:communities, 'community')%>
48 48  
49 49 <%= hidden_field_tag('back_to', @back_to) %>
50 50  
... ...
app/views/templates/index.html.erb
... ... @@ -2,9 +2,9 @@
2 2  
3 3 <%= _('Manage the templates used on creation of profiles') %>
4 4  
5   -<% list_of_templates = [[_('Person') , Person.templates(environment) , 'person' ],
6   - [_('Community') , Community.templates(environment) , 'community' ],
7   - [_('Enterprise'), Enterprise.templates(environment), 'enterprise']] %>
  5 +<% list_of_templates = [[_('Person') , environment.people.templates , 'person' ],
  6 + [_('Community') , environment.communities.templates, 'community' ],
  7 + [_('Enterprise'), environment.enterprises.templates, 'enterprise']] %>
8 8  
9 9 <% list_of_templates.each do |title, templates, kind|%>
10 10 <div class='template-kind'>
... ...
app/views/users/_index_buttons.rhtml 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +<% button_bar do %>
  2 + <%= button :'text-plain', _('User list as [CSV]'), :action => :download, :format => 'csv' %>
  3 + <%= button :'text-html', _('User list as [XML]'), :action => :download, :format => 'xml' %>
  4 + <%= button :send, _('Send e-mail to all users'), :action => 'send_mail' %>
  5 + <%= button :back, _('Back'), :controller => 'admin_panel' %>
  6 +<% end %>
... ...
app/views/users/_users_list.rhtml 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +<div class="environment-users-results-header">
  2 + <div id='environment-users-filter-title'><%= filter_title(@filter) %></div>
  3 + <%= filter_selector(@filter) %>
  4 + <div style="clear: both"></div>
  5 +</div>
  6 +
  7 +<table>
  8 + <colgroup>
  9 + <col width="80%">
  10 + <col width="20%">
  11 + </colgroup>
  12 + <tr>
  13 + <th><%= _('Member') %></th>
  14 + <th><%= _('Actions') %></th>
  15 + </tr>
  16 + <% @collection.each do |p| %>
  17 + <tr title="<%= p.name %>">
  18 + <td><%= link_to_profile p.short_name, p.identifier, :title => p.name %> </td>
  19 + <td class='actions'>
  20 + <div class="members-buttons-cell">
  21 + <% if p.is_admin? %>
  22 + <%= button_without_text :'reset-admin-role', _('Reset admin role'), :action => 'reset_admin_role', :id => p, :q => @q, :filter => @filter %>
  23 + <% else %>
  24 + <%= button_without_text :'set-admin-role', _('Set admin role'), :action => 'set_admin_role', :id => p, :q => @q, :filter => @filter %>
  25 + <% end %>
  26 + <% if !p.user.activated? %>
  27 + <%= button_without_text :'activate-user', _('Activate user'), :action => 'activate', :id => p, :q => @q, :filter => @filter %>
  28 + <% else %>
  29 + <%= button_without_text :'deactivate-user', _('Deactivate user'), :action => 'deactivate', :id => p, :q => @q, :filter => @filter %>
  30 + <% end %>
  31 + </div>
  32 + </td>
  33 + </tr>
  34 + <% end %>
  35 +</table>
  36 +
  37 +<%= pagination_links @collection, {:param_name => 'npage', :page_links => true} %>
... ...
app/views/users/_users_search_form.rhtml 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 + <div class="search-field">
  2 + <span class="formfield">
  3 + <%= text_field_tag 'q', @q, :title => _("Find users") %>
  4 + </span>
  5 + <%= submit_button(:search, _('Search')) %>
  6 + </div>
0 7 \ No newline at end of file
... ...
app/views/users/index.rhtml
1 1 <h1><%= _('Manage users') %></h1>
2 2  
3   -<ul>
4   - <li>
5   - <%= _('Download users list') %>:
6   - <%= link_to '[CSV]', :format => 'csv' %>
7   - <%= link_to '[XML]', :format => 'xml' %>
8   - </li>
9   - <li>
10   - <%= link_to _('Send e-mail to users'), :action => 'send_mail' %>
11   - </li>
12   -</ul>
13   -
14   -<% button_bar do %>
15   - <%= button :back, _('Back to admin panel'), :controller => 'admin_panel' %>
  3 +<% form_tag( { :action => 'index' }, :method => 'get', :class => 'users-search' ) do %>
  4 +<div id="search-users">
  5 + <%= render :partial => 'users_search_form' %>
  6 +</div>
  7 +<div id="users-list">
  8 + <%= render :partial => 'users_list' %>
  9 +</div>
16 10 <% end %>
  11 +
  12 +<%= render :partial => 'index_buttons' %>
17 13 \ No newline at end of file
... ...
public/designs/icons/tango/style.css
... ... @@ -100,6 +100,11 @@
100 100 .icon-user-unknown { background-image: url(Tango/16x16/status/dialog-error.png) }
101 101 .icon-alert { background-image: url(Tango/16x16/status/dialog-warning.png) }
102 102  
  103 +.icon-activate-user { background-image: url(Tango/16x16/emblems/emblem-system.png) }
  104 +.icon-deactivate-user { background-image: url(Tango/16x16/emblems/emblem-unreadable.png) }
  105 +.icon-set-admin-role { background-image: url(mod/16x16/apps/user.png) }
  106 +.icon-reset-admin-role { background-image: url(/images/icons-app/person-icon.png) }
  107 +
103 108 /******************LARGE ICONS********************/
104 109 .image-gallery-item .folder { background-image: url(mod/96x96/places/folder.png) }
105 110 .image-gallery-item .gallery { background-image: url(mod/96x96/mimetypes/image-x-generic.png) }
... ...
public/stylesheets/application.css
... ... @@ -4191,6 +4191,41 @@ h1#agenda-title {
4191 4191 -webkit-border-radius:10px;
4192 4192 }
4193 4193  
  4194 +/* ==> public/stylesheets/controller_environment_users.css <== */
  4195 +.controller-users td.actions {
  4196 + text-align: center;
  4197 +}
  4198 +
  4199 +.controller-users .search-field #q {
  4200 + width: 85%;
  4201 +}
  4202 +
  4203 +.controller-users .search-field input[type='submit'] {
  4204 + float: right;
  4205 +}
  4206 +
  4207 +#environment-users-search form {
  4208 + padding: 10px;
  4209 + margin-bottom: 15px;
  4210 + background-color: #E6E6E6;
  4211 + -moz-border-radius: 5px;
  4212 + -webkit-border-radius: 5px;
  4213 +}
  4214 +
  4215 +.environment-users-results-header {
  4216 + font-size: 0.9em;
  4217 + padding: 6px 0px 0px 0px;
  4218 + margin:0 0 5px 0;
  4219 + border-bottom: 2px dotted #999;
  4220 + text-align: right;
  4221 +}
  4222 +#environment-users-filter-title {
  4223 + font-weight: bold;
  4224 + font-size: 130%;
  4225 + line-height: 35px;
  4226 + float: left;
  4227 +}
  4228 +
4194 4229 /* * * Profile search * * * * * * * */
4195 4230  
4196 4231 #public-profile-search, #profile-search-results form, .profile-search-block form {
... ...
test/fixtures/profiles.yml
... ... @@ -13,12 +13,6 @@ joerandomhacker:
13 13 identifier: joerandomhacker
14 14 environment_id: 1
15 15 user_id: 2
16   -john_and_joe:
17   - id: 3
18   - name: "John and Joe's Production Cooperative"
19   - type: 'Person'
20   - identifier: john_and_joe
21   - environment_id: 1
22 16 ze:
23 17 id: 4
24 18 name: "Zé"
... ...
test/functional/users_controller_test.rb
... ... @@ -6,11 +6,13 @@ class UsersController; def rescue_action(e) raise e end; end
6 6  
7 7 class UsersControllerTest < ActionController::TestCase
8 8  
9   - all_fixtures
10 9 def setup
11 10 @controller = UsersController.new
12 11 @request = ActionController::TestRequest.new
13 12 @response = ActionController::TestResponse.new
  13 +
  14 + admin_user = create_user_with_permission('adminuser', 'manage_environment_users', Environment.default)
  15 + login_as('adminuser')
14 16 end
15 17  
16 18 should 'not access without right permission' do
... ... @@ -21,26 +23,89 @@ class UsersControllerTest &lt; ActionController::TestCase
21 23 end
22 24  
23 25 should 'grant access with right permission' do
24   - admin_user = create_user_with_permission('admin_user', 'manage_environment_users', Environment.default)
25   - login_as('admin_user')
26   -
27 26 get :index
28 27 assert_response :success
29 28 end
30 29  
31   - should 'response as XML to export users' do
32   - admin_user = create_user_with_permission('admin_user', 'manage_environment_users', Environment.default)
33   - login_as('admin_user')
  30 + should 'blank search results include activated and deactivated users' do
  31 + deactivated = create_user('deactivated')
  32 + deactivated.activated_at = nil
  33 + deactivated.person.visible = false
  34 + deactivated.save!
  35 + get :index, :q => ''
  36 + assert_tag :tag => 'div', :attributes => { :id => /users-list/ }, :descendant => {:tag => 'a', :attributes => {:title => /adminuser/}}
  37 + assert_tag :tag => 'div', :attributes => { :id => /users-list/ }, :descendant => {:tag => 'a', :attributes => {:title => /deactivated/}}
  38 + end
  39 +
  40 + should 'blank search include all users' do
  41 + (1..5).each {|i|
  42 + u = create_user('user'+i.to_s)
  43 + }
  44 + get :index, :q => '' # blank search
  45 + assert_tag :tag => 'div', :attributes => { :id => /users-list/ }, :descendant => {:tag => 'a', :attributes => {:title => /adminuser/}}
  46 + (1..5).each {|i|
  47 + u = 'user'+i.to_s
  48 + assert_tag :tag => 'div', :attributes => { :id => /users-list/ }, :descendant => {:tag => 'a', :attributes => {:title => u}}
  49 + }
  50 + end
  51 +
  52 + should 'search not include all users' do
  53 + (1..5).each {|i|
  54 + u = create_user('user'+i.to_s)
  55 + }
  56 + get :index, :q => 'er5' # search
  57 + assert_tag :tag => 'div', :attributes => { :id => /users-list/ }, :descendant => {:tag => 'a', :attributes => {:title => /user5/}}
  58 + (1..4).each {|i|
  59 + u = 'user'+i.to_s
  60 + assert_no_tag :tag => 'div', :attributes => { :id => /users-list/ }, :descendant => {:tag => 'a', :attributes => {:title => u}}
  61 + }
  62 + end
  63 +
  64 + should 'set admin role' do
  65 + person = create_user.person
  66 + assert_equal false, person.is_admin?
  67 + post :set_admin_role, :id => person.id, :q => ''
  68 + person.reload
  69 + assert person.is_admin?
  70 + end
34 71  
35   - get :index, :format => 'xml'
  72 + should 'reset admin role' do
  73 + environment = Environment.default
  74 + person = create_user.person
  75 + environment.add_admin(person)
  76 + assert person.is_admin?
  77 +
  78 + post :reset_admin_role, :id => person.id, :q => ''
  79 + person.reload
  80 + assert !person.is_admin?
  81 + end
  82 +
  83 + should 'activate user' do
  84 + u = create_user()
  85 + assert_equal false, u.activated?
  86 + post :activate, :id => u.person.id, :q => ''
  87 + u.reload
  88 + assert u.activated?
  89 + end
  90 +
  91 + should 'deactivate user' do
  92 + u = create_user()
  93 + u.activated_at = Time.now.utc
  94 + u.activation_code = nil
  95 + u.person.visible = true
  96 + assert u.activated?
  97 + post :deactivate, :id => u.person.id, :q => ''
  98 + u.reload
  99 + assert_equal false, u.activated?
  100 + end
  101 +
  102 + should 'response as XML to export users' do
  103 + get :download, :format => 'xml'
36 104 assert_equal 'text/xml', @response.content_type
37 105 end
38 106  
39 107 should 'response as CSV to export users' do
40   - admin_user = create_user_with_permission('admin_user', 'manage_environment_users', Environment.default)
41   - login_as('admin_user')
42   -
43   - get :index, :format => 'csv'
  108 + get :download, :format => 'csv'
44 109 assert_equal 'text/csv', @response.content_type
45 110 assert_equal 'name;email', @response.body.split("\n")[0]
46 111 end
... ...
test/unit/application_helper_test.rb
... ... @@ -256,7 +256,7 @@ class ApplicationHelperTest &lt; ActiveSupport::TestCase
256 256  
257 257 should 'not display templates options when there is no template' do
258 258 self.stubs(:environment).returns(Environment.default)
259   - [Person, Community, Enterprise].each do |klass|
  259 + [:people, :communities, :enterprises].each do |klass|
260 260 assert_equal '', template_options(klass, 'profile_data')
261 261 end
262 262 end
... ...
test/unit/person_test.rb
... ... @@ -1335,4 +1335,50 @@ class PersonTest &lt; ActiveSupport::TestCase
1335 1335 assert_includes non_abusers, not_abuser
1336 1336 end
1337 1337  
  1338 + should 'admins named_scope return persons who are admin users' do
  1339 + Person.delete_all
  1340 + e = Environment.default
  1341 + admins = []
  1342 + (1..5).each {|i|
  1343 + u = create_user('user'+i.to_s)
  1344 + e.add_admin(u.person)
  1345 + admins << u.person
  1346 + }
  1347 + (6..10).each {|i|
  1348 + u = create_user('user'+i.to_s)
  1349 + }
  1350 + assert_equal admins, Person.admins
  1351 + end
  1352 +
  1353 + should 'activated named_scope return persons who are activated users' do
  1354 + Person.delete_all
  1355 + e = Environment.default
  1356 + activated = []
  1357 + (1..5).each {|i|
  1358 + u = create_user('user'+i.to_s)
  1359 + u.activate
  1360 + activated << u.person
  1361 + }
  1362 + (6..10).each {|i|
  1363 + u = create_user('user'+i.to_s)
  1364 + u.deactivate
  1365 + }
  1366 + assert_equal activated, Person.activated
  1367 + end
  1368 +
  1369 + should 'deactivated named_scope return persons who are deactivated users' do
  1370 + Person.delete_all
  1371 + e = Environment.default
  1372 + deactivated = []
  1373 + (1..5).each {|i|
  1374 + u = create_user('user'+i.to_s)
  1375 + u.deactivate
  1376 + deactivated << u.person
  1377 + }
  1378 + (6..10).each {|i|
  1379 + u = create_user('user'+i.to_s)
  1380 + u.activate
  1381 + }
  1382 + assert_equal deactivated, Person.deactivated
  1383 + end
1338 1384 end
... ...
test/unit/profile_test.rb
... ... @@ -1370,13 +1370,27 @@ class ProfileTest &lt; ActiveSupport::TestCase
1370 1370 end
1371 1371  
1372 1372 should 'return a list of templates' do
  1373 + environment = Environment.default
1373 1374 t1 = fast_create(Profile, :is_template => true)
1374 1375 t2 = fast_create(Profile, :is_template => true)
1375 1376 profile = fast_create(Profile)
1376 1377  
1377   - assert_includes Profile.templates(Environment.default), t1
1378   - assert_includes Profile.templates(Environment.default), t2
1379   - assert_not_includes Profile.templates(Environment.default), profile
  1378 + assert_includes environment.profiles.templates, t1
  1379 + assert_includes environment.profiles.templates, t2
  1380 + assert_not_includes environment.profiles.templates, profile
  1381 + end
  1382 +
  1383 + should 'return a list of profiles that are not templates' do
  1384 + environment = Environment.default
  1385 + p1 = fast_create(Profile, :is_template => false)
  1386 + p2 = fast_create(Profile, :is_template => false)
  1387 + t1 = fast_create(Profile, :is_template => true)
  1388 + t2 = fast_create(Profile, :is_template => true)
  1389 +
  1390 + assert_includes environment.profiles.no_templates, p1
  1391 + assert_includes environment.profiles.no_templates, p2
  1392 + assert_not_includes environment.profiles.no_templates, t1
  1393 + assert_not_includes environment.profiles.no_templates, t2
1380 1394 end
1381 1395  
1382 1396 should 'not crash on a profile update with a destroyed template' do
... ...
test/unit/user_test.rb
... ... @@ -518,6 +518,22 @@ class UserTest &lt; ActiveSupport::TestCase
518 518 end
519 519 end
520 520  
  521 + should 'deactivate an user' do
  522 + user = new_user
  523 + user.activate
  524 + assert user.deactivate
  525 + assert_nil user.activated_at
  526 + assert !user.person.visible
  527 + end
  528 +
  529 + should 'return if the user is deactivated' do
  530 + user = new_user
  531 + user.activate
  532 + assert user.activated?
  533 + user.deactivate
  534 + assert !user.activated?
  535 + end
  536 +
521 537 should 'activate right after creation when confirmation is not required' do
522 538 e = Environment.default
523 539 e.enable('skip_new_user_email_confirmation')
... ...