Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Jérome Perrin
gitlab-ce
Commits
0ec54b8f
Commit
0ec54b8f
authored
Aug 14, 2017
by
Jacob Schatz
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'repo-fixes-e' into 'master'
Repo fixes part E See merge request !13472
parents
1983043c
5bf22c86
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
149 additions
and
116 deletions
+149
-116
app/assets/javascripts/repo/components/repo_edit_button.vue
app/assets/javascripts/repo/components/repo_edit_button.vue
+2
-4
app/assets/javascripts/repo/components/repo_preview.vue
app/assets/javascripts/repo/components/repo_preview.vue
+25
-5
app/assets/javascripts/repo/components/repo_sidebar.vue
app/assets/javascripts/repo/components/repo_sidebar.vue
+21
-23
app/assets/javascripts/repo/components/repo_tab.vue
app/assets/javascripts/repo/components/repo_tab.vue
+23
-5
app/assets/javascripts/repo/components/repo_tabs.vue
app/assets/javascripts/repo/components/repo_tabs.vue
+3
-14
app/assets/javascripts/repo/helpers/monaco_loader_helper.js
app/assets/javascripts/repo/helpers/monaco_loader_helper.js
+4
-1
app/assets/javascripts/repo/helpers/repo_helper.js
app/assets/javascripts/repo/helpers/repo_helper.js
+9
-12
app/assets/javascripts/repo/index.js
app/assets/javascripts/repo/index.js
+1
-2
app/assets/javascripts/repo/services/repo_service.js
app/assets/javascripts/repo/services/repo_service.js
+3
-1
app/assets/javascripts/repo/stores/repo_store.js
app/assets/javascripts/repo/stores/repo_store.js
+1
-17
app/assets/stylesheets/pages/tree.scss
app/assets/stylesheets/pages/tree.scss
+4
-0
app/views/projects/tree/_tree_header.html.haml
app/views/projects/tree/_tree_header.html.haml
+3
-2
spec/javascripts/repo/components/repo_sidebar_spec.js
spec/javascripts/repo/components/repo_sidebar_spec.js
+49
-0
spec/javascripts/repo/components/repo_tab_spec.js
spec/javascripts/repo/components/repo_tab_spec.js
+1
-19
spec/javascripts/repo/components/repo_tabs_spec.js
spec/javascripts/repo/components/repo_tabs_spec.js
+0
-11
No files found.
app/assets/javascripts/repo/components/repo_edit_button.vue
View file @
0ec54b8f
...
...
@@ -29,12 +29,10 @@ export default {
editMode
()
{
if
(
this
.
editMode
)
{
$
(
'
.project-refs-form
'
).
addClass
(
'
disabled
'
);
$
(
'
.fa-long-arrow-right
'
).
show
();
$
(
'
.project-refs-target-form
'
).
show
();
$
(
'
.js-tree-ref-target-holder
'
).
show
();
}
else
{
$
(
'
.project-refs-form
'
).
removeClass
(
'
disabled
'
);
$
(
'
.fa-long-arrow-right
'
).
hide
();
$
(
'
.project-refs-target-form
'
).
hide
();
$
(
'
.js-tree-ref-target-holder
'
).
hide
();
}
},
},
...
...
app/assets/javascripts/repo/components/repo_preview.vue
View file @
0ec54b8f
...
...
@@ -4,7 +4,7 @@ import Store from '../stores/repo_store';
export
default
{
data
:
()
=>
Store
,
mounted
()
{
$
(
this
.
$el
).
find
(
'
.file-content
'
).
syntaxHighlight
();
this
.
highlightFile
();
},
computed
:
{
html
()
{
...
...
@@ -12,10 +12,16 @@ export default {
},
},
methods
:
{
highlightFile
()
{
$
(
this
.
$el
).
find
(
'
.file-content
'
).
syntaxHighlight
();
},
},
watch
:
{
html
()
{
this
.
$nextTick
(()
=>
{
$
(
this
.
$el
).
find
(
'
.file-content
'
).
syntaxHighlight
();
this
.
highlightFile
();
});
},
},
...
...
@@ -24,9 +30,23 @@ export default {
<
template
>
<div>
<div
v-if=
"!activeFile.render_error"
v-html=
"activeFile.html"
></div>
<div
v-if=
"activeFile.render_error"
class=
"vertical-center render-error"
>
<p
class=
"text-center"
>
The source could not be displayed because it is too large. You can
<a
:href=
"activeFile.raw_path"
>
download
</a>
it instead.
</p>
<div
v-if=
"!activeFile.render_error"
v-html=
"activeFile.html"
>
</div>
<div
v-else-if=
"activeFile.tooLarge"
class=
"vertical-center render-error"
>
<p
class=
"text-center"
>
The source could not be displayed because it is too large. You can
<a
:href=
"activeFile.raw_path"
>
download
</a>
it instead.
</p>
</div>
<div
v-else
class=
"vertical-center render-error"
>
<p
class=
"text-center"
>
The source could not be displayed because a rendering error occured. You can
<a
:href=
"activeFile.raw_path"
>
download
</a>
it instead.
</p>
</div>
</div>
</
template
>
app/assets/javascripts/repo/components/repo_sidebar.vue
View file @
0ec54b8f
...
...
@@ -33,32 +33,30 @@ const RepoSidebar = {
});
},
linkClicked
(
clickedFile
)
{
let
url
=
''
;
fileClicked
(
clickedFile
)
{
let
file
=
clickedFile
;
if
(
typeof
file
===
'
object
'
)
{
file
.
loading
=
true
;
if
(
file
.
type
===
'
tree
'
&&
file
.
opened
)
{
file
=
Store
.
removeChildFilesOfTree
(
file
);
file
.
loading
=
false
;
}
else
{
url
=
file
.
url
;
Service
.
url
=
url
;
// I need to refactor this to do the `then` here.
// Not a callback. For now this is good enough.
// it works.
Helper
.
getContent
(
file
,
()
=>
{
Service
.
url
=
file
.
url
;
Helper
.
getContent
(
file
)
.
then
(()
=>
{
file
.
loading
=
false
;
Helper
.
scrollTabsRight
();
});
}
}
else
if
(
typeof
file
===
'
string
'
)
{
// go back
url
=
file
;
Service
.
url
=
url
;
Helper
.
getContent
(
null
,
()
=>
Helper
.
scrollTabsRight
());
})
.
catch
(
Helper
.
loadingError
);
}
},
goToPreviousDirectoryClicked
(
prevURL
)
{
Service
.
url
=
prevURL
;
Helper
.
getContent
(
null
)
.
then
(()
=>
Helper
.
scrollTabsRight
())
.
catch
(
Helper
.
loadingError
);
},
},
};
...
...
@@ -82,7 +80,7 @@ export default RepoSidebar;
<repo-previous-directory
v-if=
"isRoot"
:prev-url=
"prevURL"
@
linkclicked=
"
link
Clicked(prevURL)"
/>
@
linkclicked=
"
goToPreviousDirectory
Clicked(prevURL)"
/>
<repo-loading-file
v-for=
"n in 5"
:key=
"n"
...
...
@@ -94,7 +92,7 @@ export default RepoSidebar;
:key=
"file.id"
:file=
"file"
:is-mini=
"isMini"
@
linkclicked=
"
link
Clicked(file)"
@
linkclicked=
"
file
Clicked(file)"
:is-tree=
"isTree"
:has-files=
"!!files.length"
:active-file=
"activeFile"
/>
...
...
app/assets/javascripts/repo/components/repo_tab.vue
View file @
0ec54b8f
...
...
@@ -10,6 +10,12 @@ const RepoTab = {
},
computed
:
{
closeLabel
()
{
if
(
this
.
tab
.
changed
)
{
return
`
${
this
.
tab
.
name
}
changed`
;
}
return
`Close
${
this
.
tab
.
name
}
`
;
},
changedClass
()
{
const
tabChangedObj
=
{
'
fa-times
'
:
!
this
.
tab
.
changed
,
...
...
@@ -34,12 +40,24 @@ export default RepoTab;
<
template
>
<li>
<a
href=
"#"
class=
"close"
@
click.prevent=
"xClicked(tab)"
v-if=
"!tab.loading"
>
<i
class=
"fa"
:class=
"changedClass"
></i>
<a
href=
"#0"
class=
"close"
@
click.prevent=
"xClicked(tab)"
:aria-label=
"closeLabel"
>
<i
class=
"fa"
:class=
"changedClass"
aria-hidden=
"true"
>
</i>
</a>
<a
href=
"#"
class=
"repo-tab"
v-if=
"!tab.loading"
:title=
"tab.url"
@
click.prevent=
"tabClicked(tab)"
>
{{
tab
.
name
}}
</a>
<i
v-if=
"tab.loading"
class=
"fa fa-spinner fa-spin"
></i>
<a
href=
"#"
class=
"repo-tab"
:title=
"tab.url"
@
click.prevent=
"tabClicked(tab)"
>
{{
tab
.
name
}}
</a>
</li>
</
template
>
app/assets/javascripts/repo/components/repo_tabs.vue
View file @
0ec54b8f
<
script
>
import
Vue
from
'
vue
'
;
import
Store
from
'
../stores/repo_store
'
;
import
RepoTab
from
'
./repo_tab.vue
'
;
import
RepoMixin
from
'
../mixins/repo_mixin
'
;
...
...
@@ -14,29 +13,19 @@ const RepoTabs = {
data
:
()
=>
Store
,
methods
:
{
isOverflow
()
{
return
this
.
$el
.
scrollWidth
>
this
.
$el
.
offsetWidth
;
},
xClicked
(
file
)
{
Store
.
removeFromOpenedFiles
(
file
);
},
},
watch
:
{
openedFiles
()
{
Vue
.
nextTick
(()
=>
{
this
.
tabsOverflow
=
this
.
isOverflow
();
});
},
},
};
export
default
RepoTabs
;
</
script
>
<
template
>
<ul
id=
"tabs"
v-if=
"isMini"
v-cloak
:class=
"
{'overflown': tabsOverflow}">
<ul
v-if=
"isMini"
id=
"tabs"
>
<repo-tab
v-for=
"tab in openedFiles"
:key=
"tab.id"
:tab=
"tab"
:class=
"
{'active' : tab.active}" @xclicked="xClicked"/>
<li
class=
"tabs-divider"
/>
</ul>
...
...
app/assets/javascripts/repo/helpers/monaco_loader_helper.js
View file @
0ec54b8f
...
...
@@ -10,7 +10,10 @@ function repoEditorLoader() {
Store
.
monaco
=
monaco
;
Store
.
monacoLoading
=
false
;
resolve
(
RepoEditor
);
},
reject
);
},
()
=>
{
Store
.
monacoLoading
=
false
;
reject
();
});
});
}
...
...
app/assets/javascripts/repo/helpers/repo_helper.js
View file @
0ec54b8f
...
...
@@ -33,12 +33,16 @@ const RepoHelper = {
?
window
.
performance
:
Date
,
getFileExtension
(
fileName
)
{
return
fileName
.
split
(
'
.
'
).
pop
();
},
getBranch
()
{
return
$
(
'
button.dropdown-menu-toggle
'
).
attr
(
'
data-ref
'
);
},
getLanguageIDForFile
(
file
,
langs
)
{
const
ext
=
file
.
name
.
split
(
'
.
'
).
pop
(
);
const
ext
=
RepoHelper
.
getFileExtension
(
file
.
name
);
const
foundLang
=
RepoHelper
.
findLanguage
(
ext
,
langs
);
return
foundLang
?
foundLang
.
id
:
'
plaintext
'
;
...
...
@@ -135,21 +139,19 @@ const RepoHelper = {
return
isRoot
;
},
getContent
(
treeOrFile
,
cb
)
{
getContent
(
treeOrFile
)
{
let
file
=
treeOrFile
;
// const loadingData = RepoHelper.setLoading(true);
return
Service
.
getContent
()
.
then
((
response
)
=>
{
const
data
=
response
.
data
;
// RepoHelper.setLoading(false, loadingData);
if
(
cb
)
cb
();
Store
.
isTree
=
RepoHelper
.
isTree
(
data
);
if
(
!
Store
.
isTree
)
{
if
(
!
file
)
file
=
data
;
Store
.
binary
=
data
.
binary
;
if
(
data
.
binary
)
{
Store
.
binaryMimeType
=
data
.
mime_type
;
// file might be undefined
RepoHelper
.
setBinaryDataAsBase64
(
data
);
Store
.
setViewToPreview
();
...
...
@@ -188,9 +190,8 @@ const RepoHelper = {
setFile
(
data
,
file
)
{
const
newFile
=
data
;
newFile
.
url
=
file
.
url
||
location
.
pathname
;
newFile
.
url
=
file
.
url
;
if
(
newFile
.
render_error
===
'
too_large
'
)
{
if
(
newFile
.
render_error
===
'
too_large
'
||
newFile
.
render_error
===
'
collapsed
'
)
{
newFile
.
tooLarge
=
true
;
}
newFile
.
newContent
=
''
;
...
...
@@ -199,10 +200,6 @@ const RepoHelper = {
Store
.
setActiveFiles
(
newFile
);
},
toFA
(
icon
)
{
return
`fa-
${
icon
}
`
;
},
serializeBlob
(
blob
)
{
const
simpleBlob
=
RepoHelper
.
serializeRepoEntity
(
'
blob
'
,
blob
);
simpleBlob
.
lastCommitMessage
=
blob
.
last_commit
.
message
;
...
...
@@ -226,7 +223,7 @@ const RepoHelper = {
type
,
name
,
url
,
icon
:
RepoHelper
.
toFA
(
icon
)
,
icon
:
`fa-
${
icon
}
`
,
level
:
0
,
loading
:
false
,
};
...
...
@@ -244,7 +241,7 @@ const RepoHelper = {
setTimeout
(()
=>
{
const
tabs
=
document
.
getElementById
(
'
tabs
'
);
if
(
!
tabs
)
return
;
tabs
.
scrollLeft
=
12000
;
tabs
.
scrollLeft
=
tabs
.
scrollWidth
;
},
200
);
},
...
...
app/assets/javascripts/repo/index.js
View file @
0ec54b8f
...
...
@@ -7,8 +7,7 @@ import RepoEditButton from './components/repo_edit_button.vue';
import
Translate
from
'
../vue_shared/translate
'
;
function
initDropdowns
()
{
$
(
'
.project-refs-target-form
'
).
hide
();
$
(
'
.fa-long-arrow-right
'
).
hide
();
$
(
'
.js-tree-ref-target-holder
'
).
hide
();
}
function
addEventsForNonVueEls
()
{
...
...
app/assets/javascripts/repo/services/repo_service.js
View file @
0ec54b8f
...
...
@@ -2,6 +2,7 @@
import
axios
from
'
axios
'
;
import
Store
from
'
../stores/repo_store
'
;
import
Api
from
'
../../api
'
;
import
Helper
from
'
../helpers/repo_helper
'
;
const
RepoService
=
{
url
:
''
,
...
...
@@ -22,6 +23,7 @@ const RepoService = {
getRaw
(
url
)
{
return
axios
.
get
(
url
,
{
// Stop Axios from parsing a JSON file into a JS object
transformResponse
:
[
res
=>
res
],
});
},
...
...
@@ -36,7 +38,7 @@ const RepoService = {
},
urlIsRichBlob
(
url
=
this
.
url
)
{
const
extension
=
url
.
split
(
'
.
'
).
pop
(
);
const
extension
=
Helper
.
getFileExtension
(
url
);
return
this
.
richExtensionRegExp
.
test
(
extension
);
},
...
...
app/assets/javascripts/repo/stores/repo_store.js
View file @
0ec54b8f
...
...
@@ -3,13 +3,10 @@ import Helper from '../helpers/repo_helper';
import
Service
from
'
../services/repo_service
'
;
const
RepoStore
=
{
ideEl
:
{},
monaco
:
{},
monacoLoading
:
false
,
monacoInstance
:
{},
service
:
''
,
editor
:
''
,
sidebar
:
''
,
editMode
:
false
,
isTree
:
false
,
isRoot
:
false
,
...
...
@@ -17,19 +14,10 @@ const RepoStore = {
projectId
:
''
,
projectName
:
''
,
projectUrl
:
''
,
trees
:
[],
blobs
:
[],
submodules
:
[],
blobRaw
:
''
,
blobRendered
:
''
,
currentBlobView
:
'
repo-preview
'
,
openedFiles
:
[],
tabSize
:
100
,
defaultTabSize
:
100
,
minTabSize
:
30
,
tabsOverflow
:
41
,
submitCommitsLoading
:
false
,
binaryLoaded
:
false
,
dialog
:
{
open
:
false
,
title
:
''
,
...
...
@@ -45,9 +33,6 @@ const RepoStore = {
currentBranch
:
''
,
targetBranch
:
'
new-branch
'
,
commitMessage
:
''
,
binaryMimeType
:
''
,
// scroll bar space for windows
scrollWidth
:
0
,
binaryTypes
:
{
png
:
false
,
md
:
false
,
...
...
@@ -58,7 +43,6 @@ const RepoStore = {
tree
:
false
,
blob
:
false
,
},
readOnly
:
true
,
resetBinaryTypes
()
{
Object
.
keys
(
RepoStore
.
binaryTypes
).
forEach
((
key
)
=>
{
...
...
@@ -96,7 +80,6 @@ const RepoStore = {
if
(
file
.
binary
)
{
RepoStore
.
blobRaw
=
file
.
base64
;
RepoStore
.
binaryMimeType
=
file
.
mime_type
;
}
else
if
(
file
.
newContent
||
file
.
plain
)
{
RepoStore
.
blobRaw
=
file
.
newContent
||
file
.
plain
;
}
else
{
...
...
@@ -238,4 +221,5 @@ const RepoStore = {
return
RepoStore
.
currentBlobView
===
'
repo-preview
'
;
},
};
export
default
RepoStore
;
app/assets/stylesheets/pages/tree.scss
View file @
0ec54b8f
...
...
@@ -29,6 +29,10 @@
margin-right
:
15px
;
}
.tree-ref-target-holder
{
display
:
inline-block
;
}
.repo-breadcrumb
{
li
:last-of-type
{
position
:
relative
;
...
...
app/views/projects/tree/_tree_header.html.haml
View file @
0ec54b8f
...
...
@@ -2,6 +2,7 @@
.tree-ref-holder
=
render
'shared/ref_switcher'
,
destination:
'tree'
,
path:
@path
-
if
show_new_repo?
.tree-ref-target-holder.js-tree-ref-target-holder
=
icon
(
'long-arrow-right'
,
title:
'to target branch'
)
=
render
'shared/target_switcher'
,
destination:
'tree'
,
path:
@path
...
...
spec/javascripts/repo/components/repo_sidebar_spec.js
View file @
0ec54b8f
import
Vue
from
'
vue
'
;
import
Helper
from
'
~/repo/helpers/repo_helper
'
;
import
RepoService
from
'
~/repo/services/repo_service
'
;
import
RepoStore
from
'
~/repo/stores/repo_store
'
;
import
repoSidebar
from
'
~/repo/components/repo_sidebar.vue
'
;
...
...
@@ -58,4 +60,51 @@ describe('RepoSidebar', () => {
expect
(
vm
.
$el
.
querySelector
(
'
tbody .prev-directory
'
)).
toBeTruthy
();
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
fileClicked
'
,
()
=>
{
it
(
'
should fetch data for new file
'
,
()
=>
{
spyOn
(
Helper
,
'
getContent
'
).
and
.
callThrough
();
const
file1
=
{
id
:
0
,
url
:
''
,
};
RepoStore
.
files
=
[
file1
];
RepoStore
.
isRoot
=
true
;
const
vm
=
createComponent
();
vm
.
fileClicked
(
file1
);
expect
(
Helper
.
getContent
).
toHaveBeenCalledWith
(
file1
);
});
it
(
'
should hide files in directory if already open
'
,
()
=>
{
spyOn
(
RepoStore
,
'
removeChildFilesOfTree
'
).
and
.
callThrough
();
const
file1
=
{
id
:
0
,
type
:
'
tree
'
,
url
:
''
,
opened
:
true
,
};
RepoStore
.
files
=
[
file1
];
RepoStore
.
isRoot
=
true
;
const
vm
=
createComponent
();
vm
.
fileClicked
(
file1
);
expect
(
RepoStore
.
removeChildFilesOfTree
).
toHaveBeenCalledWith
(
file1
);
});
});
describe
(
'
goToPreviousDirectoryClicked
'
,
()
=>
{
it
(
'
should hide files in directory if already open
'
,
()
=>
{
const
prevUrl
=
'
foo/bar
'
;
const
vm
=
createComponent
();
vm
.
goToPreviousDirectoryClicked
(
prevUrl
);
expect
(
RepoService
.
url
).
toEqual
(
prevUrl
);
});
});
});
});
spec/javascripts/repo/components/repo_tab_spec.js
View file @
0ec54b8f
...
...
@@ -12,7 +12,6 @@ describe('RepoTab', () => {
it
(
'
renders a close link and a name link
'
,
()
=>
{
const
tab
=
{
loading
:
false
,
url
:
'
url
'
,
name
:
'
name
'
,
};
...
...
@@ -26,7 +25,7 @@ describe('RepoTab', () => {
spyOn
(
vm
,
'
tabClicked
'
);
expect
(
close
.
querySelector
(
'
.fa-times
'
)).
toBeTruthy
();
expect
(
name
.
textContent
).
toEqual
(
tab
.
name
);
expect
(
name
.
textContent
.
trim
()
).
toEqual
(
tab
.
name
);
close
.
click
();
name
.
click
();
...
...
@@ -35,25 +34,8 @@ describe('RepoTab', () => {
expect
(
vm
.
tabClicked
).
toHaveBeenCalledWith
(
tab
);
});
it
(
'
renders a spinner if tab is loading
'
,
()
=>
{
const
tab
=
{
loading
:
true
,
url
:
'
url
'
,
};
const
vm
=
createComponent
({
tab
,
});
const
close
=
vm
.
$el
.
querySelector
(
'
.close
'
);
const
name
=
vm
.
$el
.
querySelector
(
`a[title="
${
tab
.
url
}
"]`
);
expect
(
close
).
toBeFalsy
();
expect
(
name
).
toBeFalsy
();
expect
(
vm
.
$el
.
querySelector
(
'
.fa.fa-spinner.fa-spin
'
)).
toBeTruthy
();
});
it
(
'
renders an fa-circle icon if tab is changed
'
,
()
=>
{
const
tab
=
{
loading
:
false
,
url
:
'
url
'
,
name
:
'
name
'
,
changed
:
true
,
...
...
spec/javascripts/repo/components/repo_tabs_spec.js
View file @
0ec54b8f
...
...
@@ -18,13 +18,11 @@ describe('RepoTabs', () => {
it
(
'
renders a list of tabs
'
,
()
=>
{
RepoStore
.
openedFiles
=
openedFiles
;
RepoStore
.
tabsOverflow
=
true
;
const
vm
=
createComponent
();
const
tabs
=
[...
vm
.
$el
.
querySelectorAll
(
'
:scope > li
'
)];
expect
(
vm
.
$el
.
id
).
toEqual
(
'
tabs
'
);
expect
(
vm
.
$el
.
classList
.
contains
(
'
overflown
'
)).
toBeTruthy
();
expect
(
tabs
.
length
).
toEqual
(
3
);
expect
(
tabs
[
0
].
classList
.
contains
(
'
active
'
)).
toBeTruthy
();
expect
(
tabs
[
1
].
classList
.
contains
(
'
active
'
)).
toBeFalsy
();
...
...
@@ -39,15 +37,6 @@ describe('RepoTabs', () => {
expect
(
vm
.
$el
.
innerHTML
).
toBeFalsy
();
});
it
(
'
does not apply overflown class if not tabsOverflow
'
,
()
=>
{
RepoStore
.
openedFiles
=
openedFiles
;
RepoStore
.
tabsOverflow
=
false
;
const
vm
=
createComponent
();
expect
(
vm
.
$el
.
classList
.
contains
(
'
overflown
'
)).
toBeFalsy
();
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
xClicked
'
,
()
=>
{
it
(
'
calls removeFromOpenedFiles with file obj
'
,
()
=>
{
...
...
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