Commit 48dacd5e authored by Sean McGivern's avatar Sean McGivern

Merge branch 'tz-ide-file-icons' into 'master'

Multi File Editor File icons

See merge request gitlab-org/gitlab-ce!16100
parents dacef283 3a727aa6
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import timeAgoMixin from '../../vue_shared/mixins/timeago'; import timeAgoMixin from '../../vue_shared/mixins/timeago';
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue'; import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
import newDropdown from './new_dropdown/index.vue'; import newDropdown from './new_dropdown/index.vue';
import fileIcon from '../../vue_shared/components/file_icon.vue';
export default { export default {
mixins: [ mixins: [
...@@ -11,6 +12,7 @@ ...@@ -11,6 +12,7 @@
components: { components: {
skeletonLoadingContainer, skeletonLoadingContainer,
newDropdown, newDropdown,
fileIcon,
}, },
props: { props: {
file: { file: {
...@@ -26,13 +28,6 @@ ...@@ -26,13 +28,6 @@
...mapState([ ...mapState([
'leftPanelCollapsed', 'leftPanelCollapsed',
]), ]),
fileIcon() {
return {
'fa-spinner fa-spin': this.file.loading,
[this.file.icon]: !this.file.loading,
'fa-folder-open': !this.file.loading && this.file.opened,
};
},
isSubmodule() { isSubmodule() {
return this.file.type === 'submodule'; return this.file.type === 'submodule';
}, },
...@@ -94,16 +89,18 @@ ...@@ -94,16 +89,18 @@
class="multi-file-table-name" class="multi-file-table-name"
:colspan="submoduleColSpan" :colspan="submoduleColSpan"
> >
<i
class="fa fa-fw file-icon"
:class="fileIcon"
:style="levelIndentation"
aria-hidden="true"
>
</i>
<a <a
class="repo-file-name" class="repo-file-name"
> >
<file-icon
:file-name="file.name"
:loading="file.loading"
:folder="file.type === 'tree'"
:opened="file.opened"
:style="levelIndentation"
:size="16"
>
</file-icon>
{{ file.name }} {{ file.name }}
</a> </a>
<new-dropdown <new-dropdown
......
<script> <script>
import { mapActions } from 'vuex'; import { mapActions } from 'vuex';
import fileIcon from '../../vue_shared/components/file_icon.vue';
export default { export default {
props: { props: {
...@@ -8,7 +9,9 @@ export default { ...@@ -8,7 +9,9 @@ export default {
required: true, required: true,
}, },
}, },
components: {
fileIcon,
},
computed: { computed: {
closeLabel() { closeLabel() {
if (this.tab.changed || this.tab.tempFile) { if (this.tab.changed || this.tab.tempFile) {
...@@ -63,6 +66,11 @@ export default { ...@@ -63,6 +66,11 @@ export default {
:class="{active : tab.active }" :class="{active : tab.active }"
:title="tab.url" :title="tab.url"
> >
<file-icon
:file-name="tab.name"
:size="16"
>
</file-icon>
{{ tab.name }} {{ tab.name }}
</div> </div>
</li> </li>
......
<script>
import getIconForFile from './file_icon/file_icon_map';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import icon from '../../vue_shared/components/icon.vue';
/* This is a re-usable vue component for rendering a svg sprite
icon
Sample configuration:
<file-icon
name="retry"
:size="32"
css-classes="top"
/>
*/
export default {
props: {
fileName: {
type: String,
required: true,
},
folder: {
type: Boolean,
required: false,
default: false,
},
opened: {
type: Boolean,
required: false,
default: false,
},
loading: {
type: Boolean,
required: false,
default: false,
},
size: {
type: Number,
required: false,
default: 16,
},
cssClasses: {
type: String,
required: false,
default: '',
},
},
components: {
loadingIcon,
icon,
},
computed: {
spriteHref() {
const iconName = getIconForFile(this.fileName) || 'file';
return `${gon.sprite_file_icons}#${iconName}`;
},
folderIconName() {
// We don't have a open folder icon yet
return this.opened ? 'folder' : 'folder';
},
iconSizeClass() {
return this.size ? `s${this.size}` : '';
},
},
};
</script>
<template>
<span>
<svg
:class="[iconSizeClass, cssClasses]"
v-if="!loading && !folder">
<use
v-bind="{'xlink:href':spriteHref}"/>
</svg>
<icon
v-if="!loading && folder"
:name="folderIconName"
:size="size"
/>
<loading-icon
v-if="loading"
:inline="true"
/>
</span>
</template>
const fileExtensionIcons = {
html: 'html',
htm: 'html',
html_vm: 'html',
asp: 'html',
jade: 'pug',
pug: 'pug',
md: 'markdown',
'md.rendered': 'markdown',
markdown: 'markdown',
'markdown.rendered': 'markdown',
rst: 'markdown',
blink: 'blink',
css: 'css',
scss: 'sass',
sass: 'sass',
less: 'less',
json: 'json',
yaml: 'yaml',
'YAML-tmLanguage': 'yaml',
yml: 'yaml',
xml: 'xml',
plist: 'xml',
xsd: 'xml',
dtd: 'xml',
xsl: 'xml',
xslt: 'xml',
resx: 'xml',
iml: 'xml',
xquery: 'xml',
tmLanguage: 'xml',
manifest: 'xml',
project: 'xml',
png: 'image',
jpeg: 'image',
jpg: 'image',
gif: 'image',
svg: 'image',
ico: 'image',
tif: 'image',
tiff: 'image',
psd: 'image',
psb: 'image',
ami: 'image',
apx: 'image',
bmp: 'image',
bpg: 'image',
brk: 'image',
cur: 'image',
dds: 'image',
dng: 'image',
exr: 'image',
fpx: 'image',
gbr: 'image',
img: 'image',
jbig2: 'image',
jb2: 'image',
jng: 'image',
jxr: 'image',
pbm: 'image',
pgf: 'image',
pic: 'image',
raw: 'image',
webp: 'image',
js: 'javascript',
ejs: 'javascript',
esx: 'javascript',
jsx: 'react',
tsx: 'react',
ini: 'settings',
dlc: 'settings',
dll: 'settings',
config: 'settings',
conf: 'settings',
properties: 'settings',
prop: 'settings',
settings: 'settings',
option: 'settings',
props: 'settings',
toml: 'settings',
prefs: 'settings',
'sln.dotsettings': 'settings',
'sln.dotsettings.user': 'settings',
ts: 'typescript',
'd.ts': 'typescript-def',
marko: 'markojs',
pdf: 'pdf',
xlsx: 'table',
xls: 'table',
csv: 'table',
tsv: 'table',
vscodeignore: 'vscode',
vsixmanifest: 'vscode',
vsix: 'vscode',
'code-workplace': 'vscode',
suo: 'visualstudio',
sln: 'visualstudio',
csproj: 'visualstudio',
vb: 'visualstudio',
pdb: 'database',
sql: 'database',
pks: 'database',
pkb: 'database',
accdb: 'database',
mdb: 'database',
sqlite: 'database',
cs: 'csharp',
zip: 'zip',
tar: 'zip',
gz: 'zip',
xz: 'zip',
bzip2: 'zip',
gzip: 'zip',
'7z': 'zip',
rar: 'zip',
tgz: 'zip',
exe: 'exe',
msi: 'exe',
java: 'java',
jar: 'java',
jsp: 'java',
c: 'c',
m: 'c',
h: 'h',
cc: 'cpp',
cpp: 'cpp',
mm: 'cpp',
cxx: 'cpp',
hpp: 'hpp',
go: 'go',
py: 'python',
url: 'url',
sh: 'console',
ksh: 'console',
csh: 'console',
tcsh: 'console',
zsh: 'console',
bash: 'console',
bat: 'console',
cmd: 'console',
ps1: 'powershell',
psm1: 'powershell',
psd1: 'powershell',
ps1xml: 'powershell',
psc1: 'powershell',
pssc: 'powershell',
gradle: 'gradle',
doc: 'word',
docx: 'word',
rtf: 'word',
cer: 'certificate',
cert: 'certificate',
crt: 'certificate',
pub: 'key',
key: 'key',
pem: 'key',
asc: 'key',
gpg: 'key',
woff: 'font',
woff2: 'font',
ttf: 'font',
eot: 'font',
suit: 'font',
otf: 'font',
bmap: 'font',
fnt: 'font',
odttf: 'font',
ttc: 'font',
font: 'font',
fonts: 'font',
sui: 'font',
ntf: 'font',
mrf: 'font',
lib: 'lib',
bib: 'lib',
rb: 'ruby',
erb: 'ruby',
fs: 'fsharp',
fsx: 'fsharp',
fsi: 'fsharp',
fsproj: 'fsharp',
swift: 'swift',
ino: 'arduino',
dockerignore: 'docker',
dockerfile: 'docker',
tex: 'tex',
cls: 'tex',
sty: 'tex',
pptx: 'powerpoint',
ppt: 'powerpoint',
pptm: 'powerpoint',
potx: 'powerpoint',
pot: 'powerpoint',
potm: 'powerpoint',
ppsx: 'powerpoint',
ppsm: 'powerpoint',
pps: 'powerpoint',
ppam: 'powerpoint',
ppa: 'powerpoint',
webm: 'movie',
mkv: 'movie',
flv: 'movie',
vob: 'movie',
ogv: 'movie',
ogg: 'movie',
gifv: 'movie',
avi: 'movie',
mov: 'movie',
qt: 'movie',
wmv: 'movie',
yuv: 'movie',
rm: 'movie',
rmvb: 'movie',
mp4: 'movie',
m4v: 'movie',
mpg: 'movie',
mp2: 'movie',
mpeg: 'movie',
mpe: 'movie',
mpv: 'movie',
m2v: 'movie',
vdi: 'virtual',
vbox: 'virtual',
'vbox-prev': 'virtual',
ics: 'email',
mp3: 'music',
flac: 'music',
m4a: 'music',
wma: 'music',
aiff: 'music',
coffee: 'coffee',
txt: 'document',
graphql: 'graphql',
rs: 'rust',
raml: 'raml',
xaml: 'xaml',
hs: 'haskell',
kt: 'kotlin',
kts: 'kotlin',
patch: 'git',
lua: 'lua',
clj: 'clojure',
cljs: 'clojure',
groovy: 'groovy',
r: 'r',
rmd: 'r',
dart: 'dart',
as: 'actionscript',
mxml: 'mxml',
ahk: 'autohotkey',
swf: 'flash',
swc: 'swc',
cmake: 'cmake',
asm: 'assembly',
a51: 'assembly',
inc: 'assembly',
nasm: 'assembly',
s: 'assembly',
ms: 'assembly',
agc: 'assembly',
ags: 'assembly',
aea: 'assembly',
argus: 'assembly',
mitigus: 'assembly',
binsource: 'assembly',
vue: 'vue',
ml: 'ocaml',
mli: 'ocaml',
cmx: 'ocaml',
'js.map': 'javascript-map',
'css.map': 'css-map',
lock: 'lock',
hbs: 'handlebars',
mustache: 'handlebars',
pl: 'perl',
pm: 'perl',
hx: 'haxe',
'spec.ts': 'test-ts',
'test.ts': 'test-ts',
'ts.snap': 'test-ts',
'spec.tsx': 'test-jsx',
'test.tsx': 'test-jsx',
'tsx.snap': 'test-jsx',
'spec.jsx': 'test-jsx',
'test.jsx': 'test-jsx',
'jsx.snap': 'test-jsx',
'spec.js': 'test-js',
'test.js': 'test-js',
'js.snap': 'test-js',
'routing.ts': 'angular-routing',
'routing.js': 'angular-routing',
'module.ts': 'angular',
'module.js': 'angular',
'ng-template': 'angular',
'component.ts': 'angular-component',
'component.js': 'angular-component',
'guard.ts': 'angular-guard',
'guard.js': 'angular-guard',
'service.ts': 'angular-service',
'service.js': 'angular-service',
'pipe.ts': 'angular-pipe',
'pipe.js': 'angular-pipe',
'filter.js': 'angular-pipe',
'directive.ts': 'angular-directive',
'directive.js': 'angular-directive',
'resolver.ts': 'angular-resolver',
'resolver.js': 'angular-resolver',
pp: 'puppet',
ex: 'elixir',
exs: 'elixir',
ls: 'livescript',
erl: 'erlang',
twig: 'twig',
jl: 'julia',
elm: 'elm',
pure: 'purescript',
tpl: 'smarty',
styl: 'stylus',
re: 'reason',
rei: 'reason',
cmj: 'bucklescript',
merlin: 'merlin',
v: 'verilog',
vhd: 'verilog',
sv: 'verilog',
svh: 'verilog',
nb: 'mathematica',
wl: 'wolframlanguage',
wls: 'wolframlanguage',
njk: 'nunjucks',
nunjucks: 'nunjucks',
robot: 'robot',
sol: 'solidity',
au3: 'autoit',
haml: 'haml',
yang: 'yang',
tf: 'terraform',
'tf.json': 'terraform',
tfvars: 'terraform',
tfstate: 'terraform',
'blade.php': 'laravel',
'inky.php': 'laravel',
applescript: 'applescript',
cake: 'cake',
feature: 'cucumber',
nim: 'nim',
nimble: 'nim',
apib: 'apiblueprint',
apiblueprint: 'apiblueprint',
tag: 'riot',
vfl: 'vfl',
kl: 'kl',
pcss: 'postcss',
sss: 'postcss',
todo: 'todo',
cfml: 'coldfusion',
cfc: 'coldfusion',
lucee: 'coldfusion',
cabal: 'cabal',
nix: 'nix',
slim: 'slim',
http: 'http',
rest: 'http',
rql: 'restql',
restql: 'restql',
kv: 'kivy',
graphcool: 'graphcool',
sbt: 'sbt',
'reducer.ts': 'ngrx-reducer',
'rootReducer.ts': 'ngrx-reducer',
'state.ts': 'ngrx-state',
'actions.ts': 'ngrx-actions',
'effects.ts': 'ngrx-effects',
cr: 'crystal',
'drone.yml': 'drone',
cu: 'cuda',
cuh: 'cuda',
log: 'log',
};
const fileNameIcons = {
'.jscsrc': 'json',
'.jshintrc': 'json',
'tsconfig.json': 'json',
'tslint.json': 'json',
'composer.lock': 'json',
'.jsbeautifyrc': 'json',
'.esformatter': 'json',
'cdp.pid': 'json',
'.htaccess': 'xml',
'.jshintignore': 'settings',
'.buildignore': 'settings',
makefile: 'settings',
'.mrconfig': 'settings',
'.yardopts': 'settings',
'gradle.properties': 'gradle',
gradlew: 'gradle',
'gradle-wrapper.properties': 'gradle',
license: 'certificate',
'license.md': 'certificate',
'license.md.rendered': 'certificate',
'license.txt': 'certificate',
licence: 'certificate',
'licence.md': 'certificate',
'licence.md.rendered': 'certificate',
'licence.txt': 'certificate',
dockerfile: 'docker',
'docker-compose.yml': 'docker',
'.mailmap': 'email',
'.gitignore': 'git',
'.gitconfig': 'git',
'.gitattributes': 'git',
'.gitmodules': 'git',
'.gitkeep': 'git',
'git-history': 'git',
'.Rhistory': 'r',
'cmakelists.txt': 'cmake',
'cmakecache.txt': 'cmake',
'angular-cli.json': 'angular',
'.angular-cli.json': 'angular',
'.vfl': 'vfl',
'.kl': 'kl',
'postcss.config.js': 'postcss',
'.postcssrc.js': 'postcss',
'project.graphcool': 'graphcool',
'webpack.js': 'webpack',
'webpack.ts': 'webpack',
'webpack.base.js': 'webpack',
'webpack.base.ts': 'webpack',
'webpack.config.js': 'webpack',
'webpack.config.ts': 'webpack',
'webpack.common.js': 'webpack',
'webpack.common.ts': 'webpack',
'webpack.config.common.js': 'webpack',
'webpack.config.common.ts': 'webpack',
'webpack.config.common.babel.js': 'webpack',
'webpack.config.common.babel.ts': 'webpack',
'webpack.dev.js': 'webpack',
'webpack.dev.ts': 'webpack',
'webpack.config.dev.js': 'webpack',
'webpack.config.dev.ts': 'webpack',
'webpack.config.dev.babel.js': 'webpack',
'webpack.config.dev.babel.ts': 'webpack',
'webpack.prod.js': 'webpack',
'webpack.prod.ts': 'webpack',
'webpack.server.js': 'webpack',
'webpack.server.ts': 'webpack',
'webpack.client.js': 'webpack',
'webpack.client.ts': 'webpack',
'webpack.config.server.js': 'webpack',
'webpack.config.server.ts': 'webpack',
'webpack.config.client.js': 'webpack',
'webpack.config.client.ts': 'webpack',
'webpack.config.production.babel.js': 'webpack',
'webpack.config.production.babel.ts': 'webpack',
'webpack.config.prod.babel.js': 'webpack',
'webpack.config.prod.babel.ts': 'webpack',
'webpack.config.prod.js': 'webpack',
'webpack.config.prod.ts': 'webpack',
'webpack.config.production.js': 'webpack',
'webpack.config.production.ts': 'webpack',
'webpack.config.staging.js': 'webpack',
'webpack.config.staging.ts': 'webpack',
'webpack.config.babel.js': 'webpack',
'webpack.config.babel.ts': 'webpack',
'webpack.config.base.babel.js': 'webpack',
'webpack.config.base.babel.ts': 'webpack',
'webpack.config.base.js': 'webpack',
'webpack.config.base.ts': 'webpack',
'webpack.config.staging.babel.js': 'webpack',
'webpack.config.staging.babel.ts': 'webpack',
'webpack.config.coffee': 'webpack',
'webpack.config.test.js': 'webpack',
'webpack.config.test.ts': 'webpack',
'webpack.config.vendor.js': 'webpack',
'webpack.config.vendor.ts': 'webpack',
'webpack.config.vendor.production.js': 'webpack',
'webpack.config.vendor.production.ts': 'webpack',
'webpack.test.js': 'webpack',
'webpack.test.ts': 'webpack',
'webpack.dist.js': 'webpack',
'webpack.dist.ts': 'webpack',
'webpackfile.js': 'webpack',
'webpackfile.ts': 'webpack',
'ionic.config.json': 'ionic',
'.io-config.json': 'ionic',
'gulpfile.js': 'gulp',
'gulpfile.ts': 'gulp',
'gulpfile.babel.js': 'gulp',
'package.json': 'nodejs',
'package-lock.json': 'nodejs',
'.nvmrc': 'nodejs',
'.npmignore': 'npm',
'.npmrc': 'npm',
'.yarnrc': 'yarn',
'yarn.lock': 'yarn',
'.yarnclean': 'yarn',
'.yarn-integrity': 'yarn',
'yarn-error.log': 'yarn',
'androidmanifest.xml': 'android',
'.env': 'tune',
'.env.example': 'tune',
'.babelrc': 'babel',
'contributing.md': 'contributing',
'contributing.md.rendered': 'contributing',
'readme.md': 'readme',
'readme.md.rendered': 'readme',
changelog: 'changelog',
'changelog.md': 'changelog',
'changelog.md.rendered': 'changelog',
CREDITS: 'credits',
'credits.txt': 'credits',
'credits.md': 'credits',
'credits.md.rendered': 'credits',
'.flowconfig': 'flow',
'favicon.ico': 'favicon',
'karma.conf.js': 'karma',
'karma.conf.ts': 'karma',
'karma.conf.coffee': 'karma',
'karma.config.js': 'karma',
'karma.config.ts': 'karma',
'karma-main.js': 'karma',
'karma-main.ts': 'karma',
'.bithoundrc': 'bithound',
'appveyor.yml': 'appveyor',
'.travis.yml': 'travis',
'protractor.conf.js': 'protractor',
'protractor.conf.ts': 'protractor',
'protractor.conf.coffee': 'protractor',
'protractor.config.js': 'protractor',
'protractor.config.ts': 'protractor',
'fuse.js': 'fusebox',
procfile: 'heroku',
'.editorconfig': 'editorconfig',
'.gitlab-ci.yml': 'gitlab',
'.bowerrc': 'bower',
'bower.json': 'bower',
'.eslintrc.js': 'eslint',
'.eslintrc.yaml': 'eslint',
'.eslintrc.yml': 'eslint',
'.eslintrc.json': 'eslint',
'.eslintrc': 'eslint',
'.eslintignore': 'eslint',
'code_of_conduct.md': 'conduct',
'code_of_conduct.md.rendered': 'conduct',
'.watchmanconfig': 'watchman',
'aurelia.json': 'aurelia',
'mocha.opts': 'mocha',
jenkinsfile: 'jenkins',
'firebase.json': 'firebase',
'.firebaserc': 'firebase',
'rollup.config.js': 'rollup',
'rollup.config.ts': 'rollup',
'rollup-config.js': 'rollup',
'rollup-config.ts': 'rollup',
'rollup.config.prod.js': 'rollup',
'rollup.config.prod.ts': 'rollup',
'rollup.config.dev.js': 'rollup',
'rollup.config.dev.ts': 'rollup',
'rollup.config.prod.vendor.js': 'rollup',
'rollup.config.prod.vendor.ts': 'rollup',
'.hhconfig': 'hack',
'.stylelintrc': 'stylelint',
'stylelint.config.js': 'stylelint',
'.stylelintrc.json': 'stylelint',
'.stylelintrc.yaml': 'stylelint',
'.stylelintrc.yml': 'stylelint',
'.stylelintrc.js': 'stylelint',
'.stylelintignore': 'stylelint',
'.codeclimate.yml': 'code-climate',
'.prettierrc': 'prettier',
'prettier.config.js': 'prettier',
'.prettierrc.js': 'prettier',
'.prettierrc.json': 'prettier',
'.prettierrc.yaml': 'prettier',
'.prettierrc.yml': 'prettier',
'nodemon.json': 'nodemon',
'.sonarrc': 'sonar',
browserslist: 'browserlist',
'.browserslistrc': 'browserlist',
'.snyk': 'snyk',
'.drone.yml': 'drone',
};
export default function getIconForFile(name) {
return fileNameIcons[name] ||
fileExtensionIcons[name ? name.split('.').pop() : ''] ||
'';
}
...@@ -96,8 +96,14 @@ ...@@ -96,8 +96,14 @@
padding: 6px 12px; padding: 6px 12px;
} }
.multi-file-table-name { table.table tr td.multi-file-table-name {
width: 350px; width: 350px;
padding: 6px 12px;
svg {
vertical-align: middle;
margin-right: 2px;
}
} }
.multi-file-table-col-commit-message { .multi-file-table-col-commit-message {
...@@ -132,6 +138,10 @@ ...@@ -132,6 +138,10 @@
border-bottom: 1px solid $white-dark; border-bottom: 1px solid $white-dark;
cursor: pointer; cursor: pointer;
svg {
vertical-align: middle;
}
&.active { &.active {
background-color: $white-light; background-color: $white-light;
border-bottom-color: $white-light; border-bottom-color: $white-light;
......
...@@ -30,6 +30,13 @@ module IconsHelper ...@@ -30,6 +30,13 @@ module IconsHelper
ActionController::Base.helpers.image_path('icons.svg', host: sprite_base_url) ActionController::Base.helpers.image_path('icons.svg', host: sprite_base_url)
end end
def sprite_file_icons_path
# SVG Sprites currently don't work across domains, so in the case of a CDN
# we have to set the current path deliberately to prevent addition of asset_host
sprite_base_url = Gitlab.config.gitlab.url if ActionController::Base.asset_host
ActionController::Base.helpers.image_path('file_icons.svg', host: sprite_base_url)
end
def sprite_icon(icon_name, size: nil, css_class: nil) def sprite_icon(icon_name, size: nil, css_class: nil)
css_classes = size ? "s#{size}" : "" css_classes = size ? "s#{size}" : ""
css_classes << " #{css_class}" unless css_class.blank? css_classes << " #{css_class}" unless css_class.blank?
......
...@@ -21,6 +21,7 @@ module Gitlab ...@@ -21,6 +21,7 @@ module Gitlab
gon.revision = Gitlab::REVISION gon.revision = Gitlab::REVISION
gon.gitlab_logo = ActionController::Base.helpers.asset_path('gitlab_logo.png') gon.gitlab_logo = ActionController::Base.helpers.asset_path('gitlab_logo.png')
gon.sprite_icons = IconsHelper.sprite_icon_path gon.sprite_icons = IconsHelper.sprite_icon_path
gon.sprite_file_icons = IconsHelper.sprite_file_icons_path
if current_user if current_user
gon.current_user_id = current_user.id gon.current_user_id = current_user.id
......
...@@ -32,13 +32,9 @@ describe('RepoFile', () => { ...@@ -32,13 +32,9 @@ describe('RepoFile', () => {
vm.$mount(); vm.$mount();
const name = vm.$el.querySelector('.repo-file-name'); const name = vm.$el.querySelector('.repo-file-name');
const fileIcon = vm.$el.querySelector('.file-icon');
expect(vm.$el.querySelector(`.${vm.file.icon}`).style.marginLeft).toEqual('0px');
expect(name.href).toMatch(''); expect(name.href).toMatch('');
expect(name.textContent.trim()).toEqual(vm.file.name); expect(name.textContent.trim()).toEqual(vm.file.name);
expect(fileIcon.classList.contains(vm.file.icon)).toBeTruthy();
expect(fileIcon.style.marginLeft).toEqual(`${vm.file.level * 10}px`);
}); });
it('does render if hasFiles is true and is loading tree', () => { it('does render if hasFiles is true and is loading tree', () => {
...@@ -49,17 +45,6 @@ describe('RepoFile', () => { ...@@ -49,17 +45,6 @@ describe('RepoFile', () => {
expect(vm.$el.querySelector('.fa-spin.fa-spinner')).toBeFalsy(); expect(vm.$el.querySelector('.fa-spin.fa-spinner')).toBeFalsy();
}); });
it('renders a spinner if the file is loading', () => {
const f = file();
f.loading = true;
vm = createComponent({
file: f,
});
expect(vm.$el.querySelector('.fa-spin.fa-spinner')).not.toBeNull();
expect(vm.$el.querySelector('.fa-spin.fa-spinner').style.marginLeft).toEqual(`${vm.file.level * 16}px`);
});
it('does not render commit message and datetime if mini', (done) => { it('does not render commit message and datetime if mini', (done) => {
vm = createComponent({ vm = createComponent({
file: file(), file: file(),
......
import Vue from 'vue';
import fileIcon from '~/vue_shared/components/file_icon.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
describe('File Icon component', () => {
let vm;
let FileIcon;
beforeEach(() => {
FileIcon = Vue.extend(fileIcon);
});
afterEach(() => {
vm.$destroy();
});
it('should render a span element with an svg', () => {
vm = mountComponent(FileIcon, {
fileName: 'test.js',
});
expect(vm.$el.tagName).toEqual('SPAN');
expect(vm.$el.querySelector('span > svg')).toBeDefined();
});
it('should render a javascript icon based on file ending', () => {
vm = mountComponent(FileIcon, {
fileName: 'test.js',
});
expect(vm.$el.firstChild.firstChild.getAttribute('xlink:href')).toBe(`${gon.sprite_file_icons}#javascript`);
});
it('should render a image icon based on file ending', () => {
vm = mountComponent(FileIcon, {
fileName: 'test.png',
});
expect(vm.$el.firstChild.firstChild.getAttribute('xlink:href')).toBe(`${gon.sprite_file_icons}#image`);
});
it('should render a webpack icon based on file namer', () => {
vm = mountComponent(FileIcon, {
fileName: 'webpack.js',
});
expect(vm.$el.firstChild.firstChild.getAttribute('xlink:href')).toBe(`${gon.sprite_file_icons}#webpack`);
});
it('should render a standard folder icon', () => {
vm = mountComponent(FileIcon, {
fileName: 'js',
folder: true,
});
expect(vm.$el.querySelector('span > svg > use').getAttribute('xlink:href')).toBe(`${gon.sprite_file_icons}#folder`);
});
it('should render a loading icon', () => {
vm = mountComponent(FileIcon, {
fileName: 'test.js',
loading: true,
});
expect(
vm.$el.querySelector('i').getAttribute('class'),
).toEqual('fa fa-spin fa-spinner fa-1x');
});
it('should add a special class and a size class', () => {
vm = mountComponent(FileIcon, {
fileName: 'test.js',
cssClasses: 'extraclasses',
size: 120,
});
const classList = vm.$el.firstChild.classList;
const containsSizeClass = classList.contains('s120');
const containsCustomClass = classList.contains('extraclasses');
expect(containsSizeClass).toBe(true);
expect(containsCustomClass).toBe(true);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment