Merge pull request #5063 from consul/refactor_layout_components
Make it easier to customize admin and main layouts
This commit is contained in:
@@ -31,14 +31,6 @@ $table-header: #ecf1f6;
|
||||
.admin {
|
||||
@include admin-layout;
|
||||
|
||||
> header {
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
> * {
|
||||
@include full-width-background($adjust-margin: false, $adjust-padding: true);
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 100;
|
||||
margin-bottom: $line-height;
|
||||
@@ -60,86 +52,6 @@ $table-header: #ecf1f6;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.top-links {
|
||||
|
||||
a {
|
||||
line-height: rem-calc($line-height * 1.5);
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
height: auto;
|
||||
padding-top: $line-height / 2;
|
||||
|
||||
@include breakpoint(small only) {
|
||||
|
||||
.top-bar-left ul {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.top-bar-right {
|
||||
|
||||
> ul {
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.submenu {
|
||||
position: initial;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
[class^="icon-"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
[class^="icon-"] {
|
||||
font-size: $base-font-size;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: $line-height / 2;
|
||||
margin-bottom: 0;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
small {
|
||||
color: inherit;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
display: inline-block;
|
||||
font-family: "Lato" !important;
|
||||
font-size: rem-calc(24);
|
||||
font-weight: lighter;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar .menu > li {
|
||||
|
||||
@include breakpoint(medium) {
|
||||
height: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
color: inherit;
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
}
|
||||
|
||||
.notifications.unread-notifications::after {
|
||||
color: $admin-color;
|
||||
}
|
||||
|
||||
89
app/assets/stylesheets/layout/admin_header.scss
Normal file
89
app/assets/stylesheets/layout/admin_header.scss
Normal file
@@ -0,0 +1,89 @@
|
||||
.admin {
|
||||
> header {
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
> * {
|
||||
@include full-width-background($adjust-margin: false, $adjust-padding: true);
|
||||
}
|
||||
}
|
||||
|
||||
.top-links {
|
||||
|
||||
a {
|
||||
line-height: rem-calc($line-height * 1.5);
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
height: auto;
|
||||
padding-top: $line-height / 2;
|
||||
|
||||
@include breakpoint(small only) {
|
||||
|
||||
.top-bar-left ul {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.top-bar-right {
|
||||
|
||||
> ul {
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.submenu {
|
||||
position: initial;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
[class^="icon-"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
[class^="icon-"] {
|
||||
font-size: $base-font-size;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: $line-height / 2;
|
||||
margin-bottom: 0;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
small {
|
||||
color: inherit;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
display: inline-block;
|
||||
font-family: "Lato" !important;
|
||||
font-size: rem-calc(24);
|
||||
font-weight: lighter;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar .menu > li {
|
||||
|
||||
@include breakpoint(medium) {
|
||||
height: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
color: inherit;
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
}
|
||||
}
|
||||
5
app/components/layout/account_menu_component.html.erb
Normal file
5
app/components/layout/account_menu_component.html.erb
Normal file
@@ -0,0 +1,5 @@
|
||||
<ul class="menu" data-responsive-menu="medium-dropdown">
|
||||
<%= render Layout::AdminLoginItemsComponent.new(user) %>
|
||||
<%= render Layout::NotificationItemComponent.new(user) %>
|
||||
<%= render Layout::LoginItemsComponent.new(user) %>
|
||||
</ul>
|
||||
7
app/components/layout/account_menu_component.rb
Normal file
7
app/components/layout/account_menu_component.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
class Layout::AccountMenuComponent < ApplicationComponent
|
||||
attr_reader :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
end
|
||||
39
app/components/layout/admin_header_component.html.erb
Normal file
39
app/components/layout/admin_header_component.html.erb
Normal file
@@ -0,0 +1,39 @@
|
||||
<header class="header">
|
||||
<div class="top-links">
|
||||
<%= render "shared/locale_switcher" %>
|
||||
|
||||
<%= link_to root_path do %>
|
||||
<%= t("admin.dashboard.index.back", org: setting["org_name"]) %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="expanded row admin-top-bar">
|
||||
<% if show_account_menu? %>
|
||||
<div class="title-bar" data-responsive-toggle="responsive_menu" data-hide-for="medium">
|
||||
<button class="menu-button" type="button" data-toggle="responsive_menu">
|
||||
<span class="menu-icon"></span>
|
||||
<span class="title-bar-title"><%= t("application.menu") %></span>
|
||||
</button>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<h1>
|
||||
<%= link_to namespace_path do %>
|
||||
<%= setting["org_name"] %>
|
||||
<br><small><%= namespaced_header_title %></small>
|
||||
<% end %>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<% if show_account_menu? %>
|
||||
<div id="responsive_menu">
|
||||
<div class="top-bar-right">
|
||||
<%= render Layout::AccountMenuComponent.new(user) %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
32
app/components/layout/admin_header_component.rb
Normal file
32
app/components/layout/admin_header_component.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
class Layout::AdminHeaderComponent < ApplicationComponent
|
||||
attr_reader :user
|
||||
delegate :namespace, :namespaced_root_path, :show_admin_menu?, to: :helpers
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def namespaced_header_title
|
||||
if namespace == "moderation/budgets"
|
||||
t("moderation.header.title")
|
||||
elsif namespace == "management"
|
||||
t("management.dashboard.index.title")
|
||||
else
|
||||
t("#{namespace}.header.title")
|
||||
end
|
||||
end
|
||||
|
||||
def namespace_path
|
||||
if namespace == "officing"
|
||||
"#"
|
||||
else
|
||||
namespaced_root_path
|
||||
end
|
||||
end
|
||||
|
||||
def show_account_menu?
|
||||
show_admin_menu?(user) || namespace != "management"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<li class="has-submenu">
|
||||
<%= link_to t("layouts.header.administration_menu"), "#", rel: "nofollow", class: "hide-for-small-only" %>
|
||||
<%= link_list(*admin_links, class: "submenu menu", data: { submenu: true }) %>
|
||||
</li>
|
||||
49
app/components/layout/admin_login_items_component.rb
Normal file
49
app/components/layout/admin_login_items_component.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
class Layout::AdminLoginItemsComponent < ApplicationComponent
|
||||
attr_reader :user
|
||||
delegate :link_list, :show_admin_menu?, to: :helpers
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
||||
def render?
|
||||
show_admin_menu?(user)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def admin_links
|
||||
[
|
||||
(admin_link if user.administrator?),
|
||||
(moderation_link if user.administrator? || user.moderator?),
|
||||
(valuation_link if feature?(:budgets) && (user.administrator? || user.valuator?)),
|
||||
(management_link if user.administrator? || user.manager?),
|
||||
(officing_link if user.poll_officer? && Poll.current.any?),
|
||||
(sdg_management_link if feature?(:sdg) && (user.administrator? || user.sdg_manager?))
|
||||
]
|
||||
end
|
||||
|
||||
def admin_link
|
||||
[t("layouts.header.administration"), admin_root_path]
|
||||
end
|
||||
|
||||
def moderation_link
|
||||
[t("layouts.header.moderation"), moderation_root_path]
|
||||
end
|
||||
|
||||
def valuation_link
|
||||
[t("layouts.header.valuation"), valuation_root_path]
|
||||
end
|
||||
|
||||
def management_link
|
||||
[t("layouts.header.management"), management_sign_in_path]
|
||||
end
|
||||
|
||||
def officing_link
|
||||
[t("layouts.header.officing"), officing_root_path]
|
||||
end
|
||||
|
||||
def sdg_management_link
|
||||
[t("sdg_management.header.title"), sdg_management_root_path]
|
||||
end
|
||||
end
|
||||
2
app/components/layout/footer_component.rb
Normal file
2
app/components/layout/footer_component.rb
Normal file
@@ -0,0 +1,2 @@
|
||||
class Layout::FooterComponent < ApplicationComponent
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
<% if user_signed_in? %>
|
||||
<% if user %>
|
||||
<li>
|
||||
<%= layout_menu_link_to t("layouts.header.my_activity_link"),
|
||||
user_path(current_user),
|
||||
user_path(user),
|
||||
controller_name == "users",
|
||||
rel: "nofollow",
|
||||
title: t("shared.go_to_page") +
|
||||
8
app/components/layout/login_items_component.rb
Normal file
8
app/components/layout/login_items_component.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class Layout::LoginItemsComponent < ApplicationComponent
|
||||
attr_reader :user
|
||||
delegate :layout_menu_link_to, to: :helpers
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
end
|
||||
3
app/components/layout/subnavigation_component.rb
Normal file
3
app/components/layout/subnavigation_component.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
class Layout::SubnavigationComponent < ApplicationComponent
|
||||
delegate :content_block, :layout_menu_link_to, to: :helpers
|
||||
end
|
||||
@@ -3,16 +3,6 @@ module AdminHelper
|
||||
"/#{namespace}"
|
||||
end
|
||||
|
||||
def namespaced_header_title
|
||||
if namespace == "moderation/budgets"
|
||||
t("moderation.header.title")
|
||||
elsif namespace == "management"
|
||||
t("management.dashboard.index.title")
|
||||
else
|
||||
t("#{namespace}.header.title")
|
||||
end
|
||||
end
|
||||
|
||||
def official_level_options
|
||||
options = [["", 0]]
|
||||
(1..5).each do |i|
|
||||
|
||||
@@ -35,34 +35,10 @@ module UsersHelper
|
||||
end
|
||||
end
|
||||
|
||||
def current_administrator?
|
||||
current_user&.administrator?
|
||||
end
|
||||
|
||||
def current_moderator?
|
||||
current_user&.moderator?
|
||||
end
|
||||
|
||||
def current_valuator?
|
||||
current_user&.valuator?
|
||||
end
|
||||
|
||||
def current_manager?
|
||||
current_user&.manager?
|
||||
end
|
||||
|
||||
def current_sdg_manager?
|
||||
current_user&.sdg_manager?
|
||||
end
|
||||
|
||||
def current_poll_officer?
|
||||
current_user&.poll_officer?
|
||||
end
|
||||
|
||||
def show_admin_menu?(user = nil)
|
||||
def show_admin_menu?(user)
|
||||
unless namespace == "officing"
|
||||
current_administrator? || current_moderator? || current_valuator? || current_manager? ||
|
||||
user&.administrator? || current_poll_officer? || current_sdg_manager?
|
||||
user&.administrator? || user&.moderator? || user&.valuator? ||
|
||||
(user&.manager? && namespace != "management") || user&.poll_officer? || user&.sdg_manager?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<header class="header">
|
||||
<div class="top-links">
|
||||
<%= render "shared/locale_switcher" %>
|
||||
|
||||
<%= link_to root_path do %>
|
||||
<%= t("admin.dashboard.index.back", org: setting["org_name"]) %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="expanded row admin-top-bar">
|
||||
<div class="title-bar" data-responsive-toggle="responsive_menu" data-hide-for="medium">
|
||||
<button class="menu-button" type="button" data-toggle="responsive_menu">
|
||||
<span class="menu-icon"></span>
|
||||
<span class="title-bar-title"><%= t("application.menu") %></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="top-bar">
|
||||
<div class="top-bar-left">
|
||||
<% if namespace == "officing" %>
|
||||
<h1>
|
||||
<%= link_to "#" do %>
|
||||
<%= setting["org_name"] %>
|
||||
<br><small><%= namespaced_header_title %></small>
|
||||
<% end %>
|
||||
</h1>
|
||||
<% else %>
|
||||
<h1>
|
||||
<%= link_to namespaced_root_path do %>
|
||||
<%= setting["org_name"] %>
|
||||
<br><small><%= namespaced_header_title %></small>
|
||||
<% end %>
|
||||
</h1>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if show_admin_menu?(current_user) || namespace != "management" %>
|
||||
<div id="responsive_menu">
|
||||
<div class="top-bar-right">
|
||||
<ul class="menu" data-responsive-menu="medium-dropdown">
|
||||
<%= render "shared/admin_login_items", current_user: current_user %>
|
||||
<%= render "layouts/notification_item", current_user: current_user %>
|
||||
<%= render "devise/menu/login_items", current_user: current_user %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -26,15 +26,11 @@
|
||||
|
||||
<div id="responsive-menu">
|
||||
<div class="top-bar-right">
|
||||
<ul class="menu" data-responsive-menu="medium-dropdown">
|
||||
<%= render "shared/admin_login_items" %>
|
||||
<%= render "layouts/notification_item" %>
|
||||
<%= render "devise/menu/login_items" %>
|
||||
</ul>
|
||||
<%= render Layout::AccountMenuComponent.new(current_user) %>
|
||||
|
||||
<div class="show-for-small-only">
|
||||
<div class="subnavigation subnavigation-with-top-links">
|
||||
<%= render "shared/subnavigation" %>
|
||||
<%= render Layout::SubnavigationComponent.new %>
|
||||
<%= render "shared/top_links" %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,7 +40,7 @@
|
||||
|
||||
<div id="navigation_bar" class="subnavigation">
|
||||
<div class="hide-for-small-only">
|
||||
<%= render "shared/subnavigation" %>
|
||||
<%= render Layout::SubnavigationComponent.new %>
|
||||
</div>
|
||||
|
||||
<%= yield :header_addon %>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<%= render Layout::NotificationItemComponent.new(current_user) %>
|
||||
@@ -6,7 +6,7 @@
|
||||
</head>
|
||||
|
||||
<body class="admin">
|
||||
<%= render "layouts/admin_header" %>
|
||||
<%= render Layout::AdminHeaderComponent.new(current_user) %>
|
||||
|
||||
<div class="menu-and-content">
|
||||
<%= check_box_tag :show_menu, nil, false, role: "switch" %>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<%= yield %>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<%= render "layouts/footer" %>
|
||||
<%= render Layout::FooterComponent.new %>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<%= render "layouts/footer" %>
|
||||
<%= render Layout::FooterComponent.new %>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</head>
|
||||
|
||||
<body class="admin">
|
||||
<%= render "layouts/admin_header", current_user: manager_logged_in %>
|
||||
<%= render Layout::AdminHeaderComponent.new(manager_logged_in) %>
|
||||
|
||||
<div class="menu-and-content">
|
||||
<%= check_box_tag :show_menu, nil, false, role: "switch" %>
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
<% if show_admin_menu?(current_user) %>
|
||||
<li class="has-submenu">
|
||||
<%= link_to t("layouts.header.administration_menu"), "#", rel: "nofollow", class: "hide-for-small-only" %>
|
||||
<ul class="submenu menu" data-submenu>
|
||||
<% if current_user.administrator? %>
|
||||
<li>
|
||||
<%= link_to t("layouts.header.administration"), admin_root_path %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% if current_user.administrator? || current_user.moderator? %>
|
||||
<li>
|
||||
<%= link_to t("layouts.header.moderation"), moderation_root_path %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% if feature?(:budgets) &&
|
||||
(current_user.administrator? || current_user.valuator?) %>
|
||||
<li>
|
||||
<%= link_to t("layouts.header.valuation"), valuation_root_path %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% if current_user.administrator? || current_user.manager? %>
|
||||
<li>
|
||||
<%= link_to t("layouts.header.management"), management_sign_in_path %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% if current_user.poll_officer? && Poll.current.any? %>
|
||||
<li>
|
||||
<%= link_to t("layouts.header.officing"), officing_root_path %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% if feature?(:sdg) && (current_user.administrator? || current_user.sdg_manager?) %>
|
||||
<li>
|
||||
<%= link_to t("sdg_management.header.title"), sdg_management_root_path %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</li>
|
||||
<% end %>
|
||||
@@ -17,7 +17,7 @@
|
||||
<h2 class="inline-block">
|
||||
<%= avatar_image(@user, seed: @user.id, size: 60) %>
|
||||
<%= @user.name %>
|
||||
<% if current_administrator? %>
|
||||
<% if current_user&.administrator? %>
|
||||
<small><%= @user.email %></small>
|
||||
<% end %>
|
||||
</h2>
|
||||
|
||||
38
spec/components/layout/admin_header_component_spec.rb
Normal file
38
spec/components/layout/admin_header_component_spec.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Layout::AdminHeaderComponent do
|
||||
let(:user) { create(:user) }
|
||||
before { Setting["org_name"] = "CONSUL" }
|
||||
|
||||
around do |example|
|
||||
with_request_url("/") { example.run }
|
||||
end
|
||||
|
||||
context "management section", controller: Management::BaseController do
|
||||
it "shows the menu button and menu for administrators" do
|
||||
create(:administrator, user: user)
|
||||
|
||||
render_inline Layout::AdminHeaderComponent.new(user)
|
||||
|
||||
expect(page).to have_link "Go back to CONSUL"
|
||||
expect(page).to have_link "You don't have new notifications"
|
||||
expect(page).to have_link "My content"
|
||||
expect(page).to have_link "My account"
|
||||
expect(page).to have_link "Sign out"
|
||||
expect(page).to have_css "[data-toggle]"
|
||||
end
|
||||
|
||||
it "does not show the menu button and menu for managers" do
|
||||
create(:manager, user: user)
|
||||
|
||||
render_inline Layout::AdminHeaderComponent.new(user)
|
||||
|
||||
expect(page).to have_link "Go back to CONSUL"
|
||||
expect(page).not_to have_content "You don't have new notifications"
|
||||
expect(page).not_to have_content "My content"
|
||||
expect(page).not_to have_content "My account"
|
||||
expect(page).not_to have_content "Sign out"
|
||||
expect(page).not_to have_css "[data-toggle]"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,34 +2,18 @@ require "rails_helper"
|
||||
|
||||
describe "Management" do
|
||||
let(:user) { create(:user) }
|
||||
before { Setting["org_name"] = "CONSUL" }
|
||||
|
||||
scenario "Should show admin menu if logged user is admin" do
|
||||
create(:administrator, user: user)
|
||||
login_as(user)
|
||||
|
||||
visit root_path
|
||||
click_link "Menu"
|
||||
click_link "Management"
|
||||
|
||||
expect(page).to have_link "Go back to CONSUL"
|
||||
|
||||
expect(page).to have_link "You don't have new notifications"
|
||||
expect(page).to have_link "My content"
|
||||
expect(page).to have_link "My account"
|
||||
expect(page).to have_link "Sign out"
|
||||
end
|
||||
|
||||
scenario "Should not show admin menu if logged user is manager" do
|
||||
scenario "Does not show the admin menu when managing users having the admin menu" do
|
||||
create(:manager, user: user)
|
||||
create(:moderator, user: create(:user, :in_census, document_number: "12345678M"))
|
||||
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
click_link "Menu"
|
||||
click_link "Management"
|
||||
|
||||
expect(page).to have_link "Go back to CONSUL"
|
||||
visit management_sign_in_path
|
||||
click_link "Select user"
|
||||
fill_in "Document number", with: "12345678M"
|
||||
click_button "Check document"
|
||||
|
||||
expect(page).to have_content "This user account is already verified"
|
||||
expect(page).not_to have_content "You don't have new notifications"
|
||||
expect(page).not_to have_content "My content"
|
||||
expect(page).not_to have_content "My account"
|
||||
|
||||
Reference in New Issue
Block a user