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
a557f4bf
Commit
a557f4bf
authored
Jun 19, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab-ce master
parents
0e44382e
6d4f33ce
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
153 additions
and
89 deletions
+153
-89
app/assets/javascripts/api.js
app/assets/javascripts/api.js
+16
-0
scripts/frontend/test.js
scripts/frontend/test.js
+16
-7
spec/frontend/api_spec.js
spec/frontend/api_spec.js
+23
-0
spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js
...scripts/vue_shared/components/tooltip_on_truncate_spec.js
+98
-82
No files found.
app/assets/javascripts/api.js
View file @
a557f4bf
...
...
@@ -12,6 +12,7 @@ const Api = {
groupProjectsPath
:
'
/api/:version/groups/:id/projects.json
'
,
projectsPath
:
'
/api/:version/projects.json
'
,
projectPath
:
'
/api/:version/projects/:id
'
,
forkedProjectsPath
:
'
/api/:version/projects/:id/forks
'
,
projectLabelsPath
:
'
/:namespace_path/:project_path/-/labels
'
,
projectMergeRequestsPath
:
'
/api/:version/projects/:id/merge_requests
'
,
projectMergeRequestPath
:
'
/api/:version/projects/:id/merge_requests/:mrid
'
,
...
...
@@ -113,6 +114,21 @@ const Api = {
return
axios
.
get
(
url
);
},
/**
* Get all projects for a forked relationship to a specified project
* @param {string} projectPath - Path or ID of a project
* @param {Object} params - Get request parameters
* @returns {Promise} - Request promise
*/
projectForks
(
projectPath
,
params
)
{
const
url
=
Api
.
buildUrl
(
Api
.
forkedProjectsPath
).
replace
(
'
:id
'
,
encodeURIComponent
(
projectPath
),
);
return
axios
.
get
(
url
,
{
params
});
},
/**
* Get all Merge Requests for a project, eventually filtering based on
* supplied parameters
...
...
scripts/frontend/test.js
View file @
a557f4bf
...
...
@@ -5,19 +5,24 @@ const { EOL } = require('os');
const
program
=
require
(
'
commander
'
);
const
chalk
=
require
(
'
chalk
'
);
const
SUCCESS_CODE
=
0
;
const
JEST_ROUTE
=
'
spec/frontend
'
;
const
KARMA_ROUTE
=
'
spec/javascripts
'
;
const
COMMON_ARGS
=
[
'
--colors
'
];
const
JEST_ARGS
=
[
'
--passWithNoTests
'
];
const
KARMA_ARGS
=
[
'
--no-fail-on-empty-test-suite
'
];
const
SUCCESS_CODE
=
0
;
const
jestArgs
=
[...
COMMON_ARGS
,
'
--passWithNoTests
'
];
const
karmaArgs
=
[...
COMMON_ARGS
,
'
--no-fail-on-empty-test-suite
'
];
program
.
version
(
'
0.1.0
'
)
.
usage
(
'
[options] <file ...>
'
)
.
option
(
'
-p, --parallel
'
,
'
Run tests suites in parallel
'
)
.
option
(
'
-w, --watch
'
,
'
Rerun tests when files change (tests will be run in parallel if this enabled)
'
,
)
.
parse
(
process
.
argv
);
const
shouldParallelize
=
program
.
parallel
||
program
.
watch
;
const
isSuccess
=
code
=>
code
===
SUCCESS_CODE
;
const
combineExitCodes
=
codes
=>
{
...
...
@@ -31,7 +36,7 @@ const skipIfFail = fn => code => (isSuccess(code) ? fn() : code);
const
endWithEOL
=
str
=>
(
str
[
str
.
length
-
1
]
===
'
\n
'
?
str
:
`
${
str
}${
EOL
}
`
);
const
runTests
=
paths
=>
{
if
(
program
.
parallel
)
{
if
(
shouldParallelize
)
{
return
Promise
.
all
([
runJest
(
paths
),
runKarma
(
paths
)]).
then
(
combineExitCodes
);
}
else
{
return
runJest
(
paths
).
then
(
skipIfFail
(()
=>
runKarma
(
paths
)));
...
...
@@ -73,11 +78,11 @@ const spawnYarnScript = (cmd, args) => {
};
const
runJest
=
args
=>
{
return
spawnYarnScript
(
'
jest
'
,
[...
JEST_ARGS
,
...
COMMON_ARGS
,
...
toJestArgs
(
args
)]);
return
spawnYarnScript
(
'
jest
'
,
[...
jestArgs
,
...
toJestArgs
(
args
)]);
};
const
runKarma
=
args
=>
{
return
spawnYarnScript
(
'
karma
'
,
[...
KARMA_ARGS
,
...
COMMON_ARGS
,
...
toKarmaArgs
(
args
)]);
return
spawnYarnScript
(
'
karma
'
,
[...
karmaArgs
,
...
toKarmaArgs
(
args
)]);
};
const
replacePath
=
to
=>
path
=>
...
...
@@ -96,6 +101,10 @@ const toKarmaArgs = paths =>
paths
.
reduce
((
acc
,
path
)
=>
acc
.
concat
(
'
-f
'
,
replacePathForKarma
(
path
)),
[]);
const
main
=
paths
=>
{
if
(
program
.
watch
)
{
jestArgs
.
push
(
'
--watch
'
);
karmaArgs
.
push
(
'
--single-run
'
,
'
false
'
,
'
--auto-watch
'
);
}
runTests
(
paths
).
then
(
code
=>
{
console
.
log
(
'
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'
);
if
(
isSuccess
(
code
))
{
...
...
spec/frontend/api_spec.js
View file @
a557f4bf
...
...
@@ -474,4 +474,27 @@ describe('Api', () => {
.
catch
(
done
.
fail
);
});
});
describe
(
'
projectForks
'
,
()
=>
{
it
(
'
gets forked projects
'
,
done
=>
{
const
dummyProjectPath
=
'
gitlab-org/gitlab-ce
'
;
const
expectedUrl
=
`
${
dummyUrlRoot
}
/api/
${
dummyApiVersion
}
/projects/
${
encodeURIComponent
(
dummyProjectPath
,
)}
/forks`
;
jest
.
spyOn
(
axios
,
'
get
'
);
mock
.
onGet
(
expectedUrl
).
replyOnce
(
200
,
[
'
fork
'
]);
Api
.
projectForks
(
dummyProjectPath
,
{
visibility
:
'
private
'
})
.
then
(({
data
})
=>
{
expect
(
data
).
toEqual
([
'
fork
'
]);
expect
(
axios
.
get
).
toHaveBeenCalledWith
(
expectedUrl
,
{
params
:
{
visibility
:
'
private
'
},
});
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
});
spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js
View file @
a557f4bf
import
{
mountComponentWithRender
}
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
const
TEST_TITLE
=
'
lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do
'
;
const
CLASS_SHOW_TOOLTIP
=
'
js-show-tooltip
'
;
const
STYLE_TRUNCATED
=
{
display
:
'
inline-block
'
,
'
max-width
'
:
'
20px
'
,
};
const
STYLE_NORMAL
=
{
display
:
'
inline-block
'
,
'
max-width
'
:
'
1000px
'
,
};
function
mountTooltipOnTruncate
(
options
,
createChildren
)
{
return
mountComponentWithRender
(
h
=>
h
(
TooltipOnTruncate
,
options
,
createChildren
(
h
)),
'
#app
'
);
}
const
STYLE_TRUNCATED
=
'
display: inline-block; max-width: 20px;
'
;
const
STYLE_NORMAL
=
'
display: inline-block; max-width: 1000px;
'
;
describe
(
'
TooltipOnTruncate component
'
,
()
=>
{
let
vm
;
const
localVue
=
createLocalVue
();
const
createElementWithStyle
=
(
style
,
content
)
=>
`<a href="#" style="
${
style
}
">
${
content
}
</a>`
;
beforeEach
(()
=>
{
const
el
=
document
.
createElement
(
'
div
'
);
el
.
id
=
'
app
'
;
document
.
body
.
appendChild
(
el
);
describe
(
'
TooltipOnTruncate component
'
,
()
=>
{
let
wrapper
;
const
createComponent
=
({
propsData
,
...
options
}
=
{})
=>
{
wrapper
=
shallowMount
(
localVue
.
extend
(
TooltipOnTruncate
),
{
localVue
,
sync
:
false
,
attachToDocument
:
true
,
propsData
:
{
title
:
TEST_TITLE
,
...
propsData
,
},
...
options
,
});
};
afterEach
(()
=>
{
vm
.
$
destroy
();
wrapper
.
destroy
();
});
const
hasTooltip
=
()
=>
wrapper
.
classes
(
'
js-show-tooltip
'
);
describe
(
'
with default target
'
,
()
=>
{
it
(
'
renders tooltip if truncated
'
,
done
=>
{
const
options
=
{
createComponent
({
attrs
:
{
style
:
STYLE_TRUNCATED
,
props
:
{
title
:
TEST_TITLE
,
},
};
vm
=
mountTooltipOnTruncate
(
options
,
()
=>
[
TEST_TITLE
]);
slots
:
{
default
:
[
TEST_TITLE
],
},
});
vm
.
$nextTick
()
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
).
toHaveClass
(
CLASS_SHOW_TOOLTIP
);
expect
(
vm
.
$el
).
toHaveData
(
'
original-title
'
,
TEST_TITLE
);
expect
(
vm
.
$el
).
toHaveData
(
'
placement
'
,
'
top
'
);
expect
(
hasTooltip
()).
toBe
(
true
);
expect
(
wrapper
.
attributes
(
'
data-original-title
'
)).
toEqual
(
TEST_TITLE
);
expect
(
wrapper
.
attributes
(
'
data-placement
'
)).
toEqual
(
'
top
'
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
does not render tooltip if normal
'
,
done
=>
{
const
options
=
{
createComponent
({
attrs
:
{
style
:
STYLE_NORMAL
,
props
:
{
title
:
TEST_TITLE
,
},
};
vm
=
mountTooltipOnTruncate
(
options
,
()
=>
[
TEST_TITLE
]);
slots
:
{
default
:
[
TEST_TITLE
],
},
});
vm
.
$nextTick
()
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
).
not
.
toHaveClass
(
CLASS_SHOW_TOOLTIP
);
expect
(
hasTooltip
()).
toBe
(
false
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
...
...
@@ -71,37 +75,41 @@ describe('TooltipOnTruncate component', () => {
describe
(
'
with child target
'
,
()
=>
{
it
(
'
renders tooltip if truncated
'
,
done
=>
{
const
options
=
{
createComponent
({
attrs
:
{
style
:
STYLE_NORMAL
,
props
:
{
title
:
TEST_TITLE
,
},
propsData
:
{
truncateTarget
:
'
child
'
,
},
};
vm
=
mountTooltipOnTruncate
(
options
,
h
=>
[
h
(
'
a
'
,
{
style
:
STYLE_TRUNCATED
},
TEST_TITLE
)]);
slots
:
{
default
:
createElementWithStyle
(
STYLE_TRUNCATED
,
TEST_TITLE
),
},
});
vm
.
$nextTick
()
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
).
toHaveClass
(
CLASS_SHOW_TOOLTIP
);
expect
(
hasTooltip
()).
toBe
(
true
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
does not render tooltip if normal
'
,
done
=>
{
const
options
=
{
props
:
{
title
:
TEST_TITLE
,
createComponent
({
propsData
:
{
truncateTarget
:
'
child
'
,
},
};
vm
=
mountTooltipOnTruncate
(
options
,
h
=>
[
h
(
'
a
'
,
{
style
:
STYLE_NORMAL
},
TEST_TITLE
)]);
slots
:
{
default
:
createElementWithStyle
(
STYLE_NORMAL
,
TEST_TITLE
),
},
});
vm
.
$nextTick
()
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
).
not
.
toHaveClass
(
CLASS_SHOW_TOOLTIP
);
expect
(
hasTooltip
()).
toBe
(
false
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
...
...
@@ -110,22 +118,25 @@ describe('TooltipOnTruncate component', () => {
describe
(
'
with fn target
'
,
()
=>
{
it
(
'
renders tooltip if truncated
'
,
done
=>
{
const
options
=
{
createComponent
({
attrs
:
{
style
:
STYLE_NORMAL
,
props
:
{
title
:
TEST_TITLE
,
},
propsData
:
{
truncateTarget
:
el
=>
el
.
childNodes
[
1
],
},
};
vm
=
mountTooltipOnTruncate
(
options
,
h
=>
[
h
(
'
a
'
,
{
style
:
STYLE_NORMAL
},
TEST_TITLE
),
h
(
'
span
'
,
{
style
:
STYLE_TRUNCATED
},
TEST_TITLE
),
]);
slots
:
{
default
:
[
createElementWithStyle
(
''
,
TEST_TITLE
),
createElementWithStyle
(
STYLE_TRUNCATED
,
TEST_TITLE
),
],
},
});
vm
.
$nextTick
()
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
).
toHaveClass
(
CLASS_SHOW_TOOLTIP
);
expect
(
hasTooltip
()).
toBe
(
true
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
...
...
@@ -134,20 +145,25 @@ describe('TooltipOnTruncate component', () => {
describe
(
'
placement
'
,
()
=>
{
it
(
'
sets data-placement when tooltip is rendered
'
,
done
=>
{
const
options
=
{
props
:
{
title
:
TEST_TITLE
,
truncateTarget
:
'
child
'
,
placement
:
'
bottom
'
,
},
};
const
placement
=
'
bottom
'
;
vm
=
mountTooltipOnTruncate
(
options
,
h
=>
[
h
(
'
a
'
,
{
style
:
STYLE_TRUNCATED
},
TEST_TITLE
)]);
createComponent
({
propsData
:
{
placement
,
},
attrs
:
{
style
:
STYLE_TRUNCATED
,
},
slots
:
{
default
:
TEST_TITLE
,
},
});
vm
.
$nextTick
()
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
).
toHaveClass
(
CLASS_SHOW_TOOLTIP
);
expect
(
vm
.
$el
).
toHaveData
(
'
placement
'
,
options
.
props
.
placement
);
expect
(
hasTooltip
()).
toBe
(
true
);
expect
(
wrapper
.
attributes
(
'
data-placement
'
)).
toEqual
(
placement
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
...
...
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