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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
32ccde8c
Commit
32ccde8c
authored
Sep 25, 2018
by
Filipa Lacerda
Committed by
Phil Hughes
Sep 25, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use Vue component for job artifacts, Commit and Trigger Variables
parent
765686f2
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
317 additions
and
368 deletions
+317
-368
app/assets/javascripts/build_variables.js
app/assets/javascripts/build_variables.js
+0
-10
app/assets/javascripts/jobs/components/artifacts_block.vue
app/assets/javascripts/jobs/components/artifacts_block.vue
+28
-40
app/assets/javascripts/jobs/components/commit_block.vue
app/assets/javascripts/jobs/components/commit_block.vue
+32
-40
app/assets/javascripts/jobs/components/sidebar_details_block.vue
...ets/javascripts/jobs/components/sidebar_details_block.vue
+116
-79
app/assets/javascripts/jobs/components/trigger_block.vue
app/assets/javascripts/jobs/components/trigger_block.vue
+11
-17
app/assets/javascripts/jobs/job_details_mediator.js
app/assets/javascripts/jobs/job_details_mediator.js
+0
-2
app/views/projects/jobs/_sidebar.html.haml
app/views/projects/jobs/_sidebar.html.haml
+0
-57
changelogs/unreleased/50904-move-job-page-vue.yml
changelogs/unreleased/50904-move-job-page-vue.yml
+5
-0
lib/gitlab/testing/request_inspector_middleware.rb
lib/gitlab/testing/request_inspector_middleware.rb
+5
-1
locale/gitlab.pot
locale/gitlab.pot
+1
-1
spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
...tures/projects/artifacts/user_downloads_artifacts_spec.rb
+2
-12
spec/features/projects/jobs_spec.rb
spec/features/projects/jobs_spec.rb
+42
-16
spec/javascripts/jobs/components/artifacts_block_spec.js
spec/javascripts/jobs/components/artifacts_block_spec.js
+33
-33
spec/javascripts/jobs/components/commit_block_spec.js
spec/javascripts/jobs/components/commit_block_spec.js
+27
-14
spec/javascripts/jobs/components/trigger_block_spec.js
spec/javascripts/jobs/components/trigger_block_spec.js
+15
-10
spec/views/projects/jobs/show.html.haml_spec.rb
spec/views/projects/jobs/show.html.haml_spec.rb
+0
-36
No files found.
app/assets/javascripts/build_variables.js
deleted
100644 → 0
View file @
765686f2
import
$
from
'
jquery
'
;
export
default
function
handleRevealVariables
()
{
$
(
'
.js-reveal-variables
'
)
.
off
(
'
click
'
)
.
on
(
'
click
'
,
function
click
()
{
$
(
'
.js-build-variables
'
).
toggle
();
$
(
this
).
hide
();
});
}
app/assets/javascripts/jobs/components/artifacts_block.vue
View file @
32ccde8c
<
script
>
import
TimeagoTooltiop
from
'
~/vue_shared/components/time_ago_tooltip.vue
'
;
import
TimeagoTooltip
from
'
~/vue_shared/components/time_ago_tooltip.vue
'
;
import
timeagoMixin
from
'
~/vue_shared/mixins/timeago
'
;
export
default
{
components
:
{
TimeagoToolti
o
p
,
TimeagoTooltip
,
},
mixins
:
[
timeagoMixin
,
],
props
:
{
// @build.artifacts_expired?
haveArtifactsExpired
:
{
type
:
Boolean
,
artifact
:
{
type
:
Object
,
required
:
true
,
},
// @build.has_expiring_artifacts?
willArtifactsExpire
:
{
type
:
Boolean
,
required
:
true
,
},
expireAt
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
keepArtifactsPath
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
downloadArtifactsPath
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
computed
:
{
isExpired
()
{
return
this
.
artifact
.
expired
;
},
browseArtifactsPath
:
{
type
:
String
,
required
:
false
,
default
:
null
,
// Only when the key is `false` we can render this block
willExpire
()
{
return
this
.
artifact
.
expired
===
false
;
},
},
};
...
...
@@ -46,21 +33,22 @@
</div>
<p
v-if=
"
haveArtifact
sExpired"
v-if=
"
i
sExpired"
class=
"js-artifacts-removed build-detail-row"
>
{{
s__
(
'
Job|The artifacts were removed
'
)
}}
</p>
<p
v-else-if=
"will
Artifacts
Expire"
v-else-if=
"willExpire"
class=
"js-artifacts-will-be-removed build-detail-row"
>
{{
s__
(
'
Job|The artifacts will be removed
'
)
}}
{{
s__
(
'
Job|The artifacts will be removed
in
'
)
}}
</p>
<timeago-toolti
o
p
v-if=
"
expireA
t"
:time=
"
expireA
t"
<timeago-tooltip
v-if=
"
artifact.expire_a
t"
:time=
"
artifact.expire_a
t"
/>
<div
...
...
@@ -68,8 +56,8 @@
role=
"group"
>
<a
v-if=
"
keepArtifactsP
ath"
:href=
"
keepArtifactsP
ath"
v-if=
"
artifact.keep_p
ath"
:href=
"
artifact.keep_p
ath"
class=
"js-keep-artifacts btn btn-sm btn-default"
data-method=
"post"
>
...
...
@@ -77,8 +65,8 @@
</a>
<a
v-if=
"
downloadArtifactsP
ath"
:href=
"
downloadArtifactsP
ath"
v-if=
"
artifact.download_p
ath"
:href=
"
artifact.download_p
ath"
class=
"js-download-artifacts btn btn-sm btn-default"
download
rel=
"nofollow"
...
...
@@ -87,8 +75,8 @@
</a>
<a
v-if=
"
browseArtifactsP
ath"
:href=
"
browseArtifactsP
ath"
v-if=
"
artifact.browse_p
ath"
:href=
"
artifact.browse_p
ath"
class=
"js-browse-artifacts btn btn-sm btn-default"
>
{{
s__
(
'
Job|Browse
'
)
}}
...
...
app/assets/javascripts/jobs/components/commit_block.vue
View file @
32ccde8c
<
script
>
import
ClipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
import
ClipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
export
default
{
components
:
{
ClipboardButton
,
},
props
:
{
pipelineShortSha
:
{
type
:
String
,
required
:
true
,
export
default
{
components
:
{
ClipboardButton
,
},
pipelineShaPath
:
{
type
:
String
,
required
:
true
,
props
:
{
commit
:
{
type
:
Object
,
required
:
true
,
},
mergeRequest
:
{
type
:
Object
,
required
:
false
,
default
:
null
,
},
isLastBlock
:
{
type
:
Boolean
,
required
:
true
,
},
},
mergeRequestReference
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
mergeRequestPath
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
gitCommitTitlte
:
{
type
:
String
,
required
:
true
,
},
},
};
};
</
script
>
<
template
>
<div
class=
"block"
>
<div
:class=
"
{
'block-last': isLastBlock,
block: !isLastBlock
}">
<p>
{{
__
(
'
Commit
'
)
}}
<a
:href=
"
pipelineShaP
ath"
:href=
"
commit.commit_p
ath"
class=
"js-commit-sha commit-sha link-commit"
>
{{
pipelineShortSha
}}
</a>
>
{{
commit
.
short_id
}}
</a>
<clipboard-button
:text=
"
pipelineShortSha
"
:text=
"
commit.short_id
"
:title=
"__('Copy commit SHA to clipboard')"
css-class=
"btn btn-clipboard btn-transparent"
/>
<a
v-if=
"mergeRequest
Path && mergeRequestReference
"
:href=
"mergeRequest
P
ath"
v-if=
"mergeRequest"
:href=
"mergeRequest
.p
ath"
class=
"js-link-commit link-commit"
>
{{
mergeRequestReference
}}
</a>
>
{{
mergeRequest
.
iid
}}
</a>
</p>
<p
class=
"build-light-text append-bottom-0"
>
{{
gitCommitTitlt
e
}}
{{
commit
.
titl
e
}}
</p>
</div>
</
template
>
app/assets/javascripts/jobs/components/sidebar_details_block.vue
View file @
32ccde8c
<
script
>
import
timeagoMixin
from
'
~/vue_shared/mixins/timeago
'
;
import
{
timeIntervalInWords
}
from
'
~/lib/utils/datetime_utility
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
DetailRow
from
'
./sidebar_detail_row.vue
'
;
import
_
from
'
underscore
'
;
import
timeagoMixin
from
'
~/vue_shared/mixins/timeago
'
;
import
{
timeIntervalInWords
}
from
'
~/lib/utils/datetime_utility
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
DetailRow
from
'
./sidebar_detail_row.vue
'
;
import
ArtifactsBlock
from
'
./artifacts_block.vue
'
;
import
TriggerBlock
from
'
./trigger_block.vue
'
;
import
CommitBlock
from
'
./commit_block.vue
'
;
export
default
{
name
:
'
SidebarDetailsBlock
'
,
components
:
{
DetailRow
,
Icon
,
},
mixins
:
[
timeagoMixin
],
props
:
{
job
:
{
type
:
Object
,
required
:
true
,
export
default
{
name
:
'
SidebarDetailsBlock
'
,
components
:
{
ArtifactsBlock
,
CommitBlock
,
DetailRow
,
Icon
,
TriggerBlock
,
},
isLoading
:
{
type
:
Boolean
,
required
:
true
,
mixins
:
[
timeagoMixin
],
props
:
{
job
:
{
type
:
Object
,
required
:
true
,
},
isLoading
:
{
type
:
Boolean
,
required
:
true
,
},
runnerHelpUrl
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
terminalPath
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
},
runnerHelpUrl
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
terminalPath
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
},
computed
:
{
shouldRenderContent
()
{
return
!
this
.
isLoading
&&
Object
.
keys
(
this
.
job
).
length
>
0
;
},
coverage
()
{
return
`
${
this
.
job
.
coverage
}
%`
;
},
duration
()
{
return
timeIntervalInWords
(
this
.
job
.
duration
);
},
queued
()
{
return
timeIntervalInWords
(
this
.
job
.
queued
);
},
runnerId
()
{
return
`
${
this
.
job
.
runner
.
description
}
(#
${
this
.
job
.
runner
.
id
}
)`
;
},
retryButtonClass
()
{
let
className
=
'
js-retry-button float-right btn btn-retry d-none d-md-block d-lg-block d-xl-block
'
;
className
+=
this
.
job
.
status
&&
this
.
job
.
recoverable
?
'
btn-primary
'
:
'
btn-inverted-secondary
'
;
return
className
;
},
hasTimeout
()
{
return
this
.
job
.
metadata
!=
null
&&
this
.
job
.
metadata
.
timeout_human_readable
!==
null
;
},
timeout
()
{
if
(
this
.
job
.
metadata
==
null
)
{
return
''
;
}
computed
:
{
shouldRenderContent
()
{
return
!
this
.
isLoading
&&
Object
.
keys
(
this
.
job
).
length
>
0
;
},
coverage
()
{
return
`
${
this
.
job
.
coverage
}
%`
;
},
duration
()
{
return
timeIntervalInWords
(
this
.
job
.
duration
);
},
queued
()
{
return
timeIntervalInWords
(
this
.
job
.
queued
);
},
runnerId
()
{
return
`
${
this
.
job
.
runner
.
description
}
(#
${
this
.
job
.
runner
.
id
}
)`
;
},
retryButtonClass
()
{
let
className
=
'
js-retry-button float-right btn btn-retry d-none d-md-block d-lg-block d-xl-block
'
;
className
+=
this
.
job
.
status
&&
this
.
job
.
recoverable
?
'
btn-primary
'
:
'
btn-inverted-secondary
'
;
return
className
;
},
hasTimeout
()
{
return
this
.
job
.
metadata
!=
null
&&
this
.
job
.
metadata
.
timeout_human_readable
!==
null
;
},
timeout
()
{
if
(
this
.
job
.
metadata
==
null
)
{
return
''
;
}
let
t
=
this
.
job
.
metadata
.
timeout_human_readable
;
if
(
this
.
job
.
metadata
.
timeout_source
!==
''
)
{
t
+=
` (from
${
this
.
job
.
metadata
.
timeout_source
}
)`
;
}
let
t
=
this
.
job
.
metadata
.
timeout_human_readable
;
if
(
this
.
job
.
metadata
.
timeout_source
!==
''
)
{
t
+=
` (from
${
this
.
job
.
metadata
.
timeout_source
}
)`
;
}
return
t
;
},
renderBlock
()
{
return
(
this
.
job
.
merge_request
||
this
.
job
.
duration
||
this
.
job
.
finished_data
||
this
.
job
.
erased_at
||
this
.
job
.
queued
||
this
.
job
.
runner
||
this
.
job
.
coverage
||
this
.
job
.
tags
.
length
||
this
.
job
.
cancel_path
);
return
t
;
},
renderBlock
()
{
return
(
this
.
job
.
merge_request
||
this
.
job
.
duration
||
this
.
job
.
finished_data
||
this
.
job
.
erased_at
||
this
.
job
.
queued
||
this
.
job
.
runner
||
this
.
job
.
coverage
||
this
.
job
.
tags
.
length
||
this
.
job
.
cancel_path
);
},
hasArtifact
()
{
return
!
_
.
isEmpty
(
this
.
job
.
artifact
);
},
hasTriggers
()
{
return
!
_
.
isEmpty
(
this
.
job
.
trigger
);
},
hasStages
()
{
return
(
this
.
job
&&
this
.
job
.
pipeline
&&
this
.
job
.
pipeline
.
stages
&&
this
.
job
.
pipeline
.
stages
.
length
>
0
)
||
false
;
},
commit
()
{
return
this
.
job
.
pipeline
.
commit
||
{};
},
},
},
};
};
</
script
>
<
template
>
<div>
...
...
@@ -229,6 +253,19 @@ export default {
</a>
</div>
</div>
<artifacts-block
v-if=
"hasArtifact"
:artifact=
"job.artifact"
/>
<trigger-block
v-if=
"hasTriggers"
:trigger=
"job.trigger"
/>
<commit-block
:is-last-block=
"hasStages"
:commit=
"commit"
:merge-request=
"job.merge_request"
/>
</
template
>
<gl-loading-icon
v-if=
"isLoading"
...
...
app/assets/javascripts/jobs/components/trigger_block.vue
View file @
32ccde8c
<
script
>
export
default
{
props
:
{
shortToken
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
variables
:
{
trigger
:
{
type
:
Object
,
required
:
false
,
default
:
()
=>
({}),
required
:
true
,
},
},
data
()
{
...
...
@@ -20,7 +13,7 @@
},
computed
:
{
hasVariables
()
{
return
Object
.
keys
(
this
.
variables
)
.
length
>
0
;
return
this
.
trigger
.
variables
&&
this
.
trigger
.
variables
.
length
>
0
;
},
},
methods
:
{
...
...
@@ -38,17 +31,18 @@
</h4>
<p
v-if=
"
shortT
oken"
v-if=
"
trigger.short_t
oken"
class=
"js-short-token"
>
<span
class=
"build-light-text"
>
{{
__
(
'
Token
'
)
}}
</span>
{{
shortT
oken
}}
{{
trigger
.
short_t
oken
}}
</p>
<p
v-if=
"hasVariables"
>
<button
v-if=
"!areVariablesVisible"
type=
"button"
class=
"btn btn-default group js-reveal-variables"
@
click=
"revealVariables"
...
...
@@ -63,20 +57,20 @@
class=
"js-build-variables trigger-build-variables"
>
<template
v-for=
"
(value, key) in
variables"
v-for=
"
variable in trigger.
variables"
>
<dt
:key=
"`$
{key}-variable`"
:key=
"`$
{
variable.
key}-variable`"
class="js-build-variable trigger-build-variable"
>
{{
key
}}
{{
variable
.
key
}}
</dt>
<dd
:key=
"`$
{key}-value`"
:key=
"`$
{
variable.
key}-value`"
class="js-build-value trigger-build-value"
>
{{
value
}}
{{
va
riable
.
va
lue
}}
</dd>
</
template
>
</dl>
...
...
app/assets/javascripts/jobs/job_details_mediator.js
View file @
32ccde8c
...
...
@@ -4,7 +4,6 @@ import Poll from '../lib/utils/poll';
import
JobStore
from
'
./stores/job_store
'
;
import
JobService
from
'
./services/job_service
'
;
import
Job
from
'
../job
'
;
import
handleRevealVariables
from
'
../build_variables
'
;
export
default
class
JobMediator
{
constructor
(
options
=
{})
{
...
...
@@ -20,7 +19,6 @@ export default class JobMediator {
initBuildClass
()
{
this
.
build
=
new
Job
();
handleRevealVariables
();
}
fetchJob
()
{
...
...
app/views/projects/jobs/_sidebar.html.haml
View file @
32ccde8c
...
...
@@ -3,63 +3,6 @@
.blocks-container
#js-details-block-vue
{
data:
{
terminal_path:
can?
(
current_user
,
:create_build_terminal
,
@build
)
&&
@build
.
has_terminal?
?
terminal_project_job_path
(
@project
,
@build
)
:
nil
}
}
-
if
can?
(
current_user
,
:read_build
,
@project
)
&&
(
@build
.
artifacts?
||
@build
.
artifacts_expired?
)
.block
.title
Job artifacts
-
if
@build
.
artifacts_expired?
%p
.build-detail-row
The artifacts were removed
#{
time_ago_with_tooltip
(
@build
.
artifacts_expire_at
)
}
-
elsif
@build
.
has_expiring_artifacts?
%p
.build-detail-row
The artifacts will be removed
#{
time_ago_with_tooltip
(
@build
.
artifacts_expire_at
)
}
-
if
@build
.
artifacts?
.btn-group.d-flex
{
role: :group
}
-
if
@build
.
has_expiring_artifacts?
&&
can?
(
current_user
,
:update_build
,
@build
)
=
link_to
keep_project_job_artifacts_path
(
@project
,
@build
),
class:
'btn btn-sm btn-default'
,
method: :post
do
Keep
=
link_to
download_project_job_artifacts_path
(
@project
,
@build
),
rel:
'nofollow'
,
download:
''
,
class:
'btn btn-sm btn-default'
do
Download
-
if
@build
.
browsable_artifacts?
=
link_to
browse_project_job_artifacts_path
(
@project
,
@build
),
class:
'btn btn-sm btn-default'
do
Browse
-
if
@build
.
trigger_request
.build-widget.block
%h4
.title
Trigger
-
if
@build
.
trigger_request
&
.
trigger
&
.
short_token
%p
%span
.build-light-text
Token:
#{
@build
.
trigger_request
.
trigger
.
short_token
}
-
if
@build
.
trigger_variables
.
any?
%p
%button
.btn.group.js-reveal-variables
Reveal Variables
%dl
.js-build-variables.trigger-build-variables.hide
-
@build
.
trigger_variables
.
each
do
|
trigger_variable
|
%dt
.js-build-variable.trigger-build-variable
=
trigger_variable
[
:key
]
%dd
.js-build-value.trigger-build-value
=
trigger_variable
[
:value
]
%div
{
class:
(
@build
.
pipeline
.
stages_count
>
1
?
"block"
:
"block-last"
)
}
%p
Commit
=
link_to
@build
.
pipeline
.
short_sha
,
project_commit_path
(
@project
,
@build
.
pipeline
.
sha
),
class:
'commit-sha link-commit'
=
clipboard_button
(
text:
@build
.
pipeline
.
short_sha
,
title:
"Copy commit SHA to clipboard"
)
-
if
@build
.
merge_request
in
=
link_to
"
#{
@build
.
merge_request
.
to_reference
}
"
,
merge_request_path
(
@build
.
merge_request
),
class:
'link-commit'
%p
.build-light-text.append-bottom-0
#{
@build
.
pipeline
.
git_commit_title
}
-
if
@build
.
pipeline
.
stages_count
>
1
.block-last.dropdown.build-dropdown
%div
...
...
changelogs/unreleased/50904-move-job-page-vue.yml
0 → 100644
View file @
32ccde8c
---
title
:
Use Vue components and new API to render Artifacts, Trigger Variables and Commit blocks on Job page
merge_request
:
21777
author
:
type
:
other
lib/gitlab/testing/request_inspector_middleware.rb
View file @
32ccde8c
...
...
@@ -35,11 +35,15 @@ module Gitlab
request_headers
=
env_http_headers
(
env
)
status
,
headers
,
body
=
@app
.
call
(
env
)
full_body
=
''
body
.
each
{
|
b
|
full_body
<<
b
}
request
=
OpenStruct
.
new
(
url:
url
,
status_code:
status
,
request_headers:
request_headers
,
response_headers:
headers
response_headers:
headers
,
body:
full_body
)
log_request
request
...
...
locale/gitlab.pot
View file @
32ccde8c
...
...
@@ -3365,7 +3365,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
msgid "Job|The artifacts will be removed"
msgid "Job|The artifacts will be removed
in
"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
...
...
spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
View file @
32ccde8c
...
...
@@ -20,23 +20,13 @@ describe "User downloads artifacts" do
end
context
"via job id"
do
s
et
(
:url
)
{
download_project_job_artifacts_path
(
project
,
job
)
}
l
et
(
:url
)
{
download_project_job_artifacts_path
(
project
,
job
)
}
it_behaves_like
"downloading"
end
context
"via branch name and job name"
do
set
(
:url
)
{
latest_succeeded_project_artifacts_path
(
project
,
"
#{
pipeline
.
ref
}
/download"
,
job:
job
.
name
)
}
it_behaves_like
"downloading"
end
context
"via clicking the `Download` button"
do
set
(
:url
)
{
project_job_path
(
project
,
job
)
}
before
do
click_link
(
"Download"
)
end
let
(
:url
)
{
latest_succeeded_project_artifacts_path
(
project
,
"
#{
pipeline
.
ref
}
/download"
,
job:
job
.
name
)
}
it_behaves_like
"downloading"
end
...
...
spec/features/projects/jobs_spec.rb
View file @
32ccde8c
...
...
@@ -5,7 +5,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
let
(
:user
)
{
create
(
:user
)
}
let
(
:user_access_level
)
{
:developer
}
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
)
}
let
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
,
sha:
project
.
commit
(
'HEAD'
).
sha
)
}
let
(
:job
)
{
create
(
:ci_build
,
:trace_live
,
pipeline:
pipeline
)
}
let
(
:job2
)
{
create
(
:ci_build
)
}
...
...
@@ -20,7 +20,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
describe
"GET /:project/jobs"
do
let!
(
:job
)
{
create
(
:ci_build
,
pipeline:
pipeline
)
}
let!
(
:job
)
{
create
(
:ci_build
,
pipeline:
pipeline
)
}
context
"Pending scope"
do
before
do
...
...
@@ -115,22 +115,28 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
context
"Job from project"
do
let
(
:job
)
{
create
(
:ci_build
,
:success
,
:trace_live
,
pipeline:
pipeline
)
}
before
do
it
'shows status name'
,
:js
do
visit
project_job_path
(
project
,
job
)
end
it
'shows status name'
,
:js
do
wait_for_requests
expect
(
page
).
to
have_css
(
'.ci-status.ci-success'
,
text:
'passed'
)
end
it
'shows commit`s data'
do
expect
(
page
.
status_code
).
to
eq
(
200
)
it
'shows commit`s data'
,
:js
do
requests
=
inspect_requests
()
do
visit
project_job_path
(
project
,
job
)
end
wait_for_requests
expect
(
requests
.
first
.
status_code
).
to
eq
(
200
)
expect
(
page
).
to
have_content
pipeline
.
sha
[
0
..
7
]
expect
(
page
).
to
have_content
pipeline
.
git_commit_message
expect
(
page
).
to
have_content
pipeline
.
git_author_name
expect
(
page
).
to
have_content
pipeline
.
commit
.
title
end
it
'shows active job'
do
visit
project_job_path
(
project
,
job
)
expect
(
page
).
to
have_selector
(
'.build-job.active'
)
end
end
...
...
@@ -199,7 +205,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it
{
expect
(
page
.
status_code
).
to
eq
(
404
)
}
end
context
"Download artifacts"
do
context
"Download artifacts"
,
:js
do
before
do
job
.
update
(
legacy_artifacts_file:
artifacts_file
)
visit
project_job_path
(
project
,
job
)
...
...
@@ -208,9 +214,22 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it
'has button to download artifacts'
do
expect
(
page
).
to
have_content
'Download'
end
it
'downloads the zip file when user clicks the download button'
do
requests
=
inspect_requests
()
do
click_link
'Download'
end
artifact_request
=
requests
.
find
{
|
req
|
req
.
url
.
match
(
%r{artifacts/download}
)
}
expect
(
artifact_request
.
response_headers
[
"Content-Disposition"
]).
to
eq
(
%Q{attachment; filename="
#{
job
.
artifacts_file
.
filename
}
"}
)
expect
(
artifact_request
.
response_headers
[
'Content-Transfer-Encoding'
]).
to
eq
(
"binary"
)
expect
(
artifact_request
.
response_headers
[
'Content-Type'
]).
to
eq
(
"image/gif"
)
expect
(
artifact_request
.
body
).
to
eq
(
job
.
artifacts_file
.
file
.
read
.
b
)
end
end
context
'Artifacts expire date'
do
context
'Artifacts expire date'
,
:js
do
before
do
job
.
update
(
legacy_artifacts_file:
artifacts_file
,
artifacts_expire_at:
expire_at
)
...
...
@@ -231,12 +250,12 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
context
'when user has ability to update job'
do
it
'keeps artifacts when keep button is clicked'
do
expect
(
page
).
to
have_content
'The artifacts will be removed'
expect
(
page
).
to
have_content
'The artifacts will be removed
in
'
click_link
'Keep'
expect
(
page
).
to
have_no_link
'Keep'
expect
(
page
).
to
have_no_content
'The artifacts will be removed'
expect
(
page
).
to
have_no_content
'The artifacts will be removed
in
'
end
end
...
...
@@ -314,6 +333,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
shared_examples
'expected variables behavior'
do
it
'shows variable key and value after click'
,
:js
do
expect
(
page
).
to
have_content
(
'Token'
)
expect
(
page
).
to
have_css
(
'.js-reveal-variables'
)
expect
(
page
).
not_to
have_css
(
'.js-build-variable'
)
expect
(
page
).
not_to
have_css
(
'.js-build-value'
)
...
...
@@ -542,20 +562,26 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
describe
"GET /:project/jobs/:id/download"
do
describe
"GET /:project/jobs/:id/download"
,
:js
do
before
do
job
.
update
(
legacy_artifacts_file:
artifacts_file
)
visit
project_job_path
(
project
,
job
)
click_link
'Download'
end
context
"Build from other project"
do
before
do
job2
.
update
(
legacy_artifacts_file:
artifacts_file
)
visit
download_project_job_artifacts_path
(
project
,
job2
)
end
it
{
expect
(
page
.
status_code
).
to
eq
(
404
)
}
it
do
requests
=
inspect_requests
()
do
visit
download_project_job_artifacts_path
(
project
,
job2
)
end
expect
(
requests
.
first
.
status_code
).
to
eq
(
404
)
end
end
end
...
...
spec/javascripts/jobs/components/artifacts_block_spec.js
View file @
32ccde8c
...
...
@@ -11,6 +11,19 @@ describe('Artifacts block', () => {
const
timeago
=
getTimeago
();
const
formatedDate
=
timeago
.
format
(
expireAt
);
const
expiredArtifact
=
{
expire_at
:
expireAt
,
expired
:
true
,
};
const
nonExpiredArtifact
=
{
download_path
:
'
/gitlab-org/gitlab-ce/-/jobs/98314558/artifacts/download
'
,
browse_path
:
'
/gitlab-org/gitlab-ce/-/jobs/98314558/artifacts/browse
'
,
keep_path
:
'
/gitlab-org/gitlab-ce/-/jobs/98314558/artifacts/keep
'
,
expire_at
:
expireAt
,
expired
:
false
,
};
afterEach
(()
=>
{
vm
.
$destroy
();
});
...
...
@@ -18,100 +31,87 @@ describe('Artifacts block', () => {
describe
(
'
with expired artifacts
'
,
()
=>
{
it
(
'
renders expired artifact date and info
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
haveArtifactsExpired
:
true
,
willArtifactsExpire
:
false
,
expireAt
,
artifact
:
expiredArtifact
,
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-artifacts-removed
'
)).
not
.
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.js-artifacts-will-be-removed
'
)).
toBeNull
();
expect
(
vm
.
$el
.
textContent
).
toContain
(
formatedDate
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-artifacts-removed
'
).
textContent
.
trim
()).
toEqual
(
'
The artifacts were removed
'
,
);
});
});
describe
(
'
with artifacts that will expire
'
,
()
=>
{
it
(
'
renders will expire artifact date and info
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
haveArtifactsExpired
:
false
,
willArtifactsExpire
:
true
,
expireAt
,
artifact
:
nonExpiredArtifact
,
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-artifacts-removed
'
)).
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.js-artifacts-will-be-removed
'
)).
not
.
toBeNull
();
expect
(
vm
.
$el
.
textContent
).
toContain
(
formatedDate
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-artifacts-will-be-removed
'
).
textContent
.
trim
()).
toEqual
(
'
The artifacts will be removed in
'
,
);
});
});
describe
(
'
w
hen the user can keep the artifacts
'
,
()
=>
{
describe
(
'
w
ith keep path
'
,
()
=>
{
it
(
'
renders the keep button
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
haveArtifactsExpired
:
true
,
willArtifactsExpire
:
false
,
expireAt
,
keepArtifactsPath
:
'
/keep
'
,
artifact
:
nonExpiredArtifact
,
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-keep-artifacts
'
)).
not
.
toBeNull
();
});
});
describe
(
'
w
hen the user can not keep the artifacts
'
,
()
=>
{
describe
(
'
w
ithout keep path
'
,
()
=>
{
it
(
'
does not render the keep button
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
haveArtifactsExpired
:
true
,
willArtifactsExpire
:
false
,
expireAt
,
artifact
:
expiredArtifact
,
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-keep-artifacts
'
)).
toBeNull
();
});
});
describe
(
'
w
hen the user can download the artifacts
'
,
()
=>
{
describe
(
'
w
ith download path
'
,
()
=>
{
it
(
'
renders the download button
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
haveArtifactsExpired
:
true
,
willArtifactsExpire
:
false
,
expireAt
,
downloadArtifactsPath
:
'
/download
'
,
artifact
:
nonExpiredArtifact
,
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-artifacts
'
)).
not
.
toBeNull
();
});
});
describe
(
'
w
hen the user can not download the artifacts
'
,
()
=>
{
describe
(
'
w
ithout download path
'
,
()
=>
{
it
(
'
does not render the keep button
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
haveArtifactsExpired
:
true
,
willArtifactsExpire
:
false
,
expireAt
,
artifact
:
expiredArtifact
,
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-artifacts
'
)).
toBeNull
();
});
});
describe
(
'
w
hen the user can browse the artifacts
'
,
()
=>
{
describe
(
'
w
ith browse path
'
,
()
=>
{
it
(
'
does not render the browse button
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
haveArtifactsExpired
:
true
,
willArtifactsExpire
:
false
,
expireAt
,
browseArtifactsPath
:
'
/browse
'
,
artifact
:
nonExpiredArtifact
,
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-browse-artifacts
'
)).
not
.
toBeNull
();
});
});
describe
(
'
w
hen the user can not browse the artifacts
'
,
()
=>
{
describe
(
'
w
ithout browse path
'
,
()
=>
{
it
(
'
does not render the browse button
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
haveArtifactsExpired
:
true
,
willArtifactsExpire
:
false
,
expireAt
,
artifact
:
expiredArtifact
,
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-browse-artifacts
'
)).
toBeNull
();
...
...
spec/javascripts/jobs/components/commit_block_spec.js
View file @
32ccde8c
...
...
@@ -7,11 +7,16 @@ describe('Commit block', () => {
let
vm
;
const
props
=
{
pipelineShortSha
:
'
1f0fb84f
'
,
pipelineShaPath
:
'
commit/1f0fb84fb6770d74d97eee58118fd3909cd4f48c
'
,
mergeRequestReference
:
'
!21244
'
,
mergeRequestPath
:
'
merge_requests/21244
'
,
gitCommitTitlte
:
'
Regenerate pot files
'
,
commit
:
{
short_id
:
'
1f0fb84f
'
,
commit_path
:
'
commit/1f0fb84fb6770d74d97eee58118fd3909cd4f48c
'
,
title
:
'
Update README.md
'
,
},
mergeRequest
:
{
iid
:
'
!21244
'
,
path
:
'
merge_requests/21244
'
,
},
isLastBlock
:
true
,
};
afterEach
(()
=>
{
...
...
@@ -26,12 +31,18 @@ describe('Commit block', () => {
});
it
(
'
renders pipeline short sha link
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-commit-sha
'
).
getAttribute
(
'
href
'
)).
toEqual
(
props
.
pipelineShaPath
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-commit-sha
'
).
textContent
.
trim
()).
toEqual
(
props
.
pipelineShortSha
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-commit-sha
'
).
getAttribute
(
'
href
'
)).
toEqual
(
props
.
commit
.
commit_path
,
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-commit-sha
'
).
textContent
.
trim
()).
toEqual
(
props
.
commit
.
short_id
,
);
});
it
(
'
renders clipboard button
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
button
'
).
getAttribute
(
'
data-clipboard-text
'
)).
toEqual
(
props
.
pipelineShortSha
);
expect
(
vm
.
$el
.
querySelector
(
'
button
'
).
getAttribute
(
'
data-clipboard-text
'
)).
toEqual
(
props
.
commit
.
short_id
,
);
});
});
...
...
@@ -41,17 +52,19 @@ describe('Commit block', () => {
...
props
,
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-link-commit
'
).
getAttribute
(
'
href
'
)).
toEqual
(
props
.
mergeRequestPath
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-link-commit
'
).
textContent
.
trim
()).
toEqual
(
props
.
mergeRequestReference
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-link-commit
'
).
getAttribute
(
'
href
'
)).
toEqual
(
props
.
mergeRequest
.
path
,
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-link-commit
'
).
textContent
.
trim
()).
toEqual
(
props
.
mergeRequest
.
iid
,
);
});
});
describe
(
'
without merge request
'
,
()
=>
{
it
(
'
does not render merge request
'
,
()
=>
{
const
copyProps
=
Object
.
assign
({},
props
);
delete
copyProps
.
mergeRequestPath
;
delete
copyProps
.
mergeRequestReference
;
delete
copyProps
.
mergeRequest
;
vm
=
mountComponent
(
Component
,
{
...
copyProps
,
...
...
@@ -67,7 +80,7 @@ describe('Commit block', () => {
...
props
,
});
expect
(
vm
.
$el
.
textContent
).
toContain
(
props
.
gitCommitTitlt
e
);
expect
(
vm
.
$el
.
textContent
).
toContain
(
props
.
commit
.
titl
e
);
});
});
});
spec/javascripts/jobs/components/trigger_
value
_spec.js
→
spec/javascripts/jobs/components/trigger_
block
_spec.js
View file @
32ccde8c
...
...
@@ -13,7 +13,9 @@ describe('Trigger block', () => {
describe
(
'
with short token
'
,
()
=>
{
it
(
'
renders short token
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
shortToken
:
'
0a666b2
'
,
trigger
:
{
short_token
:
'
0a666b2
'
,
},
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-short-token
'
).
textContent
).
toContain
(
'
0a666b2
'
);
...
...
@@ -22,7 +24,7 @@ describe('Trigger block', () => {
describe
(
'
without short token
'
,
()
=>
{
it
(
'
does not render short token
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{});
vm
=
mountComponent
(
Component
,
{
trigger
:
{}
});
expect
(
vm
.
$el
.
querySelector
(
'
.js-short-token
'
)).
toBeNull
();
});
...
...
@@ -32,9 +34,12 @@ describe('Trigger block', () => {
describe
(
'
reveal variables
'
,
()
=>
{
it
(
'
reveals variables on click
'
,
done
=>
{
vm
=
mountComponent
(
Component
,
{
variables
:
{
key
:
'
value
'
,
variable
:
'
foo
'
,
trigger
:
{
short_token
:
'
bd7e
'
,
variables
:
[
{
key
:
'
UPLOAD_TO_GCS
'
,
value
:
'
false
'
,
public
:
false
},
{
key
:
'
UPLOAD_TO_S3
'
,
value
:
'
true
'
,
public
:
false
},
],
},
});
...
...
@@ -44,10 +49,10 @@ describe('Trigger block', () => {
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
)).
not
.
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
).
textContent
).
toContain
(
'
key
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
).
textContent
).
toContain
(
'
valu
e
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
).
textContent
).
toContain
(
'
variable
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
).
textContent
).
toContain
(
'
foo
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
).
textContent
).
toContain
(
'
UPLOAD_TO_GCS
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
).
textContent
).
toContain
(
'
fals
e
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
).
textContent
).
toContain
(
'
UPLOAD_TO_S3
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
).
textContent
).
toContain
(
'
true
'
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
...
...
@@ -57,7 +62,7 @@ describe('Trigger block', () => {
describe
(
'
without variables
'
,
()
=>
{
it
(
'
does not render variables
'
,
()
=>
{
vm
=
mountComponent
(
Component
);
vm
=
mountComponent
(
Component
,
{
trigger
:
{}
}
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-reveal-variables
'
)).
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.js-build-variables
'
)).
toBeNull
();
...
...
spec/views/projects/jobs/show.html.haml_spec.rb
View file @
32ccde8c
...
...
@@ -188,40 +188,4 @@ describe 'projects/jobs/show' do
expect
(
rendered
).
not_to
have_link
(
'New issue'
)
end
end
context
'when incomplete trigger_request is used'
do
before
do
build
.
trigger_request
=
FactoryBot
.
build
(
:ci_trigger_request
,
trigger:
nil
)
end
it
'test should not render token block'
do
render
expect
(
rendered
).
not_to
have_content
(
'Token'
)
end
end
context
'when complete trigger_request is used'
do
before
do
build
.
trigger_request
=
FactoryBot
.
build
(
:ci_trigger_request
)
end
it
'should render token'
do
render
expect
(
rendered
).
to
have_content
(
'Token'
)
expect
(
rendered
).
to
have_content
(
build
.
trigger_request
.
trigger
.
short_token
)
end
end
describe
'commit title in sidebar'
do
let
(
:commit_title
)
{
project
.
commit
.
title
}
it
'shows commit title and not show commit message'
do
render
expect
(
rendered
).
to
have_css
(
'p.build-light-text.append-bottom-0'
,
text:
/\A\n
#{
Regexp
.
escape
(
commit_title
)
}
\n\Z/
)
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