Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
953dcf16
Commit
953dcf16
authored
Nov 17, 2021
by
Jackie Fraser
Committed by
Ezekiel Kigbo
Nov 17, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Invite team members to side nav as experiment
parent
c710ad16
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
417 additions
and
41 deletions
+417
-41
app/assets/javascripts/contextual_sidebar.js
app/assets/javascripts/contextual_sidebar.js
+5
-0
app/assets/javascripts/invite_members/components/invite_members_trigger.vue
...ipts/invite_members/components/invite_members_trigger.vue
+21
-6
app/assets/javascripts/invite_members/constants.js
app/assets/javascripts/invite_members/constants.js
+2
-0
app/assets/javascripts/invite_members/init_invite_members_modal.js
...s/javascripts/invite_members/init_invite_members_modal.js
+10
-0
app/views/groups/_invite_members_side_nav_link.html.haml
app/views/groups/_invite_members_side_nav_link.html.haml
+8
-0
app/views/groups/show.html.haml
app/views/groups/show.html.haml
+0
-2
app/views/projects/_invite_members_side_nav_link.html.haml
app/views/projects/_invite_members_side_nav_link.html.haml
+8
-0
app/views/shared/nav/_sidebar_menu.html.haml
app/views/shared/nav/_sidebar_menu.html.haml
+1
-12
app/views/shared/nav/_sidebar_submenu.html.haml
app/views/shared/nav/_sidebar_submenu.html.haml
+12
-0
config/feature_flags/experiment/invite_members_in_side_nav.yml
...g/feature_flags/experiment/invite_members_in_side_nav.yml
+8
-0
lib/sidebars/groups/menus/invite_team_members_menu.rb
lib/sidebars/groups/menus/invite_team_members_menu.rb
+46
-0
lib/sidebars/groups/panel.rb
lib/sidebars/groups/panel.rb
+10
-0
lib/sidebars/panel.rb
lib/sidebars/panel.rb
+1
-0
lib/sidebars/projects/menus/invite_team_members_menu.rb
lib/sidebars/projects/menus/invite_team_members_menu.rb
+47
-0
lib/sidebars/projects/panel.rb
lib/sidebars/projects/panel.rb
+8
-0
spec/features/contextual_sidebar_spec.rb
spec/features/contextual_sidebar_spec.rb
+92
-17
spec/frontend/invite_members/components/invite_members_trigger_spec.js
.../invite_members/components/invite_members_trigger_spec.js
+31
-4
spec/lib/sidebars/groups/menus/invite_team_members_menu_spec.rb
...ib/sidebars/groups/menus/invite_team_members_menu_spec.rb
+55
-0
spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb
.../sidebars/projects/menus/invite_team_members_menu_spec.rb
+52
-0
No files found.
app/assets/javascripts/contextual_sidebar.js
View file @
953dcf16
...
@@ -2,6 +2,8 @@ import { GlBreakpointInstance as bp, breakpoints } from '@gitlab/ui/dist/utils';
...
@@ -2,6 +2,8 @@ import { GlBreakpointInstance as bp, breakpoints } from '@gitlab/ui/dist/utils';
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
import
Cookies
from
'
js-cookie
'
;
import
Cookies
from
'
js-cookie
'
;
import
{
debounce
}
from
'
lodash
'
;
import
{
debounce
}
from
'
lodash
'
;
import
initInviteMembersModal
from
'
~/invite_members/init_invite_members_modal
'
;
import
initInviteMembersTrigger
from
'
~/invite_members/init_invite_members_trigger
'
;
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
{
parseBoolean
}
from
'
~/lib/utils/common_utils
'
;
export
const
SIDEBAR_COLLAPSED_CLASS
=
'
js-sidebar-collapsed
'
;
export
const
SIDEBAR_COLLAPSED_CLASS
=
'
js-sidebar-collapsed
'
;
...
@@ -112,5 +114,8 @@ export default class ContextualSidebar {
...
@@ -112,5 +114,8 @@ export default class ContextualSidebar {
const
collapse
=
parseBoolean
(
Cookies
.
get
(
'
sidebar_collapsed
'
));
const
collapse
=
parseBoolean
(
Cookies
.
get
(
'
sidebar_collapsed
'
));
this
.
toggleCollapsedSidebar
(
collapse
,
true
);
this
.
toggleCollapsedSidebar
(
collapse
,
true
);
}
}
initInviteMembersModal
();
initInviteMembersTrigger
();
}
}
}
}
app/assets/javascripts/invite_members/components/invite_members_trigger.vue
View file @
953dcf16
<
script
>
<
script
>
import
{
GlButton
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
GlButton
,
GlLink
,
GlIcon
}
from
'
@gitlab/ui
'
;
import
ExperimentTracking
from
'
~/experimentation/experiment_tracking
'
;
import
ExperimentTracking
from
'
~/experimentation/experiment_tracking
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
s__
}
from
'
~/locale
'
;
import
eventHub
from
'
../event_hub
'
;
import
eventHub
from
'
../event_hub
'
;
import
{
TRIGGER_ELEMENT_BUTTON
,
TRIGGER_ELEMENT_SIDE_NAV
}
from
'
../constants
'
;
export
default
{
export
default
{
components
:
{
GlButton
,
GlLink
},
components
:
{
GlButton
,
GlLink
,
GlIcon
},
props
:
{
props
:
{
displayText
:
{
displayText
:
{
type
:
String
,
type
:
String
,
...
@@ -53,13 +54,11 @@ export default {
...
@@ -53,13 +54,11 @@ export default {
},
},
},
},
computed
:
{
computed
:
{
isButton
()
{
return
this
.
triggerElement
===
'
button
'
;
},
componentAttributes
()
{
componentAttributes
()
{
const
baseAttributes
=
{
const
baseAttributes
=
{
class
:
this
.
classes
,
class
:
this
.
classes
,
'
data-qa-selector
'
:
'
invite_members_button
'
,
'
data-qa-selector
'
:
'
invite_members_button
'
,
'
data-test-id
'
:
'
invite-members-button
'
,
};
};
if
(
this
.
event
&&
this
.
label
)
{
if
(
this
.
event
&&
this
.
label
)
{
...
@@ -77,6 +76,9 @@ export default {
...
@@ -77,6 +76,9 @@ export default {
this
.
trackExperimentOnShow
();
this
.
trackExperimentOnShow
();
},
},
methods
:
{
methods
:
{
checkTrigger
(
targetTriggerElement
)
{
return
this
.
triggerElement
===
targetTriggerElement
;
},
openModal
()
{
openModal
()
{
eventHub
.
$emit
(
'
openModal
'
,
{
inviteeType
:
'
members
'
,
source
:
this
.
triggerSource
});
eventHub
.
$emit
(
'
openModal
'
,
{
inviteeType
:
'
members
'
,
source
:
this
.
triggerSource
});
},
},
...
@@ -87,12 +89,14 @@ export default {
...
@@ -87,12 +89,14 @@ export default {
}
}
},
},
},
},
TRIGGER_ELEMENT_BUTTON
,
TRIGGER_ELEMENT_SIDE_NAV
,
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<gl-button
<gl-button
v-if=
"
isButton
"
v-if=
"
checkTrigger($options.TRIGGER_ELEMENT_BUTTON)
"
v-bind=
"componentAttributes"
v-bind=
"componentAttributes"
:variant=
"variant"
:variant=
"variant"
:icon=
"icon"
:icon=
"icon"
...
@@ -100,6 +104,17 @@ export default {
...
@@ -100,6 +104,17 @@ export default {
>
>
{{
displayText
}}
{{
displayText
}}
</gl-button>
</gl-button>
<gl-link
v-else-if=
"checkTrigger($options.TRIGGER_ELEMENT_SIDE_NAV)"
v-bind=
"componentAttributes"
data-is-link=
"true"
@
click=
"openModal"
>
<span
class=
"nav-icon-container"
>
<gl-icon
:name=
"icon"
/>
</span>
<span
class=
"nav-item-name"
>
{{
displayText
}}
</span>
</gl-link>
<gl-link
v-else
v-bind=
"componentAttributes"
data-is-link=
"true"
@
click=
"openModal"
>
<gl-link
v-else
v-bind=
"componentAttributes"
data-is-link=
"true"
@
click=
"openModal"
>
{{
displayText
}}
{{
displayText
}}
</gl-link>
</gl-link>
...
...
app/assets/javascripts/invite_members/constants.js
View file @
953dcf16
...
@@ -25,3 +25,5 @@ export const API_MESSAGES = {
...
@@ -25,3 +25,5 @@ export const API_MESSAGES = {
};
};
export
const
USERS_FILTER_ALL
=
'
all
'
;
export
const
USERS_FILTER_ALL
=
'
all
'
;
export
const
USERS_FILTER_SAML_PROVIDER_ID
=
'
saml_provider_id
'
;
export
const
USERS_FILTER_SAML_PROVIDER_ID
=
'
saml_provider_id
'
;
export
const
TRIGGER_ELEMENT_BUTTON
=
'
button
'
;
export
const
TRIGGER_ELEMENT_SIDE_NAV
=
'
side-nav
'
;
app/assets/javascripts/invite_members/init_invite_members_modal.js
View file @
953dcf16
...
@@ -5,7 +5,15 @@ import { parseBoolean } from '~/lib/utils/common_utils';
...
@@ -5,7 +5,15 @@ import { parseBoolean } from '~/lib/utils/common_utils';
Vue
.
use
(
GlToast
);
Vue
.
use
(
GlToast
);
let
initedInviteMembersModal
;
export
default
function
initInviteMembersModal
()
{
export
default
function
initInviteMembersModal
()
{
if
(
initedInviteMembersModal
)
{
// if we already loaded this in another part of the dom, we don't want to do it again
// else we will stack the modals
return
false
;
}
// https://gitlab.com/gitlab-org/gitlab/-/issues/344955
// https://gitlab.com/gitlab-org/gitlab/-/issues/344955
// bug lying in wait here for someone to put group and project invite in same screen
// bug lying in wait here for someone to put group and project invite in same screen
// once that happens we'll need to mount these differently, perhaps split
// once that happens we'll need to mount these differently, perhaps split
...
@@ -16,6 +24,8 @@ export default function initInviteMembersModal() {
...
@@ -16,6 +24,8 @@ export default function initInviteMembersModal() {
return
false
;
return
false
;
}
}
initedInviteMembersModal
=
true
;
return
new
Vue
({
return
new
Vue
({
el
,
el
,
provide
:
{
provide
:
{
...
...
app/views/groups/_invite_members_side_nav_link.html.haml
0 → 100644
View file @
953dcf16
.js-invite-members-trigger
{
data:
{
trigger_source:
'group-side-nav'
,
classes:
'gl-text-decoration-none! gl-shadow-none! gl-text-body!'
,
icon:
'users'
,
display_text:
title
,
trigger_element:
'side-nav'
}
}
=
render
partial:
'shared/nav/sidebar_submenu'
,
locals:
{
sidebar_menu:
sidebar_menu
}
=
render
'groups/invite_members_modal'
,
group:
group
app/views/groups/show.html.haml
View file @
953dcf16
...
@@ -32,8 +32,6 @@
...
@@ -32,8 +32,6 @@
=
render_if_exists
'groups/group_activity_analytics'
,
group:
@group
=
render_if_exists
'groups/group_activity_analytics'
,
group:
@group
=
render
'groups/invite_members_modal'
,
group:
@group
.groups-listing
{
data:
{
endpoints:
{
default:
group_children_path
(
@group
,
format: :json
),
shared:
group_shared_projects_path
(
@group
,
format: :json
)
}
}
}
.groups-listing
{
data:
{
endpoints:
{
default:
group_children_path
(
@group
,
format: :json
),
shared:
group_shared_projects_path
(
@group
,
format: :json
)
}
}
}
.top-area.group-nav-container.justify-content-between
.top-area.group-nav-container.justify-content-between
.scrolling-tabs-container.inner-page-scroll-tabs
.scrolling-tabs-container.inner-page-scroll-tabs
...
...
app/views/projects/_invite_members_side_nav_link.html.haml
0 → 100644
View file @
953dcf16
.js-invite-members-trigger
{
data:
{
trigger_source:
'project-side-nav'
,
classes:
'gl-text-decoration-none! gl-shadow-none! gl-text-body!'
,
icon:
'users'
,
display_text:
title
,
trigger_element:
'side-nav'
}
}
=
render
partial:
'shared/nav/sidebar_submenu'
,
locals:
{
sidebar_menu:
sidebar_menu
}
=
render
'projects/invite_members_modal'
,
project:
project
app/views/shared/nav/_sidebar_menu.html.haml
View file @
953dcf16
...
@@ -16,15 +16,4 @@
...
@@ -16,15 +16,4 @@
%span
.badge.badge-pill.count
{
**
sidebar_menu
.
pill_html_options
}
%span
.badge.badge-pill.count
{
**
sidebar_menu
.
pill_html_options
}
=
number_with_delimiter
(
sidebar_menu
.
pill_count
)
=
number_with_delimiter
(
sidebar_menu
.
pill_count
)
%ul
.sidebar-sub-level-items
{
class:
(
'is-fly-out-only'
unless
sidebar_menu
.
has_renderable_items?
)
}
=
render
partial:
'shared/nav/sidebar_submenu'
,
locals:
{
sidebar_menu:
sidebar_menu
}
=
nav_link
(
**
sidebar_menu
.
all_active_routes
,
html_options:
{
class:
'fly-out-top-item'
}
)
do
%span
.fly-out-top-item-container
%strong
.fly-out-top-item-name
=
sidebar_menu
.
title
-
if
sidebar_menu
.
has_pill?
%span
.badge.badge-pill.count.fly-out-badge
{
**
sidebar_menu
.
pill_html_options
}
=
number_with_delimiter
(
sidebar_menu
.
pill_count
)
-
if
sidebar_menu
.
has_renderable_items?
%li
.divider.fly-out-top-item
=
render
partial:
'shared/nav/sidebar_menu_item'
,
collection:
sidebar_menu
.
renderable_items
app/views/shared/nav/_sidebar_submenu.html.haml
0 → 100644
View file @
953dcf16
%ul
.sidebar-sub-level-items
{
class:
(
'is-fly-out-only'
unless
sidebar_menu
.
has_renderable_items?
)
}
=
nav_link
(
**
sidebar_menu
.
all_active_routes
,
html_options:
{
class:
'fly-out-top-item'
}
)
do
%span
.fly-out-top-item-container
%strong
.fly-out-top-item-name
=
sidebar_menu
.
title
-
if
sidebar_menu
.
has_pill?
%span
.badge.badge-pill.count.fly-out-badge
{
**
sidebar_menu
.
pill_html_options
}
=
number_with_delimiter
(
sidebar_menu
.
pill_count
)
-
if
sidebar_menu
.
has_renderable_items?
%li
.divider.fly-out-top-item
=
render
partial:
'shared/nav/sidebar_menu_item'
,
collection:
sidebar_menu
.
renderable_items
config/feature_flags/experiment/invite_members_in_side_nav.yml
0 → 100644
View file @
953dcf16
---
name
:
invite_members_in_side_nav
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70451
rollout_issue_url
:
https://gitlab.com/gitlab-org/gitlab/-/issues/342951
milestone
:
'
14.5'
type
:
experiment
group
:
group::expansion
default_enabled
:
false
lib/sidebars/groups/menus/invite_team_members_menu.rb
0 → 100644
View file @
953dcf16
# frozen_string_literal: true
module
Sidebars
module
Groups
module
Menus
class
InviteTeamMembersMenu
<
::
Sidebars
::
Menu
override
:title
def
title
s_
(
'InviteMember|Invite members'
)
end
override
:render?
def
render?
can?
(
context
.
current_user
,
:admin_group_member
,
context
.
group
)
&&
all_valid_members
.
size
<=
1
end
override
:menu_partial
def
menu_partial
'groups/invite_members_side_nav_link'
end
override
:menu_partial_options
def
menu_partial_options
{
group:
context
.
group
,
title:
title
,
sidebar_menu:
self
}
end
override
:extra_nav_link_html_options
def
extra_nav_link_html_options
{
'data-test-id'
:
'side-nav-invite-members'
}
end
private
def
all_valid_members
GroupMembersFinder
.
new
(
context
.
group
,
context
.
current_user
).
execute
end
end
end
end
end
lib/sidebars/groups/panel.rb
View file @
953dcf16
...
@@ -15,12 +15,22 @@ module Sidebars
...
@@ -15,12 +15,22 @@ module Sidebars
add_menu
(
Sidebars
::
Groups
::
Menus
::
PackagesRegistriesMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Groups
::
Menus
::
PackagesRegistriesMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Groups
::
Menus
::
CustomerRelationsMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Groups
::
Menus
::
CustomerRelationsMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Groups
::
Menus
::
SettingsMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Groups
::
Menus
::
SettingsMenu
.
new
(
context
))
add_invite_members_menu
end
end
override
:aria_label
override
:aria_label
def
aria_label
def
aria_label
context
.
group
.
subgroup?
?
_
(
'Subgroup navigation'
)
:
_
(
'Group navigation'
)
context
.
group
.
subgroup?
?
_
(
'Subgroup navigation'
)
:
_
(
'Group navigation'
)
end
end
private
def
add_invite_members_menu
experiment
(
:invite_members_in_side_nav
,
group:
context
.
group
)
do
|
e
|
e
.
control
{}
e
.
candidate
{
add_menu
(
Sidebars
::
Groups
::
Menus
::
InviteTeamMembersMenu
.
new
(
context
))
}
end
end
end
end
end
end
end
end
...
...
lib/sidebars/panel.rb
View file @
953dcf16
...
@@ -4,6 +4,7 @@ module Sidebars
...
@@ -4,6 +4,7 @@ module Sidebars
class
Panel
class
Panel
extend
::
Gitlab
::
Utils
::
Override
extend
::
Gitlab
::
Utils
::
Override
include
::
Sidebars
::
Concerns
::
PositionableList
include
::
Sidebars
::
Concerns
::
PositionableList
include
Gitlab
::
Experiment
::
Dsl
attr_reader
:context
,
:scope_menu
,
:hidden_menu
attr_reader
:context
,
:scope_menu
,
:hidden_menu
...
...
lib/sidebars/projects/menus/invite_team_members_menu.rb
0 → 100644
View file @
953dcf16
# frozen_string_literal: true
module
Sidebars
module
Projects
module
Menus
class
InviteTeamMembersMenu
<
::
Sidebars
::
Menu
override
:title
def
title
s_
(
'InviteMember|Invite members'
)
end
override
:render?
def
render?
can?
(
context
.
current_user
,
:admin_project_member
,
context
.
project
)
&&
all_valid_members
.
size
<=
1
end
override
:menu_partial
def
menu_partial
'projects/invite_members_side_nav_link'
end
override
:menu_partial_options
def
menu_partial_options
{
project:
context
.
project
,
title:
title
,
sidebar_menu:
self
}
end
override
:extra_nav_link_html_options
def
extra_nav_link_html_options
{
'data-test-id'
:
'side-nav-invite-members'
}
end
private
def
all_valid_members
MembersFinder
.
new
(
context
.
project
,
context
.
current_user
)
.
execute
(
include_relations:
[
:inherited
,
:direct
,
:invited_groups
])
end
end
end
end
end
lib/sidebars/projects/panel.rb
View file @
953dcf16
...
@@ -36,6 +36,14 @@ module Sidebars
...
@@ -36,6 +36,14 @@ module Sidebars
add_menu
(
Sidebars
::
Projects
::
Menus
::
ExternalWikiMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Projects
::
Menus
::
ExternalWikiMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Projects
::
Menus
::
SnippetsMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Projects
::
Menus
::
SnippetsMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Projects
::
Menus
::
SettingsMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Projects
::
Menus
::
SettingsMenu
.
new
(
context
))
add_invite_members_menu
end
def
add_invite_members_menu
experiment
(
:invite_members_in_side_nav
,
group:
context
.
project
.
group
)
do
|
e
|
e
.
control
{}
e
.
candidate
{
add_menu
(
Sidebars
::
Projects
::
Menus
::
InviteTeamMembersMenu
.
new
(
context
))
}
end
end
end
def
confluence_or_wiki_menu
def
confluence_or_wiki_menu
...
...
spec/features/contextual_sidebar_spec.rb
View file @
953dcf16
...
@@ -3,35 +3,110 @@
...
@@ -3,35 +3,110 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
'Contextual sidebar'
,
:js
do
RSpec
.
describe
'Contextual sidebar'
,
:js
do
let_it_be
(
:project
)
{
create
(
:project
)
}
context
'when context is a project'
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let
(
:user
)
{
project
.
owner
}
let
(
:user
)
{
project
.
owner
}
before
do
before
do
sign_in
(
user
)
sign_in
(
user
)
end
visit
project_path
(
project
)
context
'when analyzing the menu'
do
end
before
do
visit
project_path
(
project
)
end
it
'shows flyout navs when collapsed or expanded apart from on the active item when expanded'
,
:aggregate_failures
do
expect
(
page
).
not_to
have_selector
(
'.js-sidebar-collapsed'
)
find
(
'.rspec-link-pipelines'
).
hover
expect
(
page
).
to
have_selector
(
'.is-showing-fly-out'
)
find
(
'.rspec-project-link'
).
hover
expect
(
page
).
not_to
have_selector
(
'.is-showing-fly-out'
)
find
(
'.rspec-toggle-sidebar'
).
click
find
(
'.rspec-link-pipelines'
).
hover
expect
(
page
).
to
have_selector
(
'.is-showing-fly-out'
)
it
'shows flyout navs when collapsed or expanded apart from on the active item when expanded'
,
:aggregate_failures
do
find
(
'.rspec-project-link'
).
hover
expect
(
page
).
not_to
have_selector
(
'.js-sidebar-collapsed'
)
expect
(
page
).
to
have_selector
(
'.is-showing-fly-out'
)
end
end
context
'with invite_members_in_side_nav experiment'
,
:experiment
do
it
'allows opening of modal for the candidate experience'
do
stub_experiments
(
invite_members_in_side_nav: :candidate
)
expect
(
experiment
(
:invite_members_in_side_nav
)).
to
track
(
:assignment
)
.
with_context
(
group:
project
.
group
)
.
on_next_instance
visit
project_path
(
project
)
page
.
within
'[data-test-id="side-nav-invite-members"'
do
find
(
'[data-test-id="invite-members-button"'
).
click
end
expect
(
page
).
to
have_content
(
"You're inviting members to the"
)
end
it
'does not have invite members link in side nav for the control experience'
do
stub_experiments
(
invite_members_in_side_nav: :control
)
expect
(
experiment
(
:invite_members_in_side_nav
)).
to
track
(
:assignment
)
.
with_context
(
group:
project
.
group
)
.
on_next_instance
visit
project_path
(
project
)
expect
(
page
).
not_to
have_css
(
'[data-test-id="side-nav-invite-members"'
)
end
end
end
find
(
'.rspec-link-pipelines'
).
hover
context
'when context is a group'
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:group
)
do
create
(
:group
).
tap
do
|
g
|
g
.
add_owner
(
user
)
end
end
expect
(
page
).
to
have_selector
(
'.is-showing-fly-out'
)
before
do
sign_in
(
user
)
end
find
(
'.rspec-project-link'
).
hover
context
'with invite_members_in_side_nav experiment'
,
:experiment
do
it
'allows opening of modal for the candidate experience'
do
stub_experiments
(
invite_members_in_side_nav: :candidate
)
expect
(
experiment
(
:invite_members_in_side_nav
)).
to
track
(
:assignment
)
.
with_context
(
group:
group
)
.
on_next_instance
expect
(
page
).
not_to
have_selector
(
'.is-showing-fly-out'
)
visit
group_path
(
group
)
find
(
'.rspec-toggle-sidebar'
).
click
page
.
within
'[data-test-id="side-nav-invite-members"'
do
find
(
'[data-test-id="invite-members-button"'
).
click
end
find
(
'.rspec-link-pipelines'
).
hover
expect
(
page
).
to
have_content
(
"You're inviting members to the"
)
end
expect
(
page
).
to
have_selector
(
'.is-showing-fly-out'
)
it
'does not have invite members link in side nav for the control experience'
do
stub_experiments
(
invite_members_in_side_nav: :control
)
expect
(
experiment
(
:invite_members_in_side_nav
)).
to
track
(
:assignment
)
.
with_context
(
group:
group
)
.
on_next_instance
find
(
'.rspec-project-link'
).
hover
visit
group_path
(
group
)
expect
(
page
).
to
have_selector
(
'.is-showing-fly-out'
)
expect
(
page
).
not_to
have_css
(
'[data-test-id="side-nav-invite-members"'
)
end
end
end
end
end
end
spec/frontend/invite_members/components/invite_members_trigger_spec.js
View file @
953dcf16
import
{
GlButton
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
GlButton
,
GlLink
,
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
ExperimentTracking
from
'
~/experimentation/experiment_tracking
'
;
import
ExperimentTracking
from
'
~/experimentation/experiment_tracking
'
;
import
InviteMembersTrigger
from
'
~/invite_members/components/invite_members_trigger.vue
'
;
import
InviteMembersTrigger
from
'
~/invite_members/components/invite_members_trigger.vue
'
;
import
eventHub
from
'
~/invite_members/event_hub
'
;
import
eventHub
from
'
~/invite_members/event_hub
'
;
import
{
TRIGGER_ELEMENT_BUTTON
,
TRIGGER_ELEMENT_SIDE_NAV
}
from
'
~/invite_members/constants
'
;
jest
.
mock
(
'
~/experimentation/experiment_tracking
'
);
jest
.
mock
(
'
~/experimentation/experiment_tracking
'
);
...
@@ -15,6 +16,7 @@ let findButton;
...
@@ -15,6 +16,7 @@ let findButton;
const
triggerComponent
=
{
const
triggerComponent
=
{
button
:
GlButton
,
button
:
GlButton
,
anchor
:
GlLink
,
anchor
:
GlLink
,
'
side-nav
'
:
GlLink
,
};
};
const
createComponent
=
(
props
=
{})
=>
{
const
createComponent
=
(
props
=
{})
=>
{
...
@@ -27,9 +29,23 @@ const createComponent = (props = {}) => {
...
@@ -27,9 +29,23 @@ const createComponent = (props = {}) => {
});
});
};
};
describe
.
each
([
'
button
'
,
'
anchor
'
])(
'
with triggerElement as %s
'
,
(
triggerElement
)
=>
{
const
triggerItems
=
[
triggerProps
=
{
triggerElement
,
triggerSource
};
{
findButton
=
()
=>
wrapper
.
findComponent
(
triggerComponent
[
triggerElement
]);
triggerElement
:
TRIGGER_ELEMENT_BUTTON
,
},
{
triggerElement
:
'
anchor
'
,
},
{
triggerElement
:
TRIGGER_ELEMENT_SIDE_NAV
,
icon
:
'
plus
'
,
},
];
describe
.
each
(
triggerItems
)(
'
with triggerElement as %s
'
,
(
triggerItem
)
=>
{
triggerProps
=
{
...
triggerItem
,
triggerSource
};
findButton
=
()
=>
wrapper
.
findComponent
(
triggerComponent
[
triggerItem
.
triggerElement
]);
afterEach
(()
=>
{
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
.
destroy
();
...
@@ -91,3 +107,14 @@ describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement
...
@@ -91,3 +107,14 @@ describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement
});
});
});
});
});
});
describe
(
'
side-nav with icon
'
,
()
=>
{
it
(
'
includes the specified icon with correct size when triggerElement is link
'
,
()
=>
{
const
findIcon
=
()
=>
wrapper
.
findComponent
(
GlIcon
);
createComponent
({
triggerElement
:
TRIGGER_ELEMENT_SIDE_NAV
,
icon
:
'
plus
'
});
expect
(
findIcon
().
exists
()).
toBe
(
true
);
expect
(
findIcon
().
props
(
'
name
'
)).
toBe
(
'
plus
'
);
});
});
spec/lib/sidebars/groups/menus/invite_team_members_menu_spec.rb
0 → 100644
View file @
953dcf16
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Sidebars
::
Groups
::
Menus
::
InviteTeamMembersMenu
do
let_it_be
(
:owner
)
{
create
(
:user
)
}
let_it_be
(
:guest
)
{
create
(
:user
)
}
let_it_be
(
:group
)
do
build
(
:group
).
tap
do
|
g
|
g
.
add_owner
(
owner
)
end
end
let
(
:context
)
{
Sidebars
::
Groups
::
Context
.
new
(
current_user:
owner
,
container:
group
)
}
subject
(
:invite_menu
)
{
described_class
.
new
(
context
)
}
context
'when the group is viewed by an owner of the group'
do
describe
'#render?'
do
it
'renders the Invite team members link'
do
expect
(
invite_menu
.
render?
).
to
eq
(
true
)
end
context
'when the group already has at least 2 members'
do
before
do
group
.
add_guest
(
guest
)
end
it
'does not render the link'
do
expect
(
invite_menu
.
render?
).
to
eq
(
false
)
end
end
end
describe
'#title'
do
it
'displays the correct Invite team members text for the link in the side nav'
do
expect
(
invite_menu
.
title
).
to
eq
(
'Invite members'
)
end
end
end
context
'when the group is viewed by a guest user without admin permissions'
do
let
(
:context
)
{
Sidebars
::
Groups
::
Context
.
new
(
current_user:
guest
,
container:
group
)
}
before
do
group
.
add_guest
(
guest
)
end
describe
'#render?'
do
it
'does not render the link'
do
expect
(
subject
.
render?
).
to
eq
(
false
)
end
end
end
end
spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb
0 → 100644
View file @
953dcf16
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Sidebars
::
Projects
::
Menus
::
InviteTeamMembersMenu
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:guest
)
{
create
(
:user
)
}
let
(
:context
)
{
Sidebars
::
Projects
::
Context
.
new
(
current_user:
owner
,
container:
project
)
}
subject
(
:invite_menu
)
{
described_class
.
new
(
context
)
}
context
'when the project is viewed by an owner of the group'
do
let
(
:owner
)
{
project
.
owner
}
describe
'#render?'
do
it
'renders the Invite team members link'
do
expect
(
invite_menu
.
render?
).
to
eq
(
true
)
end
context
'when the project already has at least 2 members'
do
before
do
project
.
add_guest
(
guest
)
end
it
'does not render the link'
do
expect
(
invite_menu
.
render?
).
to
eq
(
false
)
end
end
end
describe
'#title'
do
it
'displays the correct Invite team members text for the link in the side nav'
do
expect
(
invite_menu
.
title
).
to
eq
(
'Invite members'
)
end
end
end
context
'when the project is viewed by a guest user without admin permissions'
do
let
(
:context
)
{
Sidebars
::
Projects
::
Context
.
new
(
current_user:
guest
,
container:
project
)
}
before
do
project
.
add_guest
(
guest
)
end
describe
'#render?'
do
it
'does not render'
do
expect
(
invite_menu
.
render?
).
to
eq
(
false
)
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment