-
<%= link_to user.name, admin_user_path(user) %>
-
@<%= user.username %>
+
+
+
+
<%= link_to user.name, admin_user_path(user), class: "color-base-80" %>
+ <%= link_to "@#{user.username}", admin_user_path(user), class: "color-base-60" %>
-
standing info
-
role info
+
+ <% if user.suspended? %>
+ Suspended
+ <% elsif user.warned? %>
+ Warned
+ <% elsif user.comment_suspended? %>
+ Comment suspended
+ <% elsif user.trusted? %>
+ Trusted
+ <% else %>
+ Good standing
+ <% end %>
+
+
+
+ <%= cascading_high_level_roles(user) %>
+
+
- Last activity
- - placeholder
+ - <%= format_last_activity_timestamp(user.last_activity) %>
- Joined on
- <%= user.registered_at.strftime("%d %b, %Y") %>
-
Orgs info
+
+ <% if user.organization_memberships.any? %>
+ <% user.organization_memberships.includes([:organization]).each do |org_membership| %>
+
+
+
+ <% end %>
+ <% end %>
+
@@ -54,9 +79,51 @@
- <% @users.each do |user| %>
+ <% @users.includes([:organization_memberships]).each do |user| %>
- | <%= link_to user.name, admin_user_path(user) %> |
+
+
+
+
+
+ <%= link_to user.name, admin_user_path(user), class: "color-base-80" %>
+ <%= link_to "@#{user.username}", admin_user_path(user), class: "color-base-60" %>
+
+ <%= cascading_high_level_roles(user) %>
+
+
+
+ |
+
+ <% if user.suspended? %>
+ Suspended
+ <% elsif user.warned? %>
+ Warned
+ <% elsif user.comment_suspended? %>
+ Comment suspended
+ <% elsif user.trusted? %>
+ Trusted
+ <% else %>
+ Good standing
+ <% end %>
+ |
+
+ <%= format_last_activity_timestamp(user.last_activity) %>
+
+ <%= user.registered_at.strftime("%d %b, %Y") %>
+
+ |
+
+ <% if user.organization_memberships.any? %>
+ <% user.organization_memberships.includes([:organization]).each do |org_membership| %>
+
+
+
+ <% end %>
+ <% else %>
+ -
+ <% end %>
+ |
<% end %>
diff --git a/cypress/integration/seededFlows/adminFlows/users/userIndexView.spec.js b/cypress/integration/seededFlows/adminFlows/users/userIndexView.spec.js
index 726a580c6..85dd3d248 100644
--- a/cypress/integration/seededFlows/adminFlows/users/userIndexView.spec.js
+++ b/cypress/integration/seededFlows/adminFlows/users/userIndexView.spec.js
@@ -28,7 +28,7 @@ describe('User index view', () => {
cy.findByRole('button', { name: 'Search' }).click();
- // Coreect search result should appear
+ // Correct search result should appear
cy.findByRole('heading', { name: 'Admin McAdmin' }).should('exist');
});
@@ -41,11 +41,9 @@ describe('User index view', () => {
cy.findByRole('combobox', { name: 'User role' }).select('super_admin');
cy.findByRole('button', { name: 'Filter' }).click();
- // Search results should include these two results
+ // Filter results should include these two results
cy.findByRole('heading', { name: 'Admin McAdmin' }).should('exist');
- cy.findByRole('heading', { name: 'Apple Auth Admin User' }).should(
- 'exist',
- );
+ cy.findAllByText('Apple Auth Admin User').should('exist');
});
it('Prevents both search and filter widgets being visible at the same time', () => {
@@ -65,15 +63,20 @@ describe('User index view', () => {
.should('have.attr', 'aria-expanded', 'true');
cy.findByRole('button', { name: 'Search' }).should('exist');
- // verify the filter options have now closed
+ // Verify the filter options have now closed
cy.get('@filterButton').should('have.attr', 'aria-expanded', 'false');
cy.findByRole('combobox').should('not.exist');
- // now re-click filter options and check search options have closed
+ // Now re-click filter options and check search options have closed
cy.get('@filterButton').click();
cy.get('@searchButton').should('have.attr', 'aria-expanded', 'false');
cy.findByRole('button', { name: 'Search' }).should('not.exist');
});
+
+ it(`Clicks through to the Member Detail View`, () => {
+ cy.findAllByRole('link', { name: 'Admin McAdmin' }).first().click();
+ cy.url().should('contain', '/admin/users/1');
+ });
});
});
@@ -97,6 +100,9 @@ describe('User index view', () => {
cy.findByRole('button', { name: 'Search' }).click();
+ // Correct search result should appear
+ cy.findByRole('heading', { name: 'Admin McAdmin' }).should('exist');
+
// The table headers consistitute a row, plus one result
cy.findAllByRole('row').should('have.length', 2);
});
@@ -105,9 +111,18 @@ describe('User index view', () => {
cy.findByRole('combobox', { name: 'User role' }).select('super_admin');
cy.findByRole('button', { name: 'Filter' }).click();
+ // Filter results should include these two results
+ cy.findByRole('heading', { name: 'Admin McAdmin' }).should('exist');
+ cy.findAllByText('Apple Auth Admin User').should('exist');
+
// Table header, 'normal' admin and apple auth admin
cy.findAllByRole('row').should('have.length', 3);
});
+
+ it(`Clicks through to the Member Detail View`, () => {
+ cy.findAllByRole('link', { name: 'Admin McAdmin' }).first().click();
+ cy.url().should('contain', '/admin/users/1');
+ });
});
});
});
diff --git a/spec/helpers/admin/users_helper_spec.rb b/spec/helpers/admin/users_helper_spec.rb
new file mode 100644
index 000000000..aa0bd8a61
--- /dev/null
+++ b/spec/helpers/admin/users_helper_spec.rb
@@ -0,0 +1,52 @@
+require "rails_helper"
+
+describe Admin::UsersHelper do
+ describe "#format_last_activity_timestamp" do
+ it "renders the proper 'Last activity' date for a user that was active today" do
+ timestamp = Time.zone.today
+ date = timestamp.strftime("%d %b")
+ formatted_date = helper.format_last_activity_timestamp(timestamp)
+ expect(formatted_date).to eq "Today, #{date}"
+ end
+
+ it "renders the proper 'Last activity' date for a user that was active yesterday" do
+ timestamp = Date.yesterday
+ date = timestamp.strftime("%d %b")
+ formatted_date = helper.format_last_activity_timestamp(timestamp)
+ expect(formatted_date).to eq "Yesterday, #{date}"
+ end
+
+ it "renders the proper 'Last activity' date for a user that was active recently" do
+ timestamp = 11.days.ago
+ date = timestamp.strftime("%d %b, %Y")
+ formatted_date = helper.format_last_activity_timestamp(timestamp)
+ expect(formatted_date).to eq date.to_s
+ end
+ end
+
+ describe "#cascading_high_level_roles" do
+ it "renders the proper role for a Super Admin" do
+ super_admin = create(:user, :super_admin)
+ role = helper.cascading_high_level_roles(super_admin)
+ expect(role).to eq "Super Admin"
+ end
+
+ it "renders the proper role for an Admin" do
+ admin = create(:user, :admin)
+ role = helper.cascading_high_level_roles(admin)
+ expect(role).to eq "Admin"
+ end
+
+ it "renders the proper role for a Resource Admin" do
+ resource_admin = create(:user, :single_resource_admin)
+ role = helper.cascading_high_level_roles(resource_admin)
+ expect(role).to eq "Resource Admin"
+ end
+
+ it "renders the proper role for a user that isn't a Super Admin, Admin, or Resource Admin" do
+ user = create(:user)
+ role = helper.cascading_high_level_roles(user)
+ expect(role).to be_nil
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 4d8b5d2c7..55fe1bae3 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -798,4 +798,13 @@ RSpec.describe User, type: :model do
expect(user.profile).to respond_to(:location)
end
end
+
+ describe "#last_activity" do
+ it "determines a user's last activity" do
+ Timecop.freeze do
+ user = create(:user, last_comment_at: 1.minute.ago)
+ expect(user.last_activity).to eq(Time.zone.now)
+ end
+ end
+ end
end