2015-10-24 18:46:33 +05:30
require 'spec_helper'
2016-09-29 09:46:39 +05:30
require 'tempfile'
2015-10-24 18:46:33 +05:30
2018-11-08 19:23:39 +05:30
describe 'Jobs' , :clean_gitlab_redis_shared_state do
2019-07-07 11:18:12 +05:30
include Gitlab :: Routing
include ProjectForksHelper
2017-08-17 22:00:37 +05:30
let ( :user ) { create ( :user ) }
let ( :user_access_level ) { :developer }
2017-09-10 17:25:29 +05:30
let ( :project ) { create ( :project , :repository ) }
2018-12-05 23:21:45 +05:30
let ( :pipeline ) { create ( :ci_pipeline , project : project , sha : project . commit ( 'HEAD' ) . sha ) }
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
let ( :job ) { create ( :ci_build , :trace_live , pipeline : pipeline ) }
2017-09-10 17:25:29 +05:30
let ( :job2 ) { create ( :ci_build ) }
2017-08-17 22:00:37 +05:30
let ( :artifacts_file ) do
2018-11-08 19:23:39 +05:30
fixture_file_upload ( 'spec/fixtures/banana_sample.gif' , 'image/gif' )
2017-08-17 22:00:37 +05:30
end
2015-11-26 14:37:03 +05:30
2015-10-24 18:46:33 +05:30
before do
2018-03-17 18:26:18 +05:30
project . add_role ( user , user_access_level )
2017-09-10 17:25:29 +05:30
sign_in ( user )
2019-12-04 20:38:33 +05:30
stub_feature_flags ( job_log_json : false )
2015-10-24 18:46:33 +05:30
end
2017-09-10 17:25:29 +05:30
describe " GET /:project/jobs " do
2018-12-05 23:21:45 +05:30
let! ( :job ) { create ( :ci_build , pipeline : pipeline ) }
2017-08-17 22:00:37 +05:30
2016-08-24 12:49:21 +05:30
context " Pending scope " do
before do
2017-09-10 17:25:29 +05:30
visit project_jobs_path ( project , scope : :pending )
2016-08-24 12:49:21 +05:30
end
2017-08-17 22:00:37 +05:30
it " shows Pending tab jobs " do
2016-08-24 12:49:21 +05:30
expect ( page ) . to have_selector ( '.nav-links li.active' , text : 'Pending' )
2017-09-10 17:25:29 +05:30
expect ( page ) . to have_content job . short_sha
expect ( page ) . to have_content job . ref
expect ( page ) . to have_content job . name
2016-08-24 12:49:21 +05:30
end
end
2015-10-24 18:46:33 +05:30
context " Running scope " do
before do
2017-09-10 17:25:29 +05:30
job . run!
visit project_jobs_path ( project , scope : :running )
2015-10-24 18:46:33 +05:30
end
2017-08-17 22:00:37 +05:30
it " shows Running tab jobs " do
2016-08-24 12:49:21 +05:30
expect ( page ) . to have_selector ( '.nav-links li.active' , text : 'Running' )
2017-09-10 17:25:29 +05:30
expect ( page ) . to have_content job . short_sha
expect ( page ) . to have_content job . ref
expect ( page ) . to have_content job . name
2016-08-24 12:49:21 +05:30
end
2015-10-24 18:46:33 +05:30
end
context " Finished scope " do
before do
2017-09-10 17:25:29 +05:30
job . run!
visit project_jobs_path ( project , scope : :finished )
2015-10-24 18:46:33 +05:30
end
2017-08-17 22:00:37 +05:30
it " shows Finished tab jobs " do
2016-08-24 12:49:21 +05:30
expect ( page ) . to have_selector ( '.nav-links li.active' , text : 'Finished' )
2017-08-17 22:00:37 +05:30
expect ( page ) . to have_content 'No jobs to show'
2016-08-24 12:49:21 +05:30
end
2015-10-24 18:46:33 +05:30
end
2017-08-17 22:00:37 +05:30
context " All jobs " do
2015-10-24 18:46:33 +05:30
before do
2017-08-17 22:00:37 +05:30
project . builds . running_or_pending . each ( & :success )
2017-09-10 17:25:29 +05:30
visit project_jobs_path ( project )
2015-10-24 18:46:33 +05:30
end
2017-08-17 22:00:37 +05:30
it " shows All tab jobs " do
2016-08-24 12:49:21 +05:30
expect ( page ) . to have_selector ( '.nav-links li.active' , text : 'All' )
2017-09-10 17:25:29 +05:30
expect ( page ) . to have_content job . short_sha
expect ( page ) . to have_content job . ref
expect ( page ) . to have_content job . name
2016-08-24 12:49:21 +05:30
end
2015-10-24 18:46:33 +05:30
end
2017-09-10 17:25:29 +05:30
context " when visiting old URL " do
let ( :jobs_url ) do
project_jobs_path ( project )
end
before do
visit jobs_url . sub ( '/-/jobs' , '/builds' )
end
it " redirects to new URL " do
expect ( page . current_path ) . to eq ( jobs_url )
end
end
2015-10-24 18:46:33 +05:30
end
2017-09-10 17:25:29 +05:30
describe " GET /:project/jobs/:id " do
2017-08-17 22:00:37 +05:30
context " Job from project " do
2018-05-09 12:01:36 +05:30
let ( :job ) { create ( :ci_build , :success , :trace_live , pipeline : pipeline ) }
2017-09-10 17:25:29 +05:30
2018-12-05 23:21:45 +05:30
it 'shows status name' , :js do
2017-09-10 17:25:29 +05:30
visit project_job_path ( project , job )
2018-12-05 23:21:45 +05:30
wait_for_requests
2017-09-10 17:25:29 +05:30
expect ( page ) . to have_css ( '.ci-status.ci-success' , text : 'passed' )
2016-06-16 23:09:34 +05:30
end
2018-12-05 23:21:45 +05:30
it 'shows commit`s data' , :js do
2019-03-02 22:35:43 +05:30
requests = inspect_requests do
2018-12-05 23:21:45 +05:30
visit project_job_path ( project , job )
end
wait_for_requests
expect ( requests . first . status_code ) . to eq ( 200 )
2017-08-17 22:00:37 +05:30
expect ( page ) . to have_content pipeline . sha [ 0 .. 7 ]
2018-12-05 23:21:45 +05:30
expect ( page ) . to have_content pipeline . commit . title
2017-08-17 22:00:37 +05:30
end
2018-12-05 23:21:45 +05:30
it 'shows active job' , :js do
visit project_job_path ( project , job )
wait_for_requests
2017-08-17 22:00:37 +05:30
expect ( page ) . to have_selector ( '.build-job.active' )
end
2015-10-24 18:46:33 +05:30
end
2019-07-07 11:18:12 +05:30
context 'pipeline info block' , :js do
it 'shows pipeline id and source branch' do
visit project_job_path ( project , job )
within '.js-pipeline-info' do
expect ( page ) . to have_content ( " Pipeline # #{ pipeline . id } for #{ pipeline . ref } " )
end
end
context 'when pipeline is detached merge request pipeline' do
let ( :merge_request ) do
create ( :merge_request ,
:with_detached_merge_request_pipeline ,
target_project : target_project ,
source_project : source_project )
end
let ( :source_project ) { project }
let ( :target_project ) { project }
let ( :pipeline ) { merge_request . all_pipelines . last }
let ( :job ) { create ( :ci_build , pipeline : pipeline ) }
it 'shows merge request iid and source branch' do
visit project_job_path ( project , job )
within '.js-pipeline-info' do
expect ( page ) . to have_content ( " for ! #{ pipeline . merge_request . iid } " \
" with #{ pipeline . merge_request . source_branch } " )
expect ( page ) . to have_link ( " ! #{ pipeline . merge_request . iid } " ,
href : project_merge_request_path ( project , merge_request ) )
expect ( page ) . to have_link ( pipeline . merge_request . source_branch ,
href : project_commits_path ( project , merge_request . source_branch ) )
end
end
context 'when source project is a forked project' do
let ( :source_project ) { fork_project ( project , user , repository : true ) }
let ( :target_project ) { project }
it 'shows merge request iid and source branch' do
visit project_job_path ( source_project , job )
within '.js-pipeline-info' do
expect ( page ) . to have_content ( " for ! #{ pipeline . merge_request . iid } " \
" with #{ pipeline . merge_request . source_branch } " )
expect ( page ) . to have_link ( " ! #{ pipeline . merge_request . iid } " ,
href : project_merge_request_path ( project , merge_request ) )
expect ( page ) . to have_link ( pipeline . merge_request . source_branch ,
href : project_commits_path ( source_project , merge_request . source_branch ) )
end
end
end
end
context 'when pipeline is merge request pipeline' do
let ( :merge_request ) do
create ( :merge_request ,
:with_merge_request_pipeline ,
target_project : target_project ,
source_project : source_project )
end
let ( :source_project ) { project }
let ( :target_project ) { project }
let ( :pipeline ) { merge_request . all_pipelines . last }
let ( :job ) { create ( :ci_build , pipeline : pipeline ) }
it 'shows merge request iid and source branch' do
visit project_job_path ( project , job )
within '.js-pipeline-info' do
expect ( page ) . to have_content ( " for ! #{ pipeline . merge_request . iid } " \
" with #{ pipeline . merge_request . source_branch } " \
" into #{ pipeline . merge_request . target_branch } " )
expect ( page ) . to have_link ( " ! #{ pipeline . merge_request . iid } " ,
href : project_merge_request_path ( project , merge_request ) )
expect ( page ) . to have_link ( pipeline . merge_request . source_branch ,
href : project_commits_path ( project , merge_request . source_branch ) )
expect ( page ) . to have_link ( pipeline . merge_request . target_branch ,
href : project_commits_path ( project , merge_request . target_branch ) )
end
end
context 'when source project is a forked project' do
let ( :source_project ) { fork_project ( project , user , repository : true ) }
let ( :target_project ) { project }
it 'shows merge request iid and source branch' do
visit project_job_path ( source_project , job )
within '.js-pipeline-info' do
expect ( page ) . to have_content ( " for ! #{ pipeline . merge_request . iid } " \
" with #{ pipeline . merge_request . source_branch } " \
" into #{ pipeline . merge_request . target_branch } " )
expect ( page ) . to have_link ( " ! #{ pipeline . merge_request . iid } " ,
href : project_merge_request_path ( project , merge_request ) )
expect ( page ) . to have_link ( pipeline . merge_request . source_branch ,
href : project_commits_path ( source_project , merge_request . source_branch ) )
expect ( page ) . to have_link ( pipeline . merge_request . target_branch ,
href : project_commits_path ( project , merge_request . target_branch ) )
end
end
end
end
end
2018-12-05 23:21:45 +05:30
context 'sidebar' , :js do
2018-10-15 14:42:47 +05:30
let ( :job ) { create ( :ci_build , :success , :trace_live , pipeline : pipeline , name : '<img src=x onerror=alert(document.domain)>' ) }
before do
visit project_job_path ( project , job )
2018-12-05 23:21:45 +05:30
wait_for_requests
2018-10-15 14:42:47 +05:30
end
it 'renders escaped tooltip name' do
2018-12-05 23:21:45 +05:30
page . find ( '.active.build-job a' ) . hover
expect ( page ) . to have_content ( '<img src=x onerror=alert(document.domain)> - passed' )
2018-10-15 14:42:47 +05:30
end
end
2017-09-10 17:25:29 +05:30
context 'when job is not running' , :js do
2018-05-09 12:01:36 +05:30
let ( :job ) { create ( :ci_build , :success , :trace_artifact , pipeline : pipeline ) }
2017-09-10 17:25:29 +05:30
before do
visit project_job_path ( project , job )
end
it 'shows retry button' do
expect ( page ) . to have_link ( 'Retry' )
end
context 'if job passed' do
it 'does not show New issue button' do
expect ( page ) . not_to have_link ( 'New issue' )
end
end
context 'if job failed' do
2018-05-09 12:01:36 +05:30
let ( :job ) { create ( :ci_build , :failed , :trace_artifact , pipeline : pipeline ) }
2017-09-10 17:25:29 +05:30
before do
visit project_job_path ( project , job )
end
it 'shows New issue button' do
expect ( page ) . to have_link ( 'New issue' )
end
it 'links to issues/new with the title and description filled in' do
2018-03-17 18:26:18 +05:30
button_title = " Job Failed # #{ job . id } "
2018-11-08 19:23:39 +05:30
job_url = project_job_url ( project , job , host : page . server . host , port : page . server . port )
2018-03-17 18:26:18 +05:30
options = { issue : { title : button_title , description : " Job [ # #{ job . id } ]( #{ job_url } ) failed for #{ job . sha } : \n " } }
2017-09-10 17:25:29 +05:30
href = new_project_issue_path ( project , options )
2019-03-02 22:35:43 +05:30
page . within ( '.build-sidebar' ) do
2017-09-10 17:25:29 +05:30
expect ( find ( '.js-new-issue' ) [ 'href' ] ) . to include ( href )
end
end
end
end
2018-12-13 13:39:08 +05:30
context 'when job is running' , :js do
let ( :job ) { create ( :ci_build , :running , pipeline : pipeline ) }
let ( :job_url ) { project_job_path ( project , job ) }
before do
visit job_url
wait_for_requests
end
context 'job is cancelable' do
it 'shows cancel button' do
click_link 'Cancel'
expect ( page . current_path ) . to eq ( job_url )
end
end
end
2017-08-17 22:00:37 +05:30
context " Job from other project " do
2016-06-16 23:09:34 +05:30
before do
2017-09-10 17:25:29 +05:30
visit project_job_path ( project , job2 )
2016-06-16 23:09:34 +05:30
end
it { expect ( page . status_code ) . to eq ( 404 ) }
end
2015-11-26 14:37:03 +05:30
2018-12-05 23:21:45 +05:30
context " Download artifacts " , :js do
2015-11-26 14:37:03 +05:30
before do
2019-09-04 21:01:54 +05:30
create ( :ci_job_artifact , :archive , file : artifacts_file , job : job )
2017-09-10 17:25:29 +05:30
visit project_job_path ( project , job )
2015-11-26 14:37:03 +05:30
end
2016-01-19 16:12:03 +05:30
it 'has button to download artifacts' do
2016-06-16 23:09:34 +05:30
expect ( page ) . to have_content 'Download'
end
2018-12-05 23:21:45 +05:30
it 'downloads the zip file when user clicks the download button' do
2019-03-02 22:35:43 +05:30
requests = inspect_requests do
2018-12-05 23:21:45 +05:30
click_link 'Download'
end
artifact_request = requests . find { | req | req . url . match ( %r{ artifacts/download } ) }
2019-03-02 22:35:43 +05:30
expect ( artifact_request . response_headers [ " Content-Disposition " ] ) . to eq ( %Q{ attachment; filename*=UTF-8'' #{ job . artifacts_file . filename } ; filename=" #{ job . artifacts_file . filename } " } )
2018-12-05 23:21:45 +05:30
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
2016-06-16 23:09:34 +05:30
end
2018-12-05 23:21:45 +05:30
context 'Artifacts expire date' , :js do
2016-06-16 23:09:34 +05:30
before do
2019-09-04 21:01:54 +05:30
create ( :ci_job_artifact , :archive , file : artifacts_file , expire_at : expire_at , job : job )
job . update! ( artifacts_expire_at : expire_at )
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
visit project_job_path ( project , job )
2016-06-16 23:09:34 +05:30
end
context 'no expire date defined' do
let ( :expire_at ) { nil }
it 'does not have the Keep button' do
expect ( page ) . not_to have_content 'Keep'
end
end
context 'when expire date is defined' do
let ( :expire_at ) { Time . now + 7 . days }
2017-08-17 22:00:37 +05:30
context 'when user has ability to update job' do
it 'keeps artifacts when keep button is clicked' do
2018-12-05 23:21:45 +05:30
expect ( page ) . to have_content 'The artifacts will be removed in'
2016-06-16 23:09:34 +05:30
2017-08-17 22:00:37 +05:30
click_link 'Keep'
expect ( page ) . to have_no_link 'Keep'
2018-12-05 23:21:45 +05:30
expect ( page ) . to have_no_content 'The artifacts will be removed in'
2017-08-17 22:00:37 +05:30
end
end
context 'when user does not have ability to update job' do
let ( :user_access_level ) { :guest }
it 'does not have keep button' do
expect ( page ) . to have_no_link 'Keep'
end
2016-06-16 23:09:34 +05:30
end
end
context 'when artifacts expired' do
let ( :expire_at ) { Time . now - 7 . days }
it 'does not have the Keep button' do
expect ( page ) . to have_content 'The artifacts were removed'
expect ( page ) . not_to have_link 'Keep'
2016-01-19 16:12:03 +05:30
end
end
2015-11-26 14:37:03 +05:30
end
2016-06-02 11:05:42 +05:30
2017-09-10 17:25:29 +05:30
context " when visiting old URL " do
let ( :job_url ) do
project_job_path ( project , job )
end
before do
visit job_url . sub ( '/-/jobs' , '/builds' )
end
it " redirects to new URL " do
expect ( page . current_path ) . to eq ( job_url )
end
end
2018-12-13 13:39:08 +05:30
describe 'Raw trace' , :js do
2016-06-02 11:05:42 +05:30
before do
2017-09-10 17:25:29 +05:30
job . run!
visit project_job_path ( project , job )
2016-06-02 11:05:42 +05:30
end
it do
2018-12-13 13:39:08 +05:30
wait_for_all_requests
expect ( page ) . to have_css ( '.js-raw-link-controller' )
2016-06-02 11:05:42 +05:30
end
end
2016-09-29 09:46:39 +05:30
2018-11-08 19:23:39 +05:30
describe 'HTML trace' , :js do
2017-08-17 22:00:37 +05:30
before do
2017-09-10 17:25:29 +05:30
job . run!
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
visit project_job_path ( project , job )
2017-08-17 22:00:37 +05:30
end
context 'when job has an initial trace' do
it 'loads job trace' do
expect ( page ) . to have_content 'BUILD TRACE'
2018-10-15 14:42:47 +05:30
job . trace . write ( 'a+b' ) do | stream |
2017-08-17 22:00:37 +05:30
stream . append ( ' and more trace' , 11 )
end
expect ( page ) . to have_content 'BUILD TRACE and more trace'
end
end
end
2018-11-08 19:23:39 +05:30
describe 'Variables' do
2018-03-17 18:26:18 +05:30
let ( :trigger_request ) { create ( :ci_trigger_request ) }
2019-02-15 15:39:39 +05:30
let ( :job ) { create ( :ci_build , pipeline : pipeline , trigger_request : trigger_request ) }
2017-08-17 22:00:37 +05:30
2019-02-15 15:39:39 +05:30
context 'when user is a maintainer' do
shared_examples 'no reveal button variables behavior' do
it 'renders a hidden value with no reveal values button' , :js do
expect ( page ) . to have_content ( 'Trigger token' )
expect ( page ) . to have_content ( 'Trigger variables' )
expect ( page ) . not_to have_css ( '.js-reveal-variables' )
expect ( page ) . to have_selector ( '.js-build-variable' , text : 'TRIGGER_KEY_1' )
expect ( page ) . to have_selector ( '.js-build-value' , text : '••••••' )
end
end
context 'when variables are stored in trigger_request' do
before do
trigger_request . update_attribute ( :variables , { 'TRIGGER_KEY_1' = > 'TRIGGER_VALUE_1' } )
visit project_job_path ( project , job )
end
it_behaves_like 'no reveal button variables behavior'
end
2017-08-17 22:00:37 +05:30
2019-02-15 15:39:39 +05:30
context 'when variables are stored in pipeline_variables' do
before do
create ( :ci_pipeline_variable , pipeline : pipeline , key : 'TRIGGER_KEY_1' , value : 'TRIGGER_VALUE_1' )
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
visit project_job_path ( project , job )
end
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
it_behaves_like 'no reveal button variables behavior'
2018-03-17 18:26:18 +05:30
end
2016-09-29 09:46:39 +05:30
end
2019-02-15 15:39:39 +05:30
context 'when user is a maintainer' do
2018-03-17 18:26:18 +05:30
before do
2019-02-15 15:39:39 +05:30
project . add_maintainer ( user )
end
2018-12-23 12:14:25 +05:30
2019-02-15 15:39:39 +05:30
shared_examples 'reveal button variables behavior' do
it 'renders a hidden value with a reveal values button' , :js do
expect ( page ) . to have_content ( 'Trigger token' )
expect ( page ) . to have_content ( 'Trigger variables' )
expect ( page ) . to have_css ( '.js-reveal-variables' )
expect ( page ) . to have_selector ( '.js-build-variable' , text : 'TRIGGER_KEY_1' )
expect ( page ) . to have_selector ( '.js-build-value' , text : '••••••' )
end
it 'reveals values on button click' , :js do
click_button 'Reveal values'
expect ( page ) . to have_selector ( '.js-build-variable' , text : 'TRIGGER_KEY_1' )
expect ( page ) . to have_selector ( '.js-build-value' , text : 'TRIGGER_VALUE_1' )
end
2018-03-17 18:26:18 +05:30
end
2019-02-15 15:39:39 +05:30
context 'when variables are stored in trigger_request' do
before do
trigger_request . update_attribute ( :variables , { 'TRIGGER_KEY_1' = > 'TRIGGER_VALUE_1' } )
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
visit project_job_path ( project , job )
end
2018-03-17 18:26:18 +05:30
2019-02-15 15:39:39 +05:30
it_behaves_like 'reveal button variables behavior'
2018-03-17 18:26:18 +05:30
end
2016-09-29 09:46:39 +05:30
2019-02-15 15:39:39 +05:30
context 'when variables are stored in pipeline_variables' do
before do
create ( :ci_pipeline_variable , pipeline : pipeline , key : 'TRIGGER_KEY_1' , value : 'TRIGGER_VALUE_1' )
visit project_job_path ( project , job )
end
it_behaves_like 'reveal button variables behavior'
end
2016-09-29 09:46:39 +05:30
end
2017-08-17 22:00:37 +05:30
end
2018-12-05 23:21:45 +05:30
context 'when job starts environment' , :js do
let ( :environment ) { create ( :environment , name : 'production' , project : project ) }
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
before do
visit project_job_path ( project , build )
wait_for_requests
end
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
context 'job is successful and has deployment' do
let ( :build ) { create ( :ci_build , :success , :trace_live , environment : environment . name , pipeline : pipeline , deployment : deployment ) }
let ( :deployment ) { create ( :deployment , :success , environment : environment , project : environment . project ) }
2017-08-17 22:00:37 +05:30
2018-12-05 23:21:45 +05:30
it 'shows a link for the job' do
2017-08-17 22:00:37 +05:30
expect ( page ) . to have_link environment . name
end
2018-12-05 23:21:45 +05:30
it 'shows deployment message' do
2019-12-04 20:38:33 +05:30
expect ( page ) . to have_content 'This job is the most recent deployment to production'
2018-12-05 23:21:45 +05:30
expect ( find ( '.js-environment-link' ) [ 'href' ] ) . to match ( " environments/ #{ environment . id } " )
end
2019-12-04 20:38:33 +05:30
context 'when there is a cluster used for the deployment' do
let ( :cluster ) { create ( :cluster , name : 'the-cluster' ) }
let ( :deployment ) { create ( :deployment , :success , cluster : cluster , environment : environment , project : environment . project ) }
let ( :user_access_level ) { :maintainer }
it 'shows a link to the cluster' do
expect ( page ) . to have_link 'the-cluster'
end
it 'shows the name of the cluster' do
expect ( page ) . to have_content 'Cluster the-cluster was used'
end
context 'when the user is not able to view the cluster' do
let ( :user_access_level ) { :developer }
it 'includes only the name of the cluster without a link' do
expect ( page ) . to have_content 'Cluster the-cluster was used'
expect ( page ) . not_to have_link 'the-cluster'
end
end
end
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'job is complete and not successful' do
2018-12-05 23:21:45 +05:30
let ( :build ) { create ( :ci_build , :failed , :trace_artifact , environment : environment . name , pipeline : pipeline ) }
2017-08-17 22:00:37 +05:30
it 'shows a link for the job' do
expect ( page ) . to have_link environment . name
2018-12-05 23:21:45 +05:30
expect ( find ( '.js-environment-link' ) [ 'href' ] ) . to match ( " environments/ #{ environment . id } " )
2017-08-17 22:00:37 +05:30
end
end
2018-12-05 23:21:45 +05:30
context 'deployment still not finished' do
2018-12-13 13:39:08 +05:30
let ( :build ) { create ( :ci_build , :running , environment : environment . name , pipeline : pipeline ) }
2017-08-17 22:00:37 +05:30
it 'shows a link to latest deployment' do
2018-12-05 23:21:45 +05:30
expect ( page ) . to have_link environment . name
expect ( page ) . to have_content 'This job is creating a deployment'
expect ( find ( '.js-environment-link' ) [ 'href' ] ) . to match ( " environments/ #{ environment . id } " )
end
end
end
context 'when job stops environment' , :js do
let ( :environment ) { create ( :environment , name : 'production' , project : project ) }
let ( :build ) do
create (
:ci_build ,
:success ,
:trace_live ,
environment : environment . name ,
pipeline : pipeline ,
options : { environment : { action : 'stop' } }
)
end
before do
visit project_job_path ( project , build )
wait_for_requests
end
it 'does not show environment information banner' do
expect ( page ) . not_to have_selector ( '.js-environment-container' )
expect ( page ) . not_to have_selector ( '.environment-information' )
expect ( page ) . not_to have_text ( environment . name )
end
end
describe 'environment info in job view' , :js do
before do
2018-12-13 13:39:08 +05:30
allow_any_instance_of ( Ci :: Build ) . to receive ( :create_deployment )
2018-12-05 23:21:45 +05:30
visit project_job_path ( project , job )
wait_for_requests
end
context 'job with outdated deployment' do
let ( :job ) { create ( :ci_build , :success , :trace_artifact , environment : 'staging' , pipeline : pipeline ) }
let ( :second_build ) { create ( :ci_build , :success , :trace_artifact , environment : 'staging' , pipeline : pipeline ) }
let ( :environment ) { create ( :environment , name : 'staging' , project : project ) }
2018-12-13 13:39:08 +05:30
let! ( :first_deployment ) { create ( :deployment , :success , environment : environment , deployable : job ) }
let! ( :second_deployment ) { create ( :deployment , :success , environment : environment , deployable : second_build ) }
2018-12-05 23:21:45 +05:30
it 'shows deployment message' do
expected_text = 'This job is an out-of-date deployment ' \
" to staging. View the most recent deployment # #{ second_deployment . iid } . "
expect ( page ) . to have_css ( '.environment-information' , text : expected_text )
end
it 'renders a link to the most recent deployment' do
expect ( find ( '.js-environment-link' ) [ 'href' ] ) . to match ( " environments/ #{ environment . id } " )
expect ( find ( '.js-job-deployment-link' ) [ 'href' ] ) . to include ( second_deployment . deployable . project . path , second_deployment . deployable_id . to_s )
end
2019-12-04 20:38:33 +05:30
context 'when deployment does not have a deployable' do
let! ( :second_deployment ) { create ( :deployment , :success , environment : environment , deployable : nil ) }
it 'has an empty href' do
expect ( find ( '.js-job-deployment-link' ) [ 'href' ] ) . to be_empty
end
end
2018-12-05 23:21:45 +05:30
end
context 'job failed to deploy' do
let ( :job ) { create ( :ci_build , :failed , :trace_artifact , environment : 'staging' , pipeline : pipeline ) }
let! ( :environment ) { create ( :environment , name : 'staging' , project : project ) }
it 'shows deployment message' do
expected_text = 'The deployment of this job to staging did not succeed.'
2018-12-13 13:39:08 +05:30
expect ( page ) . to have_css ( '.environment-information' , text : expected_text )
2018-12-05 23:21:45 +05:30
end
end
context 'job will deploy' do
let ( :job ) { create ( :ci_build , :running , :trace_live , environment : 'staging' , pipeline : pipeline ) }
context 'when environment exists' do
let! ( :environment ) { create ( :environment , name : 'staging' , project : project ) }
it 'shows deployment message' do
expected_text = 'This job is creating a deployment to staging'
2018-12-13 13:39:08 +05:30
expect ( page ) . to have_css ( '.environment-information' , text : expected_text )
2018-12-05 23:21:45 +05:30
expect ( find ( '.js-environment-link' ) [ 'href' ] ) . to match ( " environments/ #{ environment . id } " )
end
context 'when it has deployment' do
2018-12-13 13:39:08 +05:30
let! ( :deployment ) { create ( :deployment , :success , environment : environment ) }
2018-12-05 23:21:45 +05:30
it 'shows that deployment will be overwritten' do
expected_text = 'This job is creating a deployment to staging'
2018-12-13 13:39:08 +05:30
expect ( page ) . to have_css ( '.environment-information' , text : expected_text )
expect ( page ) . to have_css ( '.environment-information' , text : 'latest deployment' )
2018-12-05 23:21:45 +05:30
expect ( find ( '.js-environment-link' ) [ 'href' ] ) . to match ( " environments/ #{ environment . id } " )
end
end
end
context 'when environment does not exist' do
let! ( :environment ) { create ( :environment , name : 'staging' , project : project ) }
it 'shows deployment message' do
expected_text = 'This job is creating a deployment to staging'
expect ( page ) . to have_css (
'.environment-information' , text : expected_text )
expect ( page ) . not_to have_css (
'.environment-information' , text : 'latest deployment' )
expect ( find ( '.js-environment-link' ) [ 'href' ] ) . to match ( " environments/ #{ environment . id } " )
end
end
end
context 'job that failed to deploy and environment has not been created' do
let ( :job ) { create ( :ci_build , :failed , :trace_artifact , environment : 'staging' , pipeline : pipeline ) }
let! ( :environment ) { create ( :environment , name : 'staging' , project : project ) }
it 'shows deployment message' do
expected_text = 'The deployment of this job to staging did not succeed'
expect ( page ) . to have_css (
'.environment-information' , text : expected_text )
end
end
context 'job that will deploy and environment has not been created' do
let ( :job ) { create ( :ci_build , :running , :trace_live , environment : 'staging' , pipeline : pipeline ) }
let! ( :environment ) { create ( :environment , name : 'staging' , project : project ) }
it 'shows deployment message' do
expected_text = 'This job is creating a deployment to staging'
expect ( page ) . to have_css (
'.environment-information' , text : expected_text )
expect ( page ) . not_to have_css (
'.environment-information' , text : 'latest deployment' )
2017-08-17 22:00:37 +05:30
end
end
end
2018-03-17 18:26:18 +05:30
context 'Playable manual action' do
let ( :job ) { create ( :ci_build , :playable , pipeline : pipeline ) }
before do
project . add_developer ( user )
visit project_job_path ( project , job )
end
2018-12-05 23:21:45 +05:30
it 'shows manual action empty state' , :js do
2018-05-09 12:01:36 +05:30
expect ( page ) . to have_content ( job . detailed_status ( user ) . illustration [ :title ] )
2018-03-17 18:26:18 +05:30
expect ( page ) . to have_content ( 'This job requires a manual action' )
2019-10-12 21:52:04 +05:30
expect ( page ) . to have_content ( 'This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes.' )
expect ( page ) . to have_button ( 'Trigger this manual action' )
2018-03-17 18:26:18 +05:30
end
it 'plays manual action and shows pending status' , :js do
2019-10-12 21:52:04 +05:30
click_button 'Trigger this manual action'
2018-03-17 18:26:18 +05:30
wait_for_requests
expect ( page ) . to have_content ( 'This job has not started yet' )
expect ( page ) . to have_content ( 'This job is in pending state and is waiting to be picked by a runner' )
expect ( page ) . to have_content ( 'pending' )
end
end
2018-12-05 23:21:45 +05:30
context 'Delayed job' do
let ( :job ) { create ( :ci_build , :scheduled , pipeline : pipeline ) }
before do
project . add_developer ( user )
visit project_job_path ( project , job )
end
it 'shows delayed job' , :js do
2018-12-13 13:39:08 +05:30
expect ( page ) . to have_content ( 'This is a delayed job to run in' )
2019-02-15 15:39:39 +05:30
expect ( page ) . to have_content ( " This job will automatically run after its timer finishes. " )
2018-12-05 23:21:45 +05:30
expect ( page ) . to have_link ( 'Unschedule job' )
end
it 'unschedules delayed job and shows manual action' , :js do
click_link 'Unschedule job'
wait_for_requests
expect ( page ) . to have_content ( 'This job requires a manual action' )
2019-10-12 21:52:04 +05:30
expect ( page ) . to have_content ( 'This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes.' )
expect ( page ) . to have_button ( 'Trigger this manual action' )
2018-12-05 23:21:45 +05:30
end
end
2018-03-17 18:26:18 +05:30
context 'Non triggered job' do
let ( :job ) { create ( :ci_build , :created , pipeline : pipeline ) }
before do
visit project_job_path ( project , job )
end
2018-12-05 23:21:45 +05:30
it 'shows empty state' , :js do
2018-05-09 12:01:36 +05:30
expect ( page ) . to have_content ( job . detailed_status ( user ) . illustration [ :title ] )
2018-03-17 18:26:18 +05:30
expect ( page ) . to have_content ( 'This job has not been triggered yet' )
expect ( page ) . to have_content ( 'This job depends on upstream jobs that need to succeed in order for this job to be triggered' )
end
end
2018-12-05 23:21:45 +05:30
context 'Pending job' , :js do
2018-03-17 18:26:18 +05:30
let ( :job ) { create ( :ci_build , :pending , pipeline : pipeline ) }
before do
visit project_job_path ( project , job )
end
it 'shows pending empty state' do
2018-05-09 12:01:36 +05:30
expect ( page ) . to have_content ( job . detailed_status ( user ) . illustration [ :title ] )
2018-03-17 18:26:18 +05:30
expect ( page ) . to have_content ( 'This job has not started yet' )
expect ( page ) . to have_content ( 'This job is in pending state and is waiting to be picked by a runner' )
end
end
2018-05-09 12:01:36 +05:30
2018-12-13 13:39:08 +05:30
context 'Canceled job' , :js do
2018-05-09 12:01:36 +05:30
context 'with log' do
let ( :job ) { create ( :ci_build , :canceled , :trace_artifact , pipeline : pipeline ) }
before do
visit project_job_path ( project , job )
end
it 'renders job log' do
2018-12-13 13:39:08 +05:30
wait_for_all_requests
expect ( page ) . to have_selector ( '.js-build-trace' )
2018-05-09 12:01:36 +05:30
end
end
2018-12-05 23:21:45 +05:30
context 'without log' , :js do
2018-05-09 12:01:36 +05:30
let ( :job ) { create ( :ci_build , :canceled , pipeline : pipeline ) }
before do
visit project_job_path ( project , job )
end
it 'renders empty state' do
expect ( page ) . to have_content ( job . detailed_status ( user ) . illustration [ :title ] )
2018-12-13 13:39:08 +05:30
expect ( page ) . not_to have_selector ( '.js-build-trace' )
2018-05-09 12:01:36 +05:30
expect ( page ) . to have_content ( 'This job has been canceled' )
end
end
end
2018-12-05 23:21:45 +05:30
context 'Skipped job' , :js do
2018-05-09 12:01:36 +05:30
let ( :job ) { create ( :ci_build , :skipped , pipeline : pipeline ) }
before do
visit project_job_path ( project , job )
end
it 'renders empty state' do
expect ( page ) . to have_content ( job . detailed_status ( user ) . illustration [ :title ] )
2018-12-13 13:39:08 +05:30
expect ( page ) . not_to have_selector ( '.js-build-trace' )
2018-05-09 12:01:36 +05:30
expect ( page ) . to have_content ( 'This job has been skipped' )
end
end
2018-12-05 23:21:45 +05:30
context 'when job is failed but has no trace' , :js do
2018-05-09 12:01:36 +05:30
let ( :job ) { create ( :ci_build , :failed , pipeline : pipeline ) }
it 'renders empty state' do
visit project_job_path ( project , job )
expect ( job ) . not_to have_trace
expect ( page ) . to have_content ( 'This job does not have a trace.' )
end
end
2018-12-05 23:21:45 +05:30
context 'with erased job' , :js do
let ( :job ) { create ( :ci_build , :erased , pipeline : pipeline ) }
it 'renders erased job warning' do
visit project_job_path ( project , job )
wait_for_requests
page . within ( '.js-job-erased-block' ) do
expect ( page ) . to have_content ( 'Job has been erased' )
end
end
end
context 'without erased job' , :js do
let ( :job ) { create ( :ci_build , pipeline : pipeline ) }
it 'does not render erased job warning' do
visit project_job_path ( project , job )
wait_for_requests
expect ( page ) . not_to have_css ( '.js-job-erased-block' )
end
end
context 'on mobile' , :js do
let ( :job ) { create ( :ci_build , pipeline : pipeline ) }
2019-02-15 15:39:39 +05:30
it 'renders collapsed sidebar' do
2018-12-05 23:21:45 +05:30
page . current_window . resize_to ( 600 , 800 )
visit project_job_path ( project , job )
wait_for_requests
2018-12-13 13:39:08 +05:30
expect ( page ) . to have_css ( '.js-job-sidebar.right-sidebar-collapsed' , visible : false )
expect ( page ) . not_to have_css ( '.js-job-sidebar.right-sidebar-expanded' , visible : false )
2018-12-05 23:21:45 +05:30
end
end
context 'on desktop' , :js do
let ( :job ) { create ( :ci_build , pipeline : pipeline ) }
it 'renders expanded sidebar' do
visit project_job_path ( project , job )
wait_for_requests
2018-12-13 13:39:08 +05:30
expect ( page ) . to have_css ( '.js-job-sidebar.right-sidebar-expanded' )
2019-02-15 15:39:39 +05:30
expect ( page ) . not_to have_css ( '.js-job-sidebar.right-sidebar-collapsed' )
2018-12-13 13:39:08 +05:30
end
end
context 'stuck' , :js do
before do
visit project_job_path ( project , job )
wait_for_requests
end
context 'without active runners available' do
let ( :runner ) { create ( :ci_runner , :instance , active : false ) }
let ( :job ) { create ( :ci_build , :pending , pipeline : pipeline , runner : runner ) }
it 'renders message about job being stuck because no runners are active' do
expect ( page ) . to have_css ( '.js-stuck-no-active-runner' )
2019-02-15 15:39:39 +05:30
expect ( page ) . to have_content ( " This job is stuck because you don't have any active runners that can run this job. " )
2018-12-13 13:39:08 +05:30
end
end
context 'when available runners can not run specified tag' do
let ( :runner ) { create ( :ci_runner , :instance , active : false ) }
let ( :job ) { create ( :ci_build , :pending , pipeline : pipeline , runner : runner , tag_list : %w( docker linux ) ) }
it 'renders message about job being stuck because of no runners with the specified tags' do
expect ( page ) . to have_css ( '.js-stuck-with-tags' )
2019-02-15 15:39:39 +05:30
expect ( page ) . to have_content ( " This job is stuck because you don't have any active runners online with any of these tags assigned to them: " )
2018-12-13 13:39:08 +05:30
end
end
context 'when runners are offline and build has tags' do
let ( :runner ) { create ( :ci_runner , :instance , active : true ) }
let ( :job ) { create ( :ci_build , :pending , pipeline : pipeline , runner : runner , tag_list : %w( docker linux ) ) }
it 'renders message about job being stuck because of no runners with the specified tags' do
expect ( page ) . to have_css ( '.js-stuck-with-tags' )
2019-02-15 15:39:39 +05:30
expect ( page ) . to have_content ( " This job is stuck because you don't have any active runners online with any of these tags assigned to them: " )
2018-12-13 13:39:08 +05:30
end
end
context 'without any runners available' do
let ( :job ) { create ( :ci_build , :pending , pipeline : pipeline ) }
it 'renders message about job being stuck because not runners are available' do
expect ( page ) . to have_css ( '.js-stuck-no-active-runner' )
2019-02-15 15:39:39 +05:30
expect ( page ) . to have_content ( " This job is stuck because you don't have any active runners that can run this job. " )
2018-12-13 13:39:08 +05:30
end
end
context 'without available runners online' do
let ( :runner ) { create ( :ci_runner , :instance , active : true ) }
let ( :job ) { create ( :ci_build , :pending , pipeline : pipeline , runner : runner ) }
it 'renders message about job being stuck because runners are offline' do
expect ( page ) . to have_css ( '.js-stuck-no-runners' )
2019-02-15 15:39:39 +05:30
expect ( page ) . to have_content ( " This job is stuck because the project doesn't have any runners online assigned to it. " )
2018-12-13 13:39:08 +05:30
end
2018-12-05 23:21:45 +05:30
end
end
2015-10-24 18:46:33 +05:30
end
2017-09-10 17:25:29 +05:30
describe " POST /:project/jobs/:id/cancel " , :js do
2017-08-17 22:00:37 +05:30
context " Job from project " do
2016-06-16 23:09:34 +05:30
before do
2017-09-10 17:25:29 +05:30
job . run!
visit project_job_path ( project , job )
2019-03-02 22:35:43 +05:30
find ( '.js-cancel-job' ) . click
2016-06-16 23:09:34 +05:30
end
2017-08-17 22:00:37 +05:30
it 'loads the page and shows all needed controls' do
expect ( page ) . to have_content 'Retry'
end
2015-10-24 18:46:33 +05:30
end
end
2018-10-15 14:42:47 +05:30
describe " POST /:project/jobs/:id/retry " , :js do
2017-09-10 17:25:29 +05:30
context " Job from project " , :js do
2016-06-16 23:09:34 +05:30
before do
2017-09-10 17:25:29 +05:30
job . run!
2018-10-15 14:42:47 +05:30
job . cancel!
2017-09-10 17:25:29 +05:30
visit project_job_path ( project , job )
2018-10-15 14:42:47 +05:30
wait_for_requests
2018-03-17 18:26:18 +05:30
find ( '.js-retry-button' ) . click
2016-06-16 23:09:34 +05:30
end
2018-10-15 14:42:47 +05:30
it 'shows the right status and buttons' do
2016-08-24 12:49:21 +05:30
page . within ( 'aside.right-sidebar' ) do
expect ( page ) . to have_content 'Cancel'
end
end
2015-10-24 18:46:33 +05:30
end
2017-09-10 17:25:29 +05:30
context " Job that current user is not allowed to retry " do
2016-08-24 12:49:21 +05:30
before do
2017-09-10 17:25:29 +05:30
job . run!
job . cancel!
2017-08-17 22:00:37 +05:30
project . update ( visibility_level : Gitlab :: VisibilityLevel :: PUBLIC )
2016-08-24 12:49:21 +05:30
2017-09-10 17:25:29 +05:30
sign_out ( :user )
sign_in ( create ( :user ) )
visit project_job_path ( project , job )
2016-08-24 12:49:21 +05:30
end
it 'does not show the Retry button' do
page . within ( 'aside.right-sidebar' ) do
expect ( page ) . not_to have_content 'Retry'
end
end
2016-06-16 23:09:34 +05:30
end
2015-10-24 18:46:33 +05:30
end
2015-11-26 14:37:03 +05:30
2018-12-05 23:21:45 +05:30
describe " GET /:project/jobs/:id/download " , :js do
2015-11-26 14:37:03 +05:30
before do
2019-09-04 21:01:54 +05:30
create ( :ci_job_artifact , :archive , file : artifacts_file , job : job )
2017-09-10 17:25:29 +05:30
visit project_job_path ( project , job )
2018-12-05 23:21:45 +05:30
2016-06-16 23:09:34 +05:30
click_link 'Download'
2015-11-26 14:37:03 +05:30
end
2016-06-16 23:09:34 +05:30
context " Build from other project " do
before do
2019-09-04 21:01:54 +05:30
create ( :ci_job_artifact , :archive , file : artifacts_file , job : job2 )
2016-06-16 23:09:34 +05:30
end
2018-12-05 23:21:45 +05:30
it do
2019-03-02 22:35:43 +05:30
requests = inspect_requests do
2018-12-05 23:21:45 +05:30
visit download_project_job_artifacts_path ( project , job2 )
end
expect ( requests . first . status_code ) . to eq ( 404 )
end
2016-06-16 23:09:34 +05:30
end
2015-11-26 14:37:03 +05:30
end
2016-06-02 11:05:42 +05:30
2017-09-10 17:25:29 +05:30
describe 'GET /:project/jobs/:id/raw' , :js do
2016-09-29 09:46:39 +05:30
context 'access source' do
2017-09-10 17:25:29 +05:30
context 'job from project' do
2018-03-17 18:26:18 +05:30
context 'when job is running' do
before do
job . run!
end
it 'sends the right headers' do
requests = inspect_requests ( inject_headers : { 'X-Sendfile-Type' = > 'X-Sendfile' } ) do
visit raw_project_job_path ( project , job )
end
expect ( requests . first . status_code ) . to eq ( 200 )
expect ( requests . first . response_headers [ 'Content-Type' ] ) . to eq ( 'text/plain; charset=utf-8' )
expect ( requests . first . response_headers [ 'X-Sendfile' ] ) . to eq ( job . trace . send ( :current_path ) )
end
2016-09-29 09:46:39 +05:30
end
2018-03-17 18:26:18 +05:30
context 'when job is complete' do
let ( :job ) { create ( :ci_build , :success , :trace_artifact , pipeline : pipeline ) }
it 'sends the right headers' do
requests = inspect_requests ( inject_headers : { 'X-Sendfile-Type' = > 'X-Sendfile' } ) do
visit raw_project_job_path ( project , job )
end
expect ( requests . first . status_code ) . to eq ( 200 )
expect ( requests . first . response_headers [ 'Content-Type' ] ) . to eq ( 'text/plain; charset=utf-8' )
expect ( requests . first . response_headers [ 'X-Sendfile' ] ) . to eq ( job . job_artifacts_trace . file . path )
end
2016-09-29 09:46:39 +05:30
end
2016-06-16 23:09:34 +05:30
end
2017-09-10 17:25:29 +05:30
context 'job from other project' do
2016-09-29 09:46:39 +05:30
before do
2017-09-10 17:25:29 +05:30
job2 . run!
2016-09-29 09:46:39 +05:30
end
it 'sends the right headers' do
2018-03-17 18:26:18 +05:30
requests = inspect_requests ( inject_headers : { 'X-Sendfile-Type' = > 'X-Sendfile' } ) do
visit raw_project_job_path ( project , job2 )
end
expect ( requests . first . status_code ) . to eq ( 404 )
2016-09-29 09:46:39 +05:30
end
2016-06-16 23:09:34 +05:30
end
end
2017-09-10 17:25:29 +05:30
context " when visiting old URL " do
let ( :raw_job_url ) do
raw_project_job_path ( project , job )
end
before do
visit raw_job_url . sub ( '/-/jobs' , '/builds' )
end
it " redirects to new URL " do
expect ( page . current_path ) . to eq ( raw_job_url )
end
end
2016-06-16 23:09:34 +05:30
end
2017-09-10 17:25:29 +05:30
describe " GET /:project/jobs/:id/trace.json " do
context " Job from project " do
2016-06-16 23:09:34 +05:30
before do
2017-09-10 17:25:29 +05:30
visit trace_project_job_path ( project , job , format : :json )
2016-06-16 23:09:34 +05:30
end
it { expect ( page . status_code ) . to eq ( 200 ) }
end
2017-09-10 17:25:29 +05:30
context " Job from other project " do
2016-06-16 23:09:34 +05:30
before do
2017-09-10 17:25:29 +05:30
visit trace_project_job_path ( project , job2 , format : :json )
2016-06-16 23:09:34 +05:30
end
it { expect ( page . status_code ) . to eq ( 404 ) }
end
end
2017-09-10 17:25:29 +05:30
describe " GET /:project/jobs/:id/status " do
context " Job from project " do
2016-06-16 23:09:34 +05:30
before do
2017-09-10 17:25:29 +05:30
visit status_project_job_path ( project , job )
2016-06-16 23:09:34 +05:30
end
it { expect ( page . status_code ) . to eq ( 200 ) }
2016-06-02 11:05:42 +05:30
end
2017-09-10 17:25:29 +05:30
context " Job from other project " do
2016-06-16 23:09:34 +05:30
before do
2017-09-10 17:25:29 +05:30
visit status_project_job_path ( project , job2 )
2016-06-16 23:09:34 +05:30
end
2016-06-02 11:05:42 +05:30
2016-06-16 23:09:34 +05:30
it { expect ( page . status_code ) . to eq ( 404 ) }
2016-06-02 11:05:42 +05:30
end
end
2015-10-24 18:46:33 +05:30
end