Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
4410a1fa
Commit
4410a1fa
authored
Mar 28, 2018
by
Tim Zallmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Patch applied for Open MR in IDE
parent
4cb37a20
Changes
41
Hide whitespace changes
Inline
Side-by-side
Showing
41 changed files
with
1396 additions
and
582 deletions
+1396
-582
app/assets/javascripts/api.js
app/assets/javascripts/api.js
+88
-58
app/assets/javascripts/ide/components/changed_file_icon.vue
app/assets/javascripts/ide/components/changed_file_icon.vue
+17
-17
app/assets/javascripts/ide/components/editor_mode_dropdown.vue
...ssets/javascripts/ide/components/editor_mode_dropdown.vue
+63
-24
app/assets/javascripts/ide/components/ide.vue
app/assets/javascripts/ide/components/ide.vue
+43
-42
app/assets/javascripts/ide/components/mr_file_icon.vue
app/assets/javascripts/ide/components/mr_file_icon.vue
+29
-0
app/assets/javascripts/ide/components/repo_editor.vue
app/assets/javascripts/ide/components/repo_editor.vue
+17
-12
app/assets/javascripts/ide/components/repo_file.vue
app/assets/javascripts/ide/components/repo_file.vue
+13
-9
app/assets/javascripts/ide/components/repo_file_status_icon.vue
...sets/javascripts/ide/components/repo_file_status_icon.vue
+20
-20
app/assets/javascripts/ide/components/repo_tabs.vue
app/assets/javascripts/ide/components/repo_tabs.vue
+38
-33
app/assets/javascripts/ide/ide_router.js
app/assets/javascripts/ide/ide_router.js
+56
-4
app/assets/javascripts/ide/lib/common/model.js
app/assets/javascripts/ide/lib/common/model.js
+16
-12
app/assets/javascripts/ide/lib/editor.js
app/assets/javascripts/ide/lib/editor.js
+13
-7
app/assets/javascripts/ide/services/index.js
app/assets/javascripts/ide/services/index.js
+24
-1
app/assets/javascripts/ide/stores/actions.js
app/assets/javascripts/ide/stores/actions.js
+4
-7
app/assets/javascripts/ide/stores/actions/file.js
app/assets/javascripts/ide/stores/actions/file.js
+40
-33
app/assets/javascripts/ide/stores/actions/merge_request.js
app/assets/javascripts/ide/stores/actions/merge_request.js
+84
-0
app/assets/javascripts/ide/stores/actions/tree.js
app/assets/javascripts/ide/stores/actions/tree.js
+50
-48
app/assets/javascripts/ide/stores/getters.js
app/assets/javascripts/ide/stores/getters.js
+11
-4
app/assets/javascripts/ide/stores/mutation_types.js
app/assets/javascripts/ide/stores/mutation_types.js
+8
-0
app/assets/javascripts/ide/stores/mutations.js
app/assets/javascripts/ide/stores/mutations.js
+4
-7
app/assets/javascripts/ide/stores/mutations/file.js
app/assets/javascripts/ide/stores/mutations/file.js
+12
-0
app/assets/javascripts/ide/stores/mutations/merge_request.js
app/assets/javascripts/ide/stores/mutations/merge_request.js
+33
-0
app/assets/javascripts/ide/stores/mutations/project.js
app/assets/javascripts/ide/stores/mutations/project.js
+1
-0
app/assets/javascripts/ide/stores/state.js
app/assets/javascripts/ide/stores/state.js
+1
-0
app/assets/javascripts/ide/stores/utils.js
app/assets/javascripts/ide/stores/utils.js
+12
-10
app/assets/javascripts/lib/utils/url_utility.js
app/assets/javascripts/lib/utils/url_utility.js
+9
-1
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
.../vue_merge_request_widget/components/mr_widget_header.vue
+54
-43
app/assets/stylesheets/pages/repo.scss
app/assets/stylesheets/pages/repo.scss
+2
-3
spec/javascripts/api_spec.js
spec/javascripts/api_spec.js
+138
-59
spec/javascripts/ide/components/changed_file_icon_spec.js
spec/javascripts/ide/components/changed_file_icon_spec.js
+2
-1
spec/javascripts/ide/components/repo_editor_spec.js
spec/javascripts/ide/components/repo_editor_spec.js
+58
-0
spec/javascripts/ide/components/repo_tabs_spec.js
spec/javascripts/ide/components/repo_tabs_spec.js
+2
-0
spec/javascripts/ide/lib/common/model_spec.js
spec/javascripts/ide/lib/common/model_spec.js
+12
-2
spec/javascripts/ide/lib/editor_spec.js
spec/javascripts/ide/lib/editor_spec.js
+25
-0
spec/javascripts/ide/stores/actions/file_spec.js
spec/javascripts/ide/stores/actions/file_spec.js
+35
-8
spec/javascripts/ide/stores/actions/merge_request_spec.js
spec/javascripts/ide/stores/actions/merge_request_spec.js
+110
-0
spec/javascripts/ide/stores/actions/tree_spec.js
spec/javascripts/ide/stores/actions/tree_spec.js
+3
-9
spec/javascripts/ide/stores/getters_spec.js
spec/javascripts/ide/stores/getters_spec.js
+21
-1
spec/javascripts/ide/stores/mutations/file_spec.js
spec/javascripts/ide/stores/mutations/file_spec.js
+25
-1
spec/javascripts/ide/stores/mutations/merge_request_spec.js
spec/javascripts/ide/stores/mutations/merge_request_spec.js
+65
-0
spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js
...scripts/vue_mr_widget/components/mr_widget_header_spec.js
+138
-106
No files found.
app/assets/javascripts/api.js
View file @
4410a1fa
...
...
@@ -10,6 +10,9 @@ const Api = {
projectsPath
:
'
/api/:version/projects.json
'
,
projectPath
:
'
/api/:version/projects/:id
'
,
projectLabelsPath
:
'
/:namespace_path/:project_path/labels
'
,
mergeRequestPath
:
'
/api/:version/projects/:id/merge_requests/:mrid
'
,
mergeRequestChangesPath
:
'
/api/:version/projects/:id/merge_requests/:mrid/changes
'
,
mergeRequestVersionsPath
:
'
/api/:version/projects/:id/merge_requests/:mrid/versions
'
,
groupLabelsPath
:
'
/groups/:namespace_path/-/labels
'
,
licensePath
:
'
/api/:version/templates/licenses/:key
'
,
gitignorePath
:
'
/api/:version/templates/gitignores/:key
'
,
...
...
@@ -24,25 +27,27 @@ const Api = {
geoNodesPath
:
'
/api/:version/geo_nodes
'
,
group
(
groupId
,
callback
)
{
const
url
=
Api
.
buildUrl
(
Api
.
groupPath
)
.
replace
(
'
:id
'
,
groupId
);
return
axios
.
get
(
url
)
.
then
(({
data
})
=>
{
callback
(
data
);
const
url
=
Api
.
buildUrl
(
Api
.
groupPath
).
replace
(
'
:id
'
,
groupId
);
return
axios
.
get
(
url
).
then
(({
data
})
=>
{
callback
(
data
);
return
data
;
});
return
data
;
});
},
// Return groups list. Filtered by query
groups
(
query
,
options
,
callback
=
$
.
noop
)
{
const
url
=
Api
.
buildUrl
(
Api
.
groupsPath
);
return
axios
.
get
(
url
,
{
params
:
Object
.
assign
({
search
:
query
,
per_page
:
20
,
},
options
),
})
return
axios
.
get
(
url
,
{
params
:
Object
.
assign
(
{
search
:
query
,
per_page
:
20
,
},
options
,
),
})
.
then
(({
data
})
=>
{
callback
(
data
);
...
...
@@ -53,12 +58,13 @@ const Api = {
// Return namespaces list. Filtered by query
namespaces
(
query
,
callback
)
{
const
url
=
Api
.
buildUrl
(
Api
.
namespacesPath
);
return
axios
.
get
(
url
,
{
params
:
{
search
:
query
,
per_page
:
20
,
},
})
return
axios
.
get
(
url
,
{
params
:
{
search
:
query
,
per_page
:
20
,
},
})
.
then
(({
data
})
=>
callback
(
data
));
},
...
...
@@ -75,9 +81,10 @@ const Api = {
defaults
.
membership
=
true
;
}
return
axios
.
get
(
url
,
{
params
:
Object
.
assign
(
defaults
,
options
),
})
return
axios
.
get
(
url
,
{
params
:
Object
.
assign
(
defaults
,
options
),
})
.
then
(({
data
})
=>
{
callback
(
data
);
...
...
@@ -87,8 +94,32 @@ const Api = {
// Return single project
project
(
projectPath
)
{
const
url
=
Api
.
buildUrl
(
Api
.
projectPath
)
.
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
));
const
url
=
Api
.
buildUrl
(
Api
.
projectPath
).
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
));
return
axios
.
get
(
url
);
},
// Return Merge Request for project
mergeRequest
(
projectPath
,
mergeRequestId
)
{
const
url
=
Api
.
buildUrl
(
Api
.
mergeRequestPath
)
.
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
))
.
replace
(
'
:mrid
'
,
mergeRequestId
);
return
axios
.
get
(
url
);
},
mergeRequestChanges
(
projectPath
,
mergeRequestId
)
{
const
url
=
Api
.
buildUrl
(
Api
.
mergeRequestChangesPath
)
.
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
))
.
replace
(
'
:mrid
'
,
mergeRequestId
);
return
axios
.
get
(
url
);
},
mergeRequestVersions
(
projectPath
,
mergeRequestId
)
{
const
url
=
Api
.
buildUrl
(
Api
.
mergeRequestVersionsPath
)
.
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
))
.
replace
(
'
:mrid
'
,
mergeRequestId
);
return
axios
.
get
(
url
);
},
...
...
@@ -104,30 +135,30 @@ const Api = {
url
=
Api
.
buildUrl
(
Api
.
groupLabelsPath
).
replace
(
'
:namespace_path
'
,
namespacePath
);
}
return
axios
.
post
(
url
,
{
label
:
data
,
})
return
axios
.
post
(
url
,
{
label
:
data
,
})
.
then
(
res
=>
callback
(
res
.
data
))
.
catch
(
e
=>
callback
(
e
.
response
.
data
));
},
// Return group projects list. Filtered by query
groupProjects
(
groupId
,
query
,
callback
)
{
const
url
=
Api
.
buildUrl
(
Api
.
groupProjectsPath
)
.
replace
(
'
:id
'
,
groupId
);
return
axios
.
get
(
url
,
{
params
:
{
search
:
query
,
per_page
:
20
,
},
})
const
url
=
Api
.
buildUrl
(
Api
.
groupProjectsPath
)
.
replace
(
'
:id
'
,
groupId
);
return
axios
.
get
(
url
,
{
params
:
{
search
:
query
,
per_page
:
20
,
},
})
.
then
(({
data
})
=>
callback
(
data
));
},
commitMultiple
(
id
,
data
)
{
// see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
const
url
=
Api
.
buildUrl
(
Api
.
commitPath
)
.
replace
(
'
:id
'
,
encodeURIComponent
(
id
));
const
url
=
Api
.
buildUrl
(
Api
.
commitPath
).
replace
(
'
:id
'
,
encodeURIComponent
(
id
));
return
axios
.
post
(
url
,
JSON
.
stringify
(
data
),
{
headers
:
{
'
Content-Type
'
:
'
application/json; charset=utf-8
'
,
...
...
@@ -138,39 +169,34 @@ const Api = {
branchSingle
(
id
,
branch
)
{
const
url
=
Api
.
buildUrl
(
Api
.
branchSinglePath
)
.
replace
(
'
:id
'
,
encodeURIComponent
(
id
))
.
replace
(
'
:branch
'
,
branch
);
.
replace
(
'
:branch
'
,
encodeURIComponent
(
branch
)
);
return
axios
.
get
(
url
);
},
// Return text for a specific license
licenseText
(
key
,
data
,
callback
)
{
const
url
=
Api
.
buildUrl
(
Api
.
licensePath
)
.
replace
(
'
:key
'
,
key
);
return
axios
.
get
(
url
,
{
params
:
data
,
})
const
url
=
Api
.
buildUrl
(
Api
.
licensePath
)
.
replace
(
'
:key
'
,
key
);
return
axios
.
get
(
url
,
{
params
:
data
,
})
.
then
(
res
=>
callback
(
res
.
data
));
},
gitignoreText
(
key
,
callback
)
{
const
url
=
Api
.
buildUrl
(
Api
.
gitignorePath
)
.
replace
(
'
:key
'
,
key
);
return
axios
.
get
(
url
)
.
then
(({
data
})
=>
callback
(
data
));
const
url
=
Api
.
buildUrl
(
Api
.
gitignorePath
).
replace
(
'
:key
'
,
key
);
return
axios
.
get
(
url
).
then
(({
data
})
=>
callback
(
data
));
},
gitlabCiYml
(
key
,
callback
)
{
const
url
=
Api
.
buildUrl
(
Api
.
gitlabCiYmlPath
)
.
replace
(
'
:key
'
,
key
);
return
axios
.
get
(
url
)
.
then
(({
data
})
=>
callback
(
data
));
const
url
=
Api
.
buildUrl
(
Api
.
gitlabCiYmlPath
).
replace
(
'
:key
'
,
key
);
return
axios
.
get
(
url
).
then
(({
data
})
=>
callback
(
data
));
},
dockerfileYml
(
key
,
callback
)
{
const
url
=
Api
.
buildUrl
(
Api
.
dockerfilePath
).
replace
(
'
:key
'
,
key
);
return
axios
.
get
(
url
)
.
then
(({
data
})
=>
callback
(
data
));
return
axios
.
get
(
url
).
then
(({
data
})
=>
callback
(
data
));
},
issueTemplate
(
namespacePath
,
projectPath
,
key
,
type
,
callback
)
{
...
...
@@ -179,7 +205,8 @@ const Api = {
.
replace
(
'
:type
'
,
type
)
.
replace
(
'
:project_path
'
,
projectPath
)
.
replace
(
'
:namespace_path
'
,
namespacePath
);
return
axios
.
get
(
url
)
return
axios
.
get
(
url
)
.
then
(({
data
})
=>
callback
(
null
,
data
))
.
catch
(
callback
);
},
...
...
@@ -187,10 +214,13 @@ const Api = {
users
(
query
,
options
)
{
const
url
=
Api
.
buildUrl
(
this
.
usersPath
);
return
axios
.
get
(
url
,
{
params
:
Object
.
assign
({
search
:
query
,
per_page
:
20
,
},
options
),
params
:
Object
.
assign
(
{
search
:
query
,
per_page
:
20
,
},
options
,
),
});
},
...
...
app/assets/javascripts/ide/components/changed_file_icon.vue
View file @
4410a1fa
<
script
>
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
export
default
{
components
:
{
icon
,
export
default
{
components
:
{
icon
,
},
props
:
{
file
:
{
type
:
Object
,
required
:
true
,
},
props
:
{
file
:
{
type
:
Object
,
required
:
true
,
},
},
computed
:
{
changedIcon
()
{
return
this
.
file
.
tempFile
?
'
file-addition
'
:
'
file-modified
'
;
},
computed
:
{
changedIcon
()
{
return
this
.
file
.
tempFile
?
'
file-addition
'
:
'
file-modified
'
;
},
changedIconClass
()
{
return
`multi-
${
this
.
changedIcon
}
`
;
},
changedIconClass
()
{
return
`multi-
${
this
.
changedIcon
}
`
;
},
};
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/ide/components/editor_mode_dropdown.vue
View file @
4410a1fa
<
script
>
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
{
__
,
sprintf
}
from
'
~/locale
'
;
export
default
{
components
:
{
Icon
,
export
default
{
components
:
{
Icon
,
},
props
:
{
hasChanges
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
props
:
{
hasChanges
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
viewer
:
{
type
:
String
,
required
:
true
,
},
showShadow
:
{
type
:
Boolean
,
required
:
true
,
},
mergeRequestId
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
methods
:
{
changeMode
(
mode
)
{
this
.
$emit
(
'
click
'
,
mode
);
},
viewer
:
{
type
:
String
,
required
:
true
,
},
};
showShadow
:
{
type
:
Boolean
,
required
:
true
,
},
},
computed
:
{
mergeReviewLine
()
{
return
sprintf
(
__
(
'
Reviewing (merge request !%{mergeRequestId})
'
),
{
mergeRequestId
:
this
.
mergeRequestId
,
});
},
},
methods
:
{
changeMode
(
mode
)
{
this
.
$emit
(
'
click
'
,
mode
);
},
},
};
</
script
>
<
template
>
...
...
@@ -43,7 +56,10 @@
}"
data-toggle="dropdown"
>
<template
v-if=
"viewer === 'editor'"
>
<template
v-if=
"viewer === 'mrdiff' && mergeRequestId"
>
{{
mergeReviewLine
}}
</
template
>
<
template
v-else-if=
"viewer === 'editor'"
>
{{
__
(
'
Editing
'
)
}}
</
template
>
<
template
v-else
>
...
...
@@ -57,6 +73,29 @@
</button>
<div
class=
"dropdown-menu dropdown-menu-selectable dropdown-open-left"
>
<ul>
<
template
v-if=
"mergeRequestId"
>
<li>
<a
href=
"#"
@
click.prevent=
"changeMode('mrdiff')"
:class=
"
{
'is-active': viewer === 'mrdiff',
}"
>
<strong
class=
"dropdown-menu-inner-title"
>
{{
mergeReviewLine
}}
</strong>
<span
class=
"dropdown-menu-inner-content"
>
{{
__
(
'
Compare changes with the merge request target branch
'
)
}}
</span>
</a>
</li>
<li
role=
"separator"
class=
"divider"
>
</li>
</
template
>
<li>
<a
href=
"#"
...
...
app/assets/javascripts/ide/components/ide.vue
View file @
4410a1fa
<
script
>
import
{
mapState
,
mapGetters
}
from
'
vuex
'
;
import
ideSidebar
from
'
./ide_side_bar.vue
'
;
import
ideContextbar
from
'
./ide_context_bar.vue
'
;
import
repoTabs
from
'
./repo_tabs.vue
'
;
import
repoFileButtons
from
'
./repo_file_buttons.vue
'
;
import
ideStatusBar
from
'
./ide_status_bar.vue
'
;
import
repoEditor
from
'
./repo_editor.vue
'
;
import
{
mapState
,
mapGetters
}
from
'
vuex
'
;
import
ideSidebar
from
'
./ide_side_bar.vue
'
;
import
ideContextbar
from
'
./ide_context_bar.vue
'
;
import
repoTabs
from
'
./repo_tabs.vue
'
;
import
repoFileButtons
from
'
./repo_file_buttons.vue
'
;
import
ideStatusBar
from
'
./ide_status_bar.vue
'
;
import
repoEditor
from
'
./repo_editor.vue
'
;
export
default
{
components
:
{
ideSidebar
,
ideContextbar
,
repoTabs
,
repoFileButtons
,
ideStatusBar
,
repoEditor
,
export
default
{
components
:
{
ideSidebar
,
ideContextbar
,
repoTabs
,
repoFileButtons
,
ideStatusBar
,
repoEditor
,
},
props
:
{
emptyStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
props
:
{
emptyStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
noChangesStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
committedStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
noChangesStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
com
puted
:
{
...
mapState
([
'
changedFiles
'
,
'
openFiles
'
,
'
viewer
'
])
,
...
mapGetters
([
'
activeFile
'
,
'
hasChanges
'
])
,
com
mittedStateSvgPath
:
{
type
:
String
,
required
:
true
,
},
mounted
()
{
const
returnValue
=
'
Are you sure you want to lose unsaved changes?
'
;
window
.
onbeforeunload
=
e
=>
{
if
(
!
this
.
changedFiles
.
length
)
return
undefined
;
},
computed
:
{
...
mapState
([
'
changedFiles
'
,
'
openFiles
'
,
'
viewer
'
,
'
currentMergeRequestId
'
]),
...
mapGetters
([
'
activeFile
'
,
'
hasChanges
'
]),
},
mounted
()
{
const
returnValue
=
'
Are you sure you want to lose unsaved changes?
'
;
window
.
onbeforeunload
=
e
=>
{
if
(
!
this
.
changedFiles
.
length
)
return
undefined
;
Object
.
assign
(
e
,
{
returnValue
,
});
return
returnValue
;
};
},
};
Object
.
assign
(
e
,
{
returnValue
,
});
return
returnValue
;
};
},
};
</
script
>
<
template
>
...
...
@@ -63,6 +63,7 @@
:files=
"openFiles"
:viewer=
"viewer"
:has-changes=
"hasChanges"
:merge-request-id=
"currentMergeRequestId"
/>
<repo-editor
class=
"multi-file-edit-pane-content"
...
...
app/assets/javascripts/ide/components/mr_file_icon.vue
0 → 100644
View file @
4410a1fa
<
script
>
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
export
default
{
components
:
{
icon
,
},
directives
:
{
tooltip
,
},
props
:
{
file
:
{
type
:
Object
,
required
:
true
,
},
},
};
</
script
>
<
template
>
<icon
name=
"git-merge"
v-tooltip
title=
"Part of merge request changes"
css-classes=
"ide-file-changed-icon"
:size=
"12"
/>
</
template
>
app/assets/javascripts/ide/components/repo_editor.vue
View file @
4410a1fa
<
script
>
/* global monaco */
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
{
mapState
,
map
Getters
,
map
Actions
}
from
'
vuex
'
;
import
flash
from
'
~/flash
'
;
import
monacoLoader
from
'
../monaco_loader
'
;
import
Editor
from
'
../lib/editor
'
;
...
...
@@ -13,12 +13,8 @@ export default {
},
},
computed
:
{
...
mapState
([
'
leftPanelCollapsed
'
,
'
rightPanelCollapsed
'
,
'
viewer
'
,
'
delayViewerUpdated
'
,
]),
...
mapState
([
'
leftPanelCollapsed
'
,
'
rightPanelCollapsed
'
,
'
viewer
'
,
'
delayViewerUpdated
'
]),
...
mapGetters
([
'
currentMergeRequest
'
]),
shouldHideEditor
()
{
return
this
.
file
&&
this
.
file
.
binary
&&
!
this
.
file
.
raw
;
},
...
...
@@ -68,9 +64,14 @@ export default {
this
.
editor
.
clearEditor
();
this
.
getRawFileData
(
this
.
file
)
this
.
getRawFileData
({
path
:
this
.
file
.
path
,
baseSha
:
this
.
currentMergeRequest
?
this
.
currentMergeRequest
.
baseCommitSha
:
''
,
})
.
then
(()
=>
{
const
viewerPromise
=
this
.
delayViewerUpdated
?
this
.
updateViewer
(
'
editor
'
)
:
Promise
.
resolve
();
const
viewerPromise
=
this
.
delayViewerUpdated
?
this
.
updateViewer
(
'
editor
'
)
:
Promise
.
resolve
();
return
viewerPromise
;
})
...
...
@@ -78,7 +79,7 @@ export default {
this
.
updateDelayViewerUpdated
(
false
);
this
.
createEditorInstance
();
})
.
catch
(
(
err
)
=>
{
.
catch
(
err
=>
{
flash
(
'
Error setting up monaco. Please try again.
'
,
'
alert
'
,
document
,
null
,
false
,
true
);
throw
err
;
});
...
...
@@ -101,9 +102,13 @@ export default {
this
.
model
=
this
.
editor
.
createModel
(
this
.
file
);
this
.
editor
.
attachModel
(
this
.
model
);
if
(
this
.
viewer
===
'
mrdiff
'
)
{
this
.
editor
.
attachMergeRequestModel
(
this
.
model
);
}
else
{
this
.
editor
.
attachModel
(
this
.
model
);
}
this
.
model
.
onChange
(
(
model
)
=>
{
this
.
model
.
onChange
(
model
=>
{
const
{
file
}
=
model
;
if
(
file
.
active
)
{
...
...
app/assets/javascripts/ide/components/repo_file.vue
View file @
4410a1fa
...
...
@@ -6,6 +6,7 @@ import router from '../ide_router';
import
newDropdown
from
'
./new_dropdown/index.vue
'
;
import
fileStatusIcon
from
'
./repo_file_status_icon.vue
'
;
import
changedFileIcon
from
'
./changed_file_icon.vue
'
;
import
mrFileIcon
from
'
./mr_file_icon.vue
'
;
export
default
{
name
:
'
RepoFile
'
,
...
...
@@ -15,6 +16,7 @@ export default {
fileStatusIcon
,
fileIcon
,
changedFileIcon
,
mrFileIcon
,
},
props
:
{
file
:
{
...
...
@@ -56,10 +58,7 @@ export default {
...
mapActions
([
'
toggleTreeOpen
'
,
'
updateDelayViewerUpdated
'
]),
clickFile
()
{
// Manual Action if a tree is selected/opened
if
(
this
.
isTree
&&
this
.
$router
.
currentRoute
.
path
===
`/project
${
this
.
file
.
url
}
`
)
{
if
(
this
.
isTree
&&
this
.
$router
.
currentRoute
.
path
===
`/project
${
this
.
file
.
url
}
`
)
{
this
.
toggleTreeOpen
(
this
.
file
.
path
);
}
...
...
@@ -102,11 +101,16 @@ export default {
:file=
"file"
/>
</span>
<changed-file-icon
:file=
"file"
v-if=
"file.changed || file.tempFile"
class=
"prepend-top-5 pull-right"
/>
<span
class=
"pull-right"
>
<mr-file-icon
:file=
"file"
v-if=
"file.mrChange"
/>
<changed-file-icon
:file=
"file"
v-if=
"file.changed || file.tempFile"
/>
</span>
<new-dropdown
v-if=
"isTree"
:project-id=
"file.projectId"
...
...
app/assets/javascripts/ide/components/repo_file_status_icon.vue
View file @
4410a1fa
<
script
>
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
'
~/lib/utils/datetime_utility
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
'
~/lib/utils/datetime_utility
'
;
export
default
{
components
:
{
icon
,
export
default
{
components
:
{
icon
,
},
directives
:
{
tooltip
,
},
props
:
{
file
:
{
type
:
Object
,
required
:
true
,
},
directives
:
{
tooltip
,
},
computed
:
{
lockTooltip
()
{
return
`Locked by
${
this
.
file
.
file_lock
.
user
.
name
}
`
;
},
props
:
{
file
:
{
type
:
Object
,
required
:
true
,
},
},
computed
:
{
lockTooltip
()
{
return
`Locked by
${
this
.
file
.
file_lock
.
user
.
name
}
`
;
},
},
};
},
};
</
script
>
<
template
>
...
...
app/assets/javascripts/ide/components/repo_tabs.vue
View file @
4410a1fa
<
script
>
import
{
mapActions
}
from
'
vuex
'
;
import
RepoTab
from
'
./repo_tab.vue
'
;
import
EditorMode
from
'
./editor_mode_dropdown.vue
'
;
import
{
mapActions
}
from
'
vuex
'
;
import
RepoTab
from
'
./repo_tab.vue
'
;
import
EditorMode
from
'
./editor_mode_dropdown.vue
'
;
export
default
{
components
:
{
RepoTab
,
EditorMode
,
export
default
{
components
:
{
RepoTab
,
EditorMode
,
},
props
:
{
files
:
{
type
:
Array
,
required
:
true
,
},
props
:
{
files
:
{
type
:
Array
,
required
:
true
,
},
viewer
:
{
type
:
String
,
required
:
true
,
},
hasChanges
:
{
type
:
Boolean
,
required
:
true
,
},
viewer
:
{
type
:
String
,
required
:
true
,
},
data
()
{
return
{
showShadow
:
false
,
};
hasChanges
:
{
type
:
Boolean
,
required
:
true
,
},
updated
()
{
if
(
!
this
.
$refs
.
tabsScroller
)
return
;
this
.
showShadow
=
this
.
$refs
.
tabsScroller
.
scrollWidth
>
this
.
$refs
.
tabsScroller
.
offsetWidth
;
},
methods
:
{
...
mapActions
([
'
updateViewer
'
]),
mergeRequestId
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
};
},
data
()
{
return
{
showShadow
:
false
,
};
},
updated
()
{
if
(
!
this
.
$refs
.
tabsScroller
)
return
;
this
.
showShadow
=
this
.
$refs
.
tabsScroller
.
scrollWidth
>
this
.
$refs
.
tabsScroller
.
offsetWidth
;
},
methods
:
{
...
mapActions
([
'
updateViewer
'
]),
},
};
</
script
>
<
template
>
...
...
@@ -55,6 +59,7 @@
:viewer=
"viewer"
:show-shadow=
"showShadow"
:has-changes=
"hasChanges"
:merge-request-id=
"mergeRequestId"
@
click=
"updateViewer"
/>
</div>
...
...
app/assets/javascripts/ide/ide_router.js
View file @
4410a1fa
...
...
@@ -44,7 +44,7 @@ const router = new VueRouter({
component
:
EmptyRouterComponent
,
},
{
path
:
'
m
r
/:mrid
'
,
path
:
'
m
erge_requests
/:mrid
'
,
component
:
EmptyRouterComponent
,
},
],
...
...
@@ -76,9 +76,7 @@ router.beforeEach((to, from, next) => {
.
then
(()
=>
{
if
(
to
.
params
[
0
])
{
const
path
=
to
.
params
[
0
].
slice
(
-
1
)
===
'
/
'
?
to
.
params
[
0
].
slice
(
0
,
-
1
)
:
to
.
params
[
0
];
to
.
params
[
0
].
slice
(
-
1
)
===
'
/
'
?
to
.
params
[
0
].
slice
(
0
,
-
1
)
:
to
.
params
[
0
];
const
treeEntry
=
store
.
state
.
entries
[
path
];
if
(
treeEntry
)
{
store
.
dispatch
(
'
handleTreeEntryAction
'
,
treeEntry
);
...
...
@@ -96,6 +94,60 @@ router.beforeEach((to, from, next) => {
);
throw
e
;
});
}
else
if
(
to
.
params
.
mrid
)
{
store
.
dispatch
(
'
updateViewer
'
,
'
mrdiff
'
);
store
.
dispatch
(
'
getMergeRequestData
'
,
{
projectId
:
fullProjectId
,
mergeRequestId
:
to
.
params
.
mrid
,
})
.
then
(
mr
=>
{
store
.
dispatch
(
'
getBranchData
'
,
{
projectId
:
fullProjectId
,
branchId
:
mr
.
source_branch
,
});
return
store
.
dispatch
(
'
getFiles
'
,
{
projectId
:
fullProjectId
,
branchId
:
mr
.
source_branch
,
});
})
.
then
(()
=>
store
.
dispatch
(
'
getMergeRequestVersions
'
,
{
projectId
:
fullProjectId
,
mergeRequestId
:
to
.
params
.
mrid
,
}),
)
.
then
(()
=>
store
.
dispatch
(
'
getMergeRequestChanges
'
,
{
projectId
:
fullProjectId
,
mergeRequestId
:
to
.
params
.
mrid
,
}),
)
.
then
(
mrChanges
=>
{
mrChanges
.
changes
.
forEach
((
change
,
ind
)
=>
{
const
changeTreeEntry
=
store
.
state
.
entries
[
change
.
new_path
];
if
(
changeTreeEntry
)
{
store
.
dispatch
(
'
setFileMrChange
'
,
{
file
:
changeTreeEntry
,
mrChange
:
change
,
});
if
(
ind
<
10
)
{
store
.
dispatch
(
'
getFileData
'
,
{
path
:
change
.
new_path
,
makeFileActive
:
ind
===
0
,
});
}
}
});
})
.
catch
(
e
=>
{
flash
(
'
Error while loading the merge request. Please try again.
'
);
throw
e
;
});
}
})
.
catch
(
e
=>
{
...
...
app/assets/javascripts/ide/lib/common/model.js
View file @
4410a1fa
...
...
@@ -21,6 +21,15 @@ export default class Model {
new
this
.
monaco
.
Uri
(
null
,
null
,
this
.
file
.
path
),
)),
);
if
(
this
.
file
.
mrChange
)
{
this
.
disposable
.
add
(
(
this
.
baseModel
=
this
.
monaco
.
editor
.
createModel
(
this
.
file
.
baseRaw
,
undefined
,
new
this
.
monaco
.
Uri
(
null
,
null
,
`target/
${
this
.
file
.
path
}
`
),
)),
);
}
this
.
events
=
new
Map
();
...
...
@@ -28,10 +37,7 @@ export default class Model {
this
.
dispose
=
this
.
dispose
.
bind
(
this
);
eventHub
.
$on
(
`editor.update.model.dispose.
${
this
.
file
.
path
}
`
,
this
.
dispose
);
eventHub
.
$on
(
`editor.update.model.content.
${
this
.
file
.
path
}
`
,
this
.
updateContent
,
);
eventHub
.
$on
(
`editor.update.model.content.
${
this
.
file
.
path
}
`
,
this
.
updateContent
);
}
get
url
()
{
...
...
@@ -58,6 +64,10 @@ export default class Model {
return
this
.
originalModel
;
}
getBaseModel
()
{
return
this
.
baseModel
;
}
setValue
(
value
)
{
this
.
getModel
().
setValue
(
value
);
}
...
...
@@ -78,13 +88,7 @@ export default class Model {
this
.
disposable
.
dispose
();
this
.
events
.
clear
();
eventHub
.
$off
(
`editor.update.model.dispose.
${
this
.
file
.
path
}
`
,
this
.
dispose
,
);
eventHub
.
$off
(
`editor.update.model.content.
${
this
.
file
.
path
}
`
,
this
.
updateContent
,
);
eventHub
.
$off
(
`editor.update.model.dispose.
${
this
.
file
.
path
}
`
,
this
.
dispose
);
eventHub
.
$off
(
`editor.update.model.content.
${
this
.
file
.
path
}
`
,
this
.
updateContent
);
}
}
app/assets/javascripts/ide/lib/editor.js
View file @
4410a1fa
...
...
@@ -109,11 +109,19 @@ export default class Editor {
if
(
this
.
dirtyDiffController
)
this
.
dirtyDiffController
.
reDecorate
(
model
);
}
attachMergeRequestModel
(
model
)
{
this
.
instance
.
setModel
({
original
:
model
.
getBaseModel
(),
modified
:
model
.
getModel
(),
});
this
.
monaco
.
editor
.
createDiffNavigator
(
this
.
instance
,
{
alwaysRevealFirst
:
true
,
});
}
setupMonacoTheme
()
{
this
.
monaco
.
editor
.
defineTheme
(
gitlabTheme
.
themeName
,
gitlabTheme
.
monacoTheme
,
);
this
.
monaco
.
editor
.
defineTheme
(
gitlabTheme
.
themeName
,
gitlabTheme
.
monacoTheme
);
this
.
monaco
.
editor
.
setTheme
(
'
gitlab
'
);
}
...
...
@@ -161,8 +169,6 @@ export default class Editor {
onPositionChange
(
cb
)
{
if
(
!
this
.
instance
.
onDidChangeCursorPosition
)
return
;
this
.
disposable
.
add
(
this
.
instance
.
onDidChangeCursorPosition
(
e
=>
cb
(
this
.
instance
,
e
)),
);
this
.
disposable
.
add
(
this
.
instance
.
onDidChangeCursorPosition
(
e
=>
cb
(
this
.
instance
,
e
)));
}
}
app/assets/javascripts/ide/services/index.js
View file @
4410a1fa
...
...
@@ -20,12 +20,35 @@ export default {
return
Promise
.
resolve
(
file
.
raw
);
}
return
Vue
.
http
.
get
(
file
.
rawPath
,
{
params
:
{
format
:
'
json
'
}
})
return
Vue
.
http
.
get
(
file
.
rawPath
,
{
params
:
{
format
:
'
json
'
}
}).
then
(
res
=>
res
.
text
());
},
getBaseRawFileData
(
file
,
sha
)
{
if
(
file
.
tempFile
)
{
return
Promise
.
resolve
(
file
.
baseRaw
);
}
if
(
file
.
baseRaw
)
{
return
Promise
.
resolve
(
file
.
baseRaw
);
}
return
Vue
.
http
.
get
(
file
.
rawPath
.
replace
(
`/raw/
${
file
.
branchId
}
/
${
file
.
path
}
`
,
`/raw/
${
sha
}
/
${
file
.
path
}
`
),
{
params
:
{
format
:
'
json
'
},
})
.
then
(
res
=>
res
.
text
());
},
getProjectData
(
namespace
,
project
)
{
return
Api
.
project
(
`
${
namespace
}
/
${
project
}
`
);
},
getProjectMergeRequestData
(
projectId
,
mergeRequestId
)
{
return
Api
.
mergeRequest
(
projectId
,
mergeRequestId
);
},
getProjectMergeRequestChanges
(
projectId
,
mergeRequestId
)
{
return
Api
.
mergeRequestChanges
(
projectId
,
mergeRequestId
);
},
getProjectMergeRequestVersions
(
projectId
,
mergeRequestId
)
{
return
Api
.
mergeRequestVersions
(
projectId
,
mergeRequestId
);
},
getBranchData
(
projectId
,
currentBranchId
)
{
return
Api
.
branchSingle
(
projectId
,
currentBranchId
);
},
...
...
app/assets/javascripts/ide/stores/actions.js
View file @
4410a1fa
...
...
@@ -6,8 +6,7 @@ import FilesDecoratorWorker from './workers/files_decorator_worker';
export
const
redirectToUrl
=
(
_
,
url
)
=>
visitUrl
(
url
);
export
const
setInitialData
=
({
commit
},
data
)
=>
commit
(
types
.
SET_INITIAL_DATA
,
data
);
export
const
setInitialData
=
({
commit
},
data
)
=>
commit
(
types
.
SET_INITIAL_DATA
,
data
);
export
const
discardAllChanges
=
({
state
,
commit
,
dispatch
})
=>
{
state
.
changedFiles
.
forEach
(
file
=>
{
...
...
@@ -43,14 +42,11 @@ export const createTempEntry = (
)
=>
new
Promise
(
resolve
=>
{
const
worker
=
new
FilesDecoratorWorker
();
const
fullName
=
name
.
slice
(
-
1
)
!==
'
/
'
&&
type
===
'
tree
'
?
`
${
name
}
/`
:
name
;
const
fullName
=
name
.
slice
(
-
1
)
!==
'
/
'
&&
type
===
'
tree
'
?
`
${
name
}
/`
:
name
;
if
(
state
.
entries
[
name
])
{
flash
(
`The name "
${
name
.
split
(
'
/
'
)
.
pop
()}
" is already taken in this directory.`
,
`The name "
${
name
.
split
(
'
/
'
).
pop
()}
" is already taken in this directory.`
,
'
alert
'
,
document
,
null
,
...
...
@@ -119,3 +115,4 @@ export const updateDelayViewerUpdated = ({ commit }, delay) => {
export
*
from
'
./actions/tree
'
;
export
*
from
'
./actions/file
'
;
export
*
from
'
./actions/project
'
;
export
*
from
'
./actions/merge_request
'
;
app/assets/javascripts/ide/stores/actions/file.js
View file @
4410a1fa
...
...
@@ -46,53 +46,63 @@ export const setFileActive = ({ commit, state, getters, dispatch }, path) => {
commit
(
types
.
SET_CURRENT_BRANCH
,
file
.
branchId
);
};
export
const
getFileData
=
({
state
,
commit
,
dispatch
},
file
)
=>
{
export
const
getFileData
=
({
state
,
commit
,
dispatch
},
{
path
,
makeFileActive
=
true
})
=>
{
const
file
=
state
.
entries
[
path
];
commit
(
types
.
TOGGLE_LOADING
,
{
entry
:
file
});
return
service
.
getFileData
(
file
.
url
)
.
then
(
res
=>
{
const
pageTitle
=
decodeURI
(
normalizeHeaders
(
res
.
headers
)[
'
PAGE-TITLE
'
]);
setPageTitle
(
pageTitle
);
return
res
.
json
();
})
.
then
(
data
=>
{
commit
(
types
.
SET_FILE_DATA
,
{
data
,
file
});
commit
(
types
.
TOGGLE_FILE_OPEN
,
file
.
path
);
dispatch
(
'
setFileActive
'
,
file
.
path
);
commit
(
types
.
TOGGLE_FILE_OPEN
,
path
);
if
(
makeFileActive
)
dispatch
(
'
setFileActive
'
,
path
);
commit
(
types
.
TOGGLE_LOADING
,
{
entry
:
file
});
})
.
catch
(()
=>
{
commit
(
types
.
TOGGLE_LOADING
,
{
entry
:
file
});
flash
(
'
Error loading file data. Please try again.
'
,
'
alert
'
,
document
,
null
,
false
,
true
,
);
flash
(
'
Error loading file data. Please try again.
'
,
'
alert
'
,
document
,
null
,
false
,
true
);
});
};
export
const
getRawFileData
=
({
commit
,
dispatch
},
file
)
=>
service
.
getRawFileData
(
file
)
.
then
(
raw
=>
{
commit
(
types
.
SET_FILE_RAW_DATA
,
{
file
,
raw
});
})
.
catch
(()
=>
flash
(
'
Error loading file content. Please try again.
'
,
'
alert
'
,
document
,
null
,
false
,
true
,
),
);
export
const
setFileMrChange
=
({
state
,
commit
},
{
file
,
mrChange
})
=>
{
commit
(
types
.
SET_FILE_MERGE_REQUEST_CHANGE
,
{
file
,
mrChange
});
};
export
const
getRawFileData
=
({
state
,
commit
,
dispatch
},
{
path
,
baseSha
})
=>
{
const
file
=
state
.
entries
[
path
];
return
new
Promise
((
resolve
,
reject
)
=>
{
service
.
getRawFileData
(
file
)
.
then
(
raw
=>
{
commit
(
types
.
SET_FILE_RAW_DATA
,
{
file
,
raw
});
if
(
file
.
mrChange
&&
file
.
mrChange
.
new_file
===
false
)
{
service
.
getBaseRawFileData
(
file
,
baseSha
)
.
then
(
baseRaw
=>
{
commit
(
types
.
SET_FILE_BASE_RAW_DATA
,
{
file
,
baseRaw
,
});
resolve
(
raw
);
})
.
catch
(
e
=>
{
reject
(
e
);
});
}
else
{
resolve
(
raw
);
}
})
.
catch
(()
=>
{
flash
(
'
Error loading file content. Please try again.
'
);
reject
();
});
});
};
export
const
changeFileContent
=
({
state
,
commit
},
{
path
,
content
})
=>
{
const
file
=
state
.
entries
[
path
];
...
...
@@ -119,10 +129,7 @@ export const setFileEOL = ({ getters, commit }, { eol }) => {
}
};
export
const
setEditorPosition
=
(
{
getters
,
commit
},
{
editorRow
,
editorColumn
},
)
=>
{
export
const
setEditorPosition
=
({
getters
,
commit
},
{
editorRow
,
editorColumn
})
=>
{
if
(
getters
.
activeFile
)
{
commit
(
types
.
SET_FILE_POSITION
,
{
file
:
getters
.
activeFile
,
...
...
app/assets/javascripts/ide/stores/actions/merge_request.js
0 → 100644
View file @
4410a1fa
import
flash
from
'
~/flash
'
;
import
service
from
'
../../services
'
;
import
*
as
types
from
'
../mutation_types
'
;
export
const
getMergeRequestData
=
(
{
commit
,
state
,
dispatch
},
{
projectId
,
mergeRequestId
,
force
=
false
}
=
{},
)
=>
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
state
.
projects
[
projectId
].
mergeRequests
[
mergeRequestId
]
||
force
)
{
service
.
getProjectMergeRequestData
(
projectId
,
mergeRequestId
)
.
then
(
res
=>
res
.
data
)
.
then
(
data
=>
{
commit
(
types
.
SET_MERGE_REQUEST
,
{
projectPath
:
projectId
,
mergeRequestId
,
mergeRequest
:
data
,
});
if
(
!
state
.
currentMergeRequestId
)
{
commit
(
types
.
SET_CURRENT_MERGE_REQUEST
,
mergeRequestId
);
}
resolve
(
data
);
})
.
catch
(()
=>
{
flash
(
'
Error loading merge request data. Please try again.
'
);
reject
(
new
Error
(
`Merge Request not loaded
${
projectId
}
`
));
});
}
else
{
resolve
(
state
.
projects
[
projectId
].
mergeRequests
[
mergeRequestId
]);
}
});
export
const
getMergeRequestChanges
=
(
{
commit
,
state
,
dispatch
},
{
projectId
,
mergeRequestId
,
force
=
false
}
=
{},
)
=>
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
state
.
projects
[
projectId
].
mergeRequests
[
mergeRequestId
].
changes
.
length
||
force
)
{
service
.
getProjectMergeRequestChanges
(
projectId
,
mergeRequestId
)
.
then
(
res
=>
res
.
data
)
.
then
(
data
=>
{
commit
(
types
.
SET_MERGE_REQUEST_CHANGES
,
{
projectPath
:
projectId
,
mergeRequestId
,
changes
:
data
,
});
resolve
(
data
);
})
.
catch
(()
=>
{
flash
(
'
Error loading merge request changes. Please try again.
'
);
reject
(
new
Error
(
`Merge Request Changes not loaded
${
projectId
}
`
));
});
}
else
{
resolve
(
state
.
projects
[
projectId
].
mergeRequests
[
mergeRequestId
].
changes
);
}
});
export
const
getMergeRequestVersions
=
(
{
commit
,
state
,
dispatch
},
{
projectId
,
mergeRequestId
,
force
=
false
}
=
{},
)
=>
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
state
.
projects
[
projectId
].
mergeRequests
[
mergeRequestId
].
versions
.
length
||
force
)
{
service
.
getProjectMergeRequestVersions
(
projectId
,
mergeRequestId
)
.
then
(
res
=>
res
.
data
)
.
then
(
data
=>
{
commit
(
types
.
SET_MERGE_REQUEST_VERSIONS
,
{
projectPath
:
projectId
,
mergeRequestId
,
versions
:
data
,
});
resolve
(
data
);
})
.
catch
(()
=>
{
flash
(
'
Error loading merge request versions. Please try again.
'
);
reject
(
new
Error
(
`Merge Request Versions not loaded
${
projectId
}
`
));
});
}
else
{
resolve
(
state
.
projects
[
projectId
].
mergeRequests
[
mergeRequestId
].
versions
);
}
});
app/assets/javascripts/ide/stores/actions/tree.js
View file @
4410a1fa
...
...
@@ -2,9 +2,7 @@ import { normalizeHeaders } from '~/lib/utils/common_utils';
import
flash
from
'
~/flash
'
;
import
service
from
'
../../services
'
;
import
*
as
types
from
'
../mutation_types
'
;
import
{
findEntry
,
}
from
'
../utils
'
;
import
{
findEntry
}
from
'
../utils
'
;
import
FilesDecoratorWorker
from
'
../workers/files_decorator_worker
'
;
export
const
toggleTreeOpen
=
({
commit
,
dispatch
},
path
)
=>
{
...
...
@@ -21,23 +19,24 @@ export const handleTreeEntryAction = ({ commit, dispatch }, row) => {
dispatch
(
'
setFileActive
'
,
row
.
path
);
}
else
{
dispatch
(
'
getFileData
'
,
row
);
dispatch
(
'
getFileData
'
,
{
path
:
row
.
path
}
);
}
};
export
const
getLastCommitData
=
({
state
,
commit
,
dispatch
,
getters
},
tree
=
state
)
=>
{
if
(
!
tree
||
tree
.
lastCommitPath
===
null
||
!
tree
.
lastCommitPath
)
return
;
service
.
getTreeLastCommit
(
tree
.
lastCommitPath
)
.
then
((
res
)
=>
{
service
.
getTreeLastCommit
(
tree
.
lastCommitPath
)
.
then
(
res
=>
{
const
lastCommitPath
=
normalizeHeaders
(
res
.
headers
)[
'
MORE-LOGS-URL
'
]
||
null
;
commit
(
types
.
SET_LAST_COMMIT_URL
,
{
tree
,
url
:
lastCommitPath
});
return
res
.
json
();
})
.
then
(
(
data
)
=>
{
data
.
forEach
(
(
lastCommit
)
=>
{
.
then
(
data
=>
{
data
.
forEach
(
lastCommit
=>
{
const
entry
=
findEntry
(
tree
.
tree
,
lastCommit
.
type
,
lastCommit
.
file_name
);
if
(
entry
)
{
...
...
@@ -50,44 +49,47 @@ export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = s
.
catch
(()
=>
flash
(
'
Error fetching log data.
'
,
'
alert
'
,
document
,
null
,
false
,
true
));
};
export
const
getFiles
=
(
{
state
,
commit
,
dispatch
},
{
projectId
,
branchId
}
=
{},
)
=>
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
state
.
trees
[
`
${
projectId
}
/
${
branchId
}
`
])
{
const
selectedProject
=
state
.
projects
[
projectId
];
commit
(
types
.
CREATE_TREE
,
{
treePath
:
`
${
projectId
}
/
${
branchId
}
`
});
service
.
getFiles
(
selectedProject
.
web_url
,
branchId
)
.
then
(
res
=>
res
.
json
())
.
then
((
data
)
=>
{
const
worker
=
new
FilesDecoratorWorker
();
worker
.
addEventListener
(
'
message
'
,
(
e
)
=>
{
const
{
entries
,
treeList
}
=
e
.
data
;
const
selectedTree
=
state
.
trees
[
`
${
projectId
}
/
${
branchId
}
`
];
commit
(
types
.
SET_ENTRIES
,
entries
);
commit
(
types
.
SET_DIRECTORY_DATA
,
{
treePath
:
`
${
projectId
}
/
${
branchId
}
`
,
data
:
treeList
});
commit
(
types
.
TOGGLE_LOADING
,
{
entry
:
selectedTree
,
forceValue
:
false
});
worker
.
terminate
();
resolve
();
});
worker
.
postMessage
({
data
,
projectId
,
branchId
,
export
const
getFiles
=
({
state
,
commit
,
dispatch
},
{
projectId
,
branchId
}
=
{})
=>
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
state
.
trees
[
`
${
projectId
}
/
${
branchId
}
`
])
{
const
selectedProject
=
state
.
projects
[
projectId
];
commit
(
types
.
CREATE_TREE
,
{
treePath
:
`
${
projectId
}
/
${
branchId
}
`
});
service
.
getFiles
(
selectedProject
.
web_url
,
branchId
)
.
then
(
res
=>
res
.
json
())
.
then
(
data
=>
{
const
worker
=
new
FilesDecoratorWorker
();
worker
.
addEventListener
(
'
message
'
,
e
=>
{
const
{
entries
,
treeList
}
=
e
.
data
;
const
selectedTree
=
state
.
trees
[
`
${
projectId
}
/
${
branchId
}
`
];
commit
(
types
.
SET_ENTRIES
,
entries
);
commit
(
types
.
SET_DIRECTORY_DATA
,
{
treePath
:
`
${
projectId
}
/
${
branchId
}
`
,
data
:
treeList
,
});
commit
(
types
.
TOGGLE_LOADING
,
{
entry
:
selectedTree
,
forceValue
:
false
,
});
worker
.
terminate
();
resolve
();
});
worker
.
postMessage
({
data
,
projectId
,
branchId
,
});
})
.
catch
(
e
=>
{
flash
(
'
Error loading tree data. Please try again.
'
,
'
alert
'
,
document
,
null
,
false
,
true
);
reject
(
e
);
});
})
.
catch
((
e
)
=>
{
flash
(
'
Error loading tree data. Please try again.
'
,
'
alert
'
,
document
,
null
,
false
,
true
);
reject
(
e
);
});
}
else
{
resolve
();
}
});
}
else
{
resolve
();
}
});
app/assets/javascripts/ide/stores/getters.js
View file @
4410a1fa
export
const
activeFile
=
state
=>
state
.
openFiles
.
find
(
file
=>
file
.
active
)
||
null
;
export
const
activeFile
=
state
=>
state
.
openFiles
.
find
(
file
=>
file
.
active
)
||
null
;
export
const
addedFiles
=
state
=>
state
.
changedFiles
.
filter
(
f
=>
f
.
tempFile
);
export
const
modifiedFiles
=
state
=>
state
.
changedFiles
.
filter
(
f
=>
!
f
.
tempFile
);
export
const
modifiedFiles
=
state
=>
state
.
changedFiles
.
filter
(
f
=>
!
f
.
tempFile
);
export
const
projectsWithTrees
=
state
=>
Object
.
keys
(
state
.
projects
).
map
(
projectId
=>
{
...
...
@@ -23,8 +21,17 @@ export const projectsWithTrees = state =>
};
});
export
const
currentMergeRequest
=
state
=>
{
if
(
state
.
projects
[
state
.
currentProjectId
])
{
return
state
.
projects
[
state
.
currentProjectId
].
mergeRequests
[
state
.
currentMergeRequestId
];
}
return
null
;
};
// eslint-disable-next-line no-confusing-arrow
export
const
currentIcon
=
state
=>
state
.
rightPanelCollapsed
?
'
angle-double-left
'
:
'
angle-double-right
'
;
export
const
hasChanges
=
state
=>
!!
state
.
changedFiles
.
length
;
export
const
hasMergeRequest
=
state
=>
!!
state
.
currentMergeRequestId
;
app/assets/javascripts/ide/stores/mutation_types.js
View file @
4410a1fa
...
...
@@ -11,6 +11,12 @@ export const SET_PROJECT = 'SET_PROJECT';
export
const
SET_CURRENT_PROJECT
=
'
SET_CURRENT_PROJECT
'
;
export
const
TOGGLE_PROJECT_OPEN
=
'
TOGGLE_PROJECT_OPEN
'
;
// Merge Request Mutation Types
export
const
SET_MERGE_REQUEST
=
'
SET_MERGE_REQUEST
'
;
export
const
SET_CURRENT_MERGE_REQUEST
=
'
SET_CURRENT_MERGE_REQUEST
'
;
export
const
SET_MERGE_REQUEST_CHANGES
=
'
SET_MERGE_REQUEST_CHANGES
'
;
export
const
SET_MERGE_REQUEST_VERSIONS
=
'
SET_MERGE_REQUEST_VERSIONS
'
;
// Branch Mutation Types
export
const
SET_BRANCH
=
'
SET_BRANCH
'
;
export
const
SET_BRANCH_WORKING_REFERENCE
=
'
SET_BRANCH_WORKING_REFERENCE
'
;
...
...
@@ -28,6 +34,7 @@ export const SET_FILE_DATA = 'SET_FILE_DATA';
export
const
TOGGLE_FILE_OPEN
=
'
TOGGLE_FILE_OPEN
'
;
export
const
SET_FILE_ACTIVE
=
'
SET_FILE_ACTIVE
'
;
export
const
SET_FILE_RAW_DATA
=
'
SET_FILE_RAW_DATA
'
;
export
const
SET_FILE_BASE_RAW_DATA
=
'
SET_FILE_BASE_RAW_DATA
'
;
export
const
UPDATE_FILE_CONTENT
=
'
UPDATE_FILE_CONTENT
'
;
export
const
SET_FILE_LANGUAGE
=
'
SET_FILE_LANGUAGE
'
;
export
const
SET_FILE_POSITION
=
'
SET_FILE_POSITION
'
;
...
...
@@ -39,5 +46,6 @@ export const TOGGLE_FILE_CHANGED = 'TOGGLE_FILE_CHANGED';
export
const
SET_CURRENT_BRANCH
=
'
SET_CURRENT_BRANCH
'
;
export
const
SET_ENTRIES
=
'
SET_ENTRIES
'
;
export
const
CREATE_TMP_ENTRY
=
'
CREATE_TMP_ENTRY
'
;
export
const
SET_FILE_MERGE_REQUEST_CHANGE
=
'
SET_FILE_MERGE_REQUEST_CHANGE
'
;
export
const
UPDATE_VIEWER
=
'
UPDATE_VIEWER
'
;
export
const
UPDATE_DELAY_VIEWER_CHANGE
=
'
UPDATE_DELAY_VIEWER_CHANGE
'
;
app/assets/javascripts/ide/stores/mutations.js
View file @
4410a1fa
import
*
as
types
from
'
./mutation_types
'
;
import
projectMutations
from
'
./mutations/project
'
;
import
mergeRequestMutation
from
'
./mutations/merge_request
'
;
import
fileMutations
from
'
./mutations/file
'
;
import
treeMutations
from
'
./mutations/tree
'
;
import
branchMutations
from
'
./mutations/branch
'
;
...
...
@@ -11,10 +12,7 @@ export default {
[
types
.
TOGGLE_LOADING
](
state
,
{
entry
,
forceValue
=
undefined
})
{
if
(
entry
.
path
)
{
Object
.
assign
(
state
.
entries
[
entry
.
path
],
{
loading
:
forceValue
!==
undefined
?
forceValue
:
!
state
.
entries
[
entry
.
path
].
loading
,
loading
:
forceValue
!==
undefined
?
forceValue
:
!
state
.
entries
[
entry
.
path
].
loading
,
});
}
else
{
Object
.
assign
(
entry
,
{
...
...
@@ -83,9 +81,7 @@ export default {
if
(
!
foundEntry
)
{
Object
.
assign
(
state
.
trees
[
`
${
projectId
}
/
${
branchId
}
`
],
{
tree
:
state
.
trees
[
`
${
projectId
}
/
${
branchId
}
`
].
tree
.
concat
(
data
.
treeList
,
),
tree
:
state
.
trees
[
`
${
projectId
}
/
${
branchId
}
`
].
tree
.
concat
(
data
.
treeList
),
});
}
},
...
...
@@ -100,6 +96,7 @@ export default {
});
},
...
projectMutations
,
...
mergeRequestMutation
,
...
fileMutations
,
...
treeMutations
,
...
branchMutations
,
...
...
app/assets/javascripts/ide/stores/mutations/file.js
View file @
4410a1fa
...
...
@@ -28,6 +28,8 @@ export default {
rawPath
:
data
.
raw_path
,
binary
:
data
.
binary
,
renderError
:
data
.
render_error
,
raw
:
null
,
baseRaw
:
null
,
});
},
[
types
.
SET_FILE_RAW_DATA
](
state
,
{
file
,
raw
})
{
...
...
@@ -35,6 +37,11 @@ export default {
raw
,
});
},
[
types
.
SET_FILE_BASE_RAW_DATA
](
state
,
{
file
,
baseRaw
})
{
Object
.
assign
(
state
.
entries
[
file
.
path
],
{
baseRaw
,
});
},
[
types
.
UPDATE_FILE_CONTENT
](
state
,
{
path
,
content
})
{
const
changed
=
content
!==
state
.
entries
[
path
].
raw
;
...
...
@@ -59,6 +66,11 @@ export default {
editorColumn
,
});
},
[
types
.
SET_FILE_MERGE_REQUEST_CHANGE
](
state
,
{
file
,
mrChange
})
{
Object
.
assign
(
state
.
entries
[
file
.
path
],
{
mrChange
,
});
},
[
types
.
DISCARD_FILE_CHANGES
](
state
,
path
)
{
Object
.
assign
(
state
.
entries
[
path
],
{
content
:
state
.
entries
[
path
].
raw
,
...
...
app/assets/javascripts/ide/stores/mutations/merge_request.js
0 → 100644
View file @
4410a1fa
import
*
as
types
from
'
../mutation_types
'
;
export
default
{
[
types
.
SET_CURRENT_MERGE_REQUEST
](
state
,
currentMergeRequestId
)
{
Object
.
assign
(
state
,
{
currentMergeRequestId
,
});
},
[
types
.
SET_MERGE_REQUEST
](
state
,
{
projectPath
,
mergeRequestId
,
mergeRequest
})
{
Object
.
assign
(
state
.
projects
[
projectPath
],
{
mergeRequests
:
{
[
mergeRequestId
]:
{
...
mergeRequest
,
active
:
true
,
changes
:
[],
versions
:
[],
baseCommitSha
:
null
,
},
},
});
},
[
types
.
SET_MERGE_REQUEST_CHANGES
](
state
,
{
projectPath
,
mergeRequestId
,
changes
})
{
Object
.
assign
(
state
.
projects
[
projectPath
].
mergeRequests
[
mergeRequestId
],
{
changes
,
});
},
[
types
.
SET_MERGE_REQUEST_VERSIONS
](
state
,
{
projectPath
,
mergeRequestId
,
versions
})
{
Object
.
assign
(
state
.
projects
[
projectPath
].
mergeRequests
[
mergeRequestId
],
{
versions
,
baseCommitSha
:
versions
.
length
?
versions
[
0
].
base_commit_sha
:
null
,
});
},
};
app/assets/javascripts/ide/stores/mutations/project.js
View file @
4410a1fa
...
...
@@ -11,6 +11,7 @@ export default {
Object
.
assign
(
project
,
{
tree
:
[],
branches
:
{},
mergeRequests
:
{},
active
:
true
,
});
...
...
app/assets/javascripts/ide/stores/state.js
View file @
4410a1fa
export
default
()
=>
({
currentProjectId
:
''
,
currentBranchId
:
''
,
currentMergeRequestId
:
''
,
changedFiles
:
[],
endpoints
:
{},
lastCommitMsg
:
''
,
...
...
app/assets/javascripts/ide/stores/utils.js
View file @
4410a1fa
...
...
@@ -38,7 +38,7 @@ export const dataStructure = () => ({
eol
:
''
,
});
export
const
decorateData
=
(
entity
)
=>
{
export
const
decorateData
=
entity
=>
{
const
{
id
,
projectId
,
...
...
@@ -57,7 +57,6 @@ export const decorateData = (entity) => {
base64
=
false
,
file_lock
,
}
=
entity
;
return
{
...
...
@@ -80,17 +79,15 @@ export const decorateData = (entity) => {
base64
,
file_lock
,
};
};
export
const
findEntry
=
(
tree
,
type
,
name
,
prop
=
'
name
'
)
=>
tree
.
find
(
f
=>
f
.
type
===
type
&&
f
[
prop
]
===
name
,
);
export
const
findEntry
=
(
tree
,
type
,
name
,
prop
=
'
name
'
)
=>
tree
.
find
(
f
=>
f
.
type
===
type
&&
f
[
prop
]
===
name
);
export
const
findIndexOfFile
=
(
state
,
file
)
=>
state
.
findIndex
(
f
=>
f
.
path
===
file
.
path
);
export
const
setPageTitle
=
(
title
)
=>
{
export
const
setPageTitle
=
title
=>
{
document
.
title
=
title
;
};
...
...
@@ -120,6 +117,11 @@ const sortTreesByTypeAndName = (a, b) => {
return
0
;
};
export
const
sortTree
=
sortedTree
=>
sortedTree
.
map
(
entity
=>
Object
.
assign
(
entity
,
{
tree
:
entity
.
tree
.
length
?
sortTree
(
entity
.
tree
)
:
[],
})).
sort
(
sortTreesByTypeAndName
);
export
const
sortTree
=
sortedTree
=>
sortedTree
.
map
(
entity
=>
Object
.
assign
(
entity
,
{
tree
:
entity
.
tree
.
length
?
sortTree
(
entity
.
tree
)
:
[],
}),
)
.
sort
(
sortTreesByTypeAndName
);
app/assets/javascripts/lib/utils/url_utility.js
View file @
4410a1fa
...
...
@@ -51,7 +51,7 @@ export function removeParams(params) {
const
url
=
document
.
createElement
(
'
a
'
);
url
.
href
=
window
.
location
.
href
;
params
.
forEach
(
(
param
)
=>
{
params
.
forEach
(
param
=>
{
url
.
search
=
removeParamQueryString
(
url
.
search
,
param
);
});
...
...
@@ -83,3 +83,11 @@ export function refreshCurrentPage() {
export
function
redirectTo
(
url
)
{
return
window
.
location
.
assign
(
url
);
}
export
function
webIDEUrl
(
projectUrl
=
undefined
)
{
let
returnUrl
=
`
${
gon
.
relative_url_root
}
/-/ide/`
;
if
(
projectUrl
)
{
returnUrl
+=
`project
${
projectUrl
}
`
;
}
return
returnUrl
;
}
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
View file @
4410a1fa
<
script
>
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
{
n__
}
from
'
~/locale
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
clipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
{
n__
}
from
'
~/locale
'
;
import
{
webIDEUrl
}
from
'
~/lib/utils/url_utility
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
clipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
export
default
{
name
:
'
MRWidgetHeader
'
,
directives
:
{
tooltip
,
export
default
{
name
:
'
MRWidgetHeader
'
,
directives
:
{
tooltip
,
},
components
:
{
icon
,
clipboardButton
,
},
props
:
{
mr
:
{
type
:
Object
,
required
:
true
,
},
components
:
{
icon
,
clipboardButton
,
},
computed
:
{
shouldShowCommitsBehindText
()
{
return
this
.
mr
.
divergedCommitsCount
>
0
;
},
props
:
{
mr
:
{
type
:
Object
,
required
:
true
,
},
commitsText
()
{
return
n__
(
'
%d commit behind
'
,
'
%d commits behind
'
,
this
.
mr
.
divergedCommitsCount
);
},
computed
:
{
shouldShowCommitsBehindText
()
{
return
this
.
mr
.
divergedCommitsCount
>
0
;
},
commitsText
()
{
return
n__
(
'
%d commit behind
'
,
'
%d commits behind
'
,
this
.
mr
.
divergedCommitsCount
);
},
branchNameClipboardData
()
{
// This supports code in app/assets/javascripts/copy_to_clipboard.js that
// works around ClipboardJS limitations to allow the context-specific
// copy/pasting of plain text or GFM.
return
JSON
.
stringify
({
text
:
this
.
mr
.
sourceBranch
,
gfm
:
`\`
${
this
.
mr
.
sourceBranch
}
\``
,
});
},
isSourceBranchLong
()
{
return
this
.
isBranchTitleLong
(
this
.
mr
.
sourceBranch
);
},
isTargetBranchLong
()
{
return
this
.
isBranchTitleLong
(
this
.
mr
.
targetBranch
);
},
branchNameClipboardData
()
{
// This supports code in app/assets/javascripts/copy_to_clipboard.js that
// works around ClipboardJS limitations to allow the context-specific
// copy/pasting of plain text or GFM.
return
JSON
.
stringify
({
text
:
this
.
mr
.
sourceBranch
,
gfm
:
`\`
${
this
.
mr
.
sourceBranch
}
\``
,
});
},
methods
:
{
isBranchTitleLong
(
branchTitle
)
{
return
branchTitle
.
length
>
32
;
},
isSourceBranchLong
()
{
return
this
.
isBranchTitleLong
(
this
.
mr
.
sourceBranch
);
},
};
isTargetBranchLong
()
{
return
this
.
isBranchTitleLong
(
this
.
mr
.
targetBranch
);
},
webIdePath
()
{
return
webIDEUrl
(
this
.
mr
.
statusPath
.
replace
(
'
.json
'
,
''
));
},
},
methods
:
{
isBranchTitleLong
(
branchTitle
)
{
return
branchTitle
.
length
>
32
;
},
},
};
</
script
>
<
template
>
<div
class=
"mr-source-target"
>
...
...
@@ -96,6 +100,13 @@
</div>
<div
v-if=
"mr.isOpen"
>
<a
v-if=
"!mr.sourceBranchRemoved"
:href=
"webIdePath"
class=
"btn btn-sm btn-default inline js-web-ide"
>
{{
s__
(
"
mrWidget|Web IDE
"
)
}}
</a>
<button
data-target=
"#modal_merge_info"
data-toggle=
"modal"
...
...
app/assets/stylesheets/pages/repo.scss
View file @
4410a1fa
...
...
@@ -50,6 +50,7 @@
flex
:
1
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
max-width
:
inherit
;
svg
{
vertical-align
:
middle
;
...
...
@@ -720,9 +721,7 @@
}
.ide-view
{
height
:
calc
(
100vh
-
#{
$header-height
+
$performance-bar-height
+
$flash-height
}
);
height
:
calc
(
100vh
-
#{
$header-height
+
$performance-bar-height
+
$flash-height
}
);
}
}
}
...
...
spec/javascripts/api_spec.js
View file @
4410a1fa
...
...
@@ -35,14 +35,14 @@ describe('Api', () => {
});
describe
(
'
group
'
,
()
=>
{
it
(
'
fetches a group
'
,
(
done
)
=>
{
it
(
'
fetches a group
'
,
done
=>
{
const
groupId
=
'
123456
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/groups/
${
groupId
}
`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
{
name
:
'
test
'
,
});
Api
.
group
(
groupId
,
(
response
)
=>
{
Api
.
group
(
groupId
,
response
=>
{
expect
(
response
.
name
).
toBe
(
'
test
'
);
done
();
});
...
...
@@ -50,15 +50,17 @@ describe('Api', () => {
});
describe
(
'
groups
'
,
()
=>
{
it
(
'
fetches groups
'
,
(
done
)
=>
{
it
(
'
fetches groups
'
,
done
=>
{
const
query
=
'
dummy query
'
;
const
options
=
{
unused
:
'
option
'
};
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/groups.json`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[{
name
:
'
test
'
,
}]);
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[
{
name
:
'
test
'
,
},
]);
Api
.
groups
(
query
,
options
,
(
response
)
=>
{
Api
.
groups
(
query
,
options
,
response
=>
{
expect
(
response
.
length
).
toBe
(
1
);
expect
(
response
[
0
].
name
).
toBe
(
'
test
'
);
done
();
...
...
@@ -67,14 +69,16 @@ describe('Api', () => {
});
describe
(
'
namespaces
'
,
()
=>
{
it
(
'
fetches namespaces
'
,
(
done
)
=>
{
it
(
'
fetches namespaces
'
,
done
=>
{
const
query
=
'
dummy query
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/namespaces.json`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[{
name
:
'
test
'
,
}]);
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[
{
name
:
'
test
'
,
},
]);
Api
.
namespaces
(
query
,
(
response
)
=>
{
Api
.
namespaces
(
query
,
response
=>
{
expect
(
response
.
length
).
toBe
(
1
);
expect
(
response
[
0
].
name
).
toBe
(
'
test
'
);
done
();
...
...
@@ -83,31 +87,35 @@ describe('Api', () => {
});
describe
(
'
projects
'
,
()
=>
{
it
(
'
fetches projects with membership when logged in
'
,
(
done
)
=>
{
it
(
'
fetches projects with membership when logged in
'
,
done
=>
{
const
query
=
'
dummy query
'
;
const
options
=
{
unused
:
'
option
'
};
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/projects.json`
;
window
.
gon
.
current_user_id
=
1
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[{
name
:
'
test
'
,
}]);
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[
{
name
:
'
test
'
,
},
]);
Api
.
projects
(
query
,
options
,
(
response
)
=>
{
Api
.
projects
(
query
,
options
,
response
=>
{
expect
(
response
.
length
).
toBe
(
1
);
expect
(
response
[
0
].
name
).
toBe
(
'
test
'
);
done
();
});
});
it
(
'
fetches projects without membership when not logged in
'
,
(
done
)
=>
{
it
(
'
fetches projects without membership when not logged in
'
,
done
=>
{
const
query
=
'
dummy query
'
;
const
options
=
{
unused
:
'
option
'
};
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/projects.json`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[{
name
:
'
test
'
,
}]);
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[
{
name
:
'
test
'
,
},
]);
Api
.
projects
(
query
,
options
,
(
response
)
=>
{
Api
.
projects
(
query
,
options
,
response
=>
{
expect
(
response
.
length
).
toBe
(
1
);
expect
(
response
[
0
].
name
).
toBe
(
'
test
'
);
done
();
...
...
@@ -115,8 +123,65 @@ describe('Api', () => {
});
});
describe
(
'
mergerequest
'
,
()
=>
{
it
(
'
fetches a merge request
'
,
done
=>
{
const
projectPath
=
'
abc
'
;
const
mergeRequestId
=
'
123456
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/projects/
${
projectPath
}
/merge_requests/
${
mergeRequestId
}
`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
{
title
:
'
test
'
,
});
Api
.
mergeRequest
(
projectPath
,
mergeRequestId
)
.
then
(({
data
})
=>
{
expect
(
data
.
title
).
toBe
(
'
test
'
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
describe
(
'
mergerequest changes
'
,
()
=>
{
it
(
'
fetches the changes of a merge request
'
,
done
=>
{
const
projectPath
=
'
abc
'
;
const
mergeRequestId
=
'
123456
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/projects/
${
projectPath
}
/merge_requests/
${
mergeRequestId
}
/changes`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
{
title
:
'
test
'
,
});
Api
.
mergeRequestChanges
(
projectPath
,
mergeRequestId
)
.
then
(({
data
})
=>
{
expect
(
data
.
title
).
toBe
(
'
test
'
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
describe
(
'
mergerequest versions
'
,
()
=>
{
it
(
'
fetches the versions of a merge request
'
,
done
=>
{
const
projectPath
=
'
abc
'
;
const
mergeRequestId
=
'
123456
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/projects/
${
projectPath
}
/merge_requests/
${
mergeRequestId
}
/versions`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[
{
id
:
123
,
},
]);
Api
.
mergeRequestVersions
(
projectPath
,
mergeRequestId
)
.
then
(({
data
})
=>
{
expect
(
data
.
length
).
toBe
(
1
);
expect
(
data
[
0
].
id
).
toBe
(
123
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
describe
(
'
newLabel
'
,
()
=>
{
it
(
'
creates a new label
'
,
(
done
)
=>
{
it
(
'
creates a new label
'
,
done
=>
{
const
namespace
=
'
some namespace
'
;
const
project
=
'
some project
'
;
const
labelData
=
{
some
:
'
data
'
};
...
...
@@ -124,36 +189,42 @@ describe('Api', () => {
const
expectedData
=
{
label
:
labelData
,
};
mock
.
onPost
(
expectedUrl
).
reply
(
(
config
)
=>
{
mock
.
onPost
(
expectedUrl
).
reply
(
config
=>
{
expect
(
config
.
data
).
toBe
(
JSON
.
stringify
(
expectedData
));
return
[
200
,
{
name
:
'
test
'
,
}];
return
[
200
,
{
name
:
'
test
'
,
},
];
});
Api
.
newLabel
(
namespace
,
project
,
labelData
,
(
response
)
=>
{
Api
.
newLabel
(
namespace
,
project
,
labelData
,
response
=>
{
expect
(
response
.
name
).
toBe
(
'
test
'
);
done
();
});
});
it
(
'
creates a
new group label
'
,
(
done
)
=>
{
const
namespace
=
'
some namespace
'
;
it
(
'
creates a
group label
'
,
done
=>
{
const
namespace
=
'
group/subgroup
'
;
const
labelData
=
{
some
:
'
data
'
};
const
expectedUrl
=
Api
.
buildUrl
(
Api
.
groupLabelsPath
).
replace
(
'
:namespace_path
'
,
namespace
);
const
expectedData
=
{
label
:
labelData
,
};
mock
.
onPost
(
expectedUrl
).
reply
(
(
config
)
=>
{
mock
.
onPost
(
expectedUrl
).
reply
(
config
=>
{
expect
(
config
.
data
).
toBe
(
JSON
.
stringify
(
expectedData
));
return
[
200
,
{
name
:
'
test
'
,
}];
return
[
200
,
{
name
:
'
test
'
,
},
];
});
Api
.
newLabel
(
namespace
,
null
,
labelData
,
(
response
)
=>
{
Api
.
newLabel
(
namespace
,
undefined
,
labelData
,
response
=>
{
expect
(
response
.
name
).
toBe
(
'
test
'
);
done
();
});
...
...
@@ -161,15 +232,17 @@ describe('Api', () => {
});
describe
(
'
groupProjects
'
,
()
=>
{
it
(
'
fetches group projects
'
,
(
done
)
=>
{
it
(
'
fetches group projects
'
,
done
=>
{
const
groupId
=
'
123456
'
;
const
query
=
'
dummy query
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/groups/
${
groupId
}
/projects.json`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[{
name
:
'
test
'
,
}]);
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[
{
name
:
'
test
'
,
},
]);
Api
.
groupProjects
(
groupId
,
query
,
(
response
)
=>
{
Api
.
groupProjects
(
groupId
,
query
,
response
=>
{
expect
(
response
.
length
).
toBe
(
1
);
expect
(
response
[
0
].
name
).
toBe
(
'
test
'
);
done
();
...
...
@@ -178,13 +251,13 @@ describe('Api', () => {
});
describe
(
'
licenseText
'
,
()
=>
{
it
(
'
fetches a license text
'
,
(
done
)
=>
{
it
(
'
fetches a license text
'
,
done
=>
{
const
licenseKey
=
"
driver's license
"
;
const
data
=
{
unused
:
'
option
'
};
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/templates/licenses/
${
licenseKey
}
`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
'
test
'
);
Api
.
licenseText
(
licenseKey
,
data
,
(
response
)
=>
{
Api
.
licenseText
(
licenseKey
,
data
,
response
=>
{
expect
(
response
).
toBe
(
'
test
'
);
done
();
});
...
...
@@ -192,12 +265,12 @@ describe('Api', () => {
});
describe
(
'
gitignoreText
'
,
()
=>
{
it
(
'
fetches a gitignore text
'
,
(
done
)
=>
{
it
(
'
fetches a gitignore text
'
,
done
=>
{
const
gitignoreKey
=
'
ignore git
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/templates/gitignores/
${
gitignoreKey
}
`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
'
test
'
);
Api
.
gitignoreText
(
gitignoreKey
,
(
response
)
=>
{
Api
.
gitignoreText
(
gitignoreKey
,
response
=>
{
expect
(
response
).
toBe
(
'
test
'
);
done
();
});
...
...
@@ -205,12 +278,12 @@ describe('Api', () => {
});
describe
(
'
gitlabCiYml
'
,
()
=>
{
it
(
'
fetches a .gitlab-ci.yml
'
,
(
done
)
=>
{
it
(
'
fetches a .gitlab-ci.yml
'
,
done
=>
{
const
gitlabCiYmlKey
=
'
Y CI ML
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/templates/gitlab_ci_ymls/
${
gitlabCiYmlKey
}
`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
'
test
'
);
Api
.
gitlabCiYml
(
gitlabCiYmlKey
,
(
response
)
=>
{
Api
.
gitlabCiYml
(
gitlabCiYmlKey
,
response
=>
{
expect
(
response
).
toBe
(
'
test
'
);
done
();
});
...
...
@@ -218,12 +291,12 @@ describe('Api', () => {
});
describe
(
'
dockerfileYml
'
,
()
=>
{
it
(
'
fetches a Dockerfile
'
,
(
done
)
=>
{
it
(
'
fetches a Dockerfile
'
,
done
=>
{
const
dockerfileYmlKey
=
'
a giant whale
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/templates/dockerfiles/
${
dockerfileYmlKey
}
`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
'
test
'
);
Api
.
dockerfileYml
(
dockerfileYmlKey
,
(
response
)
=>
{
Api
.
dockerfileYml
(
dockerfileYmlKey
,
response
=>
{
expect
(
response
).
toBe
(
'
test
'
);
done
();
});
...
...
@@ -231,12 +304,14 @@ describe('Api', () => {
});
describe
(
'
issueTemplate
'
,
()
=>
{
it
(
'
fetches an issue template
'
,
(
done
)
=>
{
it
(
'
fetches an issue template
'
,
done
=>
{
const
namespace
=
'
some namespace
'
;
const
project
=
'
some project
'
;
const
templateKey
=
'
template #%?.key
'
;
const
templateType
=
'
template type
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/
${
namespace
}
/
${
project
}
/templates/
${
templateType
}
/
${
encodeURIComponent
(
templateKey
)}
`
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/
${
namespace
}
/
${
project
}
/templates/
${
templateType
}
/
${
encodeURIComponent
(
templateKey
,
)}
`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
'
test
'
);
Api
.
issueTemplate
(
namespace
,
project
,
templateKey
,
templateType
,
(
error
,
response
)
=>
{
...
...
@@ -247,13 +322,15 @@ describe('Api', () => {
});
describe
(
'
users
'
,
()
=>
{
it
(
'
fetches users
'
,
(
done
)
=>
{
it
(
'
fetches users
'
,
done
=>
{
const
query
=
'
dummy query
'
;
const
options
=
{
unused
:
'
option
'
};
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/users.json`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[{
name
:
'
test
'
,
}]);
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[
{
name
:
'
test
'
,
},
]);
Api
.
users
(
query
,
options
)
.
then
(({
data
})
=>
{
...
...
@@ -266,18 +343,20 @@ describe('Api', () => {
});
describe
(
'
ldap_groups
'
,
()
=>
{
it
(
'
calls callback on completion
'
,
(
done
)
=>
{
it
(
'
calls callback on completion
'
,
done
=>
{
const
query
=
'
query
'
;
const
provider
=
'
provider
'
;
const
callback
=
jasmine
.
createSpy
();
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/ldap/
${
provider
}
/groups.json`
;
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[{
name
:
'
test
'
,
}]);
mock
.
onGet
(
expectedUrl
).
reply
(
200
,
[
{
name
:
'
test
'
,
},
]);
Api
.
ldap_groups
(
query
,
provider
,
callback
)
.
then
(
(
response
)
=>
{
.
then
(
response
=>
{
expect
(
callback
).
toHaveBeenCalledWith
(
response
);
})
.
then
(
done
)
...
...
spec/javascripts/ide/components/changed_file_icon_spec.js
View file @
4410a1fa
...
...
@@ -11,6 +11,7 @@ describe('IDE changed file icon', () => {
vm
=
createComponent
(
component
,
{
file
:
{
tempFile
:
false
,
changed
:
true
,
},
});
});
...
...
@@ -20,7 +21,7 @@ describe('IDE changed file icon', () => {
});
describe
(
'
changedIcon
'
,
()
=>
{
it
(
'
equals file-modified when not a temp file
'
,
()
=>
{
it
(
'
equals file-modified when not a temp file
and has changes
'
,
()
=>
{
expect
(
vm
.
changedIcon
).
toBe
(
'
file-modified
'
);
});
...
...
spec/javascripts/ide/components/repo_editor_spec.js
View file @
4410a1fa
...
...
@@ -89,6 +89,20 @@ describe('RepoEditor', () => {
done
();
});
});
it
(
'
calls createDiffInstance when viewer is a merge request diff
'
,
done
=>
{
vm
.
$store
.
state
.
viewer
=
'
mrdiff
'
;
spyOn
(
vm
.
editor
,
'
createDiffInstance
'
);
vm
.
createEditorInstance
();
vm
.
$nextTick
(()
=>
{
expect
(
vm
.
editor
.
createDiffInstance
).
toHaveBeenCalled
();
done
();
});
});
});
describe
(
'
setupEditor
'
,
()
=>
{
...
...
@@ -134,4 +148,48 @@ describe('RepoEditor', () => {
});
});
});
describe
(
'
setup editor for merge request viewing
'
,
()
=>
{
beforeEach
(
done
=>
{
// Resetting as the main test setup has already done it
vm
.
$destroy
();
resetStore
(
vm
.
$store
);
Editor
.
editorInstance
.
modelManager
.
dispose
();
const
f
=
{
...
file
(),
active
:
true
,
tempFile
:
true
,
html
:
'
testing
'
,
mrChange
:
{
diff
:
'
ABC
'
},
baseRaw
:
'
testing
'
,
content
:
'
test
'
,
};
const
RepoEditor
=
Vue
.
extend
(
repoEditor
);
vm
=
createComponentWithStore
(
RepoEditor
,
store
,
{
file
:
f
,
});
vm
.
$store
.
state
.
openFiles
.
push
(
f
);
vm
.
$store
.
state
.
entries
[
f
.
path
]
=
f
;
vm
.
$store
.
state
.
viewer
=
'
mrdiff
'
;
vm
.
monaco
=
true
;
vm
.
$mount
();
monacoLoader
([
'
vs/editor/editor.main
'
],
()
=>
{
setTimeout
(
done
,
0
);
});
});
it
(
'
attaches merge request model to editor when merge request diff
'
,
()
=>
{
spyOn
(
vm
.
editor
,
'
attachMergeRequestModel
'
).
and
.
callThrough
();
vm
.
setupEditor
();
expect
(
vm
.
editor
.
attachMergeRequestModel
).
toHaveBeenCalledWith
(
vm
.
model
);
});
});
});
spec/javascripts/ide/components/repo_tabs_spec.js
View file @
4410a1fa
...
...
@@ -17,6 +17,7 @@ describe('RepoTabs', () => {
files
:
openedFiles
,
viewer
:
'
editor
'
,
hasChanges
:
false
,
hasMergeRequest
:
false
,
});
openedFiles
[
0
].
active
=
true
;
...
...
@@ -56,6 +57,7 @@ describe('RepoTabs', () => {
files
:
[],
viewer
:
'
editor
'
,
hasChanges
:
false
,
hasMergeRequest
:
false
,
},
'
#test-app
'
,
);
...
...
spec/javascripts/ide/lib/common/model_spec.js
View file @
4410a1fa
...
...
@@ -11,7 +11,10 @@ describe('Multi-file editor library model', () => {
spyOn
(
eventHub
,
'
$on
'
).
and
.
callThrough
();
monacoLoader
([
'
vs/editor/editor.main
'
],
()
=>
{
model
=
new
Model
(
monaco
,
file
(
'
path
'
));
const
f
=
file
(
'
path
'
);
f
.
mrChange
=
{
diff
:
'
ABC
'
};
f
.
baseRaw
=
'
test
'
;
model
=
new
Model
(
monaco
,
f
);
done
();
});
...
...
@@ -21,9 +24,10 @@ describe('Multi-file editor library model', () => {
model
.
dispose
();
});
it
(
'
creates original model & new model
'
,
()
=>
{
it
(
'
creates original model &
base model &
new model
'
,
()
=>
{
expect
(
model
.
originalModel
).
not
.
toBeNull
();
expect
(
model
.
model
).
not
.
toBeNull
();
expect
(
model
.
baseModel
).
not
.
toBeNull
();
});
it
(
'
adds eventHub listener
'
,
()
=>
{
...
...
@@ -51,6 +55,12 @@ describe('Multi-file editor library model', () => {
});
});
describe
(
'
getBaseModel
'
,
()
=>
{
it
(
'
returns base model
'
,
()
=>
{
expect
(
model
.
getBaseModel
()).
toBe
(
model
.
baseModel
);
});
});
describe
(
'
setValue
'
,
()
=>
{
it
(
'
updates models value
'
,
()
=>
{
model
.
setValue
(
'
testing 123
'
);
...
...
spec/javascripts/ide/lib/editor_spec.js
View file @
4410a1fa
...
...
@@ -151,6 +151,31 @@ describe('Multi-file editor library', () => {
});
});
describe
(
'
attachMergeRequestModel
'
,
()
=>
{
let
model
;
beforeEach
(()
=>
{
instance
.
createDiffInstance
(
document
.
createElement
(
'
div
'
));
const
f
=
file
();
f
.
mrChanges
=
{
diff
:
'
ABC
'
};
f
.
baseRaw
=
'
testing
'
;
model
=
instance
.
createModel
(
f
);
});
it
(
'
sets original & modified
'
,
()
=>
{
spyOn
(
instance
.
instance
,
'
setModel
'
);
instance
.
attachMergeRequestModel
(
model
);
expect
(
instance
.
instance
.
setModel
).
toHaveBeenCalledWith
({
original
:
model
.
getBaseModel
(),
modified
:
model
.
getModel
(),
});
});
});
describe
(
'
clearEditor
'
,
()
=>
{
it
(
'
resets the editor model
'
,
()
=>
{
instance
.
createInstance
(
document
.
createElement
(
'
div
'
));
...
...
spec/javascripts/ide/stores/actions/file_spec.js
View file @
4410a1fa
...
...
@@ -5,7 +5,7 @@ import router from '~/ide/ide_router';
import
eventHub
from
'
~/ide/eventhub
'
;
import
{
file
,
resetStore
}
from
'
../../helpers
'
;
describe
(
'
Multi-file
store file actions
'
,
()
=>
{
describe
(
'
IDE
store file actions
'
,
()
=>
{
beforeEach
(()
=>
{
spyOn
(
router
,
'
push
'
);
});
...
...
@@ -189,7 +189,7 @@ describe('Multi-file store file actions', () => {
it
(
'
calls the service
'
,
done
=>
{
store
.
dispatch
(
'
getFileData
'
,
localFile
)
.
dispatch
(
'
getFileData
'
,
{
path
:
localFile
.
path
}
)
.
then
(()
=>
{
expect
(
service
.
getFileData
).
toHaveBeenCalledWith
(
'
getFileDataURL
'
);
...
...
@@ -200,7 +200,7 @@ describe('Multi-file store file actions', () => {
it
(
'
sets the file data
'
,
done
=>
{
store
.
dispatch
(
'
getFileData
'
,
localFile
)
.
dispatch
(
'
getFileData
'
,
{
path
:
localFile
.
path
}
)
.
then
(()
=>
{
expect
(
localFile
.
blamePath
).
toBe
(
'
blame_path
'
);
...
...
@@ -211,7 +211,7 @@ describe('Multi-file store file actions', () => {
it
(
'
sets document title
'
,
done
=>
{
store
.
dispatch
(
'
getFileData
'
,
localFile
)
.
dispatch
(
'
getFileData
'
,
{
path
:
localFile
.
path
}
)
.
then
(()
=>
{
expect
(
document
.
title
).
toBe
(
'
testing getFileData
'
);
...
...
@@ -222,7 +222,7 @@ describe('Multi-file store file actions', () => {
it
(
'
sets the file as active
'
,
done
=>
{
store
.
dispatch
(
'
getFileData
'
,
localFile
)
.
dispatch
(
'
getFileData
'
,
{
path
:
localFile
.
path
}
)
.
then
(()
=>
{
expect
(
localFile
.
active
).
toBeTruthy
();
...
...
@@ -231,9 +231,20 @@ describe('Multi-file store file actions', () => {
.
catch
(
done
.
fail
);
});
it
(
'
sets the file not as active if we pass makeFileActive false
'
,
done
=>
{
store
.
dispatch
(
'
getFileData
'
,
{
path
:
localFile
.
path
,
makeFileActive
:
false
})
.
then
(()
=>
{
expect
(
localFile
.
active
).
toBeFalsy
();
done
();
})
.
catch
(
done
.
fail
);
});
it
(
'
adds the file to open files
'
,
done
=>
{
store
.
dispatch
(
'
getFileData
'
,
localFile
)
.
dispatch
(
'
getFileData
'
,
{
path
:
localFile
.
path
}
)
.
then
(()
=>
{
expect
(
store
.
state
.
openFiles
.
length
).
toBe
(
1
);
expect
(
store
.
state
.
openFiles
[
0
].
name
).
toBe
(
localFile
.
name
);
...
...
@@ -256,7 +267,7 @@ describe('Multi-file store file actions', () => {
it
(
'
calls getRawFileData service method
'
,
done
=>
{
store
.
dispatch
(
'
getRawFileData
'
,
tmpFile
)
.
dispatch
(
'
getRawFileData
'
,
{
path
:
tmpFile
.
path
}
)
.
then
(()
=>
{
expect
(
service
.
getRawFileData
).
toHaveBeenCalledWith
(
tmpFile
);
...
...
@@ -267,7 +278,7 @@ describe('Multi-file store file actions', () => {
it
(
'
updates file raw data
'
,
done
=>
{
store
.
dispatch
(
'
getRawFileData
'
,
tmpFile
)
.
dispatch
(
'
getRawFileData
'
,
{
path
:
tmpFile
.
path
}
)
.
then
(()
=>
{
expect
(
tmpFile
.
raw
).
toBe
(
'
raw
'
);
...
...
@@ -275,6 +286,22 @@ describe('Multi-file store file actions', () => {
})
.
catch
(
done
.
fail
);
});
it
(
'
calls also getBaseRawFileData service method
'
,
done
=>
{
spyOn
(
service
,
'
getBaseRawFileData
'
).
and
.
returnValue
(
Promise
.
resolve
(
'
baseraw
'
));
tmpFile
.
mrChange
=
{
new_file
:
false
};
store
.
dispatch
(
'
getRawFileData
'
,
{
path
:
tmpFile
.
path
,
baseSha
:
'
SHA
'
})
.
then
(()
=>
{
expect
(
service
.
getBaseRawFileData
).
toHaveBeenCalledWith
(
tmpFile
,
'
SHA
'
);
expect
(
tmpFile
.
baseRaw
).
toBe
(
'
baseraw
'
);
done
();
})
.
catch
(
done
.
fail
);
});
});
describe
(
'
changeFileContent
'
,
()
=>
{
...
...
spec/javascripts/ide/stores/actions/merge_request_spec.js
0 → 100644
View file @
4410a1fa
import
store
from
'
~/ide/stores
'
;
import
service
from
'
~/ide/services
'
;
import
{
resetStore
}
from
'
../../helpers
'
;
describe
(
'
IDE store merge request actions
'
,
()
=>
{
beforeEach
(()
=>
{
store
.
state
.
projects
.
abcproject
=
{
mergeRequests
:
{},
};
});
afterEach
(()
=>
{
resetStore
(
store
);
});
describe
(
'
getMergeRequestData
'
,
()
=>
{
beforeEach
(()
=>
{
spyOn
(
service
,
'
getProjectMergeRequestData
'
).
and
.
returnValue
(
Promise
.
resolve
({
data
:
{
title
:
'
mergerequest
'
}
}),
);
});
it
(
'
calls getProjectMergeRequestData service method
'
,
done
=>
{
store
.
dispatch
(
'
getMergeRequestData
'
,
{
projectId
:
'
abcproject
'
,
mergeRequestId
:
1
})
.
then
(()
=>
{
expect
(
service
.
getProjectMergeRequestData
).
toHaveBeenCalledWith
(
'
abcproject
'
,
1
);
done
();
})
.
catch
(
done
.
fail
);
});
it
(
'
sets the Merge Request Object
'
,
done
=>
{
store
.
dispatch
(
'
getMergeRequestData
'
,
{
projectId
:
'
abcproject
'
,
mergeRequestId
:
1
})
.
then
(()
=>
{
expect
(
store
.
state
.
projects
.
abcproject
.
mergeRequests
[
'
1
'
].
title
).
toBe
(
'
mergerequest
'
);
expect
(
store
.
state
.
currentMergeRequestId
).
toBe
(
1
);
done
();
})
.
catch
(
done
.
fail
);
});
});
describe
(
'
getMergeRequestChanges
'
,
()
=>
{
beforeEach
(()
=>
{
spyOn
(
service
,
'
getProjectMergeRequestChanges
'
).
and
.
returnValue
(
Promise
.
resolve
({
data
:
{
title
:
'
mergerequest
'
}
}),
);
store
.
state
.
projects
.
abcproject
.
mergeRequests
[
'
1
'
]
=
{
changes
:
[]
};
});
it
(
'
calls getProjectMergeRequestChanges service method
'
,
done
=>
{
store
.
dispatch
(
'
getMergeRequestChanges
'
,
{
projectId
:
'
abcproject
'
,
mergeRequestId
:
1
})
.
then
(()
=>
{
expect
(
service
.
getProjectMergeRequestChanges
).
toHaveBeenCalledWith
(
'
abcproject
'
,
1
);
done
();
})
.
catch
(
done
.
fail
);
});
it
(
'
sets the Merge Request Changes Object
'
,
done
=>
{
store
.
dispatch
(
'
getMergeRequestChanges
'
,
{
projectId
:
'
abcproject
'
,
mergeRequestId
:
1
})
.
then
(()
=>
{
expect
(
store
.
state
.
projects
.
abcproject
.
mergeRequests
[
'
1
'
].
changes
.
title
).
toBe
(
'
mergerequest
'
,
);
done
();
})
.
catch
(
done
.
fail
);
});
});
describe
(
'
getMergeRequestVersions
'
,
()
=>
{
beforeEach
(()
=>
{
spyOn
(
service
,
'
getProjectMergeRequestVersions
'
).
and
.
returnValue
(
Promise
.
resolve
({
data
:
[{
id
:
789
}]
}),
);
store
.
state
.
projects
.
abcproject
.
mergeRequests
[
'
1
'
]
=
{
versions
:
[]
};
});
it
(
'
calls getProjectMergeRequestVersions service method
'
,
done
=>
{
store
.
dispatch
(
'
getMergeRequestVersions
'
,
{
projectId
:
'
abcproject
'
,
mergeRequestId
:
1
})
.
then
(()
=>
{
expect
(
service
.
getProjectMergeRequestVersions
).
toHaveBeenCalledWith
(
'
abcproject
'
,
1
);
done
();
})
.
catch
(
done
.
fail
);
});
it
(
'
sets the Merge Request Versions Object
'
,
done
=>
{
store
.
dispatch
(
'
getMergeRequestVersions
'
,
{
projectId
:
'
abcproject
'
,
mergeRequestId
:
1
})
.
then
(()
=>
{
expect
(
store
.
state
.
projects
.
abcproject
.
mergeRequests
[
'
1
'
].
versions
.
length
).
toBe
(
1
);
done
();
})
.
catch
(
done
.
fail
);
});
});
});
spec/javascripts/ide/stores/actions/tree_spec.js
View file @
4410a1fa
...
...
@@ -68,9 +68,7 @@ describe('Multi-file store tree actions', () => {
expect
(
projectTree
.
tree
[
0
].
tree
[
1
].
name
).
toBe
(
'
fileinfolder.js
'
);
expect
(
projectTree
.
tree
[
1
].
type
).
toBe
(
'
blob
'
);
expect
(
projectTree
.
tree
[
0
].
tree
[
0
].
tree
[
0
].
type
).
toBe
(
'
blob
'
);
expect
(
projectTree
.
tree
[
0
].
tree
[
0
].
tree
[
0
].
name
).
toBe
(
'
fileinsubfolder.js
'
,
);
expect
(
projectTree
.
tree
[
0
].
tree
[
0
].
tree
[
0
].
name
).
toBe
(
'
fileinsubfolder.js
'
);
done
();
})
...
...
@@ -132,9 +130,7 @@ describe('Multi-file store tree actions', () => {
store
.
dispatch
(
'
getLastCommitData
'
,
projectTree
)
.
then
(()
=>
{
expect
(
service
.
getTreeLastCommit
).
toHaveBeenCalledWith
(
'
lastcommitpath
'
,
);
expect
(
service
.
getTreeLastCommit
).
toHaveBeenCalledWith
(
'
lastcommitpath
'
);
done
();
})
...
...
@@ -160,9 +156,7 @@ describe('Multi-file store tree actions', () => {
.
dispatch
(
'
getLastCommitData
'
,
projectTree
)
.
then
(
Vue
.
nextTick
)
.
then
(()
=>
{
expect
(
projectTree
.
tree
[
0
].
lastCommit
.
message
).
not
.
toBe
(
'
commit message
'
,
);
expect
(
projectTree
.
tree
[
0
].
lastCommit
.
message
).
not
.
toBe
(
'
commit message
'
);
done
();
})
...
...
spec/javascripts/ide/stores/getters_spec.js
View file @
4410a1fa
...
...
@@ -2,7 +2,7 @@ import * as getters from '~/ide/stores/getters';
import
state
from
'
~/ide/stores/state
'
;
import
{
file
}
from
'
../helpers
'
;
describe
(
'
Multi-file
store getters
'
,
()
=>
{
describe
(
'
IDE
store getters
'
,
()
=>
{
let
localState
;
beforeEach
(()
=>
{
...
...
@@ -52,4 +52,24 @@ describe('Multi-file store getters', () => {
expect
(
modifiedFiles
[
0
].
name
).
toBe
(
'
added
'
);
});
});
describe
(
'
currentMergeRequest
'
,
()
=>
{
it
(
'
returns Current Merge Request
'
,
()
=>
{
localState
.
currentProjectId
=
'
abcproject
'
;
localState
.
currentMergeRequestId
=
1
;
localState
.
projects
.
abcproject
=
{
mergeRequests
:
{
1
:
{
mergeId
:
1
},
},
};
expect
(
getters
.
currentMergeRequest
(
localState
).
mergeId
).
toBe
(
1
);
});
it
(
'
returns null if no active Merge Request was found
'
,
()
=>
{
localState
.
currentProjectId
=
'
otherproject
'
;
expect
(
getters
.
currentMergeRequest
(
localState
)).
toBeNull
();
});
});
});
spec/javascripts/ide/stores/mutations/file_spec.js
View file @
4410a1fa
...
...
@@ -2,7 +2,7 @@ import mutations from '~/ide/stores/mutations/file';
import
state
from
'
~/ide/stores/state
'
;
import
{
file
}
from
'
../../helpers
'
;
describe
(
'
Multi-file
store file mutations
'
,
()
=>
{
describe
(
'
IDE
store file mutations
'
,
()
=>
{
let
localState
;
let
localFile
;
...
...
@@ -62,6 +62,8 @@ describe('Multi-file store file mutations', () => {
expect
(
localFile
.
rawPath
).
toBe
(
'
raw
'
);
expect
(
localFile
.
binary
).
toBeTruthy
();
expect
(
localFile
.
renderError
).
toBe
(
'
render_error
'
);
expect
(
localFile
.
raw
).
toBeNull
();
expect
(
localFile
.
baseRaw
).
toBeNull
();
});
});
...
...
@@ -76,6 +78,17 @@ describe('Multi-file store file mutations', () => {
});
});
describe
(
'
SET_FILE_BASE_RAW_DATA
'
,
()
=>
{
it
(
'
sets raw data from base branch
'
,
()
=>
{
mutations
.
SET_FILE_BASE_RAW_DATA
(
localState
,
{
file
:
localFile
,
baseRaw
:
'
testing
'
,
});
expect
(
localFile
.
baseRaw
).
toBe
(
'
testing
'
);
});
});
describe
(
'
UPDATE_FILE_CONTENT
'
,
()
=>
{
beforeEach
(()
=>
{
localFile
.
raw
=
'
test
'
;
...
...
@@ -112,6 +125,17 @@ describe('Multi-file store file mutations', () => {
});
});
describe
(
'
SET_FILE_MERGE_REQUEST_CHANGE
'
,
()
=>
{
it
(
'
sets file mr change
'
,
()
=>
{
mutations
.
SET_FILE_MERGE_REQUEST_CHANGE
(
localState
,
{
file
:
localFile
,
mrChange
:
{
diff
:
'
ABC
'
},
});
expect
(
localFile
.
mrChange
.
diff
).
toBe
(
'
ABC
'
);
});
});
describe
(
'
DISCARD_FILE_CHANGES
'
,
()
=>
{
beforeEach
(()
=>
{
localFile
.
content
=
'
test
'
;
...
...
spec/javascripts/ide/stores/mutations/merge_request_spec.js
0 → 100644
View file @
4410a1fa
import
mutations
from
'
~/ide/stores/mutations/merge_request
'
;
import
state
from
'
~/ide/stores/state
'
;
describe
(
'
IDE store merge request mutations
'
,
()
=>
{
let
localState
;
beforeEach
(()
=>
{
localState
=
state
();
localState
.
projects
=
{
abcproject
:
{
mergeRequests
:
{}
}
};
mutations
.
SET_MERGE_REQUEST
(
localState
,
{
projectPath
:
'
abcproject
'
,
mergeRequestId
:
1
,
mergeRequest
:
{
title
:
'
mr
'
,
},
});
});
describe
(
'
SET_CURRENT_MERGE_REQUEST
'
,
()
=>
{
it
(
'
sets current merge request
'
,
()
=>
{
mutations
.
SET_CURRENT_MERGE_REQUEST
(
localState
,
2
);
expect
(
localState
.
currentMergeRequestId
).
toBe
(
2
);
});
});
describe
(
'
SET_MERGE_REQUEST
'
,
()
=>
{
it
(
'
setsmerge request data
'
,
()
=>
{
const
newMr
=
localState
.
projects
.
abcproject
.
mergeRequests
[
1
];
expect
(
newMr
.
title
).
toBe
(
'
mr
'
);
expect
(
newMr
.
active
).
toBeTruthy
();
});
});
describe
(
'
SET_MERGE_REQUEST_CHANGES
'
,
()
=>
{
it
(
'
sets merge request changes
'
,
()
=>
{
mutations
.
SET_MERGE_REQUEST_CHANGES
(
localState
,
{
projectPath
:
'
abcproject
'
,
mergeRequestId
:
1
,
changes
:
{
diff
:
'
abc
'
,
},
});
const
newMr
=
localState
.
projects
.
abcproject
.
mergeRequests
[
1
];
expect
(
newMr
.
changes
.
diff
).
toBe
(
'
abc
'
);
});
});
describe
(
'
SET_MERGE_REQUEST_VERSIONS
'
,
()
=>
{
it
(
'
sets merge request versions
'
,
()
=>
{
mutations
.
SET_MERGE_REQUEST_VERSIONS
(
localState
,
{
projectPath
:
'
abcproject
'
,
mergeRequestId
:
1
,
versions
:
[{
id
:
123
}],
});
const
newMr
=
localState
.
projects
.
abcproject
.
mergeRequests
[
1
];
expect
(
newMr
.
versions
.
length
).
toBe
(
1
);
expect
(
newMr
.
versions
[
0
].
id
).
toBe
(
123
);
});
});
});
spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js
View file @
4410a1fa
...
...
@@ -17,46 +17,58 @@ describe('MRWidgetHeader', () => {
describe
(
'
computed
'
,
()
=>
{
describe
(
'
shouldShowCommitsBehindText
'
,
()
=>
{
it
(
'
return true when there are divergedCommitsCount
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">Link</a>
'
,
targetBranch
:
'
master
'
,
}
});
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">Link</a>
'
,
targetBranch
:
'
master
'
,
statusPath
:
'
abc
'
,
},
});
expect
(
vm
.
shouldShowCommitsBehindText
).
toEqual
(
true
);
});
it
(
'
returns false where there are no divergedComits count
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
0
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">Link</a>
'
,
targetBranch
:
'
master
'
,
}
});
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
0
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">Link</a>
'
,
targetBranch
:
'
master
'
,
statusPath
:
'
abc
'
,
},
});
expect
(
vm
.
shouldShowCommitsBehindText
).
toEqual
(
false
);
});
});
describe
(
'
commitsText
'
,
()
=>
{
it
(
'
returns singular when there is one commit
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
1
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">Link</a>
'
,
targetBranch
:
'
master
'
,
}
});
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
1
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">Link</a>
'
,
targetBranch
:
'
master
'
,
statusPath
:
'
abc
'
,
},
});
expect
(
vm
.
commitsText
).
toEqual
(
'
1 commit behind
'
);
});
it
(
'
returns plural when there is more than one commit
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
2
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">Link</a>
'
,
targetBranch
:
'
master
'
,
}
});
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
2
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">Link</a>
'
,
targetBranch
:
'
master
'
,
statusPath
:
'
abc
'
,
},
});
expect
(
vm
.
commitsText
).
toEqual
(
'
2 commits behind
'
);
});
...
...
@@ -66,24 +78,27 @@ describe('MRWidgetHeader', () => {
describe
(
'
template
'
,
()
=>
{
describe
(
'
common elements
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
true
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
}
});
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
true
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
statusPath
:
'
abc
'
,
},
});
});
it
(
'
renders source branch link
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-source-branch
'
).
innerHTML
,
)
.
toEqual
(
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
)
;
expect
(
vm
.
$el
.
querySelector
(
'
.js-source-branch
'
).
innerHTML
).
toEqual
(
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
);
});
it
(
'
renders clipboard button
'
,
()
=>
{
...
...
@@ -101,18 +116,21 @@ describe('MRWidgetHeader', () => {
});
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
true
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
}
});
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
true
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
statusPath
:
'
abc
'
,
},
});
});
it
(
'
renders checkout branch button with modal trigger
'
,
()
=>
{
...
...
@@ -123,39 +141,49 @@ describe('MRWidgetHeader', () => {
expect
(
button
.
getAttribute
(
'
data-toggle
'
)).
toEqual
(
'
modal
'
);
});
it
(
'
renders web ide button
'
,
()
=>
{
const
button
=
vm
.
$el
.
querySelector
(
'
.js-web-ide
'
);
expect
(
button
.
textContent
.
trim
()).
toEqual
(
'
Web IDE
'
);
expect
(
button
.
getAttribute
(
'
href
'
)).
toEqual
(
'
undefined/-/ide/projectabc
'
);
});
it
(
'
renders download dropdown with links
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-email-patches
'
).
textContent
.
trim
()
,
)
.
toEqual
(
'
Email patches
'
)
;
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-email-patches
'
).
textContent
.
trim
()).
toEqual
(
'
Email patches
'
,
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-email-patches
'
).
getAttribute
(
'
href
'
)
,
)
.
toEqual
(
'
/mr/email-patches
'
)
;
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-email-patches
'
).
getAttribute
(
'
href
'
)).
toEqual
(
'
/mr/email-patches
'
,
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-plain-diff
'
).
textContent
.
trim
()
,
)
.
toEqual
(
'
Plain diff
'
)
;
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-plain-diff
'
).
textContent
.
trim
()).
toEqual
(
'
Plain diff
'
,
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-plain-diff
'
).
getAttribute
(
'
href
'
)
,
)
.
toEqual
(
'
/mr/plainDiffPath
'
)
;
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-plain-diff
'
).
getAttribute
(
'
href
'
)).
toEqual
(
'
/mr/plainDiffPath
'
,
);
});
});
describe
(
'
with a closed merge request
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
false
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
}
});
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
false
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
statusPath
:
'
abc
'
,
},
});
});
it
(
'
does not render checkout branch button with modal trigger
'
,
()
=>
{
...
...
@@ -165,30 +193,29 @@ describe('MRWidgetHeader', () => {
});
it
(
'
does not render download dropdown with links
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-email-patches
'
),
).
toEqual
(
null
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-email-patches
'
)).
toEqual
(
null
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-plain-diff
'
),
).
toEqual
(
null
);
expect
(
vm
.
$el
.
querySelector
(
'
.js-download-plain-diff
'
)).
toEqual
(
null
);
});
});
describe
(
'
without diverged commits
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
0
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
true
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
}
});
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
0
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
true
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
statusPath
:
'
abc
'
,
},
});
});
it
(
'
does not render diverged commits info
'
,
()
=>
{
...
...
@@ -198,22 +225,27 @@ describe('MRWidgetHeader', () => {
describe
(
'
with diverged commits
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
true
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
}
});
vm
=
mountComponent
(
Component
,
{
mr
:
{
divergedCommitsCount
:
12
,
sourceBranch
:
'
mr-widget-refactor
'
,
sourceBranchLink
:
'
<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>
'
,
sourceBranchRemoved
:
false
,
targetBranchPath
:
'
foo/bar/commits-path
'
,
targetBranchTreePath
:
'
foo/bar/tree/path
'
,
targetBranch
:
'
master
'
,
isOpen
:
true
,
emailPatchesPath
:
'
/mr/email-patches
'
,
plainDiffPath
:
'
/mr/plainDiffPath
'
,
statusPath
:
'
abc
'
,
},
});
});
it
(
'
renders diverged commits info
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.diverged-commits-count
'
).
textContent
.
trim
()).
toEqual
(
'
(12 commits behind)
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.diverged-commits-count
'
).
textContent
.
trim
()).
toEqual
(
'
(12 commits behind)
'
,
);
});
});
});
...
...
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