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
315b3848
Commit
315b3848
authored
Oct 29, 2021
by
Paul Gascou-Vaillancourt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Wrap pagination events in a helper
parent
aec26eeb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
74 additions
and
34 deletions
+74
-34
ee/app/assets/javascripts/on_demand_scans/components/tabs/base_tab.vue
.../javascripts/on_demand_scans/components/tabs/base_tab.vue
+37
-19
ee/spec/frontend/on_demand_scans/components/tabs/base_tab_spec.js
...frontend/on_demand_scans/components/tabs/base_tab_spec.js
+37
-15
No files found.
ee/app/assets/javascripts/on_demand_scans/components/tabs/base_tab.vue
View file @
315b3848
...
@@ -112,8 +112,14 @@ export default {
...
@@ -112,8 +112,14 @@ export default {
};
};
},
},
computed
:
{
computed
:
{
pipelineNodes
()
{
return
this
.
pipelines
?.
nodes
??
[];
},
hasPipelines
()
{
hasPipelines
()
{
return
Boolean
(
this
.
pipelines
?.
nodes
?.
length
);
return
this
.
pipelineNodes
.
length
>
0
;
},
pageInfo
()
{
return
this
.
pipelines
?.
pageInfo
;
},
},
tableFields
()
{
tableFields
()
{
return
this
.
fields
.
map
(({
key
,
label
})
=>
({
return
this
.
fields
.
map
(({
key
,
label
})
=>
({
...
@@ -124,6 +130,13 @@ export default {
...
@@ -124,6 +130,13 @@ export default {
}));
}));
},
},
},
},
watch
:
{
hasPipelines
(
hasPipelines
)
{
if
(
this
.
hasError
&&
hasPipelines
)
{
this
.
hasError
=
false
;
}
},
},
methods
:
{
methods
:
{
resetCursor
()
{
resetCursor
()
{
this
.
cursor
=
{
...
defaultCursor
};
this
.
cursor
=
{
...
defaultCursor
};
...
@@ -168,23 +181,24 @@ export default {
...
@@ -168,23 +181,24 @@ export default {
{{
title
}}
{{
title
}}
<gl-badge
size=
"sm"
class=
"gl-tab-counter-badge"
>
{{
itemsCount
}}
</gl-badge>
<gl-badge
size=
"sm"
class=
"gl-tab-counter-badge"
>
{{
itemsCount
}}
</gl-badge>
</
template
>
</
template
>
<
template
v-if=
"$apollo.queries.pipelines.loading"
>
<
template
v-if=
"$apollo.queries.pipelines.loading || hasPipelines"
>
<gl-skeleton-loader
v-for=
"i in 20"
:key=
"i"
:width=
"815"
:height=
"50"
>
<rect
width=
"85"
height=
"20"
x=
"15"
y=
"15"
rx=
"4"
/>
<rect
width=
"155"
height=
"20"
x=
"125"
y=
"15"
rx=
"4"
/>
<rect
width=
"60"
height=
"20"
x=
"350"
y=
"15"
rx=
"4"
/>
<rect
width=
"150"
height=
"20"
x=
"450"
y=
"15"
rx=
"4"
/>
<rect
width=
"70"
height=
"20"
x=
"640"
y=
"15"
rx=
"4"
/>
<rect
width=
"25"
height=
"20"
x=
"740"
y=
"15"
rx=
"4"
/>
</gl-skeleton-loader>
</
template
>
<
template
v-else-if=
"hasPipelines"
>
<gl-table
<gl-table
thead-class=
"gl-border-b-solid gl-border-gray-100 gl-border-1"
thead-class=
"gl-border-b-solid gl-border-gray-100 gl-border-1"
:fields=
"tableFields"
:fields=
"tableFields"
:items=
"pipelines.nodes"
:items=
"pipelineNodes"
:busy=
"$apollo.queries.pipelines.loading"
stacked=
"md"
stacked=
"md"
>
>
<template
#table-busy
>
<gl-skeleton-loader
v-for=
"i in 20"
:key=
"i"
:width=
"1000"
:height=
"45"
>
<rect
width=
"85"
height=
"20"
x=
"0"
y=
"5"
rx=
"4"
/>
<rect
width=
"100"
height=
"20"
x=
"150"
y=
"5"
rx=
"4"
/>
<rect
width=
"150"
height=
"20"
x=
"300"
y=
"5"
rx=
"4"
/>
<rect
width=
"100"
height=
"20"
x=
"500"
y=
"5"
rx=
"4"
/>
<rect
width=
"150"
height=
"20"
x=
"655"
y=
"5"
rx=
"4"
/>
<rect
width=
"70"
height=
"20"
x=
"855"
y=
"5"
rx=
"4"
/>
</gl-skeleton-loader>
</
template
>
<
template
#cell(detailedStatus)=
"{ item }"
>
<
template
#cell(detailedStatus)=
"{ item }"
>
<div
class=
"gl-my-3"
>
<div
class=
"gl-my-3"
>
<ci-badge-link
:status=
"item.detailedStatus"
/>
<ci-badge-link
:status=
"item.detailedStatus"
/>
...
@@ -207,7 +221,7 @@ export default {
...
@@ -207,7 +221,7 @@ export default {
<div
class=
"gl-display-flex gl-justify-content-center"
>
<div
class=
"gl-display-flex gl-justify-content-center"
>
<gl-keyset-pagination
<gl-keyset-pagination
data-testid=
"pagination"
data-testid=
"pagination"
v-bind=
"p
ipelines.p
ageInfo"
v-bind=
"pageInfo"
:prev-text=
"$options.i18n.previousPage"
:prev-text=
"$options.i18n.previousPage"
:next-text=
"$options.i18n.nextPage"
:next-text=
"$options.i18n.nextPage"
@
prev=
"prevPage"
@
prev=
"prevPage"
...
@@ -215,11 +229,15 @@ export default {
...
@@ -215,11 +229,15 @@ export default {
/>
/>
</div>
</div>
</template>
</template>
<
template
v-else-if=
"hasError"
>
<gl-alert
<gl-alert
variant=
"danger"
:dismissible=
"false"
class=
"gl-my-4"
data-testid=
"error-alert"
>
v-else-if=
"hasError"
{{
$options
.
i18n
.
errorMessage
}}
variant=
"danger"
</gl-alert>
:dismissible=
"false"
</
template
>
class=
"gl-my-4"
data-testid=
"error-alert"
>
{{ $options.i18n.errorMessage }}
</gl-alert>
<empty-state
v-else
:title=
"emptyStateTitle"
:text=
"emptyStateText"
no-primary-button
/>
<empty-state
v-else
:title=
"emptyStateTitle"
:text=
"emptyStateText"
no-primary-button
/>
</gl-tab>
</gl-tab>
</template>
</template>
ee/spec/frontend/on_demand_scans/components/tabs/base_tab_spec.js
View file @
315b3848
import
{
GlTab
,
GlTable
,
Gl
SkeletonLoader
,
Gl
Alert
}
from
'
@gitlab/ui
'
;
import
{
GlTab
,
GlTable
,
GlAlert
}
from
'
@gitlab/ui
'
;
import
{
createLocalVue
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
}
from
'
@vue/test-utils
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
allPipelinesWithPipelinesMock
from
'
test_fixtures/graphql/on_demand_scans/graphql/on_demand_scans.query.graphql.with_pipelines.json
'
;
import
allPipelinesWithPipelinesMock
from
'
test_fixtures/graphql/on_demand_scans/graphql/on_demand_scans.query.graphql.with_pipelines.json
'
;
...
@@ -32,7 +32,6 @@ describe('BaseTab', () => {
...
@@ -32,7 +32,6 @@ describe('BaseTab', () => {
const
findTable
=
()
=>
wrapper
.
findComponent
(
GlTable
);
const
findTable
=
()
=>
wrapper
.
findComponent
(
GlTable
);
const
findEmptyState
=
()
=>
wrapper
.
findComponent
(
EmptyState
);
const
findEmptyState
=
()
=>
wrapper
.
findComponent
(
EmptyState
);
const
findPagination
=
()
=>
wrapper
.
findByTestId
(
'
pagination
'
);
const
findPagination
=
()
=>
wrapper
.
findByTestId
(
'
pagination
'
);
const
findSkeletonLoader
=
()
=>
wrapper
.
findComponent
(
GlSkeletonLoader
);
const
findErrorAlert
=
()
=>
wrapper
.
findComponent
(
GlAlert
);
const
findErrorAlert
=
()
=>
wrapper
.
findComponent
(
GlAlert
);
// Helpers
// Helpers
...
@@ -40,6 +39,11 @@ describe('BaseTab', () => {
...
@@ -40,6 +39,11 @@ describe('BaseTab', () => {
return
createMockApollo
([[
onDemandScansQuery
,
requestHandler
]]);
return
createMockApollo
([[
onDemandScansQuery
,
requestHandler
]]);
};
};
const
navigateToPage
=
(
direction
)
=>
{
findPagination
().
vm
.
$emit
(
direction
);
return
wrapper
.
vm
.
$nextTick
();
};
const
createComponent
=
(
propsData
)
=>
{
const
createComponent
=
(
propsData
)
=>
{
router
=
createRouter
();
router
=
createRouter
();
wrapper
=
shallowMountExtended
(
BaseTab
,
{
wrapper
=
shallowMountExtended
(
BaseTab
,
{
...
@@ -68,7 +72,7 @@ describe('BaseTab', () => {
...
@@ -68,7 +72,7 @@ describe('BaseTab', () => {
`
,
`
,
}),
}),
GlTable
:
stubComponent
(
GlTable
,
{
GlTable
:
stubComponent
(
GlTable
,
{
props
:
[
'
items
'
],
props
:
[
'
items
'
,
'
busy
'
],
}),
}),
},
},
});
});
...
@@ -97,12 +101,14 @@ describe('BaseTab', () => {
...
@@ -97,12 +101,14 @@ describe('BaseTab', () => {
});
});
});
});
it
(
'
shows a loader
until the request resolves
'
,
async
()
=>
{
it
(
'
puts the table in the busy state
until the request resolves
'
,
async
()
=>
{
createComponent
();
createComponent
();
expect
(
findSkeletonLoader
().
exists
()).
toBe
(
true
);
expect
(
findTable
().
props
(
'
busy
'
)).
toBe
(
true
);
await
waitForPromises
();
await
waitForPromises
();
expect
(
findSkeletonLoader
().
exists
()).
toBe
(
false
);
expect
(
findTable
().
props
(
'
busy
'
)).
toBe
(
false
);
});
});
it
(
'
resets the route if no pipeline matches the cursor
'
,
async
()
=>
{
it
(
'
resets the route if no pipeline matches the cursor
'
,
async
()
=>
{
...
@@ -138,8 +144,8 @@ describe('BaseTab', () => {
...
@@ -138,8 +144,8 @@ describe('BaseTab', () => {
);
);
});
});
it
(
'
when navigating to another page, scrolls back to the top
'
,
()
=>
{
it
(
'
when navigating to another page, scrolls back to the top
'
,
async
()
=>
{
findPagination
().
vm
.
$emit
(
'
next
'
);
await
navigateToPage
(
'
next
'
);
expect
(
scrollToElement
).
toHaveBeenCalledWith
(
wrapper
.
vm
.
$el
);
expect
(
scrollToElement
).
toHaveBeenCalledWith
(
wrapper
.
vm
.
$el
);
});
});
...
@@ -148,18 +154,16 @@ describe('BaseTab', () => {
...
@@ -148,18 +154,16 @@ describe('BaseTab', () => {
expect
(
Object
.
keys
(
router
.
currentRoute
.
query
)).
not
.
toContain
(
'
after
'
);
expect
(
Object
.
keys
(
router
.
currentRoute
.
query
)).
not
.
toContain
(
'
after
'
);
expect
(
requestHandler
).
toHaveBeenCalledTimes
(
1
);
expect
(
requestHandler
).
toHaveBeenCalledTimes
(
1
);
findPagination
().
vm
.
$emit
(
'
next
'
);
await
navigateToPage
(
'
next
'
);
await
wrapper
.
vm
.
$nextTick
();
expect
(
Object
.
keys
(
router
.
currentRoute
.
query
)).
toContain
(
'
after
'
);
expect
(
Object
.
keys
(
router
.
currentRoute
.
query
)).
toContain
(
'
after
'
);
expect
(
requestHandler
).
toHaveBeenCalledTimes
(
2
);
expect
(
requestHandler
).
toHaveBeenCalledTimes
(
2
);
});
});
it
(
'
when navigating back to the previous page, the route is updated and pipelines are fetched
'
,
async
()
=>
{
it
(
'
when navigating back to the previous page, the route is updated and pipelines are fetched
'
,
async
()
=>
{
findPagination
().
vm
.
$emit
(
'
next
'
);
await
navigateToPage
(
'
next
'
);
await
waitForPromises
();
await
waitForPromises
();
findPagination
().
vm
.
$emit
(
'
prev
'
);
await
navigateToPage
(
'
prev
'
);
await
wrapper
.
vm
.
$nextTick
();
expect
(
Object
.
keys
(
router
.
currentRoute
.
query
)).
not
.
toContain
(
'
after
'
);
expect
(
Object
.
keys
(
router
.
currentRoute
.
query
)).
not
.
toContain
(
'
after
'
);
expect
(
Object
.
keys
(
router
.
currentRoute
.
query
)).
toContain
(
'
before
'
);
expect
(
Object
.
keys
(
router
.
currentRoute
.
query
)).
toContain
(
'
before
'
);
...
@@ -179,14 +183,32 @@ describe('BaseTab', () => {
...
@@ -179,14 +183,32 @@ describe('BaseTab', () => {
});
});
describe
(
'
when the request errors out
'
,
()
=>
{
describe
(
'
when the request errors out
'
,
()
=>
{
let
respondWithError
;
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
requestHandler
=
jest
.
fn
().
mockRejectedValue
();
respondWithError
=
true
;
requestHandler
=
()
=>
{
const
response
=
respondWithError
?
Promise
.
reject
()
:
Promise
.
resolve
(
allPipelinesWithPipelinesMock
);
respondWithError
=
false
;
return
response
;
};
createComponent
();
createComponent
();
await
waitForPromises
();
await
waitForPromises
();
});
});
it
(
'
show an error alert
'
,
()
=>
{
it
(
'
show
s
an error alert
'
,
()
=>
{
expect
(
findErrorAlert
().
exists
()).
toBe
(
true
);
expect
(
findErrorAlert
().
exists
()).
toBe
(
true
);
});
});
it
(
'
removes the alert if the next request succeeds
'
,
async
()
=>
{
expect
(
findErrorAlert
().
exists
()).
toBe
(
true
);
wrapper
.
vm
.
$apollo
.
queries
.
pipelines
.
refetch
();
await
waitForPromises
();
expect
(
findErrorAlert
().
exists
()).
toBe
(
false
);
});
});
});
});
});
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