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
cd15d0e6
Commit
cd15d0e6
authored
Dec 06, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add latest changes from gitlab-org/gitlab@master
parent
dd6afb4b
Changes
60
Show whitespace changes
Inline
Side-by-side
Showing
60 changed files
with
1216 additions
and
103 deletions
+1216
-103
app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
...fidential_merge_request/components/project_form_group.vue
+17
-13
app/assets/stylesheets/framework/dropdowns.scss
app/assets/stylesheets/framework/dropdowns.scss
+1
-1
app/assets/stylesheets/pages/issues.scss
app/assets/stylesheets/pages/issues.scss
+0
-1
app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
...esolvers/error_tracking/sentry_detailed_error_resolver.rb
+28
-0
app/graphql/types/error_tracking/sentry_detailed_error_type.rb
...raphql/types/error_tracking/sentry_detailed_error_type.rb
+93
-0
app/graphql/types/error_tracking/sentry_error_frequency_type.rb
...aphql/types/error_tracking/sentry_error_frequency_type.rb
+18
-0
app/graphql/types/error_tracking/sentry_error_status_enum.rb
app/graphql/types/error_tracking/sentry_error_status_enum.rb
+15
-0
app/graphql/types/project_type.rb
app/graphql/types/project_type.rb
+6
-0
app/models/concerns/issuable.rb
app/models/concerns/issuable.rb
+1
-1
app/policies/error_tracking/detailed_error_policy.rb
app/policies/error_tracking/detailed_error_policy.rb
+7
-0
app/presenters/sentry_detailed_error_presenter.rb
app/presenters/sentry_detailed_error_presenter.rb
+15
-0
app/views/projects/issues/_new_branch.html.haml
app/views/projects/issues/_new_branch.html.haml
+1
-1
changelogs/unreleased/34943-graphql-sentry-details.yml
changelogs/unreleased/34943-graphql-sentry-details.yml
+5
-0
changelogs/unreleased/38244-fix-release-filter-on-mr-page.yml
...gelogs/unreleased/38244-fix-release-filter-on-mr-page.yml
+5
-0
changelogs/unreleased/confidential_mr_styling.yml
changelogs/unreleased/confidential_mr_styling.yml
+5
-0
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+154
-0
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+490
-0
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+34
-0
doc/ci/yaml/README.md
doc/ci/yaml/README.md
+29
-1
lib/gitlab/error_tracking/detailed_error.rb
lib/gitlab/error_tracking/detailed_error.rb
+6
-0
locale/gitlab.pot
locale/gitlab.pot
+5
-2
spec/factories/error_tracking/detailed_error.rb
spec/factories/error_tracking/detailed_error.rb
+8
-4
spec/features/issues/user_creates_confidential_merge_request_spec.rb
...es/issues/user_creates_confidential_merge_request_spec.rb
+1
-1
spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap
.../components/__snapshots__/project_form_group_spec.js.snap
+8
-22
spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
...ers/error_tracking/sentry_detailed_error_resolver_spec.rb
+62
-0
spec/graphql/types/error_tracking/sentry_detailed_error_type_spec.rb
...l/types/error_tracking/sentry_detailed_error_type_spec.rb
+37
-0
spec/graphql/types/project_type_spec.rb
spec/graphql/types/project_type_spec.rb
+1
-2
spec/javascripts/vue_shared/components/bar_chart_spec.js
spec/javascripts/vue_shared/components/bar_chart_spec.js
+1
-1
spec/javascripts/vue_shared/components/ci_badge_link_spec.js
spec/javascripts/vue_shared/components/ci_badge_link_spec.js
+1
-1
spec/javascripts/vue_shared/components/ci_icon_spec.js
spec/javascripts/vue_shared/components/ci_icon_spec.js
+1
-1
spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
...e_shared/components/content_viewer/content_viewer_spec.js
+2
-2
spec/javascripts/vue_shared/components/deprecated_modal_2_spec.js
...ascripts/vue_shared/components/deprecated_modal_2_spec.js
+1
-1
spec/javascripts/vue_shared/components/deprecated_modal_spec.js
...avascripts/vue_shared/components/deprecated_modal_spec.js
+1
-1
spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
...pts/vue_shared/components/diff_viewer/diff_viewer_spec.js
+1
-1
spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
.../components/diff_viewer/viewers/image_diff_viewer_spec.js
+1
-1
spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
...ts/vue_shared/components/dropdown/dropdown_button_spec.js
+1
-2
spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js
..._shared/components/dropdown/dropdown_hidden_input_spec.js
+1
-2
spec/javascripts/vue_shared/components/dropdown/dropdown_search_input_spec.js
..._shared/components/dropdown/dropdown_search_input_spec.js
+1
-2
spec/javascripts/vue_shared/components/file_finder/index_spec.js
...vascripts/vue_shared/components/file_finder/index_spec.js
+2
-2
spec/javascripts/vue_shared/components/file_finder/item_spec.js
...avascripts/vue_shared/components/file_finder/item_spec.js
+1
-1
spec/javascripts/vue_shared/components/file_row_spec.js
spec/javascripts/vue_shared/components/file_row_spec.js
+1
-1
spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
...ts/vue_shared/components/filtered_search_dropdown_spec.js
+1
-1
spec/javascripts/vue_shared/components/header_ci_component_spec.js
...scripts/vue_shared/components/header_ci_component_spec.js
+1
-1
spec/javascripts/vue_shared/components/icon_spec.js
spec/javascripts/vue_shared/components/icon_spec.js
+2
-2
spec/javascripts/vue_shared/components/loading_button_spec.js
.../javascripts/vue_shared/components/loading_button_spec.js
+1
-1
spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
...avascripts/vue_shared/components/markdown/toolbar_spec.js
+1
-1
spec/javascripts/vue_shared/components/navigation_tabs_spec.js
...javascripts/vue_shared/components/navigation_tabs_spec.js
+1
-1
spec/javascripts/vue_shared/components/panel_resizer_spec.js
spec/javascripts/vue_shared/components/panel_resizer_spec.js
+1
-1
spec/javascripts/vue_shared/components/pikaday_spec.js
spec/javascripts/vue_shared/components/pikaday_spec.js
+1
-1
spec/javascripts/vue_shared/components/project_avatar/default_spec.js
...ipts/vue_shared/components/project_avatar/default_spec.js
+2
-2
spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
...red/components/project_selector/project_list_item_spec.js
+1
-1
spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
...ared/components/project_selector/project_selector_spec.js
+2
-2
spec/javascripts/vue_shared/components/smart_virtual_list_spec.js
...ascripts/vue_shared/components/smart_virtual_list_spec.js
+1
-1
spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
...cripts/vue_shared/components/stacked_progress_bar_spec.js
+1
-2
spec/javascripts/vue_shared/components/toggle_button_spec.js
spec/javascripts/vue_shared/components/toggle_button_spec.js
+1
-1
spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
...vue_shared/components/user_avatar/user_avatar_svg_spec.js
+1
-1
spec/javascripts/vue_shared/translate_spec.js
spec/javascripts/vue_shared/translate_spec.js
+1
-1
spec/models/concerns/issuable_spec.rb
spec/models/concerns/issuable_spec.rb
+31
-15
spec/presenters/sentry_detailed_error_presenter_spec.rb
spec/presenters/sentry_detailed_error_presenter_spec.rb
+29
-0
spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
...ject/error_tracking/sentry_detailed_error_request_spec.rb
+69
-0
No files found.
app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
View file @
cd15d0e6
<
script
>
import
{
GlLink
}
from
'
@gitlab/ui
'
;
import
{
__
,
sprintf
}
from
'
../../locale
'
;
import
{
GlLink
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
__
}
from
'
../../locale
'
;
import
createFlash
from
'
../../flash
'
;
import
Api
from
'
../../api
'
;
import
state
from
'
../state
'
;
...
...
@@ -9,6 +9,7 @@ import Dropdown from './dropdown.vue';
export
default
{
components
:
{
GlLink
,
GlSprintf
,
Dropdown
,
},
props
:
{
...
...
@@ -38,15 +39,6 @@ export default {
selectedProject
()
{
return
state
.
selectedProject
;
},
noForkText
()
{
return
sprintf
(
__
(
"
To protect this issue's confidentiality, %{link_start}fork the project%{link_end} and set the forks visibility to private.
"
,
),
{
link_start
:
`<a href="
${
this
.
newForkPath
}
" class="help-link">`
,
link_end
:
'
</a>
'
},
false
,
);
},
},
mounted
()
{
this
.
fetchProjects
();
...
...
@@ -123,8 +115,20 @@ export default {
}}
</
template
>
<
template
v-else
>
{{
__
(
'
No forks available to you.
'
)
}}
<br
/>
<span
v-html=
"noForkText"
></span>
{{
__
(
'
No forks are available to you.
'
)
}}
<br
/>
<gl-sprintf
:message=
"
__(
`To protect this issue's confidentiality, %
{forkLink} and set the fork's visibility to private.`,
)
"
>
<template
#forkLink
>
<a
:href=
"newForkPath"
target=
"_blank"
class=
"help-link"
>
{{
__
(
'
fork this project
'
)
}}
</a>
</
template
>
</gl-sprintf>
</template>
<gl-link
:href=
"helpPagePath"
...
...
app/assets/stylesheets/framework/dropdowns.scss
View file @
cd15d0e6
...
...
@@ -288,7 +288,7 @@
list-style
:
none
;
padding
:
0
1px
;
a
,
a
:not
(
.help-link
)
,
button
,
.menu-item
{
@include
dropdown-link
;
...
...
app/assets/stylesheets/pages/issues.scss
View file @
cd15d0e6
...
...
@@ -214,7 +214,6 @@ ul.related-merge-requests > li {
}
.create-merge-request-dropdown-menu
{
width
:
300px
;
opacity
:
1
;
visibility
:
visible
;
transform
:
translateY
(
0
);
...
...
app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
module
Resolvers
module
ErrorTracking
class
SentryDetailedErrorResolver
<
BaseResolver
argument
:id
,
GraphQL
::
ID_TYPE
,
required:
true
,
description:
'ID of the Sentry issue'
def
resolve
(
**
args
)
project
=
object
current_user
=
context
[
:current_user
]
issue_id
=
GlobalID
.
parse
(
args
[
:id
]).
model_id
# Get data from Sentry
response
=
::
ErrorTracking
::
IssueDetailsService
.
new
(
project
,
current_user
,
{
issue_id:
issue_id
}
).
execute
issue
=
response
[
:issue
]
issue
.
gitlab_project
=
project
if
issue
issue
end
end
end
end
app/graphql/types/error_tracking/sentry_detailed_error_type.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
module
Types
module
ErrorTracking
class
SentryDetailedErrorType
<
::
Types
::
BaseObject
graphql_name
'SentryDetailedError'
present_using
SentryDetailedErrorPresenter
authorize
:read_sentry_issue
field
:id
,
GraphQL
::
ID_TYPE
,
null:
false
,
description:
"ID (global ID) of the error"
field
:sentry_id
,
GraphQL
::
STRING_TYPE
,
method: :id
,
null:
false
,
description:
"ID (Sentry ID) of the error"
field
:title
,
GraphQL
::
STRING_TYPE
,
null:
false
,
description:
"Title of the error"
field
:type
,
GraphQL
::
STRING_TYPE
,
null:
false
,
description:
"Type of the error"
field
:user_count
,
GraphQL
::
INT_TYPE
,
null:
false
,
description:
"Count of users affected by the error"
field
:count
,
GraphQL
::
INT_TYPE
,
null:
false
,
description:
"Count of occurrences"
field
:first_seen
,
Types
::
TimeType
,
null:
false
,
description:
"Timestamp when the error was first seen"
field
:last_seen
,
Types
::
TimeType
,
null:
false
,
description:
"Timestamp when the error was last seen"
field
:message
,
GraphQL
::
STRING_TYPE
,
null:
true
,
description:
"Sentry metadata message of the error"
field
:culprit
,
GraphQL
::
STRING_TYPE
,
null:
false
,
description:
"Culprit of the error"
field
:external_url
,
GraphQL
::
STRING_TYPE
,
null:
false
,
description:
"External URL of the error"
field
:sentry_project_id
,
GraphQL
::
ID_TYPE
,
method: :project_id
,
null:
false
,
description:
"ID of the project (Sentry project)"
field
:sentry_project_name
,
GraphQL
::
STRING_TYPE
,
method: :project_name
,
null:
false
,
description:
"Name of the project affected by the error"
field
:sentry_project_slug
,
GraphQL
::
STRING_TYPE
,
method: :project_slug
,
null:
false
,
description:
"Slug of the project affected by the error"
field
:short_id
,
GraphQL
::
STRING_TYPE
,
null:
false
,
description:
"Short ID (Sentry ID) of the error"
field
:status
,
Types
::
ErrorTracking
::
SentryErrorStatusEnum
,
null:
false
,
description:
"Status of the error"
field
:frequency
,
[
Types
::
ErrorTracking
::
SentryErrorFrequencyType
],
null:
false
,
description:
"Last 24hr stats of the error"
field
:first_release_last_commit
,
GraphQL
::
STRING_TYPE
,
null:
true
,
description:
"Commit the error was first seen"
field
:last_release_last_commit
,
GraphQL
::
STRING_TYPE
,
null:
true
,
description:
"Commit the error was last seen"
field
:first_release_short_version
,
GraphQL
::
STRING_TYPE
,
null:
true
,
description:
"Release version the error was first seen"
field
:last_release_short_version
,
GraphQL
::
STRING_TYPE
,
null:
true
,
description:
"Release version the error was last seen"
def
first_seen
DateTime
.
parse
(
object
.
first_seen
)
end
def
last_seen
DateTime
.
parse
(
object
.
last_seen
)
end
def
project_id
Gitlab
::
GlobalId
.
build
(
model_name:
'Project'
,
id:
object
.
project_id
).
to_s
end
end
end
end
app/graphql/types/error_tracking/sentry_error_frequency_type.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
module
Types
module
ErrorTracking
# rubocop: disable Graphql/AuthorizeTypes
class
SentryErrorFrequencyType
<
::
Types
::
BaseObject
graphql_name
'SentryErrorFrequency'
field
:time
,
Types
::
TimeType
,
null:
false
,
description:
"Time the error frequency stats were recorded"
field
:count
,
GraphQL
::
INT_TYPE
,
null:
false
,
description:
"Count of errors received since the previously recorded time"
end
# rubocop: enable Graphql/AuthorizeTypes
end
end
app/graphql/types/error_tracking/sentry_error_status_enum.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
module
Types
module
ErrorTracking
class
SentryErrorStatusEnum
<
::
Types
::
BaseEnum
graphql_name
'SentryErrorStatus'
description
'State of a Sentry error'
value
'RESOLVED'
,
value:
'resolved'
,
description:
'Error has been resolved'
value
'RESOLVED_IN_NEXT_RELEASE'
,
value:
'resolvedInNextRelease'
,
description:
'Error has been ignored until next release'
value
'UNRESOLVED'
,
value:
'unresolved'
,
description:
'Error is unresolved'
value
'IGNORED'
,
value:
'ignored'
,
description:
'Error has been ignored'
end
end
end
app/graphql/types/project_type.rb
View file @
cd15d0e6
...
...
@@ -145,5 +145,11 @@ module Types
null:
true
,
description:
'Build pipelines of the project'
,
resolver:
Resolvers
::
ProjectPipelinesResolver
field
:sentry_detailed_error
,
Types
::
ErrorTracking
::
SentryDetailedErrorType
,
null:
true
,
description:
'Detailed version of a Sentry error on the project'
,
resolver:
Resolvers
::
ErrorTracking
::
SentryDetailedErrorResolver
end
end
app/models/concerns/issuable.rb
View file @
cd15d0e6
...
...
@@ -128,7 +128,7 @@ module Issuable
end
scope
:joins_milestone_releases
,
->
do
joins
(
"JOIN milestone_releases ON
issues
.milestone_id = milestone_releases.milestone_id
joins
(
"JOIN milestone_releases ON
#{
table_name
}
.milestone_id = milestone_releases.milestone_id
JOIN releases ON milestone_releases.release_id = releases.id"
).
distinct
end
...
...
app/policies/error_tracking/detailed_error_policy.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
module
ErrorTracking
class
DetailedErrorPolicy
<
BasePolicy
delegate
{
@subject
.
gitlab_project
}
end
end
app/presenters/sentry_detailed_error_presenter.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
class
SentryDetailedErrorPresenter
<
Gitlab
::
View
::
Presenter
::
Delegated
presents
:error
FrequencyStruct
=
Struct
.
new
(
:time
,
:count
,
keyword_init:
true
)
def
frequency
utc_offset
=
Time
.
zone_offset
(
'UTC'
)
error
.
frequency
.
map
do
|
f
|
FrequencyStruct
.
new
(
time:
Time
.
at
(
f
[
0
],
in:
utc_offset
),
count:
f
[
1
])
end
end
end
app/views/projects/issues/_new_branch.html.haml
View file @
cd15d0e6
...
...
@@ -28,7 +28,7 @@
%ul
#create-merge-request-dropdown
.create-merge-request-dropdown-menu.dropdown-menu.dropdown-menu-right.gl-show-field-errors
{
class:
(
"create-confidential-merge-request-dropdown-menu"
if
can_create_confidential_merge_request?
),
data:
{
dropdown:
true
}
}
-
if
can_create_merge_request
%li
.droplab-item-selected
{
role:
'button'
,
data:
{
value:
'create-mr'
,
text:
create_mr_text
}
}
.menu-item
.menu-item
.text-nowrap
=
icon
(
'check'
,
class:
'icon'
)
-
if
can_create_confidential_merge_request?
=
_
(
'Create confidential merge request and branch'
)
...
...
changelogs/unreleased/34943-graphql-sentry-details.yml
0 → 100644
View file @
cd15d0e6
---
title
:
GraphQL for Sentry rror details
merge_request
:
19733
author
:
type
:
added
changelogs/unreleased/38244-fix-release-filter-on-mr-page.yml
0 → 100644
View file @
cd15d0e6
---
title
:
Fixed query behind release filter on merge request search page.
merge_request
:
38244
author
:
type
:
fixed
changelogs/unreleased/confidential_mr_styling.yml
0 → 100644
View file @
cd15d0e6
---
title
:
Improve create confidential MR dropdown styling.
merge_request
:
20176
author
:
Lee Tickett
type
:
other
doc/api/graphql/reference/gitlab_schema.graphql
View file @
cd15d0e6
...
...
@@ -4400,6 +4400,16 @@ type Project {
"""
requestAccessEnabled
:
Boolean
"""
Detailed
version
of
a
Sentry
error
on
the
project
"""
sentryDetailedError
(
"""
ID
of
the
Sentry
issue
"""
id
:
ID
!
):
SentryDetailedError
"""
Indicates
if
shared
runners
are
enabled
on
the
project
"""
...
...
@@ -4886,6 +4896,150 @@ type RootStorageStatistics {
wikiSize
:
Int
!
}
type
SentryDetailedError
{
"""
Count
of
occurrences
"""
count
:
Int
!
"""
Culprit
of
the
error
"""
culprit
:
String
!
"""
External
URL
of
the
error
"""
externalUrl
:
String
!
"""
Commit
the
error
was
first
seen
"""
firstReleaseLastCommit
:
String
"""
Release
version
the
error
was
first
seen
"""
firstReleaseShortVersion
:
String
"""
Timestamp
when
the
error
was
first
seen
"""
firstSeen
:
Time
!
"""
Last
24
hr
stats
of
the
error
"""
frequency
:
[
SentryErrorFrequency
!]!
"""
ID
(
global
ID
)
of
the
error
"""
id
:
ID
!
"""
Commit
the
error
was
last
seen
"""
lastReleaseLastCommit
:
String
"""
Release
version
the
error
was
last
seen
"""
lastReleaseShortVersion
:
String
"""
Timestamp
when
the
error
was
last
seen
"""
lastSeen
:
Time
!
"""
Sentry
metadata
message
of
the
error
"""
message
:
String
"""
ID
(
Sentry
ID
)
of
the
error
"""
sentryId
:
String
!
"""
ID
of
the
project
(
Sentry
project
)
"""
sentryProjectId
:
ID
!
"""
Name
of
the
project
affected
by
the
error
"""
sentryProjectName
:
String
!
"""
Slug
of
the
project
affected
by
the
error
"""
sentryProjectSlug
:
String
!
"""
Short
ID
(
Sentry
ID
)
of
the
error
"""
shortId
:
String
!
"""
Status
of
the
error
"""
status
:
SentryErrorStatus
!
"""
Title
of
the
error
"""
title
:
String
!
"""
Type
of
the
error
"""
type
:
String
!
"""
Count
of
users
affected
by
the
error
"""
userCount
:
Int
!
}
type
SentryErrorFrequency
{
"""
Count
of
errors
received
since
the
previously
recorded
time
"""
count
:
Int
!
"""
Time
the
error
frequency
stats
were
recorded
"""
time
:
Time
!
}
"""
State of a Sentry error
"""
enum
SentryErrorStatus
{
"""
Error
has
been
ignored
"""
IGNORED
"""
Error
has
been
resolved
"""
RESOLVED
"""
Error
has
been
ignored
until
next
release
"""
RESOLVED_IN_NEXT_RELEASE
"""
Error
is
unresolved
"""
UNRESOLVED
}
type
Submodule
implements
Entry
{
flatPath
:
String
!
id
:
ID
!
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
cd15d0e6
...
...
@@ -1166,6 +1166,33 @@
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"sentryDetailedError"
,
"description"
:
"Detailed version of a Sentry error on the project"
,
"args"
:
[
{
"name"
:
"id"
,
"description"
:
"ID of the Sentry issue"
,
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"ID"
,
"ofType"
:
null
}
},
"defaultValue"
:
null
}
],
"type"
:
{
"kind"
:
"OBJECT"
,
"name"
:
"SentryDetailedError"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"sharedRunnersEnabled"
,
"description"
:
"Indicates if shared runners are enabled on the project"
,
...
...
@@ -13788,6 +13815,469 @@
],
"possibleTypes"
:
null
},
{
"kind"
:
"OBJECT"
,
"name"
:
"SentryDetailedError"
,
"description"
:
null
,
"fields"
:
[
{
"name"
:
"count"
,
"description"
:
"Count of occurrences"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"Int"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"culprit"
,
"description"
:
"Culprit of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"externalUrl"
,
"description"
:
"External URL of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"firstReleaseLastCommit"
,
"description"
:
"Commit the error was first seen"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"firstReleaseShortVersion"
,
"description"
:
"Release version the error was first seen"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"firstSeen"
,
"description"
:
"Timestamp when the error was first seen"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"Time"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"frequency"
,
"description"
:
"Last 24hr stats of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"LIST"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"OBJECT"
,
"name"
:
"SentryErrorFrequency"
,
"ofType"
:
null
}
}
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"id"
,
"description"
:
"ID (global ID) of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"ID"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"lastReleaseLastCommit"
,
"description"
:
"Commit the error was last seen"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"lastReleaseShortVersion"
,
"description"
:
"Release version the error was last seen"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"lastSeen"
,
"description"
:
"Timestamp when the error was last seen"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"Time"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"message"
,
"description"
:
"Sentry metadata message of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"sentryId"
,
"description"
:
"ID (Sentry ID) of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"sentryProjectId"
,
"description"
:
"ID of the project (Sentry project)"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"ID"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"sentryProjectName"
,
"description"
:
"Name of the project affected by the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"sentryProjectSlug"
,
"description"
:
"Slug of the project affected by the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"shortId"
,
"description"
:
"Short ID (Sentry ID) of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"status"
,
"description"
:
"Status of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"ENUM"
,
"name"
:
"SentryErrorStatus"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"title"
,
"description"
:
"Title of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"type"
,
"description"
:
"Type of the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"userCount"
,
"description"
:
"Count of users affected by the error"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"Int"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
}
],
"inputFields"
:
null
,
"interfaces"
:
[
],
"enumValues"
:
null
,
"possibleTypes"
:
null
},
{
"kind"
:
"ENUM"
,
"name"
:
"SentryErrorStatus"
,
"description"
:
"State of a Sentry error"
,
"fields"
:
null
,
"inputFields"
:
null
,
"interfaces"
:
null
,
"enumValues"
:
[
{
"name"
:
"RESOLVED"
,
"description"
:
"Error has been resolved"
,
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"RESOLVED_IN_NEXT_RELEASE"
,
"description"
:
"Error has been ignored until next release"
,
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"UNRESOLVED"
,
"description"
:
"Error is unresolved"
,
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"IGNORED"
,
"description"
:
"Error has been ignored"
,
"isDeprecated"
:
false
,
"deprecationReason"
:
null
}
],
"possibleTypes"
:
null
},
{
"kind"
:
"OBJECT"
,
"name"
:
"SentryErrorFrequency"
,
"description"
:
null
,
"fields"
:
[
{
"name"
:
"count"
,
"description"
:
"Count of errors received since the previously recorded time"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"Int"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"time"
,
"description"
:
"Time the error frequency stats were recorded"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"Time"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
}
],
"inputFields"
:
null
,
"interfaces"
:
[
],
"enumValues"
:
null
,
"possibleTypes"
:
null
},
{
"kind"
:
"OBJECT"
,
"name"
:
"Metadata"
,
...
...
doc/api/graphql/reference/index.md
View file @
cd15d0e6
...
...
@@ -664,6 +664,7 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
|
`repository`
| Repository | Git repository of the project |
|
`mergeRequest`
| MergeRequest | A single merge request of the project |
|
`issue`
| Issue | A single issue of the project |
|
`sentryDetailedError`
| SentryDetailedError | Detailed version of a Sentry error on the project |
### ProjectPermissions
...
...
@@ -751,6 +752,39 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
|
`packagesSize`
| Int! | The packages size in bytes |
|
`wikiSize`
| Int! | The wiki size in bytes |
### SentryDetailedError
| Name | Type | Description |
| --- | ---- | ---------- |
|
`id`
| ID! | ID (global ID) of the error |
|
`sentryId`
| String! | ID (Sentry ID) of the error |
|
`title`
| String! | Title of the error |
|
`type`
| String! | Type of the error |
|
`userCount`
| Int! | Count of users affected by the error |
|
`count`
| Int! | Count of occurrences |
|
`firstSeen`
| Time! | Timestamp when the error was first seen |
|
`lastSeen`
| Time! | Timestamp when the error was last seen |
|
`message`
| String | Sentry metadata message of the error |
|
`culprit`
| String! | Culprit of the error |
|
`externalUrl`
| String! | External URL of the error |
|
`sentryProjectId`
| ID! | ID of the project (Sentry project) |
|
`sentryProjectName`
| String! | Name of the project affected by the error |
|
`sentryProjectSlug`
| String! | Slug of the project affected by the error |
|
`shortId`
| String! | Short ID (Sentry ID) of the error |
|
`status`
| SentryErrorStatus! | Status of the error |
|
`frequency`
| SentryErrorFrequency! => Array | Last 24hr stats of the error |
|
`firstReleaseLastCommit`
| String | Commit the error was first seen |
|
`lastReleaseLastCommit`
| String | Commit the error was last seen |
|
`firstReleaseShortVersion`
| String | Release version the error was first seen |
|
`lastReleaseShortVersion`
| String | Release version the error was last seen |
### SentryErrorFrequency
| Name | Type | Description |
| --- | ---- | ---------- |
|
`time`
| Time! | Time the error frequency stats were recorded |
|
`count`
| Int! | Count of errors received since the previously recorded time |
### Submodule
| Name | Type | Description |
...
...
doc/ci/yaml/README.md
View file @
cd15d0e6
...
...
@@ -203,7 +203,7 @@ job:
You can use
[
YAML anchors
](
#anchors
)
with scripts, which makes it possible to
include a predefined list of commands in multiple jobs.
E
xample:
For e
xample:
```
yaml
.something
:
&something
...
...
@@ -1413,6 +1413,11 @@ Also in the example, `GIT_STRATEGY` is set to `none` so that GitLab Runner won
try to check out the code after the branch is deleted when the
`stop_review_app`
job is
[
automatically triggered
](
../environments.md#automatically-stopping-an-environment
)
.
NOTE:
**Note:**
The above example overwrites global variables. If your stop environment job depends
on global variables, you can use
[
anchor variables
](
#yaml-anchors-for-variables
)
when setting the
`GIT_STRATEGY`
to change it without overriding the global variables.
The
`stop_review_app`
job is
**required**
to have the following keywords defined:
-
`when`
-
[
reference
](
#when
)
...
...
@@ -3159,6 +3164,29 @@ which can be set in GitLab's UI.
Learn more about
[
variables and their priority
][
variables
]
.
#### YAML anchors for variables
[
YAML anchors
](
#anchors
)
can be used with
`variables`
, to easily repeat assignment
of variables across multiple jobs. It can also enable more flexibility when a job
requires a specific
`variables`
block that would otherwise override the global variables.
In the example below, we will override the
`GIT_STRATEGY`
variable without affecting
the use of the
`SAMPLE_VARIABLE`
variable:
```
yaml
# global variables
variables
:
&global-variables
SAMPLE_VARIABLE
:
sample_variable_value
# a job that needs to set the GIT_STRATEGY variable, yet depend on global variables
job_no_git_strategy
:
stage
:
cleanup
variables
:
<<
:
*global-variables
GIT_STRATEGY
:
none
script
:
echo $SAMPLE_VARIABLE
```
#### Git strategy
> Introduced in GitLab 8.9 as an experimental feature. May change or be removed
...
...
lib/gitlab/error_tracking/detailed_error.rb
View file @
cd15d0e6
...
...
@@ -4,6 +4,7 @@ module Gitlab
module
ErrorTracking
class
DetailedError
include
ActiveModel
::
Model
include
GlobalID
::
Identification
attr_accessor
:count
,
:culprit
,
...
...
@@ -13,6 +14,7 @@ module Gitlab
:first_release_short_version
,
:first_seen
,
:frequency
,
:gitlab_project
,
:id
,
:last_release_last_commit
,
:last_release_short_version
,
...
...
@@ -26,6 +28,10 @@ module Gitlab
:title
,
:type
,
:user_count
def
self
.
declarative_policy_class
'ErrorTracking::DetailedErrorPolicy'
end
end
end
end
locale/gitlab.pot
View file @
cd15d0e6
...
...
@@ -11641,7 +11641,7 @@ msgstr ""
msgid "No files found."
msgstr ""
msgid "No forks available to you."
msgid "No forks a
re a
vailable to you."
msgstr ""
msgid "No issues for the selected time period."
...
...
@@ -18447,7 +18447,7 @@ msgstr ""
msgid "To preserve performance only <strong>%{display_size} of %{real_size}</strong> files are displayed."
msgstr ""
msgid "To protect this issue's confidentiality, %{
link_start}fork the project%{link_end} and set the fork
s visibility to private."
msgid "To protect this issue's confidentiality, %{
forkLink} and set the fork'
s visibility to private."
msgstr ""
msgid "To protect this issue's confidentiality, a private fork of this project was selected."
...
...
@@ -21049,6 +21049,9 @@ msgstr ""
msgid "for this project"
msgstr ""
msgid "fork this project"
msgstr ""
msgid "from"
msgstr ""
...
...
spec/factories/error_tracking/detailed_error.rb
View file @
cd15d0e6
...
...
@@ -2,13 +2,13 @@
FactoryBot
.
define
do
factory
:detailed_error_tracking_error
,
class:
Gitlab
::
ErrorTracking
::
DetailedError
do
id
{
'
id
'
}
id
{
'
1
'
}
title
{
'title'
}
type
{
'error'
}
user_count
{
1
}
count
{
2
}
first_seen
{
Time
.
now
}
last_seen
{
Time
.
now
}
first_seen
{
Time
.
now
.
iso8601
}
last_seen
{
Time
.
now
.
iso8601
}
message
{
'message'
}
culprit
{
'culprit'
}
external_url
{
'http://example.com/id'
}
...
...
@@ -18,7 +18,11 @@ FactoryBot.define do
project_slug
{
'project_name'
}
short_id
{
'ID'
}
status
{
'unresolved'
}
frequency
{
[]
}
frequency
do
[
[
Time
.
now
.
to_i
,
10
]
]
end
first_release_last_commit
{
'68c914da9'
}
last_release_last_commit
{
'9ad419c86'
}
first_release_short_version
{
'abc123'
}
...
...
spec/features/issues/user_creates_confidential_merge_request_spec.rb
View file @
cd15d0e6
...
...
@@ -29,7 +29,7 @@ describe 'User creates confidential merge request on issue page', :js do
click_button
'Create confidential merge request'
page
.
within
'.create-confidential-merge-request-dropdown-menu'
do
expect
(
page
).
to
have_content
(
'No forks available to you'
)
expect
(
page
).
to
have_content
(
'No forks a
re a
vailable to you'
)
end
end
end
...
...
spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap
View file @
cd15d0e6
...
...
@@ -15,19 +15,12 @@ exports[`Confidential merge request project form group component renders empty s
class="text-muted mt-1 mb-0"
>
No forks available to you.
No forks a
re a
vailable to you.
<br />
<span>
To protect this issue's confidentiality,
<a
class="help-link"
href="https://test.com"
>
fork the project
</a>
and set the forks visibility to private.
</span>
<glsprintf-stub
message="To protect this issue's confidentiality, %{forkLink} and set the fork's visibility to private."
/>
<gllink-stub
class="w-auto p-0 d-inline-block text-primary bg-transparent"
...
...
@@ -65,19 +58,12 @@ exports[`Confidential merge request project form group component renders fork dr
class="text-muted mt-1 mb-0"
>
No forks available to you.
No forks a
re a
vailable to you.
<br />
<span>
To protect this issue's confidentiality,
<a
class="help-link"
href="https://test.com"
>
fork the project
</a>
and set the forks visibility to private.
</span>
<glsprintf-stub
message="To protect this issue's confidentiality, %{forkLink} and set the fork's visibility to private."
/>
<gllink-stub
class="w-auto p-0 d-inline-block text-primary bg-transparent"
...
...
spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
require
'spec_helper'
describe
Resolvers
::
ErrorTracking
::
SentryDetailedErrorResolver
do
include
GraphqlHelpers
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let
(
:issue_details_service
)
{
spy
(
'ErrorTracking::IssueDetailsService'
)
}
before
do
project
.
add_developer
(
current_user
)
allow
(
ErrorTracking
::
IssueDetailsService
)
.
to
receive
(
:new
)
.
and_return
issue_details_service
end
describe
'#resolve'
do
let
(
:args
)
{
{
id:
issue_global_id
(
1234
)
}
}
it
'fetches the data via the sentry API'
do
resolve_error
(
args
)
expect
(
issue_details_service
).
to
have_received
(
:execute
)
end
context
'error matched'
do
let
(
:detailed_error
)
{
build
(
:detailed_error_tracking_error
)
}
before
do
allow
(
issue_details_service
).
to
receive
(
:execute
)
.
and_return
({
issue:
detailed_error
})
end
it
'resolves to a detailed error'
do
expect
(
resolve_error
(
args
)).
to
eq
detailed_error
end
it
'assigns the gitlab project'
do
expect
(
resolve_error
(
args
).
gitlab_project
).
to
eq
project
end
end
it
'resolves to nil if no match'
do
allow
(
issue_details_service
).
to
receive
(
:execute
)
.
and_return
({
issue:
nil
})
result
=
resolve_error
(
args
)
expect
(
result
).
to
eq
nil
end
end
def
resolve_error
(
args
=
{},
context
=
{
current_user:
current_user
})
resolve
(
described_class
,
obj:
project
,
args:
args
,
ctx:
context
)
end
def
issue_global_id
(
issue_id
)
Gitlab
::
ErrorTracking
::
DetailedError
.
new
(
id:
issue_id
).
to_global_id
.
to_s
end
end
spec/graphql/types/error_tracking/sentry_detailed_error_type_spec.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
require
'spec_helper'
describe
GitlabSchema
.
types
[
'SentryDetailedError'
]
do
it
{
expect
(
described_class
.
graphql_name
).
to
eq
(
'SentryDetailedError'
)
}
it
{
expect
(
described_class
).
to
require_graphql_authorizations
(
:read_sentry_issue
)
}
it
'exposes the expected fields'
do
expected_fields
=
%i[
id
sentryId
title
type
userCount
count
firstSeen
lastSeen
message
culprit
externalUrl
sentryProjectId
sentryProjectName
sentryProjectSlug
shortId
status
frequency
firstReleaseLastCommit
lastReleaseLastCommit
firstReleaseShortVersion
lastReleaseShortVersion
]
is_expected
.
to
have_graphql_fields
(
*
expected_fields
)
end
end
spec/graphql/types/project_type_spec.rb
View file @
cd15d0e6
...
...
@@ -22,8 +22,7 @@ describe GitlabSchema.types['Project'] do
only_allow_merge_if_pipeline_succeeds request_access_enabled
only_allow_merge_if_all_discussions_are_resolved printing_merge_request_link_enabled
namespace group statistics repository merge_requests merge_request issues
issue pipelines
removeSourceBranchAfterMerge
issue pipelines removeSourceBranchAfterMerge sentryDetailedError
]
is_expected
.
to
have_graphql_fields
(
*
expected_fields
)
...
...
spec/javascripts/vue_shared/components/bar_chart_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
BarChart
from
'
~/vue_shared/components/bar_chart.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
BarChart
from
'
~/vue_shared/components/bar_chart.vue
'
;
function
getRandomArbitrary
(
min
,
max
)
{
return
Math
.
random
()
*
(
max
-
min
)
+
min
;
...
...
spec/javascripts/vue_shared/components/ci_badge_link_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
ciBadge
from
'
~/vue_shared/components/ci_badge_link.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
ciBadge
from
'
~/vue_shared/components/ci_badge_link.vue
'
;
describe
(
'
CI Badge Link Component
'
,
()
=>
{
let
CIBadge
;
...
...
spec/javascripts/vue_shared/components/ci_icon_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
ciIcon
from
'
~/vue_shared/components/ci_icon.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
ciIcon
from
'
~/vue_shared/components/ci_icon.vue
'
;
describe
(
'
CI Icon component
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
ciIcon
);
...
...
spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
contentViewer
from
'
~/vue_shared/components/content_viewer/content_viewer.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
GREEN_BOX_IMAGE_URL
}
from
'
spec/test_constants
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
contentViewer
from
'
~/vue_shared/components/content_viewer/content_viewer.vue
'
;
import
'
~/behaviors/markdown/render_gfm
'
;
describe
(
'
ContentViewer
'
,
()
=>
{
...
...
spec/javascripts/vue_shared/components/deprecated_modal_2_spec.js
View file @
cd15d0e6
import
$
from
'
jquery
'
;
import
Vue
from
'
vue
'
;
import
DeprecatedModal2
from
'
~/vue_shared/components/deprecated_modal_2.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
DeprecatedModal2
from
'
~/vue_shared/components/deprecated_modal_2.vue
'
;
const
modalComponent
=
Vue
.
extend
(
DeprecatedModal2
);
...
...
spec/javascripts/vue_shared/components/deprecated_modal_spec.js
View file @
cd15d0e6
import
$
from
'
jquery
'
;
import
Vue
from
'
vue
'
;
import
DeprecatedModal
from
'
~/vue_shared/components/deprecated_modal.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
DeprecatedModal
from
'
~/vue_shared/components/deprecated_modal.vue
'
;
const
modalComponent
=
Vue
.
extend
(
DeprecatedModal
);
...
...
spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
diffViewer
from
'
~/vue_shared/components/diff_viewer/diff_viewer.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
GREEN_BOX_IMAGE_URL
,
RED_BOX_IMAGE_URL
}
from
'
spec/test_constants
'
;
import
diffViewer
from
'
~/vue_shared/components/diff_viewer/diff_viewer.vue
'
;
describe
(
'
DiffViewer
'
,
()
=>
{
const
requiredProps
=
{
...
...
spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
imageDiffViewer
from
'
~/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
GREEN_BOX_IMAGE_URL
,
RED_BOX_IMAGE_URL
}
from
'
spec/test_constants
'
;
import
imageDiffViewer
from
'
~/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
'
;
describe
(
'
ImageDiffViewer
'
,
()
=>
{
const
requiredProps
=
{
...
...
spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
dropdownButtonComponent
from
'
~/vue_shared/components/dropdown/dropdown_button.vue
'
;
import
{
mountComponentWithSlots
}
from
'
spec/helpers/vue_mount_component_helper
'
;
import
dropdownButtonComponent
from
'
~/vue_shared/components/dropdown/dropdown_button.vue
'
;
const
defaultLabel
=
'
Select
'
;
const
customLabel
=
'
Select project
'
;
...
...
spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
dropdownHiddenInputComponent
from
'
~/vue_shared/components/dropdown/dropdown_hidden_input.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
dropdownHiddenInputComponent
from
'
~/vue_shared/components/dropdown/dropdown_hidden_input.vue
'
;
import
{
mockLabels
}
from
'
./mock_data
'
;
...
...
spec/javascripts/vue_shared/components/dropdown/dropdown_search_input_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
dropdownSearchInputComponent
from
'
~/vue_shared/components/dropdown/dropdown_search_input.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
dropdownSearchInputComponent
from
'
~/vue_shared/components/dropdown/dropdown_search_input.vue
'
;
const
componentConfig
=
{
placeholderText
:
'
Search something
'
,
...
...
spec/javascripts/vue_shared/components/file_finder/index_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
Mousetrap
from
'
mousetrap
'
;
import
FindFileComponent
from
'
~/vue_shared/components/file_finder/index.vue
'
;
import
{
UP_KEY_CODE
,
DOWN_KEY_CODE
,
ENTER_KEY_CODE
,
ESC_KEY_CODE
}
from
'
~/lib/utils/keycodes
'
;
import
{
file
}
from
'
spec/ide/helpers
'
;
import
timeoutPromise
from
'
spec/helpers/set_timeout_promise_helper
'
;
import
FindFileComponent
from
'
~/vue_shared/components/file_finder/index.vue
'
;
import
{
UP_KEY_CODE
,
DOWN_KEY_CODE
,
ENTER_KEY_CODE
,
ESC_KEY_CODE
}
from
'
~/lib/utils/keycodes
'
;
describe
(
'
File finder item spec
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
FindFileComponent
);
...
...
spec/javascripts/vue_shared/components/file_finder/item_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
ItemComponent
from
'
~/vue_shared/components/file_finder/item.vue
'
;
import
{
file
}
from
'
spec/ide/helpers
'
;
import
ItemComponent
from
'
~/vue_shared/components/file_finder/item.vue
'
;
import
createComponent
from
'
../../../helpers/vue_mount_component_helper
'
;
describe
(
'
File finder item spec
'
,
()
=>
{
...
...
spec/javascripts/vue_shared/components/file_row_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
{
file
}
from
'
spec/ide/helpers
'
;
import
FileRow
from
'
~/vue_shared/components/file_row.vue
'
;
import
FileRowExtra
from
'
~/ide/components/file_row_extra.vue
'
;
import
{
file
}
from
'
spec/ide/helpers
'
;
import
mountComponent
from
'
../../helpers/vue_mount_component_helper
'
;
describe
(
'
File row component
'
,
()
=>
{
...
...
spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
component
from
'
~/vue_shared/components/filtered_search_dropdown.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
component
from
'
~/vue_shared/components/filtered_search_dropdown.vue
'
;
describe
(
'
Filtered search dropdown
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
component
);
...
...
spec/javascripts/vue_shared/components/header_ci_component_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
headerCi
from
'
~/vue_shared/components/header_ci_component.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
headerCi
from
'
~/vue_shared/components/header_ci_component.vue
'
;
describe
(
'
Header CI Component
'
,
()
=>
{
let
HeaderCi
;
...
...
spec/javascripts/vue_shared/components/icon_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
describe
(
'
Sprite Icon Component
'
,
function
()
{
describe
(
'
Initialization
'
,
function
()
{
...
...
spec/javascripts/vue_shared/components/loading_button_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
loadingButton
from
'
~/vue_shared/components/loading_button.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
loadingButton
from
'
~/vue_shared/components/loading_button.vue
'
;
const
LABEL
=
'
Hello
'
;
...
...
spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
toolbar
from
'
~/vue_shared/components/markdown/toolbar.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
toolbar
from
'
~/vue_shared/components/markdown/toolbar.vue
'
;
describe
(
'
toolbar
'
,
()
=>
{
let
vm
;
...
...
spec/javascripts/vue_shared/components/navigation_tabs_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
navigationTabs
from
'
~/vue_shared/components/navigation_tabs.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
navigationTabs
from
'
~/vue_shared/components/navigation_tabs.vue
'
;
describe
(
'
navigation tabs component
'
,
()
=>
{
let
vm
;
...
...
spec/javascripts/vue_shared/components/panel_resizer_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
panelResizer
from
'
~/vue_shared/components/panel_resizer.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
panelResizer
from
'
~/vue_shared/components/panel_resizer.vue
'
;
describe
(
'
Panel Resizer component
'
,
()
=>
{
let
vm
;
...
...
spec/javascripts/vue_shared/components/pikaday_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
datePicker
from
'
~/vue_shared/components/pikaday.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
datePicker
from
'
~/vue_shared/components/pikaday.vue
'
;
describe
(
'
datePicker
'
,
()
=>
{
let
vm
;
...
...
spec/javascripts/vue_shared/components/project_avatar/default_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
ProjectAvatarDefault
from
'
~/vue_shared/components/project_avatar/default.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
projectData
}
from
'
spec/ide/mock_data
'
;
import
{
getFirstCharacterCapitalized
}
from
'
~/lib/utils/text_utility
'
;
import
{
TEST_HOST
}
from
'
spec/test_constants
'
;
import
{
getFirstCharacterCapitalized
}
from
'
~/lib/utils/text_utility
'
;
import
ProjectAvatarDefault
from
'
~/vue_shared/components/project_avatar/default.vue
'
;
describe
(
'
ProjectAvatarDefault component
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
ProjectAvatarDefault
);
...
...
spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
View file @
cd15d0e6
import
ProjectListItem
from
'
~/vue_shared/components/project_selector/project_list_item.vue
'
;
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
{
trimText
}
from
'
spec/helpers/text_helper
'
;
import
ProjectListItem
from
'
~/vue_shared/components/project_selector/project_list_item.vue
'
;
const
localVue
=
createLocalVue
();
...
...
spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
_
from
'
underscore
'
;
import
ProjectSelector
from
'
~/vue_shared/components/project_selector/project_selector.vue
'
;
import
ProjectListItem
from
'
~/vue_shared/components/project_selector/project_list_item.vue
'
;
import
{
GlSearchBoxByType
,
GlInfiniteScroll
}
from
'
@gitlab/ui
'
;
import
{
mount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
{
trimText
}
from
'
spec/helpers/text_helper
'
;
import
ProjectListItem
from
'
~/vue_shared/components/project_selector/project_list_item.vue
'
;
import
ProjectSelector
from
'
~/vue_shared/components/project_selector/project_selector.vue
'
;
const
localVue
=
createLocalVue
();
...
...
spec/javascripts/vue_shared/components/smart_virtual_list_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
SmartVirtualScrollList
from
'
~/vue_shared/components/smart_virtual_list.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
SmartVirtualScrollList
from
'
~/vue_shared/components/smart_virtual_list.vue
'
;
describe
(
'
Toggle Button
'
,
()
=>
{
let
vm
;
...
...
spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
stackedProgressBarComponent
from
'
~/vue_shared/components/stacked_progress_bar.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
stackedProgressBarComponent
from
'
~/vue_shared/components/stacked_progress_bar.vue
'
;
const
createComponent
=
config
=>
{
const
Component
=
Vue
.
extend
(
stackedProgressBarComponent
);
...
...
spec/javascripts/vue_shared/components/toggle_button_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
toggleButton
from
'
~/vue_shared/components/toggle_button.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
toggleButton
from
'
~/vue_shared/components/toggle_button.vue
'
;
describe
(
'
Toggle Button
'
,
()
=>
{
let
vm
;
...
...
spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
UserAvatarSvg
from
'
~/vue_shared/components/user_avatar/user_avatar_svg.vue
'
;
import
avatarSvg
from
'
icons/_icon_random.svg
'
;
import
UserAvatarSvg
from
'
~/vue_shared/components/user_avatar/user_avatar_svg.vue
'
;
const
UserAvatarSvgComponent
=
Vue
.
extend
(
UserAvatarSvg
);
...
...
spec/javascripts/vue_shared/translate_spec.js
View file @
cd15d0e6
import
Vue
from
'
vue
'
;
import
Jed
from
'
jed
'
;
import
{
trimText
}
from
'
spec/helpers/text_helper
'
;
import
locale
from
'
~/locale
'
;
import
Translate
from
'
~/vue_shared/translate
'
;
import
{
trimText
}
from
'
spec/helpers/text_helper
'
;
describe
(
'
Vue translate filter
'
,
()
=>
{
let
el
;
...
...
spec/models/concerns/issuable_spec.rb
View file @
cd15d0e6
...
...
@@ -3,6 +3,8 @@
require
'spec_helper'
describe
Issuable
do
include
ProjectForksHelper
let
(
:issuable_class
)
{
Issue
}
let
(
:issue
)
{
create
(
:issue
,
title:
'An issue'
,
description:
'A description'
)
}
let
(
:user
)
{
create
(
:user
)
}
...
...
@@ -855,6 +857,7 @@ describe Issuable do
describe
'release scopes'
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let
(
:forked_project
)
{
fork_project
(
project
)
}
let_it_be
(
:release_1
)
{
create
(
:release
,
tag:
'v1.0'
,
project:
project
)
}
let_it_be
(
:release_2
)
{
create
(
:release
,
tag:
'v2.0'
,
project:
project
)
}
...
...
@@ -875,52 +878,65 @@ describe Issuable do
let_it_be
(
:issue_5
)
{
create
(
:issue
,
milestone:
milestone_6
,
project:
project
)
}
let_it_be
(
:issue_6
)
{
create
(
:issue
,
project:
project
)
}
let_it_be
(
:items
)
{
Issue
.
all
}
let
(
:mr_1
)
{
create
(
:merge_request
,
milestone:
milestone_1
,
target_project:
project
,
source_project:
project
)
}
let
(
:mr_2
)
{
create
(
:merge_request
,
milestone:
milestone_3
,
target_project:
project
,
source_project:
forked_project
)
}
let
(
:mr_3
)
{
create
(
:merge_request
,
source_project:
project
)
}
let_it_be
(
:issue_items
)
{
Issue
.
all
}
let
(
:mr_items
)
{
MergeRequest
.
all
}
describe
'#without_release'
do
it
'returns the issues not tied to any milestone and the ones tied to milestone with no release'
do
expect
(
items
.
without_release
).
to
contain_exactly
(
issue_5
,
issue_6
)
it
'returns the issues or mrs not tied to any milestone and the ones tied to milestone with no release'
do
expect
(
issue_items
.
without_release
).
to
contain_exactly
(
issue_5
,
issue_6
)
expect
(
mr_items
.
without_release
).
to
contain_exactly
(
mr_3
)
end
end
describe
'#any_release'
do
it
'returns all issues tied to a release'
do
expect
(
items
.
any_release
).
to
contain_exactly
(
issue_1
,
issue_2
,
issue_3
,
issue_4
)
it
'returns all issues or all mrs tied to a release'
do
expect
(
issue_items
.
any_release
).
to
contain_exactly
(
issue_1
,
issue_2
,
issue_3
,
issue_4
)
expect
(
mr_items
.
any_release
).
to
contain_exactly
(
mr_1
,
mr_2
)
end
end
describe
'#with_release'
do
it
'returns the issues tied a specfic release'
do
expect
(
items
.
with_release
(
'v1.0'
,
project
.
id
)).
to
contain_exactly
(
issue_1
,
issue_2
,
issue_3
)
it
'returns the issues tied to a specfic release'
do
expect
(
issue_items
.
with_release
(
'v1.0'
,
project
.
id
)).
to
contain_exactly
(
issue_1
,
issue_2
,
issue_3
)
end
it
'returns the mrs tied to a specific release'
do
expect
(
mr_items
.
with_release
(
'v1.0'
,
project
.
id
)).
to
contain_exactly
(
mr_1
)
end
context
'when a release has a milestone with one issue and another one with no issue'
do
it
'returns that one issue'
do
expect
(
items
.
with_release
(
'v2.0'
,
project
.
id
)).
to
contain_exactly
(
issue_3
)
expect
(
i
ssue_i
tems
.
with_release
(
'v2.0'
,
project
.
id
)).
to
contain_exactly
(
issue_3
)
end
context
'when the milestone with no issue is added as a filter'
do
it
'returns an empty list'
do
expect
(
items
.
with_release
(
'v2.0'
,
project
.
id
).
with_milestone
(
'm3'
)).
to
be_empty
expect
(
i
ssue_i
tems
.
with_release
(
'v2.0'
,
project
.
id
).
with_milestone
(
'm3'
)).
to
be_empty
end
end
context
'when the milestone with the issue is added as a filter'
do
it
'returns this issue'
do
expect
(
items
.
with_release
(
'v2.0'
,
project
.
id
).
with_milestone
(
'm2'
)).
to
contain_exactly
(
issue_3
)
expect
(
i
ssue_i
tems
.
with_release
(
'v2.0'
,
project
.
id
).
with_milestone
(
'm2'
)).
to
contain_exactly
(
issue_3
)
end
end
end
context
'when there is no issue under a specific release'
do
it
'returns no issue'
do
expect
(
items
.
with_release
(
'v4.0'
,
project
.
id
)).
to
be_empty
context
'when there is no issue or mr under a specific release'
do
it
'returns no issue or no mr'
do
expect
(
issue_items
.
with_release
(
'v4.0'
,
project
.
id
)).
to
be_empty
expect
(
mr_items
.
with_release
(
'v4.0'
,
project
.
id
)).
to
be_empty
end
end
context
'when a non-existent release tag is passed in'
do
it
'returns no issue'
do
expect
(
items
.
with_release
(
'v999.0'
,
project
.
id
)).
to
be_empty
it
'returns no issue or no mr'
do
expect
(
issue_items
.
with_release
(
'v999.0'
,
project
.
id
)).
to
be_empty
expect
(
mr_items
.
with_release
(
'v999.0'
,
project
.
id
)).
to
be_empty
end
end
end
...
...
spec/presenters/sentry_detailed_error_presenter_spec.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
require
'spec_helper'
describe
SentryDetailedErrorPresenter
do
let
(
:error
)
{
build
(
:detailed_error_tracking_error
)
}
let
(
:presenter
)
{
described_class
.
new
(
error
)
}
describe
'#frequency'
do
subject
{
presenter
.
frequency
}
it
'returns an array of frequency structs'
do
expect
(
subject
).
to
include
(
a_kind_of
(
SentryDetailedErrorPresenter
::
FrequencyStruct
))
end
it
'converts the times into UTC time objects'
do
time
=
subject
.
first
.
time
expect
(
time
).
to
be_a
(
Time
)
expect
(
time
.
strftime
(
'%z'
)).
to
eq
'+0000'
end
it
'returns the correct counts'
do
count
=
subject
.
first
.
count
expect
(
count
).
to
eq
error
.
frequency
.
first
[
1
]
end
end
end
spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
0 → 100644
View file @
cd15d0e6
# frozen_string_literal: true
require
'spec_helper'
describe
'getting a detailed sentry error'
do
include
GraphqlHelpers
let_it_be
(
:project
)
{
create
(
:project
,
:repository
)
}
let_it_be
(
:project_setting
)
{
create
(
:project_error_tracking_setting
,
project:
project
)
}
let_it_be
(
:current_user
)
{
project
.
owner
}
let_it_be
(
:sentry_detailed_error
)
{
build
(
:detailed_error_tracking_error
)
}
let
(
:sentry_gid
)
{
sentry_detailed_error
.
to_global_id
.
to_s
}
let
(
:fields
)
do
<<~
QUERY
#{
all_graphql_fields_for
(
'SentryDetailedError'
.
classify
)
}
QUERY
end
let
(
:query
)
do
graphql_query_for
(
'project'
,
{
'fullPath'
=>
project
.
full_path
},
query_graphql_field
(
'sentryDetailedError'
,
{
id:
sentry_gid
},
fields
)
)
end
let
(
:error_data
)
{
graphql_data
[
'project'
][
'sentryDetailedError'
]
}
it_behaves_like
'a working graphql query'
do
before
do
post_graphql
(
query
,
current_user:
current_user
)
end
end
context
'when data is loading via reactive cache'
do
before
do
post_graphql
(
query
,
current_user:
current_user
)
end
it
"is expected to return an empty error"
do
expect
(
error_data
).
to
eq
nil
end
end
context
'reactive cache returns data'
do
before
do
expect_any_instance_of
(
ErrorTracking
::
ProjectErrorTrackingSetting
)
.
to
receive
(
:issue_details
)
.
and_return
({
issue:
sentry_detailed_error
})
post_graphql
(
query
,
current_user:
current_user
)
end
it
"is expected to return a valid error"
do
expect
(
error_data
[
'id'
]).
to
eql
sentry_gid
expect
(
error_data
[
'sentryId'
]).
to
eql
sentry_detailed_error
.
id
.
to_s
expect
(
error_data
[
'status'
]).
to
eql
sentry_detailed_error
.
status
.
upcase
expect
(
error_data
[
'firstSeen'
]).
to
eql
sentry_detailed_error
.
first_seen
expect
(
error_data
[
'lastSeen'
]).
to
eql
sentry_detailed_error
.
last_seen
end
it
'is expected to return the frequency correctly'
do
expect
(
error_data
[
'frequency'
].
count
).
to
eql
sentry_detailed_error
.
frequency
.
count
first_frequency
=
error_data
[
'frequency'
].
first
expect
(
Time
.
parse
(
first_frequency
[
'time'
])).
to
eql
Time
.
at
(
sentry_detailed_error
.
frequency
[
0
][
0
],
in:
0
)
expect
(
first_frequency
[
'count'
]).
to
eql
sentry_detailed_error
.
frequency
[
0
][
1
]
end
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