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
174c2f80
Commit
174c2f80
authored
Mar 16, 2018
by
Phil Hughes
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into ide-code-cleanup
parents
2a7fedaf
97c7c8ec
Changes
34
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
1040 additions
and
416 deletions
+1040
-416
app/assets/javascripts/merge_request_tabs.js
app/assets/javascripts/merge_request_tabs.js
+5
-0
app/assets/stylesheets/pages/repo.scss
app/assets/stylesheets/pages/repo.scss
+88
-2
doc/administration/geo/replication/configuration.md
doc/administration/geo/replication/configuration.md
+11
-7
doc/ci/examples/code_climate.md
doc/ci/examples/code_climate.md
+15
-7
doc/development/doc_styleguide.md
doc/development/doc_styleguide.md
+71
-266
doc/development/writing_documentation.md
doc/development/writing_documentation.md
+245
-30
ee/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
...s/javascripts/ide/components/commit_sidebar/list_item.vue
+3
-0
ee/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
...ssets/javascripts/ide/components/editor_mode_dropdown.vue
+91
-0
ee/app/assets/javascripts/ide/components/ide.vue
ee/app/assets/javascripts/ide/components/ide.vue
+5
-8
ee/app/assets/javascripts/ide/components/repo_editor.vue
ee/app/assets/javascripts/ide/components/repo_editor.vue
+28
-3
ee/app/assets/javascripts/ide/components/repo_file.vue
ee/app/assets/javascripts/ide/components/repo_file.vue
+13
-5
ee/app/assets/javascripts/ide/components/repo_tabs.vue
ee/app/assets/javascripts/ide/components/repo_tabs.vue
+42
-8
ee/app/assets/javascripts/ide/lib/common/model.js
ee/app/assets/javascripts/ide/lib/common/model.js
+4
-0
ee/app/assets/javascripts/ide/lib/common/model_manager.js
ee/app/assets/javascripts/ide/lib/common/model_manager.js
+9
-0
ee/app/assets/javascripts/ide/lib/decorations/controller.js
ee/app/assets/javascripts/ide/lib/decorations/controller.js
+2
-0
ee/app/assets/javascripts/ide/lib/editor.js
ee/app/assets/javascripts/ide/lib/editor.js
+69
-25
ee/app/assets/javascripts/ide/lib/editor_options.js
ee/app/assets/javascripts/ide/lib/editor_options.js
+15
-3
ee/app/assets/javascripts/ide/lib/themes/gl_theme.js
ee/app/assets/javascripts/ide/lib/themes/gl_theme.js
+3
-0
ee/app/assets/javascripts/ide/stores/actions.js
ee/app/assets/javascripts/ide/stores/actions.js
+8
-0
ee/app/assets/javascripts/ide/stores/actions/file.js
ee/app/assets/javascripts/ide/stores/actions/file.js
+47
-15
ee/app/assets/javascripts/ide/stores/getters.js
ee/app/assets/javascripts/ide/stores/getters.js
+22
-16
ee/app/assets/javascripts/ide/stores/mutation_types.js
ee/app/assets/javascripts/ide/stores/mutation_types.js
+2
-3
ee/app/assets/javascripts/ide/stores/mutations.js
ee/app/assets/javascripts/ide/stores/mutations.js
+22
-5
ee/app/assets/javascripts/ide/stores/state.js
ee/app/assets/javascripts/ide/stores/state.js
+2
-0
spec/javascripts/ide/components/commit_sidebar/list_item_spec.js
...vascripts/ide/components/commit_sidebar/list_item_spec.js
+11
-0
spec/javascripts/ide/components/repo_editor_spec.js
spec/javascripts/ide/components/repo_editor_spec.js
+28
-0
spec/javascripts/ide/components/repo_tabs_spec.js
spec/javascripts/ide/components/repo_tabs_spec.js
+51
-1
spec/javascripts/ide/lib/common/model_manager_spec.js
spec/javascripts/ide/lib/common/model_manager_spec.js
+34
-0
spec/javascripts/ide/lib/common/model_spec.js
spec/javascripts/ide/lib/common/model_spec.js
+15
-0
spec/javascripts/ide/lib/editor_spec.js
spec/javascripts/ide/lib/editor_spec.js
+55
-12
spec/javascripts/ide/stores/actions/file_spec.js
spec/javascripts/ide/stores/actions/file_spec.js
+3
-0
spec/javascripts/ide/stores/actions_spec.js
spec/javascripts/ide/stores/actions_spec.js
+11
-0
spec/javascripts/ide/stores/modules/commit/actions_spec.js
spec/javascripts/ide/stores/modules/commit/actions_spec.js
+2
-0
spec/javascripts/ide/stores/mutations_spec.js
spec/javascripts/ide/stores/mutations_spec.js
+8
-0
No files found.
app/assets/javascripts/merge_request_tabs.js
View file @
174c2f80
...
...
@@ -73,6 +73,7 @@ export default class MergeRequestTabs {
constructor
({
action
,
setUrl
,
stubLocation
}
=
{})
{
const
mergeRequestTabs
=
document
.
querySelector
(
'
.js-tabs-affix
'
);
const
navbar
=
document
.
querySelector
(
'
.navbar-gitlab
'
);
const
peek
=
document
.
getElementById
(
'
peek
'
);
const
paddingTop
=
16
;
this
.
diffsLoaded
=
false
;
...
...
@@ -86,6 +87,10 @@ export default class MergeRequestTabs {
this
.
showTab
=
this
.
showTab
.
bind
(
this
);
this
.
stickyTop
=
navbar
?
navbar
.
offsetHeight
-
paddingTop
:
0
;
if
(
peek
)
{
this
.
stickyTop
+=
peek
.
offsetHeight
;
}
if
(
mergeRequestTabs
)
{
this
.
stickyTop
+=
mergeRequestTabs
.
offsetHeight
;
}
...
...
app/assets/stylesheets/pages/repo.scss
View file @
174c2f80
...
...
@@ -132,13 +132,35 @@
.multi-file-tabs
{
display
:
flex
;
overflow-x
:
auto
;
background-color
:
$white-normal
;
box-shadow
:
inset
0
-1px
$white-dark
;
>
li
{
>
ul
{
display
:
flex
;
overflow-x
:
auto
;
}
li
{
position
:
relative
;
}
.dropdown
{
display
:
flex
;
margin-left
:
auto
;
margin-bottom
:
1px
;
padding
:
0
$grid-size
;
border-left
:
1px
solid
$white-dark
;
background-color
:
$white-light
;
&
.shadow
{
box-shadow
:
0
0
10px
$dropdown-shadow-color
;
}
.btn
{
margin-top
:
auto
;
margin-bottom
:
auto
;
}
}
}
.multi-file-tab
{
...
...
@@ -207,6 +229,70 @@
.vertical-center
{
min-height
:
auto
;
}
.monaco-editor
.lines-content
.cigr
{
display
:
none
;
}
.monaco-diff-editor.vs
{
.editor.modified
{
box-shadow
:
none
;
}
.diagonal-fill
{
display
:
none
!
important
;
}
.diffOverview
{
background-color
:
$white-light
;
border-left
:
1px
solid
$white-dark
;
cursor
:
ns-resize
;
}
.diffViewport
{
display
:
none
;
}
.char-insert
{
background-color
:
$line-added-dark
;
}
.char-delete
{
background-color
:
$line-removed-dark
;
}
.line-numbers
{
color
:
$black-transparent
;
}
.view-overlays
{
.line-insert
{
background-color
:
$line-added
;
}
.line-delete
{
background-color
:
$line-removed
;
}
}
.margin
{
background-color
:
$gray-light
;
border-right
:
1px
solid
$white-normal
;
.line-insert
{
border-right
:
1px
solid
$line-added-dark
;
}
.line-delete
{
border-right
:
1px
solid
$line-removed-dark
;
}
}
.margin-view-overlays
.insert-sign
,
.margin-view-overlays
.delete-sign
{
opacity
:
.4
;
}
}
}
.multi-file-editor-holder
{
...
...
doc/administration/geo/replication/configuration.md
View file @
174c2f80
...
...
@@ -29,7 +29,7 @@ in your testing/production environment.
GitLab stores a number of secret values in the
`/etc/gitlab/gitlab-secrets.json`
file which
*must*
match between the primary and secondary nodes. Until there is
a means of automatically replicating these between nodes (see issue [gitlab-org/gitlab-ee#3789]),
a means of automatically replicating these between nodes (see issue [gitlab-org/gitlab-ee#3789]),
they must be manually replicated to the secondary.
1.
SSH into the
**primary**
node, and execute the command below:
...
...
@@ -127,7 +127,11 @@ keys must be manually replicated to the secondary node.
1.
Restart sshd:
```bash
service ssh restart
# Debian or Ubuntu installations
sudo service ssh reload
# CentOS installations
sudo service sshd reload
```
### Step 3. Add the secondary GitLab node
...
...
@@ -145,13 +149,13 @@ keys must be manually replicated to the secondary node.
```
gitlab-ctl restart
```
Check if there are any common issue with your Geo setup by running:
```
gitlab-rake gitlab:geo:check
```
1.
SSH into your GitLab
**primary**
server and login as root to verify the
secondary is reachable or there are any common issue with your Geo setup:
...
...
@@ -164,13 +168,13 @@ replicating missing data from the primary in a process known as **backfill**.
Meanwhile, the primary node will start to notify the secondary of any changes, so
that the secondary can act on those notifications immediately.
Make sure the secondary instance is running and accessible.
Make sure the secondary instance is running and accessible.
You can login to the secondary node with the same credentials as used in the primary.
### Step 4. (Optional) Enabling hashed storage (from GitLab 10.0)
CAUTION:
**Warning**
:
Hashed storage is in
**Beta**
. It is not considered production-ready. See
Hashed storage is in
**Beta**
. It is not considered production-ready. See
[Hashed Storage] for more detail, and for the latest updates, check
infrastructure issue [gitlab-com/infrastructure#2821].
...
...
doc/ci/examples/code_climate.md
View file @
174c2f80
...
...
@@ -16,18 +16,26 @@ codequality:
-
docker:dind
script
:
-
docker pull codeclimate/codeclimate
-
docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate:0.69.0 init
-
docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate:0.69.0 analyze -f json > codeclimate.json ||
true
-
export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
-
docker run
--env SOURCE_CODE="$PWD" \
--volume "$PWD":/code \
--volume /var/run/docker.sock:/var/run/docker.sock \
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts
:
paths
:
[
codeclimate.json
]
```
This will create a
`codequality`
job in your CI pipeline and will allow you to
download and analyze the report artifact in JSON format.
The above example will create a
`codequality`
job in your CI/CD pipeline which
will scan your source code for code quality issues. The report will be saved
as an artifact that you can later download and analyze.
For
[
GitLab Starter
][
ee
]
users, this information can be automatically
extracted and shown right in the merge request widget.
[
Learn more on code quality
diffs in merge requests
](
../../user/project/merge_requests/code_quality_diff.md
)
.
TIP:
**Tip:**
Starting with
[
GitLab Starter
][
ee
]
9.3, this information will
be automatically extracted and shown right in the merge request widget. To do
so, the CI/CD job must be named
`codequality`
and the artifact path must be
`codeclimate.json`
.
[
Learn more on code quality diffs in merge requests
](
../../user/project/merge_requests/code_quality_diff.md
)
.
[
cli
]:
https://github.com/codeclimate/codeclimate
[
dind
]:
../docker/using_docker_build.md#use-docker-in-docker-executor
...
...
doc/development/doc_styleguide.md
View file @
174c2f80
This diff is collapsed.
Click to expand it.
doc/development/writing_documentation.md
View file @
174c2f80
This diff is collapsed.
Click to expand it.
ee/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
View file @
174c2f80
...
...
@@ -24,8 +24,11 @@
methods
:
{
...
mapActions
([
'
discardFileChanges
'
,
'
updateViewer
'
,
]),
openFileInEditor
(
file
)
{
this
.
updateViewer
(
'
diff
'
);
router
.
push
(
`/project
${
file
.
url
}
`
);
},
},
...
...
ee/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
0 → 100644
View file @
174c2f80
<
script
>
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
export
default
{
components
:
{
Icon
,
},
props
:
{
hasChanges
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
viewer
:
{
type
:
String
,
required
:
true
,
},
showShadow
:
{
type
:
Boolean
,
required
:
true
,
},
},
methods
:
{
changeMode
(
mode
)
{
this
.
$emit
(
'
click
'
,
mode
);
},
},
};
</
script
>
<
template
>
<div
class=
"dropdown"
:class=
"
{
shadow: showShadow,
}"
>
<button
type=
"button"
class=
"btn btn-primary btn-sm"
:class=
"
{
'btn-inverted': hasChanges,
}"
data-toggle="dropdown"
>
<template
v-if=
"viewer === 'editor'"
>
{{
__
(
'
Editing
'
)
}}
</
template
>
<
template
v-else
>
{{
__
(
'
Reviewing
'
)
}}
</
template
>
<icon
name=
"angle-down"
:size=
"12"
css-classes=
"caret-down"
/>
</button>
<div
class=
"dropdown-menu dropdown-menu-selectable dropdown-open-left"
>
<ul>
<li>
<a
href=
"#"
@
click.prevent=
"changeMode('editor')"
:class=
"{
'is-active': viewer === 'editor',
}"
>
<strong
class=
"dropdown-menu-inner-title"
>
{{ __('Editing') }}
</strong>
<span
class=
"dropdown-menu-inner-content"
>
{{ __('View and edit lines') }}
</span>
</a>
</li>
<li>
<a
href=
"#"
@
click.prevent=
"changeMode('diff')"
:class=
"{
'is-active': viewer === 'diff',
}"
>
<strong
class=
"dropdown-menu-inner-title"
>
{{ __('Reviewing') }}
</strong>
<span
class=
"dropdown-menu-inner-content"
>
{{ __('Compare changes with the last commit') }}
</span>
</a>
</li>
</ul>
</div>
</div>
</template>
ee/app/assets/javascripts/ide/components/ide.vue
View file @
174c2f80
...
...
@@ -31,17 +31,12 @@
},
},
computed
:
{
...
mapState
([
'
changedFiles
'
,
'
openFiles
'
,
]),
...
mapGetters
([
'
activeFile
'
,
]),
...
mapState
([
'
changedFiles
'
,
'
openFiles
'
,
'
viewer
'
]),
...
mapGetters
([
'
activeFile
'
,
'
hasChanges
'
]),
},
mounted
()
{
const
returnValue
=
'
Are you sure you want to lose unsaved changes?
'
;
window
.
onbeforeunload
=
(
e
)
=>
{
window
.
onbeforeunload
=
e
=>
{
if
(
!
this
.
changedFiles
.
length
)
return
undefined
;
Object
.
assign
(
e
,
{
...
...
@@ -66,6 +61,8 @@
>
<repo-tabs
:files=
"openFiles"
:viewer=
"viewer"
:has-changes=
"hasChanges"
/>
<repo-editor
class=
"multi-file-edit-pane-content"
...
...
ee/app/assets/javascripts/ide/components/repo_editor.vue
View file @
174c2f80
...
...
@@ -16,6 +16,8 @@ export default {
...
mapState
([
'
leftPanelCollapsed
'
,
'
rightPanelCollapsed
'
,
'
viewer
'
,
'
delayViewerUpdated
'
,
]),
shouldHideEditor
()
{
return
this
.
file
&&
this
.
file
.
binary
&&
!
this
.
file
.
raw
;
...
...
@@ -33,6 +35,9 @@ export default {
rightPanelCollapsed
()
{
this
.
editor
.
updateDimensions
();
},
viewer
()
{
this
.
createEditorInstance
();
},
},
beforeDestroy
()
{
this
.
editor
.
dispose
();
...
...
@@ -55,6 +60,8 @@ export default {
'
setFileLanguage
'
,
'
setEditorPosition
'
,
'
setFileEOL
'
,
'
updateViewer
'
,
'
updateDelayViewerUpdated
'
,
]),
initMonaco
()
{
if
(
this
.
shouldHideEditor
)
return
;
...
...
@@ -63,16 +70,34 @@ export default {
this
.
getRawFileData
(
this
.
file
)
.
then
(()
=>
{
this
.
editor
.
createInstance
(
this
.
$refs
.
editor
);
const
viewerPromise
=
this
.
delayViewerUpdated
?
this
.
updateViewer
(
'
editor
'
)
:
Promise
.
resolve
();
return
viewerPromise
;
})
.
then
(()
=>
{
this
.
updateDelayViewerUpdated
(
false
);
this
.
createEditorInstance
();
})
.
then
(()
=>
this
.
setupEditor
())
.
catch
((
err
)
=>
{
flash
(
'
Error setting up monaco. Please try again.
'
,
'
alert
'
,
document
,
null
,
false
,
true
);
throw
err
;
});
},
createEditorInstance
()
{
this
.
editor
.
dispose
();
this
.
$nextTick
(()
=>
{
if
(
this
.
viewer
===
'
editor
'
)
{
this
.
editor
.
createInstance
(
this
.
$refs
.
editor
);
}
else
{
this
.
editor
.
createDiffInstance
(
this
.
$refs
.
editor
);
}
this
.
setupEditor
();
});
},
setupEditor
()
{
if
(
!
this
.
file
)
return
;
if
(
!
this
.
file
||
!
this
.
editor
.
instance
)
return
;
this
.
model
=
this
.
editor
.
createModel
(
this
.
file
);
...
...
ee/app/assets/javascripts/ide/components/repo_file.vue
View file @
174c2f80
...
...
@@ -52,15 +52,23 @@
}
},
methods
:
{
...
mapActions
([
'
toggleTreeOpen
'
,
]),
...
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
);
}
router
.
push
(
`/project
${
this
.
file
.
url
}
`
);
const
delayPromise
=
this
.
file
.
changed
?
Promise
.
resolve
()
:
this
.
updateDelayViewerUpdated
(
true
);
return
delayPromise
.
then
(()
=>
{
router
.
push
(
`/project
${
this
.
file
.
url
}
`
);
});
},
},
};
...
...
ee/app/assets/javascripts/ide/components/repo_tabs.vue
View file @
174c2f80
<
script
>
import
{
mapActions
}
from
'
vuex
'
;
import
RepoTab
from
'
./repo_tab.vue
'
;
import
EditorMode
from
'
./editor_mode_dropdown.vue
'
;
export
default
{
components
:
{
RepoTab
,
EditorMode
,
},
props
:
{
files
:
{
type
:
Array
,
required
:
true
,
},
viewer
:
{
type
:
String
,
required
:
true
,
},
hasChanges
:
{
type
:
Boolean
,
required
:
true
,
},
},
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
>
<ul
class=
"multi-file-tabs list-unstyled append-bottom-0"
>
<repo-tab
v-for=
"file in files"
:key=
"file.key"
:tab=
"file"
<div
class=
"multi-file-tabs"
>
<ul
class=
"list-unstyled append-bottom-0"
ref=
"tabsScroller"
>
<repo-tab
v-for=
"tab in files"
:key=
"tab.key"
:tab=
"tab"
/>
</ul>
<editor-mode
:viewer=
"viewer"
:show-shadow=
"showShadow"
:has-changes=
"hasChanges"
@
click=
"updateViewer"
/>
</
ul
>
</
div
>
</
template
>
ee/app/assets/javascripts/ide/lib/common/model.js
View file @
174c2f80
...
...
@@ -26,6 +26,9 @@ export default class Model {
this
.
events
=
new
Map
();
this
.
updateContent
=
this
.
updateContent
.
bind
(
this
);
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
);
}
...
...
@@ -75,6 +78,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
);
}
}
ee/app/assets/javascripts/ide/lib/common/model_manager.js
View file @
174c2f80
import
eventHub
from
'
ee/ide/eventhub
'
;
import
Disposable
from
'
./disposable
'
;
import
Model
from
'
./model
'
;
...
...
@@ -25,9 +26,17 @@ export default class ModelManager {
this
.
models
.
set
(
model
.
path
,
model
);
this
.
disposable
.
add
(
model
);
eventHub
.
$on
(
`editor.update.model.dispose.
${
file
.
path
}
`
,
this
.
removeCachedModel
.
bind
(
this
,
file
));
return
model
;
}
removeCachedModel
(
file
)
{
this
.
models
.
delete
(
file
.
path
);
eventHub
.
$off
(
`editor.update.model.dispose.
${
file
.
path
}
`
,
this
.
removeCachedModel
);
}
dispose
()
{
// dispose of all the models
this
.
disposable
.
dispose
();
...
...
ee/app/assets/javascripts/ide/lib/decorations/controller.js
View file @
174c2f80
...
...
@@ -27,6 +27,8 @@ export default class DecorationsController {
}
decorate
(
model
)
{
if
(
!
this
.
editor
.
instance
)
return
;
const
decorations
=
this
.
getAllDecorationsForModel
(
model
);
const
oldDecorations
=
this
.
editorDecorations
.
get
(
model
.
url
)
||
[];
...
...
ee/app/assets/javascripts/ide/lib/editor.js
View file @
174c2f80
...
...
@@ -3,9 +3,16 @@ import DecorationsController from './decorations/controller';
import
DirtyDiffController
from
'
./diff/controller
'
;
import
Disposable
from
'
./common/disposable
'
;
import
ModelManager
from
'
./common/model_manager
'
;
import
editorOptions
from
'
./editor_options
'
;
import
editorOptions
,
{
defaultEditorOptions
}
from
'
./editor_options
'
;
import
gitlabTheme
from
'
./themes/gl_theme
'
;
import
gitlabTheme
from
'
ee/ide/lib/themes/gl_theme
'
;
// eslint-disable-line import/first
export
const
clearDomElement
=
el
=>
{
if
(
!
el
||
!
el
.
firstChild
)
return
;
while
(
el
.
firstChild
)
{
el
.
removeChild
(
el
.
firstChild
);
}
};
export
default
class
Editor
{
static
create
(
monaco
)
{
...
...
@@ -34,19 +41,31 @@ export default class Editor {
createInstance
(
domElement
)
{
if
(
!
this
.
instance
)
{
clearDomElement
(
domElement
);
this
.
disposable
.
add
(
(
this
.
instance
=
this
.
monaco
.
editor
.
create
(
domElement
,
{
...
defaultEditorOptions
,
})),
(
this
.
dirtyDiffController
=
new
DirtyDiffController
(
this
.
modelManager
,
this
.
decorationsController
,
)),
);
window
.
addEventListener
(
'
resize
'
,
this
.
debouncedUpdate
,
false
);
}
}
createDiffInstance
(
domElement
)
{
if
(
!
this
.
instance
)
{
clearDomElement
(
domElement
);
this
.
disposable
.
add
(
this
.
instance
=
this
.
monaco
.
editor
.
create
(
domElement
,
{
model
:
null
,
readOnly
:
false
,
contextmenu
:
true
,
scrollBeyondLastLine
:
false
,
minimap
:
{
enabled
:
false
,
},
}),
this
.
dirtyDiffController
=
new
DirtyDiffController
(
this
.
modelManager
,
this
.
decorationsController
,
),
(
this
.
instance
=
this
.
monaco
.
editor
.
createDiffEditor
(
domElement
,
{
...
defaultEditorOptions
,
readOnly
:
true
,
})),
);
window
.
addEventListener
(
'
resize
'
,
this
.
debouncedUpdate
,
false
);
...
...
@@ -58,25 +77,39 @@ export default class Editor {
}
attachModel
(
model
)
{
if
(
this
.
instance
.
getEditorType
()
===
'
vs.editor.IDiffEditor
'
)
{
this
.
instance
.
setModel
({
original
:
model
.
getOriginalModel
(),
modified
:
model
.
getModel
(),
});
return
;
}
this
.
instance
.
setModel
(
model
.
getModel
());
if
(
this
.
dirtyDiffController
)
this
.
dirtyDiffController
.
attachModel
(
model
);
this
.
currentModel
=
model
;
this
.
instance
.
updateOptions
(
editorOptions
.
reduce
((
acc
,
obj
)
=>
{
Object
.
keys
(
obj
).
forEach
((
key
)
=>
{
Object
.
assign
(
acc
,
{
[
key
]:
obj
[
key
](
model
),
this
.
instance
.
updateOptions
(
editorOptions
.
reduce
((
acc
,
obj
)
=>
{
Object
.
keys
(
obj
).
forEach
(
key
=>
{
Object
.
assign
(
acc
,
{
[
key
]:
obj
[
key
](
model
),
});
});
})
;
return
acc
;
},
{})
);
return
acc
;
},
{}),
);
if
(
this
.
dirtyDiffController
)
this
.
dirtyDiffController
.
reDecorate
(
model
);
}
setupMonacoTheme
()
{
this
.
monaco
.
editor
.
defineTheme
(
gitlabTheme
.
themeName
,
gitlabTheme
.
monacoTheme
);
this
.
monaco
.
editor
.
defineTheme
(
gitlabTheme
.
themeName
,
gitlabTheme
.
monacoTheme
,
);
this
.
monaco
.
editor
.
setTheme
(
'
gitlab
'
);
}
...
...
@@ -88,12 +121,21 @@ export default class Editor {
}
dispose
()
{
this
.
disposable
.
dispose
();
window
.
removeEventListener
(
'
resize
'
,
this
.
debouncedUpdate
);
// dispose main monaco instance
if
(
this
.
instance
)
{
// catch any potential errors with disposing the error
// this is mainly for tests caused by elements not existing
try
{
this
.
disposable
.
dispose
();
this
.
instance
=
null
;
}
catch
(
e
)
{
this
.
instance
=
null
;
if
(
process
.
env
.
NODE_ENV
!==
'
test
'
)
{
// eslint-disable-next-line no-console
console
.
error
(
e
);
}
}
}
...
...
@@ -113,6 +155,8 @@ export default class Editor {
}
onPositionChange
(
cb
)
{
if
(
!
this
.
instance
.
onDidChangeCursorPosition
)
return
;
this
.
disposable
.
add
(
this
.
instance
.
onDidChangeCursorPosition
(
e
=>
cb
(
this
.
instance
,
e
)),
);
...
...
ee/app/assets/javascripts/ide/lib/editor_options.js
View file @
174c2f80
export
default
[{
readOnly
:
model
=>
!!
model
.
file
.
file_lock
,
}];
export
const
defaultEditorOptions
=
{
model
:
null
,
readOnly
:
false
,
contextmenu
:
true
,
scrollBeyondLastLine
:
false
,
minimap
:
{
enabled
:
false
,
},
};
export
default
[
{
readOnly
:
model
=>
!!
model
.
file
.
file_lock
,
},
];
ee/app/assets/javascripts/ide/lib/themes/gl_theme.js
View file @
174c2f80
...
...
@@ -6,6 +6,9 @@ export default {
rules
:
[],
colors
:
{
'
editorLineNumber.foreground
'
:
'
#CCCCCC
'
,
'
diffEditor.insertedTextBackground
'
:
'
#ddfbe6
'
,
'
diffEditor.removedTextBackground
'
:
'
#f9d7dc
'
,
'
editor.selectionBackground
'
:
'
#aad6f8
'
,
},
},
};
ee/app/assets/javascripts/ide/stores/actions.js
View file @
174c2f80
...
...
@@ -108,6 +108,14 @@ export const scrollToTab = () => {
});
};
export
const
updateViewer
=
({
commit
},
viewer
)
=>
{
commit
(
types
.
UPDATE_VIEWER
,
viewer
);
};
export
const
updateDelayViewerUpdated
=
({
commit
},
delay
)
=>
{
commit
(
types
.
UPDATE_DELAY_VIEWER_CHANGE
,
delay
);
};
export
*
from
'
./actions/tree
'
;
export
*
from
'
./actions/file
'
;
export
*
from
'
./actions/project
'
;
ee/app/assets/javascripts/ide/stores/actions/file.js
View file @
174c2f80
import
{
normalizeHeaders
}
from
'
~/lib/utils/common_utils
'
;
import
flash
from
'
~/flash
'
;
import
eventHub
from
'
ee/ide/eventhub
'
;
import
service
from
'
../../services
'
;
import
*
as
types
from
'
../mutation_types
'
;
import
router
from
'
../../ide_router
'
;
import
{
setPageTitle
,
}
from
'
../utils
'
;
import
{
setPageTitle
}
from
'
../utils
'
;
export
const
closeFile
=
({
commit
,
state
,
getters
,
dispatch
},
path
)
=>
{
const
indexOfClosedFile
=
state
.
openFiles
.
indexOf
(
path
);
...
...
@@ -23,6 +22,8 @@ export const closeFile = ({ commit, state, getters, dispatch }, path) => {
}
else
if
(
!
state
.
openFiles
.
length
)
{
router
.
push
(
`/project/
${
file
.
projectId
}
/tree/
${
file
.
branchId
}
/`
);
}
eventHub
.
$emit
(
`editor.update.model.dispose.
${
file
.
path
}
`
);
};
export
const
setFileActive
=
({
commit
,
state
,
getters
,
dispatch
},
path
)
=>
{
...
...
@@ -32,7 +33,10 @@ export const setFileActive = ({ commit, state, getters, dispatch }, path) => {
if
(
file
.
active
)
return
;
if
(
currentActiveFile
)
{
commit
(
types
.
SET_FILE_ACTIVE
,
{
path
:
currentActiveFile
.
path
,
active
:
false
});
commit
(
types
.
SET_FILE_ACTIVE
,
{
path
:
currentActiveFile
.
path
,
active
:
false
,
});
}
commit
(
types
.
SET_FILE_ACTIVE
,
{
path
,
active
:
true
});
...
...
@@ -45,15 +49,16 @@ export const setFileActive = ({ commit, state, getters, dispatch }, path) => {
export
const
getFileData
=
({
state
,
commit
,
dispatch
},
file
)
=>
{
commit
(
types
.
TOGGLE_LOADING
,
{
entry
:
file
});
return
service
.
getFileData
(
file
.
url
)
.
then
((
res
)
=>
{
return
service
.
getFileData
(
file
.
url
)
.
then
(
res
=>
{
const
pageTitle
=
decodeURI
(
normalizeHeaders
(
res
.
headers
)[
'
PAGE-TITLE
'
]);
setPageTitle
(
pageTitle
);
return
res
.
json
();
})
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
commit
(
types
.
SET_FILE_DATA
,
{
data
,
file
});
commit
(
types
.
TOGGLE_FILE_OPEN
,
file
.
path
);
dispatch
(
'
setFileActive
'
,
file
.
path
);
...
...
@@ -61,15 +66,33 @@ export const getFileData = ({ state, commit, dispatch }, 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
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
changeFileContent
=
({
state
,
commit
},
{
path
,
content
})
=>
{
const
file
=
state
.
entries
[
path
];
...
...
@@ -96,9 +119,16 @@ 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
,
editorRow
,
editorColumn
});
commit
(
types
.
SET_FILE_POSITION
,
{
file
:
getters
.
activeFile
,
editorRow
,
editorColumn
,
});
}
};
...
...
@@ -111,4 +141,6 @@ export const discardFileChanges = ({ state, commit }, path) => {
if
(
file
.
tempFile
&&
file
.
opened
)
{
commit
(
types
.
TOGGLE_FILE_OPEN
,
path
);
}
eventHub
.
$emit
(
`editor.update.model.content.
${
file
.
path
}
`
,
file
.
raw
);
};
ee/app/assets/javascripts/ide/stores/getters.js
View file @
174c2f80
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
)
=>
{
const
project
=
state
.
projects
[
projectId
];
export
const
projectsWithTrees
=
state
=>
Object
.
keys
(
state
.
projects
).
map
(
projectId
=>
{
const
project
=
state
.
projects
[
projectId
];
return
{
...
project
,
branches
:
Object
.
keys
(
project
.
branches
).
map
((
branchId
)
=>
{
const
branch
=
project
.
branches
[
branchId
];
return
{
...
project
,
branches
:
Object
.
keys
(
project
.
branches
).
map
(
branchId
=>
{
const
branch
=
project
.
branches
[
branchId
];
return
{
...
branch
,
tree
:
state
.
trees
[
branch
.
treeId
],
};
}),
};
});
return
{
...
branch
,
tree
:
state
.
trees
[
branch
.
treeId
],
};
}),
};
});
// eslint-disable-next-line no-confusing-arrow
export
const
currentIcon
=
state
=>
(
state
.
rightPanelCollapsed
?
'
angle-double-left
'
:
'
angle-double-right
'
);
state
.
rightPanelCollapsed
?
'
angle-double-left
'
:
'
angle-double-right
'
;
export
const
hasChanges
=
state
=>
!!
state
.
changedFiles
.
length
;
ee/app/assets/javascripts/ide/stores/mutation_types.js
View file @
174c2f80
...
...
@@ -36,9 +36,8 @@ export const DISCARD_FILE_CHANGES = 'DISCARD_FILE_CHANGES';
export
const
ADD_FILE_TO_CHANGED
=
'
ADD_FILE_TO_CHANGED
'
;
export
const
REMOVE_FILE_FROM_CHANGED
=
'
REMOVE_FILE_FROM_CHANGED
'
;
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
UPDATE_VIEWER
=
'
UPDATE_VIEWER
'
;
export
const
UPDATE_DELAY_VIEWER_CHANGE
=
'
UPDATE_DELAY_VIEWER_CHANGE
'
;
ee/app/assets/javascripts/ide/stores/mutations.js
View file @
174c2f80
...
...
@@ -11,7 +11,10 @@ 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
,
{
...
...
@@ -63,8 +66,8 @@ export default {
[
key
]:
entry
,
});
}
else
{
const
tree
=
entry
.
tree
.
filter
(
f
=>
foundEntry
.
tree
.
find
(
e
=>
e
.
path
===
f
.
path
)
===
undefined
,
const
tree
=
entry
.
tree
.
filter
(
f
=>
f
oundEntry
.
tree
.
find
(
e
=>
e
.
path
===
f
.
path
)
===
undefined
,
);
Object
.
assign
(
foundEntry
,
{
tree
:
foundEntry
.
tree
.
concat
(
tree
),
...
...
@@ -74,14 +77,28 @@ export default {
return
acc
.
concat
(
key
);
},
[]);
const
foundEntry
=
state
.
trees
[
`
${
projectId
}
/
${
branchId
}
`
].
tree
.
find
(
e
=>
e
.
path
===
data
.
treeList
[
0
].
path
);
const
foundEntry
=
state
.
trees
[
`
${
projectId
}
/
${
branchId
}
`
].
tree
.
find
(
e
=>
e
.
path
===
data
.
treeList
[
0
].
path
,
);
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
,
),
});
}
},
[
types
.
UPDATE_VIEWER
](
state
,
viewer
)
{
Object
.
assign
(
state
,
{
viewer
,
});
},
[
types
.
UPDATE_DELAY_VIEWER_CHANGE
](
state
,
delayViewerUpdated
)
{
Object
.
assign
(
state
,
{
delayViewerUpdated
,
});
},
...
projectMutations
,
...
fileMutations
,
...
treeMutations
,
...
...
ee/app/assets/javascripts/ide/stores/state.js
View file @
174c2f80
...
...
@@ -14,4 +14,6 @@ export default () => ({
rightPanelCollapsed
:
false
,
panelResizing
:
false
,
entries
:
{},
viewer
:
'
editor
'
,
delayViewerUpdated
:
false
,
});
spec/javascripts/ide/components/commit_sidebar/list_item_spec.js
View file @
174c2f80
...
...
@@ -36,6 +36,7 @@ describe('Multi-file editor commit sidebar list item', () => {
it
(
'
opens a closed file in the editor when clicking the file path
'
,
()
=>
{
spyOn
(
vm
,
'
openFileInEditor
'
).
and
.
callThrough
();
spyOn
(
vm
,
'
updateViewer
'
);
spyOn
(
router
,
'
push
'
);
vm
.
$el
.
querySelector
(
'
.multi-file-commit-list-path
'
).
click
();
...
...
@@ -44,6 +45,16 @@ describe('Multi-file editor commit sidebar list item', () => {
expect
(
router
.
push
).
toHaveBeenCalled
();
});
it
(
'
calls updateViewer with diff when clicking file
'
,
()
=>
{
spyOn
(
vm
,
'
openFileInEditor
'
).
and
.
callThrough
();
spyOn
(
vm
,
'
updateViewer
'
);
spyOn
(
router
,
'
push
'
);
vm
.
$el
.
querySelector
(
'
.multi-file-commit-list-path
'
).
click
();
expect
(
vm
.
updateViewer
).
toHaveBeenCalledWith
(
'
diff
'
);
});
describe
(
'
computed
'
,
()
=>
{
describe
(
'
iconName
'
,
()
=>
{
it
(
'
returns modified when not a tempFile
'
,
()
=>
{
...
...
spec/javascripts/ide/components/repo_editor_spec.js
View file @
174c2f80
...
...
@@ -63,6 +63,34 @@ describe('RepoEditor', () => {
});
});
describe
(
'
createEditorInstance
'
,
()
=>
{
it
(
'
calls createInstance when viewer is editor
'
,
(
done
)
=>
{
spyOn
(
vm
.
editor
,
'
createInstance
'
);
vm
.
createEditorInstance
();
vm
.
$nextTick
(()
=>
{
expect
(
vm
.
editor
.
createInstance
).
toHaveBeenCalled
();
done
();
});
});
it
(
'
calls createDiffInstance when viewer is diff
'
,
(
done
)
=>
{
vm
.
$store
.
state
.
viewer
=
'
diff
'
;
spyOn
(
vm
.
editor
,
'
createDiffInstance
'
);
vm
.
createEditorInstance
();
vm
.
$nextTick
(()
=>
{
expect
(
vm
.
editor
.
createDiffInstance
).
toHaveBeenCalled
();
done
();
});
});
});
describe
(
'
setupEditor
'
,
()
=>
{
it
(
'
creates new model
'
,
()
=>
{
spyOn
(
vm
.
editor
,
'
createModel
'
).
and
.
callThrough
();
...
...
spec/javascripts/ide/components/repo_tabs_spec.js
View file @
174c2f80
...
...
@@ -12,9 +12,11 @@ describe('RepoTabs', () => {
vm
.
$destroy
();
});
it
(
'
renders a list of tabs
'
,
(
done
)
=>
{
it
(
'
renders a list of tabs
'
,
done
=>
{
vm
=
createComponent
(
RepoTabs
,
{
files
:
openedFiles
,
viewer
:
'
editor
'
,
hasChanges
:
false
,
});
openedFiles
[
0
].
active
=
true
;
...
...
@@ -28,4 +30,52 @@ describe('RepoTabs', () => {
done
();
});
});
describe
(
'
updated
'
,
()
=>
{
it
(
'
sets showShadow as true when scroll width is larger than width
'
,
done
=>
{
const
el
=
document
.
createElement
(
'
div
'
);
el
.
innerHTML
=
'
<div id="test-app"></div>
'
;
document
.
body
.
appendChild
(
el
);
const
style
=
document
.
createElement
(
'
style
'
);
style
.
innerText
=
`
.multi-file-tabs {
width: 100px;
}
.multi-file-tabs .list-unstyled {
display: flex;
overflow-x: auto;
}
`
;
document
.
head
.
appendChild
(
style
);
vm
=
createComponent
(
RepoTabs
,
{
files
:
[],
viewer
:
'
editor
'
,
hasChanges
:
false
,
},
'
#test-app
'
,
);
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
showShadow
).
toEqual
(
false
);
vm
.
files
=
openedFiles
;
})
.
then
(
vm
.
$nextTick
)
.
then
(()
=>
{
expect
(
vm
.
showShadow
).
toEqual
(
true
);
style
.
remove
();
el
.
remove
();
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
});
spec/javascripts/ide/lib/common/model_manager_spec.js
View file @
174c2f80
/* global monaco */
import
eventHub
from
'
ee/ide/eventhub
'
;
import
monacoLoader
from
'
ee/ide/monaco_loader
'
;
import
ModelManager
from
'
ee/ide/lib/common/model_manager
'
;
import
{
file
}
from
'
../../helpers
'
;
...
...
@@ -47,6 +48,15 @@ describe('Multi-file editor library model manager', () => {
expect
(
instance
.
models
.
get
).
toHaveBeenCalled
();
});
it
(
'
adds eventHub listener
'
,
()
=>
{
const
f
=
file
();
spyOn
(
eventHub
,
'
$on
'
).
and
.
callThrough
();
instance
.
addModel
(
f
);
expect
(
eventHub
.
$on
).
toHaveBeenCalledWith
(
`editor.update.model.dispose.
${
f
.
path
}
`
,
jasmine
.
anything
());
});
});
describe
(
'
hasCachedModel
'
,
()
=>
{
...
...
@@ -69,6 +79,30 @@ describe('Multi-file editor library model manager', () => {
});
});
describe
(
'
removeCachedModel
'
,
()
=>
{
let
f
;
beforeEach
(()
=>
{
f
=
file
();
instance
.
addModel
(
f
);
});
it
(
'
clears cached model
'
,
()
=>
{
instance
.
removeCachedModel
(
f
);
expect
(
instance
.
models
.
size
).
toBe
(
0
);
});
it
(
'
removes eventHub listener
'
,
()
=>
{
spyOn
(
eventHub
,
'
$off
'
).
and
.
callThrough
();
instance
.
removeCachedModel
(
f
);
expect
(
eventHub
.
$off
).
toHaveBeenCalledWith
(
`editor.update.model.dispose.
${
f
.
path
}
`
,
jasmine
.
anything
());
});
});
describe
(
'
dispose
'
,
()
=>
{
it
(
'
clears cached models
'
,
()
=>
{
instance
.
addModel
(
file
());
...
...
spec/javascripts/ide/lib/common/model_spec.js
View file @
174c2f80
/* global monaco */
import
eventHub
from
'
ee/ide/eventhub
'
;
import
monacoLoader
from
'
ee/ide/monaco_loader
'
;
import
Model
from
'
ee/ide/lib/common/model
'
;
import
{
file
}
from
'
../../helpers
'
;
...
...
@@ -7,6 +8,8 @@ describe('Multi-file editor library model', () => {
let
model
;
beforeEach
((
done
)
=>
{
spyOn
(
eventHub
,
'
$on
'
).
and
.
callThrough
();
monacoLoader
([
'
vs/editor/editor.main
'
],
()
=>
{
model
=
new
Model
(
monaco
,
file
(
'
path
'
));
...
...
@@ -23,6 +26,10 @@ describe('Multi-file editor library model', () => {
expect
(
model
.
model
).
not
.
toBeNull
();
});
it
(
'
adds eventHub listener
'
,
()
=>
{
expect
(
eventHub
.
$on
).
toHaveBeenCalledWith
(
`editor.update.model.dispose.
${
model
.
file
.
path
}
`
,
jasmine
.
anything
());
});
describe
(
'
path
'
,
()
=>
{
it
(
'
returns file path
'
,
()
=>
{
expect
(
model
.
path
).
toBe
(
'
path
'
);
...
...
@@ -88,5 +95,13 @@ describe('Multi-file editor library model', () => {
expect
(
model
.
events
.
size
).
toBe
(
0
);
});
it
(
'
removes eventHub listener
'
,
()
=>
{
spyOn
(
eventHub
,
'
$off
'
).
and
.
callThrough
();
model
.
dispose
();
expect
(
eventHub
.
$off
).
toHaveBeenCalledWith
(
`editor.update.model.dispose.
${
model
.
file
.
path
}
`
,
jasmine
.
anything
());
});
});
});
spec/javascripts/ide/lib/editor_spec.js
View file @
174c2f80
...
...
@@ -5,8 +5,16 @@ import { file } from '../helpers';
describe
(
'
Multi-file editor library
'
,
()
=>
{
let
instance
;
let
el
;
let
holder
;
beforeEach
(
done
=>
{
el
=
document
.
createElement
(
'
div
'
);
holder
=
document
.
createElement
(
'
div
'
);
el
.
appendChild
(
holder
);
document
.
body
.
appendChild
(
el
);
beforeEach
((
done
)
=>
{
monacoLoader
([
'
vs/editor/editor.main
'
],
()
=>
{
instance
=
editor
.
create
(
monaco
);
...
...
@@ -16,6 +24,8 @@ describe('Multi-file editor library', () => {
afterEach
(()
=>
{
instance
.
dispose
();
el
.
remove
();
});
it
(
'
creates instance of editor
'
,
()
=>
{
...
...
@@ -27,33 +37,48 @@ describe('Multi-file editor library', () => {
});
describe
(
'
createInstance
'
,
()
=>
{
let
el
;
beforeEach
(()
=>
{
el
=
document
.
createElement
(
'
div
'
);
});
it
(
'
creates editor instance
'
,
()
=>
{
spyOn
(
instance
.
monaco
.
editor
,
'
create
'
).
and
.
callThrough
();
instance
.
createInstance
(
el
);
instance
.
createInstance
(
holder
);
expect
(
instance
.
monaco
.
editor
.
create
).
toHaveBeenCalled
();
});
it
(
'
creates dirty diff controller
'
,
()
=>
{
instance
.
createInstance
(
el
);
instance
.
createInstance
(
holder
);
expect
(
instance
.
dirtyDiffController
).
not
.
toBeNull
();
});
it
(
'
creates model manager
'
,
()
=>
{
instance
.
createInstance
(
el
);
instance
.
createInstance
(
holder
);
expect
(
instance
.
modelManager
).
not
.
toBeNull
();
});
});
describe
(
'
createDiffInstance
'
,
()
=>
{
it
(
'
creates editor instance
'
,
()
=>
{
spyOn
(
instance
.
monaco
.
editor
,
'
createDiffEditor
'
).
and
.
callThrough
();
instance
.
createDiffInstance
(
holder
);
expect
(
instance
.
monaco
.
editor
.
createDiffEditor
).
toHaveBeenCalledWith
(
holder
,
{
model
:
null
,
contextmenu
:
true
,
minimap
:
{
enabled
:
false
,
},
readOnly
:
true
,
scrollBeyondLastLine
:
false
,
},
);
});
});
describe
(
'
createModel
'
,
()
=>
{
it
(
'
calls model manager addModel
'
,
()
=>
{
spyOn
(
instance
.
modelManager
,
'
addModel
'
);
...
...
@@ -87,12 +112,28 @@ describe('Multi-file editor library', () => {
expect
(
instance
.
instance
.
setModel
).
toHaveBeenCalledWith
(
model
.
getModel
());
});
it
(
'
sets original & modified when diff editor
'
,
()
=>
{
spyOn
(
instance
.
instance
,
'
getEditorType
'
).
and
.
returnValue
(
'
vs.editor.IDiffEditor
'
,
);
spyOn
(
instance
.
instance
,
'
setModel
'
);
instance
.
attachModel
(
model
);
expect
(
instance
.
instance
.
setModel
).
toHaveBeenCalledWith
({
original
:
model
.
getOriginalModel
(),
modified
:
model
.
getModel
(),
});
});
it
(
'
attaches the model to the dirty diff controller
'
,
()
=>
{
spyOn
(
instance
.
dirtyDiffController
,
'
attachModel
'
);
instance
.
attachModel
(
model
);
expect
(
instance
.
dirtyDiffController
.
attachModel
).
toHaveBeenCalledWith
(
model
);
expect
(
instance
.
dirtyDiffController
.
attachModel
).
toHaveBeenCalledWith
(
model
,
);
});
it
(
'
re-decorates with the dirty diff controller
'
,
()
=>
{
...
...
@@ -100,7 +141,9 @@ describe('Multi-file editor library', () => {
instance
.
attachModel
(
model
);
expect
(
instance
.
dirtyDiffController
.
reDecorate
).
toHaveBeenCalledWith
(
model
);
expect
(
instance
.
dirtyDiffController
.
reDecorate
).
toHaveBeenCalledWith
(
model
,
);
});
});
...
...
spec/javascripts/ide/stores/actions/file_spec.js
View file @
174c2f80
...
...
@@ -2,6 +2,7 @@ import Vue from 'vue';
import
store
from
'
ee/ide/stores
'
;
import
service
from
'
ee/ide/services
'
;
import
router
from
'
ee/ide/ide_router
'
;
import
eventHub
from
'
ee/ide/eventhub
'
;
import
{
file
,
resetStore
}
from
'
../../helpers
'
;
describe
(
'
Multi-file store file actions
'
,
()
=>
{
...
...
@@ -295,6 +296,8 @@ describe('Multi-file store file actions', () => {
let
tmpFile
;
beforeEach
(()
=>
{
spyOn
(
eventHub
,
'
$on
'
);
tmpFile
=
file
();
tmpFile
.
content
=
'
testing
'
;
...
...
spec/javascripts/ide/stores/actions_spec.js
View file @
174c2f80
...
...
@@ -291,4 +291,15 @@ describe('Multi-file store actions', () => {
.
catch
(
done
.
fail
);
});
});
describe
(
'
updateViewer
'
,
()
=>
{
it
(
'
updates viewer state
'
,
(
done
)
=>
{
store
.
dispatch
(
'
updateViewer
'
,
'
diff
'
)
.
then
(()
=>
{
expect
(
store
.
state
.
viewer
).
toBe
(
'
diff
'
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
});
spec/javascripts/ide/stores/modules/commit/actions_spec.js
View file @
174c2f80
...
...
@@ -409,6 +409,8 @@ describe('IDE commit module actions', () => {
});
it
(
'
redirects to new merge request page
'
,
(
done
)
=>
{
spyOn
(
eventHub
,
'
$on
'
);
store
.
state
.
commit
.
commitAction
=
'
3
'
;
store
.
dispatch
(
'
commit/commitChanges
'
)
...
...
spec/javascripts/ide/stores/mutations_spec.js
View file @
174c2f80
...
...
@@ -68,4 +68,12 @@ describe('Multi-file store mutations', () => {
expect
(
localState
.
rightPanelCollapsed
).
toBeFalsy
();
});
});
describe
(
'
UPDATE_VIEWER
'
,
()
=>
{
it
(
'
sets viewer state
'
,
()
=>
{
mutations
.
UPDATE_VIEWER
(
localState
,
'
diff
'
);
expect
(
localState
.
viewer
).
toBe
(
'
diff
'
);
});
});
});
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