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
17dd37c6
Commit
17dd37c6
authored
Nov 26, 2021
by
Jannik Lehmann
Committed by
Ezekiel Kigbo
Nov 26, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor confirm modal to work without querySelector
parent
2cd0a687
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
346 additions
and
121 deletions
+346
-121
app/assets/javascripts/admin/users/components/actions/activate.vue
...s/javascripts/admin/users/components/actions/activate.vue
+11
-10
app/assets/javascripts/admin/users/components/actions/approve.vue
...ts/javascripts/admin/users/components/actions/approve.vue
+11
-10
app/assets/javascripts/admin/users/components/actions/ban.vue
...assets/javascripts/admin/users/components/actions/ban.vue
+10
-9
app/assets/javascripts/admin/users/components/actions/block.vue
...sets/javascripts/admin/users/components/actions/block.vue
+10
-9
app/assets/javascripts/admin/users/components/actions/deactivate.vue
...javascripts/admin/users/components/actions/deactivate.vue
+10
-9
app/assets/javascripts/admin/users/components/actions/reject.vue
...ets/javascripts/admin/users/components/actions/reject.vue
+10
-9
app/assets/javascripts/admin/users/components/actions/unban.vue
...sets/javascripts/admin/users/components/actions/unban.vue
+10
-9
app/assets/javascripts/admin/users/components/actions/unblock.vue
...ts/javascripts/admin/users/components/actions/unblock.vue
+11
-9
app/assets/javascripts/admin/users/components/actions/unlock.vue
...ets/javascripts/admin/users/components/actions/unlock.vue
+10
-9
app/assets/javascripts/vue_shared/components/confirm_modal.vue
...ssets/javascripts/vue_shared/components/confirm_modal.vue
+47
-25
app/assets/javascripts/vue_shared/components/confirm_modal_eventhub.js
...vascripts/vue_shared/components/confirm_modal_eventhub.js
+5
-0
app/assets/javascripts/vue_shared/components/dom_element_listener.vue
...avascripts/vue_shared/components/dom_element_listener.vue
+28
-0
spec/frontend/admin/users/components/actions/actions_spec.js
spec/frontend/admin/users/components/actions/actions_spec.js
+2
-5
spec/frontend/vue_shared/components/confirm_modal_spec.js
spec/frontend/vue_shared/components/confirm_modal_spec.js
+55
-8
spec/frontend/vue_shared/components/dom_element_listener_spec.js
...ontend/vue_shared/components/dom_element_listener_spec.js
+116
-0
No files found.
app/assets/javascripts/admin/users/components/actions/activate.vue
View file @
17dd37c6
<
script
>
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
sprintf
,
s__
,
__
}
from
'
~/locale
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
{
I18N_USER_ACTIONS
}
from
'
../../constants
'
;
// TODO: To be replaced with
<
template
>
content
in
https
:
//gitlab.com/gitlab-org/gitlab/-/issues/320922
...
...
@@ -26,16 +27,15 @@ export default {
required
:
true
,
},
},
computed
:
{
modalAttributes
()
{
return
{
'
data-path
'
:
this
.
path
,
'
data-method
'
:
'
put
'
,
'
data-modal-attributes
'
:
JSON
.
stringify
(
{
methods
:
{
onClick
()
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
{
path
:
this
.
path
,
method
:
'
put
'
,
modalAttributes
:
{
title
:
sprintf
(
s__
(
'
AdminUsers|Activate user %{username}?
'
),
{
username
:
this
.
username
,
}),
messageHtml
,
actionCancel
:
{
text
:
__
(
'
Cancel
'
),
},
...
...
@@ -43,15 +43,16 @@ export default {
text
:
I18N_USER_ACTIONS
.
activate
,
attributes
:
[{
variant
:
'
confirm
'
}],
},
}),
};
messageHtml
,
},
});
},
},
};
</
script
>
<
template
>
<gl-dropdown-item
button-class=
"js-confirm-modal-button"
v-bind=
"
{ ...modalAttributes }
">
<gl-dropdown-item
@
click=
"onClick
"
>
<slot></slot>
</gl-dropdown-item>
</
template
>
app/assets/javascripts/admin/users/components/actions/approve.vue
View file @
17dd37c6
<
script
>
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
sprintf
,
s__
,
__
}
from
'
~/locale
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
{
I18N_USER_ACTIONS
}
from
'
../../constants
'
;
// TODO: To be replaced with
<
template
>
content
in
https
:
//gitlab.com/gitlab-org/gitlab/-/issues/320922
...
...
@@ -28,12 +29,12 @@ export default {
required
:
true
,
},
},
computed
:
{
attributes
()
{
return
{
'
data-path
'
:
this
.
path
,
'
data-method
'
:
'
put
'
,
'
data-modal-attributes
'
:
JSON
.
stringify
(
{
methods
:
{
onClick
()
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
{
path
:
this
.
path
,
method
:
'
put
'
,
modalAttributes
:
{
title
:
sprintf
(
s__
(
'
AdminUsers|Approve user %{username}?
'
),
{
username
:
this
.
username
,
}),
...
...
@@ -45,16 +46,16 @@ export default {
attributes
:
[{
variant
:
'
confirm
'
,
'
data-qa-selector
'
:
'
approve_user_confirm_button
'
}],
},
messageHtml
,
})
,
'
data-qa-selector
'
:
'
approve_user_button
'
,
};
'
data-qa-selector
'
:
'
approve_user_button
'
,
}
,
}
)
;
},
},
};
</
script
>
<
template
>
<gl-dropdown-item
button-class=
"js-confirm-modal-button"
v-bind=
"
{ ...attributes }
">
<gl-dropdown-item
@
click=
"onClick
"
>
<slot></slot>
</gl-dropdown-item>
</
template
>
app/assets/javascripts/admin/users/components/actions/ban.vue
View file @
17dd37c6
...
...
@@ -2,6 +2,7 @@
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
helpPagePath
}
from
'
~/helpers/help_page_helper
'
;
import
{
sprintf
,
s__
,
__
}
from
'
~/locale
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
{
I18N_USER_ACTIONS
}
from
'
../../constants
'
;
// TODO: To be replaced with
<
template
>
content
in
https
:
//gitlab.com/gitlab-org/gitlab/-/issues/320922
...
...
@@ -39,12 +40,12 @@ export default {
required
:
true
,
},
},
computed
:
{
modalAttributes
()
{
return
{
'
data-path
'
:
this
.
path
,
'
data-method
'
:
'
put
'
,
'
data-modal-attributes
'
:
JSON
.
stringify
(
{
methods
:
{
onClick
()
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
{
path
:
this
.
path
,
method
:
'
put
'
,
modalAttributes
:
{
title
:
sprintf
(
s__
(
'
AdminUsers|Ban user %{username}?
'
),
{
username
:
this
.
username
,
}),
...
...
@@ -56,15 +57,15 @@ export default {
attributes
:
[{
variant
:
'
confirm
'
}],
},
messageHtml
,
}
)
,
};
},
}
)
;
},
},
};
</
script
>
<
template
>
<gl-dropdown-item
button-class=
"js-confirm-modal-button"
v-bind=
"
{ ...modalAttributes }
">
<gl-dropdown-item
@
click=
"onClick
"
>
<slot></slot>
</gl-dropdown-item>
</
template
>
app/assets/javascripts/admin/users/components/actions/block.vue
View file @
17dd37c6
<
script
>
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
sprintf
,
s__
,
__
}
from
'
~/locale
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
{
I18N_USER_ACTIONS
}
from
'
../../constants
'
;
// TODO: To be replaced with
<
template
>
content
in
https
:
//gitlab.com/gitlab-org/gitlab/-/issues/320922
...
...
@@ -29,12 +30,12 @@ export default {
required
:
true
,
},
},
computed
:
{
modalAttributes
()
{
return
{
'
data-path
'
:
this
.
path
,
'
data-method
'
:
'
put
'
,
'
data-modal-attributes
'
:
JSON
.
stringify
(
{
methods
:
{
onClick
()
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
{
path
:
this
.
path
,
method
:
'
put
'
,
modalAttributes
:
{
title
:
sprintf
(
s__
(
'
AdminUsers|Block user %{username}?
'
),
{
username
:
this
.
username
}),
actionCancel
:
{
text
:
__
(
'
Cancel
'
),
...
...
@@ -44,15 +45,15 @@ export default {
attributes
:
[{
variant
:
'
confirm
'
}],
},
messageHtml
,
}
)
,
};
},
}
)
;
},
},
};
</
script
>
<
template
>
<gl-dropdown-item
button-class=
"js-confirm-modal-button"
v-bind=
"
{ ...modalAttributes }
">
<gl-dropdown-item
@
click=
"onClick
"
>
<slot></slot>
</gl-dropdown-item>
</
template
>
app/assets/javascripts/admin/users/components/actions/deactivate.vue
View file @
17dd37c6
<
script
>
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
sprintf
,
s__
,
__
}
from
'
~/locale
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
{
I18N_USER_ACTIONS
}
from
'
../../constants
'
;
// TODO: To be replaced with
<
template
>
content
in
https
:
//gitlab.com/gitlab-org/gitlab/-/issues/320922
...
...
@@ -36,12 +37,12 @@ export default {
required
:
true
,
},
},
computed
:
{
modalAttributes
()
{
return
{
'
data-path
'
:
this
.
path
,
'
data-method
'
:
'
put
'
,
'
data-modal-attributes
'
:
JSON
.
stringify
(
{
methods
:
{
onClick
()
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
{
path
:
this
.
path
,
method
:
'
put
'
,
modalAttributes
:
{
title
:
sprintf
(
s__
(
'
AdminUsers|Deactivate user %{username}?
'
),
{
username
:
this
.
username
,
}),
...
...
@@ -53,15 +54,15 @@ export default {
attributes
:
[{
variant
:
'
confirm
'
}],
},
messageHtml
,
}
)
,
};
},
}
)
;
},
},
};
</
script
>
<
template
>
<gl-dropdown-item
button-class=
"js-confirm-modal-button"
v-bind=
"
{ ...modalAttributes }
">
<gl-dropdown-item
@
click=
"onClick
"
>
<slot></slot>
</gl-dropdown-item>
</
template
>
app/assets/javascripts/admin/users/components/actions/reject.vue
View file @
17dd37c6
...
...
@@ -2,6 +2,7 @@
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
helpPagePath
}
from
'
~/helpers/help_page_helper
'
;
import
{
sprintf
,
s__
,
__
}
from
'
~/locale
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
{
I18N_USER_ACTIONS
}
from
'
../../constants
'
;
// TODO: To be replaced with
<
template
>
content
in
https
:
//gitlab.com/gitlab-org/gitlab/-/issues/320922
...
...
@@ -39,12 +40,12 @@ export default {
required
:
true
,
},
},
computed
:
{
modalAttributes
()
{
return
{
'
data-path
'
:
this
.
path
,
'
data-method
'
:
'
delete
'
,
'
data-modal-attributes
'
:
JSON
.
stringify
(
{
methods
:
{
onClick
()
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
{
path
:
this
.
path
,
method
:
'
delete
'
,
modalAttributes
:
{
title
:
sprintf
(
s__
(
'
AdminUsers|Reject user %{username}?
'
),
{
username
:
this
.
username
,
}),
...
...
@@ -56,15 +57,15 @@ export default {
attributes
:
[{
variant
:
'
danger
'
}],
},
messageHtml
,
}
)
,
};
},
}
)
;
},
},
};
</
script
>
<
template
>
<gl-dropdown-item
button-class=
"js-confirm-modal-button"
v-bind=
"
{ ...modalAttributes }
">
<gl-dropdown-item
@
click=
"onClick
"
>
<slot></slot>
</gl-dropdown-item>
</
template
>
app/assets/javascripts/admin/users/components/actions/unban.vue
View file @
17dd37c6
<
script
>
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
sprintf
,
s__
,
__
}
from
'
~/locale
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
{
I18N_USER_ACTIONS
}
from
'
../../constants
'
;
// TODO: To be replaced with
<
template
>
content
in
https
:
//gitlab.com/gitlab-org/gitlab/-/issues/320922
...
...
@@ -22,12 +23,12 @@ export default {
required
:
true
,
},
},
computed
:
{
modalAttributes
()
{
return
{
'
data-path
'
:
this
.
path
,
'
data-method
'
:
'
put
'
,
'
data-modal-attributes
'
:
JSON
.
stringify
(
{
methods
:
{
onClick
()
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
{
path
:
this
.
path
,
method
:
'
put
'
,
modalAttributes
:
{
title
:
sprintf
(
s__
(
'
AdminUsers|Unban user %{username}?
'
),
{
username
:
this
.
username
,
}),
...
...
@@ -39,15 +40,15 @@ export default {
attributes
:
[{
variant
:
'
confirm
'
}],
},
messageHtml
,
}
)
,
};
},
}
)
;
},
},
};
</
script
>
<
template
>
<gl-dropdown-item
button-class=
"js-confirm-modal-button"
v-bind=
"
{ ...modalAttributes }
">
<gl-dropdown-item
@
click=
"onClick
"
>
<slot></slot>
</gl-dropdown-item>
</
template
>
app/assets/javascripts/admin/users/components/actions/unblock.vue
View file @
17dd37c6
<
script
>
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
sprintf
,
s__
,
__
}
from
'
~/locale
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
{
I18N_USER_ACTIONS
}
from
'
../../constants
'
;
export
default
{
...
...
@@ -17,12 +18,13 @@ export default {
required
:
true
,
},
},
computed
:
{
modalAttributes
()
{
return
{
'
data-path
'
:
this
.
path
,
'
data-method
'
:
'
put
'
,
'
data-modal-attributes
'
:
JSON
.
stringify
({
methods
:
{
onClick
()
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
{
path
:
this
.
path
,
method
:
'
put
'
,
modalAttributes
:
{
title
:
sprintf
(
s__
(
'
AdminUsers|Unblock user %{username}?
'
),
{
username
:
this
.
username
}),
message
:
s__
(
'
AdminUsers|You can always block their account again if needed.
'
),
actionCancel
:
{
...
...
@@ -32,15 +34,15 @@ export default {
text
:
I18N_USER_ACTIONS
.
unblock
,
attributes
:
[{
variant
:
'
confirm
'
}],
},
}
)
,
};
},
}
)
;
},
},
};
</
script
>
<
template
>
<gl-dropdown-item
button-class=
"js-confirm-modal-button"
v-bind=
"
{ ...modalAttributes }
">
<gl-dropdown-item
@
click=
"onClick
"
>
<slot></slot>
</gl-dropdown-item>
</
template
>
app/assets/javascripts/admin/users/components/actions/unlock.vue
View file @
17dd37c6
<
script
>
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
sprintf
,
s__
,
__
}
from
'
~/locale
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
{
I18N_USER_ACTIONS
}
from
'
../../constants
'
;
export
default
{
...
...
@@ -17,12 +18,12 @@ export default {
required
:
true
,
},
},
computed
:
{
modalAttributes
()
{
return
{
'
data-path
'
:
this
.
path
,
'
data-method
'
:
'
put
'
,
'
data-modal-attributes
'
:
JSON
.
stringify
(
{
methods
:
{
onClick
()
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
{
path
:
this
.
path
,
method
:
'
put
'
,
modalAttributes
:
{
title
:
sprintf
(
s__
(
'
AdminUsers|Unlock user %{username}?
'
),
{
username
:
this
.
username
}),
message
:
__
(
'
Are you sure?
'
),
actionCancel
:
{
...
...
@@ -32,15 +33,15 @@ export default {
text
:
I18N_USER_ACTIONS
.
unlock
,
attributes
:
[{
variant
:
'
confirm
'
}],
},
}
)
,
};
},
}
)
;
},
},
};
</
script
>
<
template
>
<gl-dropdown-item
button-class=
"js-confirm-modal-button"
v-bind=
"
{ ...modalAttributes }
">
<gl-dropdown-item
@
click=
"onClick
"
>
<slot></slot>
</gl-dropdown-item>
</
template
>
app/assets/javascripts/vue_shared/components/confirm_modal.vue
View file @
17dd37c6
...
...
@@ -2,10 +2,13 @@
import
{
GlModal
,
GlSafeHtmlDirective
as
SafeHtml
}
from
'
@gitlab/ui
'
;
import
{
uniqueId
}
from
'
lodash
'
;
import
csrf
from
'
~/lib/utils/csrf
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
./confirm_modal_eventhub
'
;
import
DomElementListener
from
'
./dom_element_listener.vue
'
;
export
default
{
components
:
{
GlModal
,
DomElementListener
,
},
directives
:
{
SafeHtml
,
...
...
@@ -30,18 +33,35 @@ export default {
};
},
mounted
()
{
document
.
querySelectorAll
(
this
.
selector
).
forEach
((
button
)
=>
{
button
.
addEventListener
(
'
click
'
,
(
e
)
=>
{
e
.
preventDefault
();
this
.
path
=
button
.
dataset
.
path
;
this
.
method
=
button
.
dataset
.
method
;
this
.
modalAttributes
=
JSON
.
parse
(
button
.
dataset
.
modalAttributes
);
this
.
openModal
();
});
});
eventHub
.
$on
(
EVENT_OPEN_CONFIRM_MODAL
,
this
.
onOpenEvent
);
},
destroyed
()
{
eventHub
.
$off
(
EVENT_OPEN_CONFIRM_MODAL
,
this
.
onOpenEvent
);
},
methods
:
{
onButtonPress
(
e
)
{
const
element
=
e
.
currentTarget
;
if
(
!
element
.
dataset
.
path
)
{
return
;
}
const
modalAttributes
=
element
.
dataset
.
modalAttributes
?
JSON
.
parse
(
element
.
dataset
.
modalAttributes
)
:
{};
this
.
onOpenEvent
({
path
:
element
.
dataset
.
path
,
method
:
element
.
dataset
.
method
,
modalAttributes
,
});
},
onOpenEvent
({
path
,
method
,
modalAttributes
})
{
this
.
path
=
path
;
this
.
method
=
method
;
this
.
modalAttributes
=
modalAttributes
;
this
.
openModal
();
},
openModal
()
{
this
.
$refs
.
modal
.
show
();
},
...
...
@@ -61,21 +81,23 @@ export default {
</
script
>
<
template
>
<gl-modal
ref=
"modal"
:modal-id=
"modalId"
v-bind=
"modalAttributes"
@
primary=
"submitModal"
@
cancel=
"closeModal"
>
<form
ref=
"form"
:action=
"path"
method=
"post"
>
<!-- Rails workaround for
<form
method=
"delete"
/>
<dom-element-listener
:selector=
"selector"
@
click.prevent=
"onButtonPress"
>
<gl-modal
ref=
"modal"
:modal-id=
"modalId"
v-bind=
"modalAttributes"
@
primary=
"submitModal"
@
cancel=
"closeModal"
>
<form
ref=
"form"
:action=
"path"
method=
"post"
>
<!-- Rails workaround for
<form
method=
"delete"
/>
https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts/rails-ujs/features/method.coffee
-->
<input
type=
"hidden"
name=
"_method"
:value=
"method"
/>
<input
type=
"hidden"
name=
"authenticity_token"
:value=
"$options.csrf.token"
/>
<div
v-if=
"modalAttributes.messageHtml"
v-safe-html=
"modalAttributes.messageHtml"
></div>
<div
v-else
>
{{
modalAttributes
.
message
}}
</div>
</form>
</gl-modal>
<input
type=
"hidden"
name=
"_method"
:value=
"method"
/>
<input
type=
"hidden"
name=
"authenticity_token"
:value=
"$options.csrf.token"
/>
<div
v-if=
"modalAttributes.messageHtml"
v-safe-html=
"modalAttributes.messageHtml"
></div>
<div
v-else
>
{{
modalAttributes
.
message
}}
</div>
</form>
</gl-modal>
</dom-element-listener>
</
template
>
app/assets/javascripts/vue_shared/components/confirm_modal_eventhub.js
0 → 100644
View file @
17dd37c6
import
createEventHub
from
'
~/helpers/event_hub_factory
'
;
export
default
createEventHub
();
export
const
EVENT_OPEN_CONFIRM_MODAL
=
Symbol
(
'
OPEN
'
);
app/assets/javascripts/vue_shared/components/dom_element_listener.vue
0 → 100644
View file @
17dd37c6
<
script
>
export
default
{
props
:
{
selector
:
{
type
:
String
,
required
:
true
,
},
},
mounted
()
{
this
.
disposables
=
Array
.
from
(
document
.
querySelectorAll
(
this
.
selector
)).
flatMap
((
button
)
=>
{
return
Object
.
entries
(
this
.
$listeners
).
map
(([
key
,
value
])
=>
{
button
.
addEventListener
(
key
,
value
);
return
()
=>
{
button
.
removeEventListener
(
key
,
value
);
};
});
});
},
destroyed
()
{
this
.
disposables
.
forEach
((
x
)
=>
{
x
();
});
},
render
()
{
return
this
.
$slots
.
default
;
},
};
</
script
>
spec/frontend/admin/users/components/actions/actions_spec.js
View file @
17dd37c6
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
kebabCase
}
from
'
lodash
'
;
import
{
nextTick
}
from
'
vue
'
;
import
{
kebabCase
}
from
'
lodash
'
;
import
Actions
from
'
~/admin/users/components/actions
'
;
import
SharedDeleteAction
from
'
~/admin/users/components/actions/shared/shared_delete_action.vue
'
;
import
{
capitalizeFirstCharacter
}
from
'
~/lib/utils/text_utility
'
;
...
...
@@ -39,9 +39,6 @@ describe('Action components', () => {
});
await
nextTick
();
expect
(
wrapper
.
attributes
(
'
data-path
'
)).
toBe
(
'
/test
'
);
expect
(
wrapper
.
attributes
(
'
data-modal-attributes
'
)).
toContain
(
'
John Doe
'
);
expect
(
findDropdownItem
().
exists
()).
toBe
(
true
);
});
});
...
...
@@ -66,7 +63,6 @@ describe('Action components', () => {
});
await
nextTick
();
const
sharedAction
=
wrapper
.
find
(
SharedDeleteAction
);
expect
(
sharedAction
.
attributes
(
'
data-block-user-url
'
)).
toBe
(
paths
.
block
);
...
...
@@ -76,6 +72,7 @@ describe('Action components', () => {
expect
(
sharedAction
.
attributes
(
'
data-user-deletion-obstacles
'
)).
toBe
(
JSON
.
stringify
(
userDeletionObstacles
),
);
expect
(
findDropdownItem
().
exists
()).
toBe
(
true
);
},
);
...
...
spec/frontend/vue_shared/components/confirm_modal_spec.js
View file @
17dd37c6
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
merge
}
from
'
lodash
'
;
import
{
TEST_HOST
}
from
'
helpers/test_constants
'
;
import
eventHub
,
{
EVENT_OPEN_CONFIRM_MODAL
}
from
'
~/vue_shared/components/confirm_modal_eventhub
'
;
import
ConfirmModal
from
'
~/vue_shared/components/confirm_modal.vue
'
;
import
DomElementListener
from
'
~/vue_shared/components/dom_element_listener.vue
'
;
jest
.
mock
(
'
~/lib/utils/csrf
'
,
()
=>
({
token
:
'
test-csrf-token
'
}));
...
...
@@ -54,12 +57,50 @@ describe('vue_shared/components/confirm_modal', () => {
findForm
()
.
findAll
(
'
input
'
)
.
wrappers
.
map
((
x
)
=>
({
name
:
x
.
attributes
(
'
name
'
),
value
:
x
.
attributes
(
'
value
'
)
}));
const
findDomElementListener
=
()
=>
wrapper
.
find
(
DomElementListener
);
const
triggerOpenWithEventHub
=
(
modalData
)
=>
{
eventHub
.
$emit
(
EVENT_OPEN_CONFIRM_MODAL
,
modalData
);
};
const
triggerOpenWithDomListener
=
(
modalData
)
=>
{
const
element
=
document
.
createElement
(
'
button
'
);
element
.
dataset
.
path
=
modalData
.
path
;
element
.
dataset
.
method
=
modalData
.
method
;
element
.
dataset
.
modalAttributes
=
JSON
.
stringify
(
modalData
.
modalAttributes
);
findDomElementListener
().
vm
.
$emit
(
'
click
'
,
{
preventDefault
:
jest
.
fn
(),
currentTarget
:
element
,
});
};
describe
(
'
default
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
});
it
(
'
renders empty GlModal
'
,
()
=>
{
expect
(
findModal
().
props
()).
toEqual
({});
});
it
(
'
renders form missing values
'
,
()
=>
{
expect
(
findForm
().
attributes
(
'
action
'
)).
toBe
(
''
);
expect
(
findFormData
()).
toEqual
([
{
name
:
'
_method
'
,
value
:
undefined
},
{
name
:
'
authenticity_token
'
,
value
:
'
test-csrf-token
'
},
]);
});
});
describe
(
'
template
'
,
()
=>
{
describe
(
'
when modal data is set
'
,
()
=>
{
describe
.
each
`
desc | trigger
${
'
when opened from eventhub
'
}
|
${
triggerOpenWithEventHub
}
${
'
when opened from dom listener
'
}
|
${
triggerOpenWithDomListener
}
`
(
'
$desc
'
,
({
trigger
})
=>
{
beforeEach
(()
=>
{
createComponent
();
wrapper
.
vm
.
modalAttributes
=
MOCK_MODAL_DATA
.
modalAttributes
;
trigger
(
MOCK_MODAL_DATA
)
;
});
it
(
'
renders GlModal with data
'
,
()
=>
{
...
...
@@ -71,6 +112,14 @@ describe('vue_shared/components/confirm_modal', () => {
}),
);
});
it
(
'
renders form
'
,
()
=>
{
expect
(
findForm
().
attributes
(
'
action
'
)).
toBe
(
MOCK_MODAL_DATA
.
path
);
expect
(
findFormData
()).
toEqual
([
{
name
:
'
_method
'
,
value
:
MOCK_MODAL_DATA
.
method
},
{
name
:
'
authenticity_token
'
,
value
:
'
test-csrf-token
'
},
]);
});
});
describe
.
each
`
...
...
@@ -79,11 +128,10 @@ describe('vue_shared/components/confirm_modal', () => {
${
'
when message has html
'
}
|
${{
messageHtml
:
'
<p>Header</p><ul onhover="alert(1)"><li>First</li></ul>
'
}
} |
${
'
<p>Header</p><ul><li>First</li></ul>
'
}
`
(
'
$desc
'
,
({
attrs
,
expectation
})
=>
{
beforeEach
(()
=>
{
const
modalData
=
merge
({
...
MOCK_MODAL_DATA
},
{
modalAttributes
:
attrs
});
createComponent
();
wrapper
.
vm
.
modalAttributes
=
{
...
MOCK_MODAL_DATA
.
modalAttributes
,
...
attrs
,
};
triggerOpenWithEventHub
(
modalData
);
});
it
(
'
renders message
'
,
()
=>
{
...
...
@@ -96,8 +144,7 @@ describe('vue_shared/components/confirm_modal', () => {
describe
(
'
submitModal
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
wrapper
.
vm
.
path
=
MOCK_MODAL_DATA
.
path
;
wrapper
.
vm
.
method
=
MOCK_MODAL_DATA
.
method
;
triggerOpenWithEventHub
(
MOCK_MODAL_DATA
);
});
it
(
'
does not submit form
'
,
()
=>
{
...
...
spec/frontend/vue_shared/components/dom_element_listener_spec.js
0 → 100644
View file @
17dd37c6
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
setHTMLFixture
}
from
'
helpers/fixtures
'
;
import
DomElementListener
from
'
~/vue_shared/components/dom_element_listener.vue
'
;
const
DEFAULT_SLOT_CONTENT
=
'
Default slot content
'
;
const
SELECTOR
=
'
.js-test-include
'
;
const
HTML
=
`
<div>
<button class="js-test-include" data-testid="lorem">Lorem</button>
<button class="js-test-include" data-testid="ipsum">Ipsum</button>
<button data-testid="hello">Hello</a>
</div>
`
;
describe
(
'
~/vue_shared/components/dom_element_listener.vue
'
,
()
=>
{
let
wrapper
;
let
spies
;
const
createComponent
=
()
=>
{
wrapper
=
mount
(
DomElementListener
,
{
propsData
:
{
selector
:
SELECTOR
,
},
listeners
:
spies
,
slots
:
{
default
:
DEFAULT_SLOT_CONTENT
,
},
});
};
const
findElement
=
(
testId
)
=>
document
.
querySelector
(
`[data-testid="
${
testId
}
"]`
);
const
spiesCallCount
=
()
=>
Object
.
values
(
spies
)
.
map
((
x
)
=>
x
.
mock
.
calls
.
length
)
.
reduce
((
a
,
b
)
=>
a
+
b
);
beforeEach
(()
=>
{
setHTMLFixture
(
HTML
);
spies
=
{
click
:
jest
.
fn
(),
focus
:
jest
.
fn
(),
};
});
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
default
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
});
it
(
'
renders default slot
'
,
()
=>
{
expect
(
wrapper
.
text
()).
toBe
(
DEFAULT_SLOT_CONTENT
);
});
it
(
'
does not initially trigger listeners
'
,
()
=>
{
expect
(
spiesCallCount
()).
toBe
(
0
);
});
describe
.
each
`
event | testId
${
'
click
'
}
|
${
'
lorem
'
}
${
'
focus
'
}
|
${
'
ipsum
'
}
`
(
'
when matching element triggers event (testId=$testId, event=$event)
'
,
({
event
,
testId
})
=>
{
beforeEach
(()
=>
{
findElement
(
testId
).
dispatchEvent
(
new
Event
(
event
));
});
it
(
'
triggers listener
'
,
()
=>
{
expect
(
spiesCallCount
()).
toBe
(
1
);
expect
(
spies
[
event
]).
toHaveBeenCalledWith
(
expect
.
any
(
Event
));
expect
(
spies
[
event
]).
toHaveBeenCalledWith
(
expect
.
objectContaining
({
target
:
findElement
(
testId
),
}),
);
});
},
);
describe
.
each
`
desc | event | testId
${
'
when non-matching element triggers event
'
}
|
${
'
click
'
}
|
${
'
hello
'
}
${
'
when matching element triggers unlistened event
'
}
|
${
'
hover
'
}
|
${
'
lorem
'
}
`
(
'
$desc
'
,
({
event
,
testId
})
=>
{
beforeEach
(()
=>
{
findElement
(
testId
).
dispatchEvent
(
new
Event
(
event
));
});
it
(
'
does not trigger listeners
'
,
()
=>
{
expect
(
spiesCallCount
()).
toBe
(
0
);
});
});
});
describe
(
'
after destroyed
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
wrapper
.
destroy
();
});
describe
(
'
when matching element triggers event
'
,
()
=>
{
beforeEach
(()
=>
{
findElement
(
'
lorem
'
).
dispatchEvent
(
new
Event
(
'
click
'
));
});
it
(
'
does not trigger any listeners
'
,
()
=>
{
expect
(
spiesCallCount
()).
toBe
(
0
);
});
});
});
});
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