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
da2f1b46
Commit
da2f1b46
authored
Oct 04, 2021
by
Illya Klymov
Committed by
Phil Hughes
Oct 04, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
View History of All Group Imports - Frontend
parent
b52f21df
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
623 additions
and
4 deletions
+623
-4
app/assets/javascripts/api/bulk_imports_api.js
app/assets/javascripts/api/bulk_imports_api.js
+7
-0
app/assets/javascripts/import_entities/components/pagination_bar.vue
...javascripts/import_entities/components/pagination_bar.vue
+90
-0
app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue
...k_imports/history/components/bulk_imports_history_app.vue
+176
-0
app/assets/javascripts/pages/import/bulk_imports/history/index.js
...ts/javascripts/pages/import/bulk_imports/history/index.js
+15
-0
app/assets/javascripts/pages/import/bulk_imports/history/utils/error_messages.js
...pages/import/bulk_imports/history/utils/error_messages.js
+3
-0
app/assets/javascripts/rest_api.js
app/assets/javascripts/rest_api.js
+1
-0
app/views/groups/_import_group_from_another_instance_panel.html.haml
...roups/_import_group_from_another_instance_panel.html.haml
+6
-4
app/views/import/bulk_imports/history.html.haml
app/views/import/bulk_imports/history.html.haml
+6
-0
config/routes/import.rb
config/routes/import.rb
+1
-0
locale/gitlab.pot
locale/gitlab.pot
+21
-0
spec/features/groups/import_export/migration_history_spec.rb
spec/features/groups/import_export/migration_history_spec.rb
+30
-0
spec/frontend/import_entities/components/pagination_bar_spec.js
...rontend/import_entities/components/pagination_bar_spec.js
+92
-0
spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js
...ports/history/components/bulk_imports_history_app_spec.js
+175
-0
No files found.
app/assets/javascripts/api/bulk_imports_api.js
0 → 100644
View file @
da2f1b46
import
{
buildApiUrl
}
from
'
~/api/api_utils
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
const
BULK_IMPORT_ENTITIES_PATH
=
'
/api/:version/bulk_imports/entities
'
;
export
const
getBulkImportsHistory
=
(
params
)
=>
axios
.
get
(
buildApiUrl
(
BULK_IMPORT_ENTITIES_PATH
),
{
params
});
app/assets/javascripts/import_entities/components/pagination_bar.vue
0 → 100644
View file @
da2f1b46
<
script
>
import
{
GlDropdown
,
GlDropdownItem
,
GlIcon
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
__
}
from
'
~/locale
'
;
import
PaginationLinks
from
'
~/vue_shared/components/pagination_links.vue
'
;
const
DEFAULT_PAGE_SIZES
=
[
20
,
50
,
100
];
export
default
{
components
:
{
PaginationLinks
,
GlDropdown
,
GlDropdownItem
,
GlIcon
,
GlSprintf
,
},
props
:
{
pageInfo
:
{
required
:
true
,
type
:
Object
,
},
pageSizes
:
{
required
:
false
,
type
:
Array
,
default
:
()
=>
DEFAULT_PAGE_SIZES
,
},
itemsCount
:
{
required
:
true
,
type
:
Number
,
},
},
computed
:
{
humanizedTotal
()
{
return
this
.
pageInfo
.
total
>=
1000
?
__
(
'
1000+
'
)
:
this
.
pageInfo
.
total
;
},
paginationInfo
()
{
const
{
page
,
perPage
}
=
this
.
pageInfo
;
const
start
=
(
page
-
1
)
*
perPage
+
1
;
const
end
=
start
+
this
.
itemsCount
-
1
;
return
{
start
,
end
};
},
},
methods
:
{
setPage
(
page
)
{
this
.
$emit
(
'
set-page
'
,
page
);
},
},
};
</
script
>
<
template
>
<div
class=
"gl-display-flex gl-align-items-center"
>
<pagination-links
:change=
"setPage"
:page-info=
"pageInfo"
class=
"gl-m-0"
/>
<gl-dropdown
category=
"tertiary"
class=
"gl-ml-auto"
>
<template
#button-content
>
<span
class=
"gl-font-weight-bold"
>
<gl-sprintf
:message=
"__('%
{count} items per page')">
<template
#count
>
{{
pageInfo
.
perPage
}}
</
template
>
</gl-sprintf>
</span>
<gl-icon
class=
"gl-button-icon dropdown-chevron"
name=
"chevron-down"
/>
</template>
<gl-dropdown-item
v-for=
"size in pageSizes"
:key=
"size"
@
click=
"$emit('set-page-size', size)"
>
<gl-sprintf
:message=
"__('%{count} items per page')"
>
<
template
#count
>
{{
size
}}
</
template
>
</gl-sprintf>
</gl-dropdown-item>
</gl-dropdown>
<div
class=
"gl-ml-2"
data-testid=
"information"
>
<gl-sprintf
:message=
"s__('BulkImport|Showing %{start}-%{end} of %{total}')"
>
<
template
#start
>
{{
paginationInfo
.
start
}}
</
template
>
<
template
#end
>
{{
paginationInfo
.
end
}}
</
template
>
<
template
#total
>
{{
humanizedTotal
}}
</
template
>
</gl-sprintf>
</div>
</div>
</template>
app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue
0 → 100644
View file @
da2f1b46
<
script
>
import
{
GlButton
,
GlEmptyState
,
GlLink
,
GlLoadingIcon
,
GlTable
}
from
'
@gitlab/ui
'
;
import
{
s__
,
__
}
from
'
~/locale
'
;
import
createFlash
from
'
~/flash
'
;
import
{
parseIntPagination
,
normalizeHeaders
}
from
'
~/lib/utils/common_utils
'
;
import
{
joinPaths
}
from
'
~/lib/utils/url_utility
'
;
import
{
getBulkImportsHistory
}
from
'
~/rest_api
'
;
import
ImportStatus
from
'
~/import_entities/components/import_status.vue
'
;
import
PaginationBar
from
'
~/import_entities/components/pagination_bar.vue
'
;
import
TimeAgo
from
'
~/vue_shared/components/time_ago_tooltip.vue
'
;
import
{
DEFAULT_ERROR
}
from
'
../utils/error_messages
'
;
const
DEFAULT_PER_PAGE
=
20
;
const
DEFAULT_TH_CLASSES
=
'
gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-200! gl-border-b-1! gl-p-5!
'
;
const
tableCell
=
(
config
)
=>
({
thClass
:
`
${
DEFAULT_TH_CLASSES
}
`
,
tdClass
:
(
value
,
key
,
item
)
=>
{
return
{
// eslint-disable-next-line no-underscore-dangle
'
gl-border-b-0!
'
:
item
.
_showDetails
,
};
},
...
config
,
});
export
default
{
components
:
{
GlButton
,
GlEmptyState
,
GlLink
,
GlLoadingIcon
,
GlTable
,
PaginationBar
,
ImportStatus
,
TimeAgo
,
},
data
()
{
return
{
loading
:
true
,
historyItems
:
[],
paginationConfig
:
{
page
:
1
,
perPage
:
DEFAULT_PER_PAGE
,
},
pageInfo
:
{},
};
},
fields
:
[
tableCell
({
key
:
'
source_full_path
'
,
label
:
s__
(
'
BulkImport|Source group
'
),
thClass
:
`
${
DEFAULT_TH_CLASSES
}
gl-w-30p`
,
}),
tableCell
({
key
:
'
destination_name
'
,
label
:
s__
(
'
BulkImport|New group
'
),
thClass
:
`
${
DEFAULT_TH_CLASSES
}
gl-w-40p`
,
}),
tableCell
({
key
:
'
created_at
'
,
label
:
__
(
'
Date
'
),
}),
tableCell
({
key
:
'
status
'
,
label
:
__
(
'
Status
'
),
tdAttr
:
{
'
data-qa-selector
'
:
'
import_status_indicator
'
},
}),
],
computed
:
{
hasHistoryItems
()
{
return
this
.
historyItems
.
length
>
0
;
},
},
watch
:
{
paginationConfig
:
{
handler
()
{
this
.
loadHistoryItems
();
},
deep
:
true
,
immediate
:
true
,
},
},
methods
:
{
async
loadHistoryItems
()
{
try
{
this
.
loading
=
true
;
const
{
data
:
historyItems
,
headers
}
=
await
getBulkImportsHistory
({
page
:
this
.
paginationConfig
.
page
,
per_page
:
this
.
paginationConfig
.
perPage
,
});
this
.
pageInfo
=
parseIntPagination
(
normalizeHeaders
(
headers
));
this
.
historyItems
=
historyItems
;
}
catch
(
e
)
{
createFlash
({
message
:
DEFAULT_ERROR
,
captureError
:
true
,
error
:
e
});
}
finally
{
this
.
loading
=
false
;
}
},
getDestinationUrl
({
destination_name
:
name
,
destination_namespace
:
namespace
})
{
return
[
namespace
,
name
].
filter
(
Boolean
).
join
(
'
/
'
);
},
getFullDestinationUrl
(
params
)
{
return
joinPaths
(
gon
.
relative_url_root
||
''
,
this
.
getDestinationUrl
(
params
));
},
},
gitlabLogo
:
window
.
gon
.
gitlab_logo
,
};
</
script
>
<
template
>
<div>
<div
class=
"gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1 gl-display-flex gl-align-items-center"
>
<h1
class=
"gl-my-0 gl-py-4 gl-font-size-h1"
>
<img
:src=
"$options.gitlabLogo"
class=
"gl-w-6 gl-h-6 gl-mb-2 gl-display-inline gl-mr-2"
/>
{{
s__
(
'
BulkImport|Group import history
'
)
}}
</h1>
</div>
<gl-loading-icon
v-if=
"loading"
size=
"md"
class=
"gl-mt-5"
/>
<gl-empty-state
v-else-if=
"!hasHistoryItems"
:title=
"s__('BulkImport|No history is available')"
:description=
"s__('BulkImport|Your imported groups will appear here.')"
/>
<template
v-else
>
<gl-table
:fields=
"$options.fields"
:items=
"historyItems"
data-qa-selector=
"import_history_table"
class=
"gl-w-full"
>
<template
#cell(destination_name)=
"
{ item }">
<gl-link
:href=
"getFullDestinationUrl(item)"
target=
"_blank"
>
{{
getDestinationUrl
(
item
)
}}
</gl-link>
</
template
>
<
template
#cell(created_at)=
"{ value }"
>
<time-ago
:time=
"value"
/>
</
template
>
<
template
#cell(status)=
"{ value, item, toggleDetails, detailsShowing }"
>
<import-status
:status=
"value"
class=
"gl-display-inline-block gl-w-13"
/>
<gl-button
v-if=
"item.failures.length"
class=
"gl-ml-3"
:selected=
"detailsShowing"
@
click=
"toggleDetails"
>
{{
__
(
'
Details
'
)
}}
</gl-button
>
</
template
>
<
template
#row-details=
"{ item }"
>
<pre>
{{
item
.
failures
}}
</pre>
</
template
>
</gl-table>
<pagination-bar
:page-info=
"pageInfo"
:items-count=
"historyItems.length"
class=
"gl-m-0 gl-mt-3"
@
set-page=
"paginationConfig.page = $event"
@
set-page-size=
"paginationConfig.perPage = $event"
/>
</template>
</div>
</template>
app/assets/javascripts/pages/import/bulk_imports/history/index.js
0 → 100644
View file @
da2f1b46
import
Vue
from
'
vue
'
;
import
BulkImportHistoryApp
from
'
./components/bulk_imports_history_app.vue
'
;
function
mountImportHistoryApp
(
mountElement
)
{
if
(
!
mountElement
)
return
undefined
;
return
new
Vue
({
el
:
mountElement
,
render
(
createElement
)
{
return
createElement
(
BulkImportHistoryApp
);
},
});
}
mountImportHistoryApp
(
document
.
querySelector
(
'
#import-history-mount-element
'
));
app/assets/javascripts/pages/import/bulk_imports/history/utils/error_messages.js
0 → 100644
View file @
da2f1b46
import
{
__
}
from
'
~/locale
'
;
export
const
DEFAULT_ERROR
=
__
(
'
Something went wrong on our end.
'
);
app/assets/javascripts/rest_api.js
View file @
da2f1b46
...
...
@@ -2,6 +2,7 @@ export * from './api/groups_api';
export
*
from
'
./api/projects_api
'
;
export
*
from
'
./api/user_api
'
;
export
*
from
'
./api/markdown_api
'
;
export
*
from
'
./api/bulk_imports_api
'
;
// Note: It's not possible to spy on methods imported from this file in
// Jest tests.
...
...
app/views/groups/_import_group_from_another_instance_panel.html.haml
View file @
da2f1b46
=
form_with
url:
configure_import_bulk_imports_path
,
class:
'group-form gl-show-field-errors'
do
|
f
|
.gl-border-l-solid.gl-border-r-solid.gl-border-gray-100.gl-border-1.gl-p-5
%h4
.gl-display-flex
=
s_
(
'GroupsNew|Import groups from another instance of GitLab'
)
%span
.badge.badge-info.badge-pill.gl-badge.md.gl-ml-3
=
_
(
'Beta'
)
.gl-display-flex.gl-align-items-center
%h4
.gl-display-inline-flex
=
s_
(
'GroupsNew|Import groups from another instance of GitLab'
)
%span
.badge.badge-info.badge-pill.gl-badge.md.gl-ml-3
=
_
(
'Beta'
)
=
link_to
_
(
'History'
),
history_import_bulk_imports_path
,
class:
'gl-link gl-ml-auto'
.gl-alert.gl-alert-warning
{
role:
'alert'
}
=
sprite_icon
(
'warning'
,
css_class:
'gl-icon s16 gl-alert-icon gl-alert-icon-no-title'
)
.gl-alert-body
...
...
app/views/import/bulk_imports/history.html.haml
0 → 100644
View file @
da2f1b46
-
add_to_breadcrumbs
_
(
'New group'
),
new_group_path
-
add_to_breadcrumbs
_
(
'Import group'
),
new_group_path
(
anchor:
'import-group-pane'
)
-
add_page_specific_style
'page_bundles/import'
-
page_title
_
(
'Import history'
)
#import-history-mount-element
config/routes/import.rb
View file @
da2f1b46
...
...
@@ -70,6 +70,7 @@ namespace :import do
post
:configure
get
:status
get
:realtime_changes
get
:history
end
resource
:manifest
,
only:
[
:create
,
:new
],
controller: :manifest
do
...
...
locale/gitlab.pot
View file @
da2f1b46
...
...
@@ -5860,6 +5860,9 @@ msgstr ""
msgid "BulkImport|From source group"
msgstr ""
msgid "BulkImport|Group import history"
msgstr ""
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
msgstr ""
...
...
@@ -5878,6 +5881,12 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
msgid "BulkImport|New group"
msgstr ""
msgid "BulkImport|No history is available"
msgstr ""
msgid "BulkImport|No parent"
msgstr ""
...
...
@@ -5890,6 +5899,9 @@ msgstr ""
msgid "BulkImport|Showing %{start}-%{end} of %{total} matching filter \"%{filter}\" from %{link}"
msgstr ""
msgid "BulkImport|Source group"
msgstr ""
msgid "BulkImport|To new group"
msgstr ""
...
...
@@ -5899,6 +5911,9 @@ msgstr ""
msgid "BulkImport|You have no groups to import"
msgstr ""
msgid "BulkImport|Your imported groups will appear here."
msgstr ""
msgid "BulkImport|expected an associated Group but has an associated Project"
msgstr ""
...
...
@@ -17208,12 +17223,18 @@ msgstr ""
msgid "Import from Jira"
msgstr ""
msgid "Import group"
msgstr ""
msgid "Import group from file"
msgstr ""
msgid "Import groups"
msgstr ""
msgid "Import history"
msgstr ""
msgid "Import in progress"
msgstr ""
...
...
spec/features/groups/import_export/migration_history_spec.rb
0 → 100644
View file @
da2f1b46
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Import/Export - GitLab migration history'
,
:js
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:user_import_1
)
{
create
(
:bulk_import
,
user:
user
)
}
let_it_be
(
:finished_entity_1
)
{
create
(
:bulk_import_entity
,
:finished
,
bulk_import:
user_import_1
)
}
let_it_be
(
:user_import_2
)
{
create
(
:bulk_import
,
user:
user
)
}
let_it_be
(
:failed_entity_2
)
{
create
(
:bulk_import_entity
,
:failed
,
bulk_import:
user_import_2
)
}
before
do
gitlab_sign_in
(
user
)
visit
new_group_path
click_link
'Import group'
end
it
'successfully displays import history'
do
click_link
'History'
wait_for_requests
expect
(
page
).
to
have_content
'Group import history'
expect
(
page
.
find
(
'tbody'
)).
to
have_css
(
'tr'
,
count:
2
)
end
end
spec/frontend/import_entities/components/pagination_bar_spec.js
0 → 100644
View file @
da2f1b46
import
{
GlPagination
,
GlDropdown
,
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
PaginationBar
from
'
~/import_entities/components/pagination_bar.vue
'
;
import
PaginationLinks
from
'
~/vue_shared/components/pagination_links.vue
'
;
describe
(
'
Pagination bar
'
,
()
=>
{
const
DEFAULT_PROPS
=
{
pageInfo
:
{
total
:
50
,
page
:
1
,
perPage
:
20
,
},
itemsCount
:
17
,
};
let
wrapper
;
const
createComponent
=
(
propsData
)
=>
{
wrapper
=
mount
(
PaginationBar
,
{
propsData
:
{
...
DEFAULT_PROPS
,
...
propsData
,
},
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
events
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
});
it
(
'
emits set-page event when page is selected
'
,
()
=>
{
const
NEXT_PAGE
=
3
;
// PaginationLinks uses prop instead of event for handling page change
// So we go one level deep to test this
wrapper
.
findComponent
(
PaginationLinks
)
.
findComponent
(
GlPagination
)
.
vm
.
$emit
(
'
input
'
,
NEXT_PAGE
);
expect
(
wrapper
.
emitted
(
'
set-page
'
)).
toEqual
([[
NEXT_PAGE
]]);
});
it
(
'
emits set-page-size event when page size is selected
'
,
()
=>
{
const
firstItemInPageSizeDropdown
=
wrapper
.
findComponent
(
GlDropdownItem
);
firstItemInPageSizeDropdown
.
vm
.
$emit
(
'
click
'
);
const
[
emittedPageSizeChange
]
=
wrapper
.
emitted
(
'
set-page-size
'
)[
0
];
expect
(
firstItemInPageSizeDropdown
.
text
()).
toMatchInterpolatedText
(
`
${
emittedPageSizeChange
}
items per page`
,
);
});
});
it
(
'
renders current page size
'
,
()
=>
{
const
CURRENT_PAGE_SIZE
=
40
;
createComponent
({
pageInfo
:
{
...
DEFAULT_PROPS
.
pageInfo
,
perPage
:
CURRENT_PAGE_SIZE
,
},
});
expect
(
wrapper
.
find
(
GlDropdown
).
find
(
'
button
'
).
text
()).
toMatchInterpolatedText
(
`
${
CURRENT_PAGE_SIZE
}
items per page`
,
);
});
it
(
'
renders current page information
'
,
()
=>
{
createComponent
();
expect
(
wrapper
.
find
(
'
[data-testid="information"]
'
).
text
()).
toMatchInterpolatedText
(
'
Showing 1 - 17 of 50
'
,
);
});
it
(
'
renders current page information when total count is over 1000
'
,
()
=>
{
createComponent
({
pageInfo
:
{
...
DEFAULT_PROPS
.
pageInfo
,
total
:
1200
,
},
});
expect
(
wrapper
.
find
(
'
[data-testid="information"]
'
).
text
()).
toMatchInterpolatedText
(
'
Showing 1 - 17 of 1000+
'
,
);
});
});
spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js
0 → 100644
View file @
da2f1b46
import
{
GlEmptyState
,
GlLoadingIcon
,
GlTable
}
from
'
@gitlab/ui
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
PaginationBar
from
'
~/import_entities/components/pagination_bar.vue
'
;
import
BulkImportsHistoryApp
from
'
~/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue
'
;
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
describe
(
'
BulkImportsHistoryApp
'
,
()
=>
{
const
API_URL
=
'
/api/v4/bulk_imports/entities
'
;
const
DEFAULT_HEADERS
=
{
'
x-page
'
:
1
,
'
x-per-page
'
:
20
,
'
x-next-page
'
:
2
,
'
x-total
'
:
22
,
'
x-total-pages
'
:
2
,
'
x-prev-page
'
:
null
,
};
const
DUMMY_RESPONSE
=
[
{
id
:
1
,
bulk_import_id
:
1
,
status
:
'
finished
'
,
source_full_path
:
'
top-level-group-12
'
,
destination_name
:
'
top-level-group-12
'
,
destination_namespace
:
'
h5bp
'
,
created_at
:
'
2021-07-08T10:03:44.743Z
'
,
failures
:
[],
},
{
id
:
2
,
bulk_import_id
:
2
,
status
:
'
failed
'
,
source_full_path
:
'
autodevops-demo
'
,
destination_name
:
'
autodevops-demo
'
,
destination_namespace
:
'
flightjs
'
,
parent_id
:
null
,
namespace_id
:
null
,
project_id
:
null
,
created_at
:
'
2021-07-13T12:52:26.664Z
'
,
updated_at
:
'
2021-07-13T13:34:49.403Z
'
,
failures
:
[
{
pipeline_class
:
'
BulkImports::Groups::Pipelines::GroupPipeline
'
,
pipeline_step
:
'
loader
'
,
exception_class
:
'
ActiveRecord::RecordNotUnique
'
,
correlation_id_value
:
'
01FAFYSYZ7XPF3P9NSMTS693SZ
'
,
created_at
:
'
2021-07-13T13:34:49.344Z
'
,
},
],
},
];
let
wrapper
;
let
mock
;
function
createComponent
({
shallow
=
true
}
=
{})
{
const
mountFn
=
shallow
?
shallowMount
:
mount
;
wrapper
=
mountFn
(
BulkImportsHistoryApp
);
}
const
originalApiVersion
=
gon
.
api_version
;
beforeAll
(()
=>
{
gon
.
api_version
=
'
v4
'
;
});
afterAll
(()
=>
{
gon
.
api_version
=
originalApiVersion
;
});
beforeEach
(()
=>
{
mock
=
new
MockAdapter
(
axios
);
});
afterEach
(()
=>
{
mock
.
restore
();
wrapper
.
destroy
();
});
describe
(
'
general behavior
'
,
()
=>
{
it
(
'
renders loading state when loading
'
,
()
=>
{
createComponent
();
expect
(
wrapper
.
find
(
GlLoadingIcon
).
exists
()).
toBe
(
true
);
});
it
(
'
renders empty state when no data is available
'
,
async
()
=>
{
mock
.
onGet
(
API_URL
).
reply
(
200
,
[],
DEFAULT_HEADERS
);
createComponent
();
await
axios
.
waitForAll
();
expect
(
wrapper
.
find
(
GlLoadingIcon
).
exists
()).
toBe
(
false
);
expect
(
wrapper
.
find
(
GlEmptyState
).
exists
()).
toBe
(
true
);
});
it
(
'
renders table with data when history is available
'
,
async
()
=>
{
mock
.
onGet
(
API_URL
).
reply
(
200
,
DUMMY_RESPONSE
,
DEFAULT_HEADERS
);
createComponent
();
await
axios
.
waitForAll
();
const
table
=
wrapper
.
find
(
GlTable
);
expect
(
table
.
exists
()).
toBe
(
true
);
// can't use .props() or .attributes() here
expect
(
table
.
vm
.
$attrs
.
items
).
toHaveLength
(
DUMMY_RESPONSE
.
length
);
});
it
(
'
changes page when requested by pagination bar
'
,
async
()
=>
{
const
NEW_PAGE
=
4
;
mock
.
onGet
(
API_URL
).
reply
(
200
,
DUMMY_RESPONSE
,
DEFAULT_HEADERS
);
createComponent
();
await
axios
.
waitForAll
();
mock
.
resetHistory
();
wrapper
.
findComponent
(
PaginationBar
).
vm
.
$emit
(
'
set-page
'
,
NEW_PAGE
);
await
axios
.
waitForAll
();
expect
(
mock
.
history
.
get
.
length
).
toBe
(
1
);
expect
(
mock
.
history
.
get
[
0
].
params
).
toStrictEqual
(
expect
.
objectContaining
({
page
:
NEW_PAGE
}));
});
});
it
(
'
changes page size when requested by pagination bar
'
,
async
()
=>
{
const
NEW_PAGE_SIZE
=
4
;
mock
.
onGet
(
API_URL
).
reply
(
200
,
DUMMY_RESPONSE
,
DEFAULT_HEADERS
);
createComponent
();
await
axios
.
waitForAll
();
mock
.
resetHistory
();
wrapper
.
findComponent
(
PaginationBar
).
vm
.
$emit
(
'
set-page-size
'
,
NEW_PAGE_SIZE
);
await
axios
.
waitForAll
();
expect
(
mock
.
history
.
get
.
length
).
toBe
(
1
);
expect
(
mock
.
history
.
get
[
0
].
params
).
toStrictEqual
(
expect
.
objectContaining
({
per_page
:
NEW_PAGE_SIZE
}),
);
});
describe
(
'
details button
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onGet
(
API_URL
).
reply
(
200
,
DUMMY_RESPONSE
,
DEFAULT_HEADERS
);
createComponent
({
shallow
:
false
});
return
axios
.
waitForAll
();
});
it
(
'
renders details button if relevant item has failures
'
,
async
()
=>
{
expect
(
extendedWrapper
(
wrapper
.
find
(
'
tbody
'
).
findAll
(
'
tr
'
).
at
(
1
)).
findByText
(
'
Details
'
).
exists
(),
).
toBe
(
true
);
});
it
(
'
does not render details button if relevant item has no failures
'
,
()
=>
{
expect
(
extendedWrapper
(
wrapper
.
find
(
'
tbody
'
).
findAll
(
'
tr
'
).
at
(
0
)).
findByText
(
'
Details
'
).
exists
(),
).
toBe
(
false
);
});
it
(
'
expands details when details button is clicked
'
,
async
()
=>
{
const
ORIGINAL_ROW_INDEX
=
1
;
await
extendedWrapper
(
wrapper
.
find
(
'
tbody
'
).
findAll
(
'
tr
'
).
at
(
ORIGINAL_ROW_INDEX
))
.
findByText
(
'
Details
'
)
.
trigger
(
'
click
'
);
const
detailsRowContent
=
wrapper
.
find
(
'
tbody
'
)
.
findAll
(
'
tr
'
)
.
at
(
ORIGINAL_ROW_INDEX
+
1
)
.
find
(
'
pre
'
);
expect
(
detailsRowContent
.
exists
()).
toBe
(
true
);
expect
(
JSON
.
parse
(
detailsRowContent
.
text
())).
toStrictEqual
(
DUMMY_RESPONSE
[
1
].
failures
);
});
});
});
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