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
574f6a58
Commit
574f6a58
authored
Aug 14, 2017
by
Jacob Schatz
Committed by
Simon Knox
Aug 15, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge branch 'repo-fixes-e' into 'master'
Repo fixes part E See merge request !13472
parent
da18aa8e
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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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 @
574f6a58
<
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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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 @
574f6a58
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 @
574f6a58
...
...
@@ -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 @
574f6a58
...
...
@@ -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