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
21f86195
Commit
21f86195
authored
May 11, 2018
by
Phil Hughes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Show CI jobs in web IDE
Closes #44604
parent
4d674bd3
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
484 additions
and
2 deletions
+484
-2
app/assets/javascripts/api.js
app/assets/javascripts/api.js
+16
-0
app/assets/javascripts/ide/stores/index.js
app/assets/javascripts/ide/stores/index.js
+2
-0
app/assets/javascripts/ide/stores/modules/pipelines/actions.js
...ssets/javascripts/ide/stores/modules/pipelines/actions.js
+43
-0
app/assets/javascripts/ide/stores/modules/pipelines/index.js
app/assets/javascripts/ide/stores/modules/pipelines/index.js
+10
-0
app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
...avascripts/ide/stores/modules/pipelines/mutation_types.js
+7
-0
app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
...ets/javascripts/ide/stores/modules/pipelines/mutations.js
+34
-0
app/assets/javascripts/ide/stores/modules/pipelines/state.js
app/assets/javascripts/ide/stores/modules/pipelines/state.js
+6
-0
spec/javascripts/helpers/vuex_action_helper.js
spec/javascripts/helpers/vuex_action_helper.js
+1
-1
spec/javascripts/ide/mock_data.js
spec/javascripts/ide/mock_data.js
+39
-1
spec/javascripts/ide/stores/modules/pipelines/actions_spec.js
.../javascripts/ide/stores/modules/pipelines/actions_spec.js
+242
-0
spec/javascripts/ide/stores/modules/pipelines/mutations_spec.js
...avascripts/ide/stores/modules/pipelines/mutations_spec.js
+84
-0
No files found.
app/assets/javascripts/api.js
View file @
21f86195
...
@@ -23,6 +23,8 @@ const Api = {
...
@@ -23,6 +23,8 @@ const Api = {
commitPath
:
'
/api/:version/projects/:id/repository/commits
'
,
commitPath
:
'
/api/:version/projects/:id/repository/commits
'
,
branchSinglePath
:
'
/api/:version/projects/:id/repository/branches/:branch
'
,
branchSinglePath
:
'
/api/:version/projects/:id/repository/branches/:branch
'
,
createBranchPath
:
'
/api/:version/projects/:id/repository/branches
'
,
createBranchPath
:
'
/api/:version/projects/:id/repository/branches
'
,
pipelinesPath
:
'
/api/:version/projects/:id/pipelines
'
,
pipelineJobsPath
:
'
/api/:version/projects/:id/pipelines/:pipeline_id/jobs
'
,
group
(
groupId
,
callback
)
{
group
(
groupId
,
callback
)
{
const
url
=
Api
.
buildUrl
(
Api
.
groupPath
).
replace
(
'
:id
'
,
groupId
);
const
url
=
Api
.
buildUrl
(
Api
.
groupPath
).
replace
(
'
:id
'
,
groupId
);
...
@@ -222,6 +224,20 @@ const Api = {
...
@@ -222,6 +224,20 @@ const Api = {
});
});
},
},
pipelines
(
projectPath
,
params
=
{})
{
const
url
=
Api
.
buildUrl
(
this
.
pipelinesPath
).
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
));
return
axios
.
get
(
url
,
{
params
});
},
pipelineJobs
(
projectPath
,
pipelineId
)
{
const
url
=
Api
.
buildUrl
(
this
.
pipelineJobsPath
)
.
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
))
.
replace
(
'
:pipeline_id
'
,
pipelineId
);
return
axios
.
get
(
url
);
},
buildUrl
(
url
)
{
buildUrl
(
url
)
{
let
urlRoot
=
''
;
let
urlRoot
=
''
;
if
(
gon
.
relative_url_root
!=
null
)
{
if
(
gon
.
relative_url_root
!=
null
)
{
...
...
app/assets/javascripts/ide/stores/index.js
View file @
21f86195
...
@@ -5,6 +5,7 @@ import * as actions from './actions';
...
@@ -5,6 +5,7 @@ import * as actions from './actions';
import
*
as
getters
from
'
./getters
'
;
import
*
as
getters
from
'
./getters
'
;
import
mutations
from
'
./mutations
'
;
import
mutations
from
'
./mutations
'
;
import
commitModule
from
'
./modules/commit
'
;
import
commitModule
from
'
./modules/commit
'
;
import
pipelines
from
'
./modules/pipelines
'
;
Vue
.
use
(
Vuex
);
Vue
.
use
(
Vuex
);
...
@@ -15,5 +16,6 @@ export default new Vuex.Store({
...
@@ -15,5 +16,6 @@ export default new Vuex.Store({
getters
,
getters
,
modules
:
{
modules
:
{
commit
:
commitModule
,
commit
:
commitModule
,
pipelines
,
},
},
});
});
app/assets/javascripts/ide/stores/modules/pipelines/actions.js
0 → 100644
View file @
21f86195
import
{
__
}
from
'
../../../../locale
'
;
import
Api
from
'
../../../../api
'
;
import
flash
from
'
../../../../flash
'
;
import
*
as
types
from
'
./mutation_types
'
;
export
const
requestLatestPipeline
=
({
commit
})
=>
commit
(
types
.
REQUEST_LATEST_PIPELINE
);
export
const
receiveLatestPipelineError
=
({
commit
})
=>
{
flash
(
__
(
'
There was an error loading latest pipeline
'
));
commit
(
types
.
RECEIVE_LASTEST_PIPELINE_ERROR
);
};
export
const
receiveLatestPipelineSuccess
=
({
commit
},
pipeline
)
=>
commit
(
types
.
RECEIVE_LASTEST_PIPELINE_SUCCESS
,
pipeline
);
export
const
fetchLatestPipeline
=
({
dispatch
,
rootState
},
sha
)
=>
{
dispatch
(
'
requestLatestPipeline
'
);
return
Api
.
pipelines
(
rootState
.
currentProjectId
,
{
sha
,
per_page
:
'
1
'
})
.
then
(({
data
})
=>
{
if
(
data
.
length
)
{
dispatch
(
'
receiveLatestPipelineSuccess
'
,
data
.
pop
());
}
})
.
catch
(()
=>
dispatch
(
'
receiveLatestPipelineError
'
));
};
export
const
requestJobs
=
({
commit
})
=>
commit
(
types
.
REQUEST_JOBS
);
export
const
receiveJobsError
=
({
commit
})
=>
{
flash
(
__
(
'
There was an error loading jobs
'
));
commit
(
types
.
RECEIVE_JOBS_ERROR
);
};
export
const
receiveJobsSuccess
=
({
commit
},
data
)
=>
commit
(
types
.
RECEIVE_JOBS_SUCCESS
,
data
);
export
const
fetchJobs
=
({
dispatch
,
state
,
rootState
})
=>
{
dispatch
(
'
requestJobs
'
);
Api
.
pipelineJobs
(
rootState
.
currentProjectId
,
state
.
latestPipeline
.
id
)
.
then
(({
data
})
=>
{
dispatch
(
'
receiveJobsSuccess
'
,
data
);
})
.
catch
(()
=>
dispatch
(
'
receiveJobsError
'
));
};
export
default
()
=>
{};
app/assets/javascripts/ide/stores/modules/pipelines/index.js
0 → 100644
View file @
21f86195
import
state
from
'
./state
'
;
import
*
as
actions
from
'
./actions
'
;
import
mutations
from
'
./mutations
'
;
export
default
{
namespaced
:
true
,
state
:
state
(),
actions
,
mutations
,
};
app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
0 → 100644
View file @
21f86195
export
const
REQUEST_LATEST_PIPELINE
=
'
REQUEST_LATEST_PIPELINE
'
;
export
const
RECEIVE_LASTEST_PIPELINE_ERROR
=
'
RECEIVE_LASTEST_PIPELINE_ERROR
'
;
export
const
RECEIVE_LASTEST_PIPELINE_SUCCESS
=
'
RECEIVE_LASTEST_PIPELINE_SUCCESS
'
;
export
const
REQUEST_JOBS
=
'
REQUEST_JOBS
'
;
export
const
RECEIVE_JOBS_ERROR
=
'
RECEIVE_JOBS_ERROR
'
;
export
const
RECEIVE_JOBS_SUCCESS
=
'
RECEIVE_JOBS_SUCCESS
'
;
app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
0 → 100644
View file @
21f86195
/* eslint-disable no-param-reassign */
import
*
as
types
from
'
./mutation_types
'
;
export
default
{
[
types
.
REQUEST_LATEST_PIPELINE
](
state
)
{
state
.
isLoadingPipeline
=
true
;
},
[
types
.
RECEIVE_LASTEST_PIPELINE_ERROR
](
state
)
{
state
.
isLoadingPipeline
=
false
;
},
[
types
.
RECEIVE_LASTEST_PIPELINE_SUCCESS
](
state
,
pipeline
)
{
state
.
isLoadingPipeline
=
false
;
state
.
latestPipeline
=
{
id
:
pipeline
.
id
,
status
:
pipeline
.
status
,
};
},
[
types
.
REQUEST_JOBS
](
state
)
{
state
.
isLoadingJobs
=
true
;
},
[
types
.
RECEIVE_JOBS_ERROR
](
state
)
{
state
.
isLoadingJobs
=
false
;
},
[
types
.
RECEIVE_JOBS_SUCCESS
](
state
,
jobs
)
{
state
.
isLoadingJobs
=
false
;
state
.
jobs
=
jobs
.
map
(
job
=>
({
id
:
job
.
id
,
name
:
job
.
name
,
status
:
job
.
status
,
stage
:
job
.
stage
,
duration
:
job
.
duration
,
}));
},
};
app/assets/javascripts/ide/stores/modules/pipelines/state.js
0 → 100644
View file @
21f86195
export
default
()
=>
({
isLoadingPipeline
:
false
,
isLoadingJobs
:
false
,
latestPipeline
:
null
,
jobs
:
[],
});
spec/javascripts/helpers/vuex_action_helper.js
View file @
21f86195
...
@@ -55,7 +55,7 @@ export default (action, payload, state, expectedMutations, expectedActions, done
...
@@ -55,7 +55,7 @@ export default (action, payload, state, expectedMutations, expectedActions, done
};
};
// call the action with mocked store and arguments
// call the action with mocked store and arguments
action
({
commit
,
state
,
dispatch
},
payload
);
action
({
commit
,
state
,
dispatch
,
rootState
:
state
},
payload
);
// check if no mutations should have been dispatched
// check if no mutations should have been dispatched
if
(
expectedMutations
.
length
===
0
)
{
if
(
expectedMutations
.
length
===
0
)
{
...
...
spec/javascripts/ide/mock_data.js
View file @
21f86195
// eslint-disable-next-line import/prefer-default-export
export
const
projectData
=
{
export
const
projectData
=
{
id
:
1
,
id
:
1
,
name
:
'
abcproject
'
,
name
:
'
abcproject
'
,
...
@@ -14,3 +13,42 @@ export const projectData = {
...
@@ -14,3 +13,42 @@ export const projectData = {
mergeRequests
:
{},
mergeRequests
:
{},
merge_requests_enabled
:
true
,
merge_requests_enabled
:
true
,
};
};
export
const
pipelines
=
[
{
id
:
1
,
ref
:
'
master
'
,
sha
:
'
123
'
,
status
:
'
failed
'
,
},
{
id
:
2
,
ref
:
'
master
'
,
sha
:
'
213
'
,
status
:
'
success
'
,
},
];
export
const
jobs
=
[
{
id
:
1
,
name
:
'
test
'
,
status
:
'
failed
'
,
stage
:
'
test
'
,
duration
:
1
,
},
{
id
:
2
,
name
:
'
test 2
'
,
status
:
'
failed
'
,
stage
:
'
test
'
,
duration
:
1
,
},
{
id
:
3
,
name
:
'
test 3
'
,
status
:
'
failed
'
,
stage
:
'
test
'
,
duration
:
1
,
},
];
spec/javascripts/ide/stores/modules/pipelines/actions_spec.js
0 → 100644
View file @
21f86195
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
actions
,
{
requestLatestPipeline
,
receiveLatestPipelineError
,
receiveLatestPipelineSuccess
,
fetchLatestPipeline
,
requestJobs
,
receiveJobsError
,
receiveJobsSuccess
,
fetchJobs
,
}
from
'
~/ide/stores/modules/pipelines/actions
'
;
import
state
from
'
~/ide/stores/modules/pipelines/state
'
;
import
*
as
types
from
'
~/ide/stores/modules/pipelines/mutation_types
'
;
import
testAction
from
'
../../../../helpers/vuex_action_helper
'
;
import
{
pipelines
,
jobs
}
from
'
../../../mock_data
'
;
describe
(
'
IDE pipelines actions
'
,
()
=>
{
let
mockedState
;
let
mock
;
beforeEach
(()
=>
{
mockedState
=
state
();
mock
=
new
MockAdapter
(
axios
);
gon
.
api_version
=
'
v4
'
;
mockedState
.
currentProjectId
=
'
test/project
'
;
});
afterEach
(()
=>
{
mock
.
restore
();
});
describe
(
'
requestLatestPipeline
'
,
()
=>
{
it
(
'
commits request
'
,
done
=>
{
testAction
(
requestLatestPipeline
,
null
,
mockedState
,
[{
type
:
types
.
REQUEST_LATEST_PIPELINE
}],
[],
done
,
);
});
});
describe
(
'
receiveLatestPipelineError
'
,
()
=>
{
it
(
'
commits error
'
,
done
=>
{
testAction
(
receiveLatestPipelineError
,
null
,
mockedState
,
[{
type
:
types
.
RECEIVE_LASTEST_PIPELINE_ERROR
}],
[],
done
,
);
});
it
(
'
creates flash message
'
,
()
=>
{
const
flashSpy
=
spyOnDependency
(
actions
,
'
flash
'
);
receiveLatestPipelineError
({
commit
()
{}
});
expect
(
flashSpy
).
toHaveBeenCalled
();
});
});
describe
(
'
receiveLatestPipelineSuccess
'
,
()
=>
{
it
(
'
commits pipeline
'
,
done
=>
{
testAction
(
receiveLatestPipelineSuccess
,
pipelines
[
0
],
mockedState
,
[{
type
:
types
.
RECEIVE_LASTEST_PIPELINE_SUCCESS
,
payload
:
pipelines
[
0
]
}],
[],
done
,
);
});
});
describe
(
'
fetchLatestPipeline
'
,
()
=>
{
describe
(
'
success
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onGet
(
/
\/
api
\/
v4
\/
projects
\/(
.*
)\/
pipelines
(
.*
)
/
).
replyOnce
(
200
,
pipelines
);
});
it
(
'
dispatches request
'
,
done
=>
{
testAction
(
fetchLatestPipeline
,
'
123
'
,
mockedState
,
[],
[{
type
:
'
requestLatestPipeline
'
},
{
type
:
'
receiveLatestPipelineSuccess
'
}],
done
,
);
});
it
(
'
dispatches success with latest pipeline
'
,
done
=>
{
testAction
(
fetchLatestPipeline
,
'
123
'
,
mockedState
,
[],
[
{
type
:
'
requestLatestPipeline
'
},
{
type
:
'
receiveLatestPipelineSuccess
'
,
payload
:
pipelines
[
0
]
},
],
done
,
);
});
it
(
'
calls axios with correct params
'
,
()
=>
{
const
apiSpy
=
spyOn
(
axios
,
'
get
'
).
and
.
callThrough
();
fetchLatestPipeline
({
dispatch
()
{},
rootState
:
state
},
'
123
'
);
expect
(
apiSpy
).
toHaveBeenCalledWith
(
jasmine
.
anything
(),
{
params
:
{
sha
:
'
123
'
,
per_page
:
'
1
'
,
},
});
});
});
describe
(
'
error
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onGet
(
/
\/
api
\/
v4
\/
projects
\/(
.*
)\/
pipelines
(
.*
)
/
).
replyOnce
(
500
);
});
it
(
'
dispatches error
'
,
done
=>
{
testAction
(
fetchLatestPipeline
,
'
123
'
,
mockedState
,
[],
[{
type
:
'
requestLatestPipeline
'
},
{
type
:
'
receiveLatestPipelineError
'
}],
done
,
);
});
});
});
describe
(
'
requestJobs
'
,
()
=>
{
it
(
'
commits request
'
,
done
=>
{
testAction
(
requestJobs
,
null
,
mockedState
,
[{
type
:
types
.
REQUEST_JOBS
}],
[],
done
);
});
});
describe
(
'
receiveJobsError
'
,
()
=>
{
it
(
'
commits error
'
,
done
=>
{
testAction
(
receiveJobsError
,
null
,
mockedState
,
[{
type
:
types
.
RECEIVE_JOBS_ERROR
}],
[],
done
,
);
});
it
(
'
creates flash message
'
,
()
=>
{
const
flashSpy
=
spyOnDependency
(
actions
,
'
flash
'
);
receiveJobsError
({
commit
()
{}
});
expect
(
flashSpy
).
toHaveBeenCalled
();
});
});
describe
(
'
receiveJobsSuccess
'
,
()
=>
{
it
(
'
commits jobs
'
,
done
=>
{
testAction
(
receiveJobsSuccess
,
jobs
,
mockedState
,
[{
type
:
types
.
RECEIVE_JOBS_SUCCESS
,
payload
:
jobs
}],
[],
done
,
);
});
});
describe
(
'
fetchJobs
'
,
()
=>
{
beforeEach
(()
=>
{
mockedState
.
latestPipeline
=
pipelines
[
0
];
});
describe
(
'
success
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onGet
(
/
\/
api
\/
v4
\/
projects
\/(
.*
)\/
pipelines
\/(
.*
)\/
jobs/
).
replyOnce
(
200
,
jobs
);
});
it
(
'
dispatches request
'
,
done
=>
{
testAction
(
fetchJobs
,
null
,
mockedState
,
[],
[{
type
:
'
requestJobs
'
},
{
type
:
'
receiveJobsSuccess
'
}],
done
,
);
});
it
(
'
dispatches success with latest pipeline
'
,
done
=>
{
testAction
(
fetchJobs
,
null
,
mockedState
,
[],
[{
type
:
'
requestJobs
'
},
{
type
:
'
receiveJobsSuccess
'
,
payload
:
jobs
}],
done
,
);
});
it
(
'
calls axios with correct URL
'
,
()
=>
{
const
apiSpy
=
spyOn
(
axios
,
'
get
'
).
and
.
callThrough
();
fetchJobs
({
dispatch
()
{},
state
:
mockedState
,
rootState
:
mockedState
});
expect
(
apiSpy
).
toHaveBeenCalledWith
(
'
/api/v4/projects/test%2Fproject/pipelines/1/jobs
'
);
});
});
describe
(
'
error
'
,
()
=>
{
beforeEach
(()
=>
{
mock
.
onGet
(
/
\/
api
\/
v4
\/
projects
\/(
.*
)\/
pipelines
(
.*
)
/
).
replyOnce
(
500
);
});
it
(
'
dispatches error
'
,
done
=>
{
testAction
(
fetchJobs
,
null
,
mockedState
,
[],
[{
type
:
'
requestJobs
'
},
{
type
:
'
receiveJobsError
'
}],
done
,
);
});
});
});
});
spec/javascripts/ide/stores/modules/pipelines/mutations_spec.js
0 → 100644
View file @
21f86195
import
mutations
from
'
~/ide/stores/modules/pipelines/mutations
'
;
import
state
from
'
~/ide/stores/modules/pipelines/state
'
;
import
*
as
types
from
'
~/ide/stores/modules/pipelines/mutation_types
'
;
import
{
pipelines
,
jobs
}
from
'
../../../mock_data
'
;
describe
(
'
IDE pipelines mutations
'
,
()
=>
{
let
mockedState
;
beforeEach
(()
=>
{
mockedState
=
state
;
});
describe
(
types
.
REQUEST_LATEST_PIPELINE
,
()
=>
{
it
(
'
sets loading to true
'
,
()
=>
{
mutations
[
types
.
REQUEST_LATEST_PIPELINE
](
mockedState
);
expect
(
mockedState
.
isLoadingPipeline
).
toBe
(
true
);
});
});
describe
(
types
.
RECEIVE_LASTEST_PIPELINE_ERROR
,
()
=>
{
it
(
'
sets loading to false
'
,
()
=>
{
mutations
[
types
.
RECEIVE_LASTEST_PIPELINE_ERROR
](
mockedState
);
expect
(
mockedState
.
isLoadingPipeline
).
toBe
(
false
);
});
});
describe
(
types
.
RECEIVE_LASTEST_PIPELINE_SUCCESS
,
()
=>
{
it
(
'
sets loading to false on success
'
,
()
=>
{
mutations
[
types
.
RECEIVE_LASTEST_PIPELINE_SUCCESS
](
mockedState
,
pipelines
[
0
]);
expect
(
mockedState
.
isLoadingPipeline
).
toBe
(
false
);
});
it
(
'
sets latestPipeline
'
,
()
=>
{
mutations
[
types
.
RECEIVE_LASTEST_PIPELINE_SUCCESS
](
mockedState
,
pipelines
[
0
]);
expect
(
mockedState
.
latestPipeline
).
toEqual
({
id
:
pipelines
[
0
].
id
,
status
:
pipelines
[
0
].
status
,
});
});
});
describe
(
types
.
REQUEST_JOBS
,
()
=>
{
it
(
'
sets jobs loading to true
'
,
()
=>
{
mutations
[
types
.
REQUEST_JOBS
](
mockedState
);
expect
(
mockedState
.
isLoadingJobs
).
toBe
(
true
);
});
});
describe
(
types
.
RECEIVE_JOBS_ERROR
,
()
=>
{
it
(
'
sets jobs loading to false
'
,
()
=>
{
mutations
[
types
.
RECEIVE_JOBS_ERROR
](
mockedState
);
expect
(
mockedState
.
isLoadingJobs
).
toBe
(
false
);
});
});
describe
(
types
.
RECEIVE_JOBS_SUCCESS
,
()
=>
{
it
(
'
sets jobs loading to false on success
'
,
()
=>
{
mutations
[
types
.
RECEIVE_JOBS_SUCCESS
](
mockedState
,
jobs
);
expect
(
mockedState
.
isLoadingJobs
).
toBe
(
false
);
});
it
(
'
sets jobs
'
,
()
=>
{
mutations
[
types
.
RECEIVE_JOBS_SUCCESS
](
mockedState
,
jobs
);
expect
(
mockedState
.
jobs
.
length
).
toBe
(
3
);
expect
(
mockedState
.
jobs
).
toEqual
(
jobs
.
map
(
job
=>
({
id
:
job
.
id
,
name
:
job
.
name
,
status
:
job
.
status
,
stage
:
job
.
stage
,
duration
:
job
.
duration
,
})),
);
});
});
});
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