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
064de929
Commit
064de929
authored
Jun 04, 2021
by
Brandon Labuschagne
Committed by
Martin Wortschack
Jun 04, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
DevOps Adoption separate adoption and groups loading state
parent
712f99a7
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
102 additions
and
83 deletions
+102
-83
ee/app/assets/javascripts/analytics/devops_report/devops_adoption/components/devops_adoption_app.vue
...report/devops_adoption/components/devops_adoption_app.vue
+22
-7
ee/app/assets/javascripts/analytics/devops_report/devops_adoption/components/devops_adoption_segment_modal.vue
...ops_adoption/components/devops_adoption_segment_modal.vue
+49
-32
ee/spec/frontend/analytics/devops_report/devops_adoption/components/devops_adoption_app_spec.js
...rt/devops_adoption/components/devops_adoption_app_spec.js
+0
-33
ee/spec/frontend/analytics/devops_report/devops_adoption/components/devops_adoption_segment_modal_spec.js
...adoption/components/devops_adoption_segment_modal_spec.js
+31
-11
No files found.
ee/app/assets/javascripts/analytics/devops_report/devops_adoption/components/devops_adoption_app.vue
View file @
064de929
...
...
@@ -87,6 +87,9 @@ export default {
apollo
:
{
devopsAdoptionEnabledNamespaces
:
{
query
:
devopsAdoptionEnabledNamespacesQuery
,
context
:
{
isSingleRequest
:
true
,
},
variables
()
{
return
this
.
segmentsQueryVariables
;
},
...
...
@@ -132,6 +135,11 @@ export default {
this
.
$apollo
.
queries
.
devopsAdoptionEnabledNamespaces
.
loading
);
},
isLoadingAdoptionData
()
{
return
(
this
.
isLoadingEnableGroup
||
this
.
$apollo
.
queries
.
devopsAdoptionEnabledNamespaces
.
loading
);
},
segmentLimitReached
()
{
return
this
.
devopsAdoptionEnabledNamespaces
?.
nodes
?.
length
>
this
.
$options
.
maxSegments
;
},
...
...
@@ -140,14 +148,17 @@ export default {
?
this
.
$options
.
i18n
.
groupLevelLabel
:
this
.
$options
.
i18n
.
tableHeader
.
button
;
},
canRenderModal
()
{
return
this
.
hasGroupData
&&
!
this
.
isLoading
;
},
tabIndexValues
()
{
const
tabs
=
this
.
$options
.
devopsAdoptionTableConfiguration
.
map
((
item
)
=>
item
.
tab
);
return
this
.
isGroup
?
tabs
:
[...
tabs
,
'
devops-score
'
];
},
availableGroups
()
{
return
this
.
groups
?.
nodes
||
[];
},
enabledGroups
()
{
return
this
.
devopsAdoptionEnabledNamespaces
?.
nodes
||
[];
},
},
created
()
{
this
.
fetchGroups
();
...
...
@@ -214,6 +225,9 @@ export default {
this
.
$apollo
.
query
({
query
:
getGroupsQuery
,
context
:
{
isSingleRequest
:
true
,
},
variables
:
{
nextPage
,
},
...
...
@@ -304,7 +318,7 @@ export default {
<devops-adoption-section
v-else
:is-loading=
"isLoading"
:is-loading=
"isLoading
AdoptionData
"
:has-segments-data=
"hasSegmentsData"
:timestamp=
"timestamp"
:has-group-data=
"hasGroupData"
...
...
@@ -324,10 +338,11 @@ export default {
</gl-tabs>
<devops-adoption-segment-modal
v-if=
"
canRenderModal
"
v-if=
"
!hasLoadingError
"
ref=
"addRemoveModal"
:groups=
"groups.nodes"
:enabled-groups=
"devopsAdoptionEnabledNamespaces.nodes"
:groups=
"availableGroups"
:enabled-groups=
"enabledGroups"
:is-loading=
"isLoading"
@
segmentsAdded=
"addSegmentsToCache"
@
segmentsRemoved=
"deleteSegmentsFromCache"
@
trackModalOpenState=
"trackModalOpenState"
...
...
ee/app/assets/javascripts/analytics/devops_report/devops_adoption/components/devops_adoption_segment_modal.vue
View file @
064de929
<
script
>
import
{
GlFormGroup
,
GlFormInput
,
GlFormCheckboxTree
,
GlModal
,
GlAlert
,
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
GlFormGroup
,
GlFormInput
,
GlFormCheckboxTree
,
GlModal
,
GlAlert
,
GlIcon
,
GlLoadingIcon
,
}
from
'
@gitlab/ui
'
;
import
*
as
Sentry
from
'
@sentry/browser
'
;
import
_
from
'
lodash
'
;
import
{
convertToGraphQLId
,
getIdFromGraphQLId
,
TYPE_GROUP
}
from
'
~/graphql_shared/utils
'
;
...
...
@@ -20,6 +28,7 @@ export default {
GlFormCheckboxTree
,
GlAlert
,
GlIcon
,
GlLoadingIcon
,
},
inject
:
{
isGroup
:
{
...
...
@@ -39,6 +48,11 @@ export default {
required
:
false
,
default
:
()
=>
[],
},
isLoading
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
i18n
:
DEVOPS_ADOPTION_STRINGS
.
modal
,
data
()
{
...
...
@@ -239,37 +253,40 @@ export default {
@
hidden=
"resetForm"
@
show=
"$emit('trackModalOpenState', true)"
>
<gl-alert
v-if=
"errors.length"
variant=
"danger"
class=
"gl-mb-3"
@
dismiss=
"clearErrors"
>
{{
displayError
}}
</gl-alert>
<gl-form-group
class=
"gl-mb-3"
data-testid=
"filter"
>
<gl-icon
name=
"search"
:size=
"18"
use-deprecated-sizes
class=
"gl-text-gray-300 gl-absolute gl-mt-3 gl-ml-3"
/>
<gl-form-input
v-model=
"filter"
class=
"gl-pl-7!"
type=
"text"
:placeholder=
"$options.i18n.filterPlaceholder"
:disabled=
"loading"
/>
</gl-form-group>
<gl-form-group
class=
"gl-mb-0"
>
<gl-form-checkbox-tree
v-if=
"filteredOptions.length"
v-model=
"checkboxValues"
data-testid=
"groups"
:options=
"filteredOptions"
:hide-toggle-all=
"true"
:disabled=
"loading"
class=
"gl-p-3 gl-pb-0 gl-mb-2 gl-border-1 gl-border-solid gl-border-gray-100 gl-rounded-base"
/>
<gl-alert
v-else
variant=
"info"
:dismissible=
"false"
data-testid=
"filter-warning"
>
{{
$options
.
i18n
.
noResults
}}
<gl-loading-icon
v-if=
"isLoading"
size=
"md"
class=
"gl-mt-4"
/>
<div
v-else
>
<gl-alert
v-if=
"errors.length"
variant=
"danger"
class=
"gl-mb-3"
@
dismiss=
"clearErrors"
>
{{
displayError
}}
</gl-alert>
</gl-form-group>
<gl-form-group
class=
"gl-mb-3"
data-testid=
"filter"
>
<gl-icon
name=
"search"
:size=
"18"
use-deprecated-sizes
class=
"gl-text-gray-300 gl-absolute gl-mt-3 gl-ml-3"
/>
<gl-form-input
v-model=
"filter"
class=
"gl-pl-7!"
type=
"text"
:placeholder=
"$options.i18n.filterPlaceholder"
:disabled=
"loading"
/>
</gl-form-group>
<gl-form-group
class=
"gl-mb-0"
>
<gl-form-checkbox-tree
v-if=
"filteredOptions.length"
v-model=
"checkboxValues"
data-testid=
"groups"
:options=
"filteredOptions"
:hide-toggle-all=
"true"
:disabled=
"loading"
class=
"gl-p-3 gl-pb-0 gl-mb-2 gl-border-1 gl-border-solid gl-border-gray-100 gl-rounded-base"
/>
<gl-alert
v-else
variant=
"info"
:dismissible=
"false"
data-testid=
"filter-warning"
>
{{
$options
.
i18n
.
noResults
}}
</gl-alert>
</gl-form-group>
</div>
</gl-modal>
</
template
>
ee/spec/frontend/analytics/devops_report/devops_adoption/components/devops_adoption_app_spec.js
View file @
064de929
...
...
@@ -102,18 +102,6 @@ describe('DevopsAdoptionApp', () => {
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
(
'
when loading
'
,
()
=>
{
beforeEach
(()
=>
{
const
mockApollo
=
createMockApolloProvider
();
wrapper
=
createComponent
({
mockApollo
});
});
it
(
'
does not render the modal
'
,
()
=>
{
expect
(
wrapper
.
find
(
DevopsAdoptionSegmentModal
).
exists
()).
toBe
(
false
);
});
});
describe
(
'
initial request
'
,
()
=>
{
...
...
@@ -123,19 +111,6 @@ describe('DevopsAdoptionApp', () => {
groupsSpy
=
null
;
});
describe
(
'
when no group data is present
'
,
()
=>
{
beforeEach
(
async
()
=>
{
groupsSpy
=
jest
.
fn
().
mockResolvedValueOnce
({
__typename
:
'
Groups
'
,
nodes
:
[]
});
const
mockApollo
=
createMockApolloProvider
({
groupsSpy
});
wrapper
=
createComponent
({
mockApollo
});
await
waitForPromises
();
});
it
(
'
does not render the segment modal
'
,
()
=>
{
expect
(
wrapper
.
find
(
DevopsAdoptionSegmentModal
).
exists
()).
toBe
(
false
);
});
});
describe
(
'
when group data is present
'
,
()
=>
{
beforeEach
(
async
()
=>
{
groupsSpy
=
jest
.
fn
().
mockResolvedValueOnce
({
...
initialResponse
,
pageInfo
:
null
});
...
...
@@ -164,10 +139,6 @@ describe('DevopsAdoptionApp', () => {
await
waitForPromises
();
});
it
(
'
does not render the segment modal
'
,
()
=>
{
expect
(
wrapper
.
find
(
DevopsAdoptionSegmentModal
).
exists
()).
toBe
(
false
);
});
it
(
'
should fetch data once
'
,
()
=>
{
expect
(
groupsSpy
).
toHaveBeenCalledTimes
(
1
);
});
...
...
@@ -251,10 +222,6 @@ describe('DevopsAdoptionApp', () => {
await
waitForPromises
();
});
it
(
'
does not render the segment modal
'
,
()
=>
{
expect
(
wrapper
.
find
(
DevopsAdoptionSegmentModal
).
exists
()).
toBe
(
false
);
});
it
(
'
should fetch data twice
'
,
()
=>
{
expect
(
groupsSpy
).
toHaveBeenCalledTimes
(
2
);
});
...
...
ee/spec/frontend/analytics/devops_report/devops_adoption/components/devops_adoption_segment_modal_spec.js
View file @
064de929
import
{
GlModal
,
GlFormInput
,
GlSprintf
,
GlAlert
,
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
GlModal
,
GlFormInput
,
GlSprintf
,
GlAlert
,
GlIcon
,
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
*
as
Sentry
from
'
@sentry/browser
'
;
import
{
createLocalVue
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
}
from
'
@vue/test-utils
'
;
import
Vue
,
{
nextTick
}
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
DevopsAdoptionSegmentModal
from
'
ee/analytics/devops_report/devops_adoption/components/devops_adoption_segment_modal.vue
'
;
...
...
@@ -8,6 +8,7 @@ import { DEVOPS_ADOPTION_SEGMENT_MODAL_ID } from 'ee/analytics/devops_report/dev
import
bulkEnableDevopsAdoptionNamespacesMutation
from
'
ee/analytics/devops_report/devops_adoption/graphql/mutations/bulk_enable_devops_adoption_namespaces.mutation.graphql
'
;
import
disableDevopsAdoptionNamespaceMutation
from
'
ee/analytics/devops_report/devops_adoption/graphql/mutations/disable_devops_adoption_namespace.mutation.graphql
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
{
shallowMountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
{
groupNodes
,
...
...
@@ -64,7 +65,7 @@ describe('DevopsAdoptionSegmentModal', () => {
[
bulkEnableDevopsAdoptionNamespacesMutation
,
addSegmentsSpy
],
]);
wrapper
=
shallowMount
(
DevopsAdoptionSegmentModal
,
{
wrapper
=
shallowMount
Extended
(
DevopsAdoptionSegmentModal
,
{
localVue
,
apolloProvider
:
mockApollo
,
propsData
:
{
...
...
@@ -81,7 +82,6 @@ describe('DevopsAdoptionSegmentModal', () => {
};
const
findModal
=
()
=>
wrapper
.
find
(
GlModal
);
const
findByTestId
=
(
testId
)
=>
findModal
().
find
(
`[data-testid="
${
testId
}
"]`
);
const
actionButtonDisabledState
=
()
=>
findModal
().
props
(
'
actionPrimary
'
).
attributes
[
0
].
disabled
;
const
cancelButtonDisabledState
=
()
=>
findModal
().
props
(
'
actionCancel
'
).
attributes
[
0
].
disabled
;
const
actionButtonLoadingState
=
()
=>
findModal
().
props
(
'
actionPrimary
'
).
attributes
[
0
].
loading
;
...
...
@@ -100,6 +100,26 @@ describe('DevopsAdoptionSegmentModal', () => {
expect
(
modal
.
props
(
'
modalId
'
)).
toBe
(
DEVOPS_ADOPTION_SEGMENT_MODAL_ID
);
});
describe
(
'
while loading
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
props
:
{
isLoading
:
true
}
});
});
it
(
'
displays the loading icon
'
,
()
=>
{
expect
(
wrapper
.
findComponent
(
GlLoadingIcon
).
exists
()).
toBe
(
true
);
});
it
(
'
does not display the form
'
,
()
=>
{
expect
(
wrapper
.
findByTestId
(
'
groups
'
).
exists
()).
toBe
(
false
);
});
});
it
(
'
does not display the loading icon
'
,
()
=>
{
createComponent
();
expect
(
wrapper
.
findComponent
(
GlLoadingIcon
).
exists
()).
toBe
(
false
);
});
describe
(
'
modal title
'
,
()
=>
{
it
(
'
contains the correct admin level title
'
,
()
=>
{
createComponent
();
...
...
@@ -144,7 +164,7 @@ describe('DevopsAdoptionSegmentModal', () => {
};
it
(
'
contains the checkbox tree component
'
,
()
=>
{
const
checkboxes
=
findByTestId
(
'
groups
'
);
const
checkboxes
=
wrapper
.
findByTestId
(
'
groups
'
);
expect
(
checkboxes
.
exists
()).
toBe
(
true
);
...
...
@@ -157,14 +177,14 @@ describe('DevopsAdoptionSegmentModal', () => {
describe
(
'
filtering
'
,
()
=>
{
describe
(
'
filter input field
'
,
()
=>
{
it
(
'
contains the filter input
'
,
()
=>
{
const
filter
=
findByTestId
(
'
filter
'
);
const
filter
=
wrapper
.
findByTestId
(
'
filter
'
);
expect
(
filter
.
exists
()).
toBe
(
true
);
expect
(
filter
.
find
(
GlFormInput
).
exists
()).
toBe
(
true
);
});
it
(
'
contains the filter icon
'
,
()
=>
{
const
icon
=
findByTestId
(
'
filter
'
).
find
(
GlIcon
);
const
icon
=
wrapper
.
findByTestId
(
'
filter
'
).
find
(
GlIcon
);
expect
(
icon
.
exists
()).
toBe
(
true
);
expect
(
icon
.
props
(
'
name
'
)).
toBe
(
'
search
'
);
...
...
@@ -183,7 +203,7 @@ describe('DevopsAdoptionSegmentModal', () => {
await
nextTick
();
const
checkboxes
=
findByTestId
(
'
groups
'
);
const
checkboxes
=
wrapper
.
findByTestId
(
'
groups
'
);
expect
(
checkboxes
.
props
(
'
options
'
)).
toStrictEqual
(
results
);
},
...
...
@@ -197,7 +217,7 @@ describe('DevopsAdoptionSegmentModal', () => {
});
it
(
'
displays a warning message when there are no results
'
,
async
()
=>
{
const
warning
=
findByTestId
(
'
filter-warning
'
);
const
warning
=
wrapper
.
findByTestId
(
'
filter-warning
'
);
expect
(
warning
.
exists
()).
toBe
(
true
);
expect
(
warning
.
text
()).
toBe
(
'
No filter results.
'
);
...
...
@@ -205,7 +225,7 @@ describe('DevopsAdoptionSegmentModal', () => {
});
it
(
'
hides the checkboxes
'
,
()
=>
{
const
checkboxes
=
findByTestId
(
'
groups
'
);
const
checkboxes
=
wrapper
.
findByTestId
(
'
groups
'
);
expect
(
checkboxes
.
exists
()).
toBe
(
false
);
});
...
...
@@ -250,7 +270,7 @@ describe('DevopsAdoptionSegmentModal', () => {
});
it
(
'
disables the form inputs
'
,
async
()
=>
{
const
checkboxes
=
findByTestId
(
'
groups
'
);
const
checkboxes
=
wrapper
.
findByTestId
(
'
groups
'
);
expect
(
checkboxes
.
attributes
(
'
disabled
'
)).
not
.
toBeDefined
();
...
...
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