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
833eadad
Commit
833eadad
authored
Oct 29, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add latest changes from gitlab-org/gitlab@master
parent
acdf997e
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
439 additions
and
673 deletions
+439
-673
app/helpers/dashboard_helper.rb
app/helpers/dashboard_helper.rb
+11
-2
app/views/admin/dashboard/index.html.haml
app/views/admin/dashboard/index.html.haml
+29
-8
changelogs/unreleased/24082-double-escaping-in-tableflip-quick-action.yml
...eased/24082-double-escaping-in-tableflip-quick-action.yml
+5
-0
changelogs/unreleased/dz-improve-admin-features.yml
changelogs/unreleased/dz-improve-admin-features.yml
+5
-0
doc/api/audit_events.md
doc/api/audit_events.md
+1
-1
lib/api/helpers/pagination.rb
lib/api/helpers/pagination.rb
+1
-248
lib/gitlab/pagination/base.rb
lib/gitlab/pagination/base.rb
+32
-0
lib/gitlab/pagination/offset_pagination.rb
lib/gitlab/pagination/offset_pagination.rb
+77
-0
lib/gitlab/quick_actions/issuable_actions.rb
lib/gitlab/quick_actions/issuable_actions.rb
+1
-1
lib/gitlab/serializer/pagination.rb
lib/gitlab/serializer/pagination.rb
+2
-3
locale/gitlab.pot
locale/gitlab.pot
+8
-2
spec/helpers/dashboard_helper_spec.rb
spec/helpers/dashboard_helper_spec.rb
+42
-19
spec/lib/api/helpers/pagination_spec.rb
spec/lib/api/helpers/pagination_spec.rb
+10
-389
spec/lib/gitlab/pagination/offset_pagination_spec.rb
spec/lib/gitlab/pagination/offset_pagination_spec.rb
+215
-0
No files found.
app/helpers/dashboard_helper.rb
View file @
833eadad
...
@@ -27,16 +27,25 @@ module DashboardHelper
...
@@ -27,16 +27,25 @@ module DashboardHelper
false
false
end
end
def
feature_entry
(
title
,
href:
nil
,
enabled:
true
)
def
feature_entry
(
title
,
href:
nil
,
enabled:
true
,
doc_href:
nil
)
enabled_text
=
enabled
?
'on'
:
'off'
enabled_text
=
enabled
?
'on'
:
'off'
label
=
"
#{
title
}
: status
#{
enabled_text
}
"
label
=
"
#{
title
}
: status
#{
enabled_text
}
"
link_or_title
=
href
&&
enabled
?
tag
.
a
(
title
,
href:
href
)
:
title
link_or_title
=
href
&&
enabled
?
tag
.
a
(
title
,
href:
href
)
:
title
tag
.
p
(
aria:
{
label:
label
})
do
tag
.
p
(
aria:
{
label:
label
})
do
concat
(
link_or_title
)
concat
(
link_or_title
)
concat
(
tag
.
span
(
class:
[
'light'
,
'float-right'
])
do
concat
(
tag
.
span
(
class:
[
'light'
,
'float-right'
])
do
concat
(
boolean_to_icon
(
enabled
)
)
boolean_to_icon
(
enabled
)
end
)
end
)
if
doc_href
.
present?
link_to_doc
=
link_to
(
sprite_icon
(
'question'
,
size:
16
),
doc_href
,
class:
'prepend-left-5'
,
title:
_
(
'Documentation'
),
target:
'_blank'
,
rel:
'noopener noreferrer'
)
concat
(
link_to_doc
)
end
end
end
end
end
...
...
app/views/admin/dashboard/index.html.haml
View file @
833eadad
...
@@ -41,17 +41,38 @@
...
@@ -41,17 +41,38 @@
.info-well
.info-well
.well-segment.admin-well.admin-well-features
.well-segment.admin-well.admin-well-features
%h4
Features
%h4
Features
=
feature_entry
(
_
(
'Sign up'
),
href:
admin_application_settings_path
(
anchor:
'js-signup-settings'
),
enabled:
allow_signup?
)
=
feature_entry
(
_
(
'Sign up'
),
=
feature_entry
(
_
(
'LDAP'
),
enabled:
Gitlab
.
config
.
ldap
.
enabled
)
href:
admin_application_settings_path
(
anchor:
'js-signup-settings'
),
=
feature_entry
(
_
(
'Gravatar'
),
href:
admin_application_settings_path
(
anchor:
'js-account-settings'
),
enabled:
gravatar_enabled?
)
enabled:
allow_signup?
)
=
feature_entry
(
_
(
'OmniAuth'
),
href:
admin_application_settings_path
(
anchor:
'js-signin-settings'
),
enabled:
Gitlab
::
Auth
.
omniauth_enabled?
)
=
feature_entry
(
_
(
'Reply by email'
),
enabled:
Gitlab
::
IncomingEmail
.
enabled?
)
=
feature_entry
(
_
(
'LDAP'
),
enabled:
Gitlab
.
config
.
ldap
.
enabled
)
=
feature_entry
(
_
(
'Gravatar'
),
href:
admin_application_settings_path
(
anchor:
'js-account-settings'
),
enabled:
gravatar_enabled?
)
=
feature_entry
(
_
(
'OmniAuth'
),
href:
admin_application_settings_path
(
anchor:
'js-signin-settings'
),
enabled:
Gitlab
::
Auth
.
omniauth_enabled?
)
=
feature_entry
(
_
(
'Reply by email'
),
enabled:
Gitlab
::
IncomingEmail
.
enabled?
)
=
render_if_exists
'admin/dashboard/elastic_and_geo'
=
render_if_exists
'admin/dashboard/elastic_and_geo'
=
feature_entry
(
_
(
'Container Registry'
),
href:
ci_cd_admin_application_settings_path
(
anchor:
'js-registry-settings'
),
enabled:
Gitlab
.
config
.
registry
.
enabled
)
=
feature_entry
(
_
(
'Container Registry'
),
=
feature_entry
(
_
(
'Gitlab Pages'
),
href:
help_instance_configuration_url
,
enabled:
Gitlab
.
config
.
pages
.
enabled
)
href:
ci_cd_admin_application_settings_path
(
anchor:
'js-registry-settings'
),
=
feature_entry
(
_
(
'Shared Runners'
),
href:
admin_runners_path
,
enabled:
Gitlab
.
config
.
gitlab_ci
.
shared_runners_enabled
)
enabled:
Gitlab
.
config
.
registry
.
enabled
,
doc_href:
help_page_path
(
'user/packages/container_registry/index'
))
=
feature_entry
(
_
(
'Gitlab Pages'
),
enabled:
Gitlab
.
config
.
pages
.
enabled
,
doc_href:
help_instance_configuration_url
)
=
feature_entry
(
_
(
'Shared Runners'
),
href:
admin_runners_path
,
enabled:
Gitlab
.
config
.
gitlab_ci
.
shared_runners_enabled
)
.col-md-4
.col-md-4
.info-well
.info-well
.well-segment.admin-well
.well-segment.admin-well
...
...
changelogs/unreleased/24082-double-escaping-in-tableflip-quick-action.yml
0 → 100644
View file @
833eadad
---
title
:
Fix double escaping in /tableflip quick action
merge_request
:
19271
author
:
Brian T
type
:
fixed
changelogs/unreleased/dz-improve-admin-features.yml
0 → 100644
View file @
833eadad
---
title
:
Improve admin dashboard features
merge_request
:
18666
author
:
type
:
changed
doc/api/audit_events.md
View file @
833eadad
...
@@ -15,7 +15,7 @@ GET /audit_events
...
@@ -15,7 +15,7 @@ GET /audit_events
|
`created_after`
| string | no | Return audit events created on or after the given time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
|
`created_after`
| string | no | Return audit events created on or after the given time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
|
`created_before`
| string | no | Return audit events created on or before the given time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
|
`created_before`
| string | no | Return audit events created on or before the given time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
|
`entity_type`
| string | no | Return audit events for the given entity type. Valid values are:
`User`
,
`Group`
, or
`Project`
. |
|
`entity_type`
| string | no | Return audit events for the given entity type. Valid values are:
`User`
,
`Group`
, or
`Project`
. |
|
`entity_id`
|
boolean
| no | Return audit events for the given entity ID. Requires
`entity_type`
attribute to be present. |
|
`entity_id`
|
integer
| no | Return audit events for the given entity ID. Requires
`entity_type`
attribute to be present. |
By default,
`GET`
requests return 20 results at a time because the API results
By default,
`GET`
requests return 20 results at a time because the API results
are paginated.
are paginated.
...
...
lib/api/helpers/pagination.rb
View file @
833eadad
...
@@ -4,254 +4,7 @@ module API
...
@@ -4,254 +4,7 @@ module API
module
Helpers
module
Helpers
module
Pagination
module
Pagination
def
paginate
(
relation
)
def
paginate
(
relation
)
strategy
=
if
params
[
:pagination
]
==
'keyset'
&&
Feature
.
enabled?
(
'api_keyset_pagination'
)
::
Gitlab
::
Pagination
::
OffsetPagination
.
new
(
self
).
paginate
(
relation
)
KeysetPaginationStrategy
else
DefaultPaginationStrategy
end
strategy
.
new
(
self
).
paginate
(
relation
)
end
class
Base
private
def
per_page
@per_page
||=
params
[
:per_page
]
end
def
base_request_uri
@base_request_uri
||=
URI
.
parse
(
request
.
url
).
tap
do
|
uri
|
uri
.
host
=
Gitlab
.
config
.
gitlab
.
host
uri
.
port
=
Gitlab
.
config
.
gitlab
.
port
end
end
def
build_page_url
(
query_params
:)
base_request_uri
.
tap
do
|
uri
|
uri
.
query
=
query_params
end
.
to_s
end
def
page_href
(
next_page_params
=
{})
query_params
=
params
.
merge
(
**
next_page_params
,
per_page:
per_page
).
to_query
build_page_url
(
query_params:
query_params
)
end
end
class
KeysetPaginationInfo
attr_reader
:relation
,
:request_context
def
initialize
(
relation
,
request_context
)
# This is because it's rather complex to support multiple values with possibly different sort directions
# (and we don't need this in the API)
if
relation
.
order_values
.
size
>
1
raise
"Pagination only supports ordering by a single column."
\
"The following columns were given:
#{
relation
.
order_values
.
map
{
|
v
|
v
.
expr
.
name
}
}"
end
@relation
=
relation
@request_context
=
request_context
end
def
fields
keys
.
zip
(
values
).
reject
{
|
_
,
v
|
v
.
nil?
}.
to_h
end
def
column_for_order_by
(
relation
)
relation
.
order_values
.
first
&
.
expr
&
.
name
end
# Sort direction (`:asc` or `:desc`)
def
sort
@sort
||=
if
order_by_primary_key?
# Default order is by id DESC
:desc
else
# API defaults to DESC order if param `sort` not present
request_context
.
params
[
:sort
]
&
.
to_sym
||
:desc
end
end
# Do we only sort by primary key?
def
order_by_primary_key?
keys
.
size
==
1
&&
keys
.
first
==
primary_key
end
def
primary_key
relation
.
model
.
primary_key
.
to_sym
end
def
sort_ascending?
sort
==
:asc
end
# Build hash of request parameters for a given record (relevant to pagination)
def
params_for
(
record
)
return
{}
unless
record
keys
.
each_with_object
({})
do
|
key
,
h
|
h
[
"ks_prev_
#{
key
}
"
.
to_sym
]
=
record
.
attributes
[
key
.
to_s
]
end
end
private
# All values present in request parameters that correspond to #keys.
def
values
@values
||=
keys
.
map
do
|
key
|
request_context
.
params
[
"ks_prev_
#{
key
}
"
.
to_sym
]
end
end
# All keys relevant to pagination.
# This always includes the primary key. Optionally, the `order_by` key is prepended.
def
keys
@keys
||=
[
column_for_order_by
(
relation
),
primary_key
].
compact
.
uniq
end
end
class
KeysetPaginationStrategy
<
Base
attr_reader
:request_context
delegate
:params
,
:header
,
:request
,
to: :request_context
def
initialize
(
request_context
)
@request_context
=
request_context
end
# rubocop: disable CodeReuse/ActiveRecord
def
paginate
(
relation
)
pagination
=
KeysetPaginationInfo
.
new
(
relation
,
request_context
)
paged_relation
=
relation
.
limit
(
per_page
)
if
conds
=
conditions
(
pagination
)
paged_relation
=
paged_relation
.
where
(
*
conds
)
end
# In all cases: sort by primary key (possibly in addition to another sort column)
paged_relation
=
paged_relation
.
order
(
pagination
.
primary_key
=>
pagination
.
sort
)
add_default_pagination_headers
if
last_record
=
paged_relation
.
last
next_page_params
=
pagination
.
params_for
(
last_record
)
add_navigation_links
(
next_page_params
)
end
paged_relation
end
# rubocop: enable CodeReuse/ActiveRecord
private
def
conditions
(
pagination
)
fields
=
pagination
.
fields
return
if
fields
.
empty?
placeholder
=
fields
.
map
{
'?'
}
comp
=
if
pagination
.
sort_ascending?
'>'
else
'<'
end
[
# Row value comparison:
# (A, B) < (a, b) <=> (A < a) OR (A = a AND B < b)
# <=> A <= a AND ((A < a) OR (A = a AND B < b))
"(
#{
fields
.
keys
.
join
(
','
)
}
)
#{
comp
}
(
#{
placeholder
.
join
(
','
)
}
)"
,
*
fields
.
values
]
end
def
add_default_pagination_headers
header
'X-Per-Page'
,
per_page
.
to_s
end
def
add_navigation_links
(
next_page_params
)
header
'X-Next-Page'
,
page_href
(
next_page_params
)
header
'Link'
,
link_for
(
'next'
,
next_page_params
)
end
def
link_for
(
rel
,
next_page_params
)
%(<#{page_href(next_page_params)}>; rel="#{rel}")
end
end
class
DefaultPaginationStrategy
<
Base
attr_reader
:request_context
delegate
:params
,
:header
,
:request
,
to: :request_context
def
initialize
(
request_context
)
@request_context
=
request_context
end
def
paginate
(
relation
)
paginate_with_limit_optimization
(
add_default_order
(
relation
)).
tap
do
|
data
|
add_pagination_headers
(
data
)
end
end
private
def
paginate_with_limit_optimization
(
relation
)
pagination_data
=
relation
.
page
(
params
[
:page
]).
per
(
params
[
:per_page
])
return
pagination_data
unless
pagination_data
.
is_a?
(
ActiveRecord
::
Relation
)
return
pagination_data
unless
Feature
.
enabled?
(
:api_kaminari_count_with_limit
)
limited_total_count
=
pagination_data
.
total_count_with_limit
if
limited_total_count
>
Kaminari
::
ActiveRecordRelationMethods
::
MAX_COUNT_LIMIT
# The call to `total_count_with_limit` memoizes `@arel` because of a call to `references_eager_loaded_tables?`
# We need to call `reset` because `without_count` relies on `@arel` being unmemoized
pagination_data
.
reset
.
without_count
else
pagination_data
end
end
def
add_default_order
(
relation
)
if
relation
.
is_a?
(
ActiveRecord
::
Relation
)
&&
relation
.
order_values
.
empty?
relation
=
relation
.
order
(
:id
)
# rubocop: disable CodeReuse/ActiveRecord
end
relation
end
def
add_pagination_headers
(
paginated_data
)
header
'X-Per-Page'
,
paginated_data
.
limit_value
.
to_s
header
'X-Page'
,
paginated_data
.
current_page
.
to_s
header
'X-Next-Page'
,
paginated_data
.
next_page
.
to_s
header
'X-Prev-Page'
,
paginated_data
.
prev_page
.
to_s
header
'Link'
,
pagination_links
(
paginated_data
)
return
if
data_without_counts?
(
paginated_data
)
header
'X-Total'
,
paginated_data
.
total_count
.
to_s
header
'X-Total-Pages'
,
total_pages
(
paginated_data
).
to_s
end
def
pagination_links
(
paginated_data
)
[].
tap
do
|
links
|
links
<<
%(<#{page_href(page: paginated_data.prev_page)}>; rel="prev")
if
paginated_data
.
prev_page
links
<<
%(<#{page_href(page: paginated_data.next_page)}>; rel="next")
if
paginated_data
.
next_page
links
<<
%(<#{page_href(page: 1)}>; rel="first")
links
<<
%(<#{page_href(page: total_pages(paginated_data))}>; rel="last")
unless
data_without_counts?
(
paginated_data
)
end
.
join
(
', '
)
end
def
total_pages
(
paginated_data
)
# Ensure there is in total at least 1 page
[
paginated_data
.
total_pages
,
1
].
max
end
def
data_without_counts?
(
paginated_data
)
paginated_data
.
is_a?
(
Kaminari
::
PaginatableWithoutCount
)
end
end
end
end
end
end
end
...
...
lib/gitlab/pagination/base.rb
0 → 100644
View file @
833eadad
# frozen_string_literal: true
module
Gitlab
module
Pagination
class
Base
private
def
per_page
@per_page
||=
params
[
:per_page
]
end
def
base_request_uri
@base_request_uri
||=
URI
.
parse
(
request
.
url
).
tap
do
|
uri
|
uri
.
host
=
Gitlab
.
config
.
gitlab
.
host
uri
.
port
=
Gitlab
.
config
.
gitlab
.
port
end
end
def
build_page_url
(
query_params
:)
base_request_uri
.
tap
do
|
uri
|
uri
.
query
=
query_params
end
.
to_s
end
def
page_href
(
next_page_params
=
{})
query_params
=
params
.
merge
(
**
next_page_params
,
per_page:
per_page
).
to_query
build_page_url
(
query_params:
query_params
)
end
end
end
end
lib/gitlab/pagination/offset_pagination.rb
0 → 100644
View file @
833eadad
# frozen_string_literal: true
module
Gitlab
module
Pagination
class
OffsetPagination
<
Base
attr_reader
:request_context
delegate
:params
,
:header
,
:request
,
to: :request_context
def
initialize
(
request_context
)
@request_context
=
request_context
end
def
paginate
(
relation
)
paginate_with_limit_optimization
(
add_default_order
(
relation
)).
tap
do
|
data
|
add_pagination_headers
(
data
)
end
end
private
def
paginate_with_limit_optimization
(
relation
)
pagination_data
=
relation
.
page
(
params
[
:page
]).
per
(
params
[
:per_page
])
return
pagination_data
unless
pagination_data
.
is_a?
(
ActiveRecord
::
Relation
)
return
pagination_data
unless
Feature
.
enabled?
(
:api_kaminari_count_with_limit
)
limited_total_count
=
pagination_data
.
total_count_with_limit
if
limited_total_count
>
Kaminari
::
ActiveRecordRelationMethods
::
MAX_COUNT_LIMIT
# The call to `total_count_with_limit` memoizes `@arel` because of a call to `references_eager_loaded_tables?`
# We need to call `reset` because `without_count` relies on `@arel` being unmemoized
pagination_data
.
reset
.
without_count
else
pagination_data
end
end
def
add_default_order
(
relation
)
if
relation
.
is_a?
(
ActiveRecord
::
Relation
)
&&
relation
.
order_values
.
empty?
relation
=
relation
.
order
(
:id
)
# rubocop: disable CodeReuse/ActiveRecord
end
relation
end
def
add_pagination_headers
(
paginated_data
)
header
'X-Per-Page'
,
paginated_data
.
limit_value
.
to_s
header
'X-Page'
,
paginated_data
.
current_page
.
to_s
header
'X-Next-Page'
,
paginated_data
.
next_page
.
to_s
header
'X-Prev-Page'
,
paginated_data
.
prev_page
.
to_s
header
'Link'
,
pagination_links
(
paginated_data
)
return
if
data_without_counts?
(
paginated_data
)
header
'X-Total'
,
paginated_data
.
total_count
.
to_s
header
'X-Total-Pages'
,
total_pages
(
paginated_data
).
to_s
end
def
pagination_links
(
paginated_data
)
[].
tap
do
|
links
|
links
<<
%(<#{page_href(page: paginated_data.prev_page)}>; rel="prev")
if
paginated_data
.
prev_page
links
<<
%(<#{page_href(page: paginated_data.next_page)}>; rel="next")
if
paginated_data
.
next_page
links
<<
%(<#{page_href(page: 1)}>; rel="first")
links
<<
%(<#{page_href(page: total_pages(paginated_data))}>; rel="last")
unless
data_without_counts?
(
paginated_data
)
end
.
join
(
', '
)
end
def
total_pages
(
paginated_data
)
# Ensure there is in total at least 1 page
[
paginated_data
.
total_pages
,
1
].
max
end
def
data_without_counts?
(
paginated_data
)
paginated_data
.
is_a?
(
Kaminari
::
PaginatableWithoutCount
)
end
end
end
end
lib/gitlab/quick_actions/issuable_actions.rb
View file @
833eadad
...
@@ -234,7 +234,7 @@ module Gitlab
...
@@ -234,7 +234,7 @@ module Gitlab
"
#{
comment
}
#{
SHRUG
}
"
"
#{
comment
}
#{
SHRUG
}
"
end
end
desc
_
(
"Append the comment with %{
TABLEFLIP
}"
)
%
{
tableflip:
TABLEFLIP
}
desc
_
(
"Append the comment with %{
tableflip
}"
)
%
{
tableflip:
TABLEFLIP
}
params
'<Comment>'
params
'<Comment>'
types
Issuable
types
Issuable
substitution
:tableflip
do
|
comment
|
substitution
:tableflip
do
|
comment
|
...
...
lib/gitlab/serializer/pagination.rb
View file @
833eadad
...
@@ -4,7 +4,6 @@ module Gitlab
...
@@ -4,7 +4,6 @@ module Gitlab
module
Serializer
module
Serializer
class
Pagination
class
Pagination
InvalidResourceError
=
Class
.
new
(
StandardError
)
InvalidResourceError
=
Class
.
new
(
StandardError
)
include
::
API
::
Helpers
::
Pagination
def
initialize
(
request
,
response
)
def
initialize
(
request
,
response
)
@request
=
request
@request
=
request
...
@@ -13,13 +12,13 @@ module Gitlab
...
@@ -13,13 +12,13 @@ module Gitlab
def
paginate
(
resource
)
def
paginate
(
resource
)
if
resource
.
respond_to?
(
:page
)
if
resource
.
respond_to?
(
:page
)
super
(
resource
)
::
Gitlab
::
Pagination
::
OffsetPagination
.
new
(
self
).
paginate
(
resource
)
else
else
raise
InvalidResourceError
raise
InvalidResourceError
end
end
end
end
# Methods needed by `
API::Helpers::
Pagination`
# Methods needed by `
Gitlab::Pagination::Offset
Pagination`
#
#
attr_reader
:request
attr_reader
:request
...
...
locale/gitlab.pot
View file @
833eadad
...
@@ -1761,10 +1761,10 @@ msgstr ""
...
@@ -1761,10 +1761,10 @@ msgstr ""
msgid "Appearance was successfully updated."
msgid "Appearance was successfully updated."
msgstr ""
msgstr ""
msgid "Append the comment with %{
TABLEFLIP
}"
msgid "Append the comment with %{
shrug
}"
msgstr ""
msgstr ""
msgid "Append the comment with %{
shrug
}"
msgid "Append the comment with %{
tableflip
}"
msgstr ""
msgstr ""
msgid "Application"
msgid "Application"
...
@@ -5742,6 +5742,9 @@ msgstr ""
...
@@ -5742,6 +5742,9 @@ msgstr ""
msgid "Dockerfile"
msgid "Dockerfile"
msgstr ""
msgstr ""
msgid "Documentation"
msgstr ""
msgid "Documentation for popular identity providers"
msgid "Documentation for popular identity providers"
msgstr ""
msgstr ""
...
@@ -10502,6 +10505,9 @@ msgstr ""
...
@@ -10502,6 +10505,9 @@ msgstr ""
msgid "Metrics|There was an error fetching the environments data, please try again"
msgid "Metrics|There was an error fetching the environments data, please try again"
msgstr ""
msgstr ""
msgid "Metrics|There was an error fetching the logs, please try again"
msgstr ""
msgid "Metrics|There was an error getting deployment information."
msgid "Metrics|There was an error getting deployment information."
msgstr ""
msgstr ""
...
...
spec/helpers/dashboard_helper_spec.rb
View file @
833eadad
...
@@ -25,39 +25,62 @@ describe DashboardHelper do
...
@@ -25,39 +25,62 @@ describe DashboardHelper do
end
end
describe
'#feature_entry'
do
describe
'#feature_entry'
do
context
'when implicitly enabled'
do
shared_examples
"a feature is enabled"
do
it
'considers feature enabled by default'
do
it
{
is_expected
.
to
include
(
'<p aria-label="Demo: status on">'
)
}
entry
=
feature_entry
(
'Demo'
,
href:
'demo.link'
)
end
shared_examples
"a feature is disabled"
do
it
{
is_expected
.
to
include
(
'<p aria-label="Demo: status off">'
)
}
end
expect
(
entry
).
to
include
(
'<p aria-label="Demo: status on">'
)
shared_examples
"a feature without link"
do
expect
(
entry
).
to
include
(
'<a href="demo.link">Demo</a>'
)
it
do
is_expected
.
not_to
have_link
(
'Demo'
)
is_expected
.
not_to
have_link
(
'Documentation'
)
end
end
end
end
shared_examples
"a feature with configuration"
do
it
{
is_expected
.
to
have_link
(
'Demo'
,
href:
'demo.link'
)
}
end
shared_examples
"a feature with documentation"
do
it
{
is_expected
.
to
have_link
(
'Documentation'
,
href:
'doc.link'
)
}
end
context
'when implicitly enabled'
do
subject
{
feature_entry
(
'Demo'
)
}
it_behaves_like
'a feature is enabled'
end
context
'when explicitly enabled'
do
context
'when explicitly enabled'
do
it
'returns a link
'
do
context
'without links
'
do
entry
=
feature_entry
(
'Demo'
,
href:
'demo.link'
,
enabled:
true
)
subject
{
feature_entry
(
'Demo'
,
enabled:
true
)
}
expect
(
entry
).
to
include
(
'<p aria-label="Demo: status on">'
)
it_behaves_like
'a feature is enabled'
expect
(
entry
).
to
include
(
'<a href="demo.link">Demo</a>'
)
it_behaves_like
'a feature without link'
end
end
it
'returns text if href is not provided
'
do
context
'with configure link
'
do
entry
=
feature_entry
(
'Demo'
,
enabled:
true
)
subject
{
feature_entry
(
'Demo'
,
href:
'demo.link'
,
enabled:
true
)
}
expect
(
entry
).
to
include
(
'<p aria-label="Demo: status on">'
)
it_behaves_like
'a feature with configuration'
expect
(
entry
).
not_to
match
(
/<a[^>]+>/
)
end
context
'with configure and documentation links'
do
subject
{
feature_entry
(
'Demo'
,
href:
'demo.link'
,
doc_href:
'doc.link'
,
enabled:
true
)
}
it_behaves_like
'a feature with configuration'
it_behaves_like
'a feature with documentation'
end
end
end
end
context
'when disabled'
do
context
'when disabled'
do
it
'returns text without link'
do
subject
{
feature_entry
(
'Demo'
,
href:
'demo.link'
,
enabled:
false
)
}
entry
=
feature_entry
(
'Demo'
,
href:
'demo.link'
,
enabled:
false
)
expect
(
entry
).
to
include
(
'<p aria-label="Demo: status off">'
)
it_behaves_like
'a feature is disabled'
expect
(
entry
).
not_to
match
(
/<a[^>]+>/
)
it_behaves_like
'a feature without link'
expect
(
entry
).
to
include
(
'Demo'
)
end
end
end
end
end
...
...
spec/lib/api/helpers/pagination_spec.rb
View file @
833eadad
This diff is collapsed.
Click to expand it.
spec/lib/gitlab/pagination/offset_pagination_spec.rb
0 → 100644
View file @
833eadad
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Pagination
::
OffsetPagination
do
let
(
:resource
)
{
Project
.
all
}
let
(
:custom_port
)
{
8080
}
let
(
:incoming_api_projects_url
)
{
"
#{
Gitlab
.
config
.
gitlab
.
url
}
:
#{
custom_port
}
/api/v4/projects"
}
before
do
stub_config_setting
(
port:
custom_port
)
end
let
(
:request_context
)
{
double
(
"request_context"
)
}
subject
do
described_class
.
new
(
request_context
)
end
describe
'#paginate'
do
let
(
:value
)
{
spy
(
'return value'
)
}
let
(
:base_query
)
{
{
foo:
'bar'
,
bar:
'baz'
}
}
let
(
:query
)
{
base_query
}
before
do
allow
(
request_context
).
to
receive
(
:header
).
and_return
(
value
)
allow
(
request_context
).
to
receive
(
:params
).
and_return
(
query
)
allow
(
request_context
).
to
receive
(
:request
).
and_return
(
double
(
url:
"
#{
incoming_api_projects_url
}
?
#{
query
.
to_query
}
"
))
end
context
'when resource can be paginated'
do
before
do
create_list
(
:project
,
3
)
end
describe
'first page'
do
shared_examples
'response with pagination headers'
do
it
'adds appropriate headers'
do
expect_header
(
'X-Total'
,
'3'
)
expect_header
(
'X-Total-Pages'
,
'2'
)
expect_header
(
'X-Per-Page'
,
'2'
)
expect_header
(
'X-Page'
,
'1'
)
expect_header
(
'X-Next-Page'
,
'2'
)
expect_header
(
'X-Prev-Page'
,
''
)
expect_header
(
'Link'
,
anything
)
do
|
_key
,
val
|
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
1
).
to_query
}
>; rel="first")
)
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
2
).
to_query
}
>; rel="last")
)
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
2
).
to_query
}
>; rel="next")
)
expect
(
val
).
not_to
include
(
'rel="prev"'
)
end
subject
.
paginate
(
resource
)
end
end
shared_examples
'paginated response'
do
it
'returns appropriate amount of resources'
do
expect
(
subject
.
paginate
(
resource
).
count
).
to
eq
2
end
it
'executes only one SELECT COUNT query'
do
expect
{
subject
.
paginate
(
resource
)
}.
to
make_queries_matching
(
/SELECT COUNT/
,
1
)
end
end
let
(
:query
)
{
base_query
.
merge
(
page:
1
,
per_page:
2
)
}
context
'when the api_kaminari_count_with_limit feature flag is unset'
do
it_behaves_like
'paginated response'
it_behaves_like
'response with pagination headers'
end
context
'when the api_kaminari_count_with_limit feature flag is disabled'
do
before
do
stub_feature_flags
(
api_kaminari_count_with_limit:
false
)
end
it_behaves_like
'paginated response'
it_behaves_like
'response with pagination headers'
end
context
'when the api_kaminari_count_with_limit feature flag is enabled'
do
before
do
stub_feature_flags
(
api_kaminari_count_with_limit:
true
)
end
context
'when resources count is less than MAX_COUNT_LIMIT'
do
before
do
stub_const
(
"::Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT"
,
4
)
end
it_behaves_like
'paginated response'
it_behaves_like
'response with pagination headers'
end
context
'when resources count is more than MAX_COUNT_LIMIT'
do
before
do
stub_const
(
"::Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT"
,
2
)
end
it_behaves_like
'paginated response'
it
'does not return the X-Total and X-Total-Pages headers'
do
expect_no_header
(
'X-Total'
)
expect_no_header
(
'X-Total-Pages'
)
expect_header
(
'X-Per-Page'
,
'2'
)
expect_header
(
'X-Page'
,
'1'
)
expect_header
(
'X-Next-Page'
,
'2'
)
expect_header
(
'X-Prev-Page'
,
''
)
expect_header
(
'Link'
,
anything
)
do
|
_key
,
val
|
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
1
).
to_query
}
>; rel="first")
)
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
2
).
to_query
}
>; rel="next")
)
expect
(
val
).
not_to
include
(
'rel="last"'
)
expect
(
val
).
not_to
include
(
'rel="prev"'
)
end
subject
.
paginate
(
resource
)
end
end
end
end
describe
'second page'
do
let
(
:query
)
{
base_query
.
merge
(
page:
2
,
per_page:
2
)
}
it
'returns appropriate amount of resources'
do
expect
(
subject
.
paginate
(
resource
).
count
).
to
eq
1
end
it
'adds appropriate headers'
do
expect_header
(
'X-Total'
,
'3'
)
expect_header
(
'X-Total-Pages'
,
'2'
)
expect_header
(
'X-Per-Page'
,
'2'
)
expect_header
(
'X-Page'
,
'2'
)
expect_header
(
'X-Next-Page'
,
''
)
expect_header
(
'X-Prev-Page'
,
'1'
)
expect_header
(
'Link'
,
anything
)
do
|
_key
,
val
|
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
1
).
to_query
}
>; rel="first")
)
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
2
).
to_query
}
>; rel="last")
)
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
1
).
to_query
}
>; rel="prev")
)
expect
(
val
).
not_to
include
(
'rel="next"'
)
end
subject
.
paginate
(
resource
)
end
end
context
'if order'
do
it
'is not present it adds default order(:id) if no order is present'
do
resource
.
order_values
=
[]
paginated_relation
=
subject
.
paginate
(
resource
)
expect
(
resource
.
order_values
).
to
be_empty
expect
(
paginated_relation
.
order_values
).
to
be_present
expect
(
paginated_relation
.
order_values
.
first
).
to
be_ascending
expect
(
paginated_relation
.
order_values
.
first
.
expr
.
name
).
to
eq
'id'
end
it
'is present it does not add anything'
do
paginated_relation
=
subject
.
paginate
(
resource
.
order
(
created_at: :desc
))
expect
(
paginated_relation
.
order_values
).
to
be_present
expect
(
paginated_relation
.
order_values
.
first
).
to
be_descending
expect
(
paginated_relation
.
order_values
.
first
.
expr
.
name
).
to
eq
'created_at'
end
end
end
context
'when resource empty'
do
describe
'first page'
do
let
(
:query
)
{
base_query
.
merge
(
page:
1
,
per_page:
2
)
}
it
'returns appropriate amount of resources'
do
expect
(
subject
.
paginate
(
resource
).
count
).
to
eq
0
end
it
'adds appropriate headers'
do
expect_header
(
'X-Total'
,
'0'
)
expect_header
(
'X-Total-Pages'
,
'1'
)
expect_header
(
'X-Per-Page'
,
'2'
)
expect_header
(
'X-Page'
,
'1'
)
expect_header
(
'X-Next-Page'
,
''
)
expect_header
(
'X-Prev-Page'
,
''
)
expect_header
(
'Link'
,
anything
)
do
|
_key
,
val
|
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
1
).
to_query
}
>; rel="first")
)
expect
(
val
).
to
include
(
%Q(<
#{
incoming_api_projects_url
}
?
#{
query
.
merge
(
page:
1
).
to_query
}
>; rel="last")
)
expect
(
val
).
not_to
include
(
'rel="prev"'
)
expect
(
val
).
not_to
include
(
'rel="next"'
)
expect
(
val
).
not_to
include
(
'page=0'
)
end
subject
.
paginate
(
resource
)
end
end
end
end
def
expect_header
(
*
args
,
&
block
)
expect
(
subject
).
to
receive
(
:header
).
with
(
*
args
,
&
block
)
end
def
expect_no_header
(
*
args
,
&
block
)
expect
(
subject
).
not_to
receive
(
:header
).
with
(
*
args
)
end
def
expect_message
(
method
)
expect
(
subject
).
to
receive
(
method
)
.
at_least
(
:once
).
and_return
(
value
)
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