Commit 3cab2087 authored by Mike Greiling's avatar Mike Greiling

Run all ee-specific files through prettier

parent b09b82f1
<script>
import Flash from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import Flash from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import GitlabSlackService from '../services/gitlab_slack_service';
import GitlabSlackService from '../services/gitlab_slack_service';
export default {
export default {
props: {
projects: {
type: Array,
......@@ -80,7 +80,7 @@
.catch(() => Flash('Unable to build Slack link.'));
},
},
};
};
</script>
<template>
......
......@@ -2,7 +2,10 @@ import $ from 'jquery';
import _ from 'underscore';
export default () => {
$('.approver-list').on('click', '.unsaved-approvers.approver .btn-remove', function approverListClickCallback(ev) {
$('.approver-list').on(
'click',
'.unsaved-approvers.approver .btn-remove',
function approverListClickCallback(ev) {
const removeElement = $(this).closest('li');
const approverId = parseInt(removeElement.attr('id').replace('user_', ''), 10);
const approverIds = $('input#merge_request_approver_ids');
......@@ -16,9 +19,13 @@ export default () => {
}
ev.preventDefault();
});
},
);
$('.approver-list').on('click', '.unsaved-approvers.approver-group .btn-remove', function approverListRemoveClickCallback(ev) {
$('.approver-list').on(
'click',
'.unsaved-approvers.approver-group .btn-remove',
function approverListRemoveClickCallback(ev) {
const removeElement = $(this).closest('li');
const approverGroupId = parseInt(removeElement.attr('id').replace('group_', ''), 10);
const approverGroupIds = $('input#merge_request_approver_group_ids');
......@@ -32,18 +39,23 @@ export default () => {
}
ev.preventDefault();
});
},
);
$('form.merge-request-form').on('submit', function mergeRequestFormSubmitCallback() {
if ($('input#merge_request_approver_ids').length) {
let approverIds = $.map($('li.unsaved-approvers.approver').not('.approver-template'), li => li.id.replace('user_', ''));
let approverIds = $.map($('li.unsaved-approvers.approver').not('.approver-template'), li =>
li.id.replace('user_', ''),
);
const approversInput = $(this).find('input#merge_request_approver_ids');
approverIds = approverIds.concat(approversInput.val().split(','));
approversInput.val(_.compact(approverIds).join(','));
}
if ($('input#merge_request_approver_group_ids').length) {
let approverGroupIds = $.map($('li.unsaved-approvers.approver-group'), li => li.id.replace('group_', ''));
let approverGroupIds = $.map($('li.unsaved-approvers.approver-group'), li =>
li.id.replace('group_', ''),
);
const approverGroupsInput = $(this).find('input#merge_request_approver_group_ids');
approverGroupIds = approverGroupIds.concat(approverGroupsInput.val().split(','));
approverGroupsInput.val(_.compact(approverGroupIds).join(','));
......@@ -58,9 +70,11 @@ export default () => {
return false;
}
const approverItemHTML = $('.unsaved-approvers.approver-template').clone()
const approverItemHTML = $('.unsaved-approvers.approver-template')
.clone()
.removeClass('hide approver-template')[0]
.outerHTML.replace(/\{approver_name\}/g, username).replace(/\{user_id\}/g, userId);
.outerHTML.replace(/\{approver_name\}/g, username)
.replace(/\{user_id\}/g, userId);
$('.no-approvers').remove();
$('.approver-list').append(approverItemHTML);
......
import BoardsListSelector from './boards_list_selector/index';
export default function () {
export default function() {
const $addListEl = document.querySelector('#js-add-list');
return new BoardsListSelector({
propsData: {
......
......@@ -20,8 +20,8 @@ export default Board.extend({
}
const { issuesSize, totalWeight } = this.list;
return sprintf(__(
`${n__('%d issue', '%d issues', issuesSize)} with %{totalWeight} total weight`),
return sprintf(
__(`${n__('%d issue', '%d issues', issuesSize)} with %{totalWeight} total weight`),
{
totalWeight,
},
......
......@@ -43,15 +43,17 @@ export default Vue.extend({
})
.catch(() => {
this.loading = false;
Flash(sprintf(__('Something went wrong while fetching %{listType} list'), {
Flash(
sprintf(__('Something went wrong while fetching %{listType} list'), {
listType: this.listType,
}));
}),
);
});
},
filterItems(term, items) {
const query = term.toLowerCase();
return items.filter((item) => {
return items.filter(item => {
const name = item.name ? item.name.toLowerCase() : item.title.toLowerCase();
const foundName = name.indexOf(query) > -1;
......
......@@ -31,7 +31,7 @@ export default {
if (!this.query) return this.items;
const query = this.query.toLowerCase();
return this.items.filter((item) => {
return this.items.filter(item => {
const name = item.name ? item.name.toLowerCase() : item.title.toLowerCase();
if (this.listType === 'milestones') {
......
......@@ -140,8 +140,7 @@ export default Vue.extend({
handleDropdownTabClick(e) {
const $addListEl = $('#js-add-list');
$addListEl.data('preventClose', true);
if (e.target.dataset.action === 'tab-assignees' &&
!this.hasAssigneesListMounted) {
if (e.target.dataset.action === 'tab-assignees' && !this.hasAssigneesListMounted) {
this.assigneeList = AssigneeList();
this.hasAssigneesListMounted = true;
}
......
import BoardsListSelector from './boards_list_selector';
export default function () {
export default function() {
const $addListEl = document.querySelector('#js-add-list');
return new BoardsListSelector({
propsData: {
......
<script>
import MilestoneSelect from '~/milestone_select';
import MilestoneSelect from '~/milestone_select';
const ANY_MILESTONE = 'Any Milestone';
const NO_MILESTONE = 'No Milestone';
const ANY_MILESTONE = 'Any Milestone';
const NO_MILESTONE = 'No Milestone';
export default {
export default {
props: {
board: {
type: Object,
......@@ -61,7 +61,7 @@
};
},
},
};
};
</script>
<template>
......
<script>
/* eslint-disable vue/require-default-prop */
/* eslint-disable vue/require-default-prop */
import WeightSelect from 'ee/weight_select';
import WeightSelect from 'ee/weight_select';
const ANY_WEIGHT = 'Any Weight';
const NO_WEIGHT = 'No Weight';
const ANY_WEIGHT = 'Any Weight';
const NO_WEIGHT = 'No Weight';
export default {
export default {
props: {
board: {
type: Object,
......@@ -65,7 +65,7 @@
return -1;
},
},
};
};
</script>
<template>
......
......@@ -19,7 +19,8 @@ const d3 = {
axisLeft,
line,
transition,
easeLinear };
easeLinear,
};
const margin = { top: 5, right: 65, bottom: 30, left: 50 };
// const parseDate = d3.timeFormat('%Y-%m-%d');
const bisectDate = d3.bisector(d => d.date).left;
......@@ -28,7 +29,9 @@ const tooltipDistance = 15;
export default class BurndownChart {
constructor({ container, startDate, dueDate }) {
this.canvas = d3.select(container).append('svg')
this.canvas = d3
.select(container)
.append('svg')
.attr('height', '100%')
.attr('width', '100%');
......@@ -56,21 +59,35 @@ export default class BurndownChart {
this.chartLegendIdealKey = this.chartLegendGroup.append('g');
this.chartLegendIdealKey.append('line').attr('class', 'ideal line');
this.chartLegendIdealKey.append('text').text('Guideline');
this.chartLegendIdealKeyBBox = this.chartLegendIdealKey.select('text').node().getBBox();
this.chartLegendIdealKeyBBox = this.chartLegendIdealKey
.select('text')
.node()
.getBBox();
this.chartLegendActualKey = this.chartLegendGroup.append('g');
this.chartLegendActualKey.append('line').attr('class', 'actual line');
this.chartLegendActualKey.append('text').text('Progress');
this.chartLegendActualKeyBBox = this.chartLegendActualKey.select('text').node().getBBox();
this.chartLegendActualKeyBBox = this.chartLegendActualKey
.select('text')
.node()
.getBBox();
// create tooltips
this.chartFocus = this.chartGroup.append('g').attr('class', 'focus').style('display', 'none');
this.chartFocus = this.chartGroup
.append('g')
.attr('class', 'focus')
.style('display', 'none');
this.chartFocus.append('circle').attr('r', 4);
this.tooltipGroup = this.chartFocus.append('g').attr('class', 'chart-tooltip');
this.tooltipGroup.append('rect').attr('rx', 3).attr('ry', 3);
this.tooltipGroup
.append('rect')
.attr('rx', 3)
.attr('ry', 3);
this.tooltipGroup.append('text');
this.chartOverlay = this.chartGroup.append('rect').attr('class', 'overlay')
this.chartOverlay = this.chartGroup
.append('rect')
.attr('class', 'overlay')
.on('mouseover', () => this.chartFocus.style('display', null))
.on('mouseout', () => this.chartFocus.style('display', 'none'))
.on('mousemove', () => this.handleMousemove());
......@@ -91,28 +108,33 @@ export default class BurndownChart {
this.yMax = 1;
// create scales
this.xScale = d3.scaleTime()
this.xScale = d3
.scaleTime()
.range([0, this.chartWidth])
.domain([this.startDate, this.xMax]);
this.yScale = d3.scaleLinear()
this.yScale = d3
.scaleLinear()
.range([this.chartHeight, 0])
.domain([0, this.yMax]);
// create axes
this.xAxis = d3.axisBottom()
this.xAxis = d3
.axisBottom()
.scale(this.xScale)
.tickFormat(d3.timeFormat('%b %-d'))
.tickPadding(6)
.tickSize(4, 0);
this.yAxis = d3.axisLeft()
this.yAxis = d3
.axisLeft()
.scale(this.yScale)
.tickPadding(6)
.tickSize(4, 0);
// create lines
this.line = d3.line()
this.line = d3
.line()
.x(d => this.xScale(new Date(d.date)))
.y(d => this.yScale(d.value));
......@@ -122,10 +144,12 @@ export default class BurndownChart {
// set data and force re-render
setData(data, { label = 'Remaining', animate } = {}) {
this.data = data.map(datum => ({
this.data = data
.map(datum => ({
date: new Date(datum[0]),
value: parseInt(datum[1], 10),
})).sort((a, b) => (a.date - b.date));
}))
.sort((a, b) => a.date - b.date);
// adjust axis domain to correspond with data
this.xMax = Math.max(d3.max(this.data, d => d.date) || 0, this.dueDate);
......@@ -138,7 +162,10 @@ export default class BurndownChart {
// (this must be done here to prevent layout thrashing)
if (this.label !== label) {
this.label = label;
this.yAxisLabelBBox = this.yAxisLabelText.text(label).node().getBBox();
this.yAxisLabelBBox = this.yAxisLabelText
.text(label)
.node()
.getBBox();
}
// set ideal line data
......@@ -206,15 +233,18 @@ export default class BurndownChart {
// replace x-axis line with one which continues into the right margin
this.xAxisGroup.select('.domain').remove();
this.xAxisGroup.select('.domain-line').attr('x1', 0).attr('x2', this.chartWidth + margin.right);
this.xAxisGroup
.select('.domain-line')
.attr('x1', 0)
.attr('x2', this.chartWidth + margin.right);
// update y-axis label
const axisLabelOffset = (this.yAxisLabelBBox.height / 2) - margin.left;
const axisLabelOffset = this.yAxisLabelBBox.height / 2 - margin.left;
const axisLabelPadding = (this.chartHeight - this.yAxisLabelBBox.width - 10) / 2;
this.yAxisLabelText
.attr('y', 0 - margin.left)
.attr('x', 0 - (this.chartHeight / 2))
.attr('x', 0 - this.chartHeight / 2)
.attr('dy', '1em')
.style('text-anchor', 'middle')
.attr('transform', 'rotate(-90)');
......@@ -240,18 +270,21 @@ export default class BurndownChart {
const idealKeyOffset = legendPadding;
const actualKeyOffset = legendPadding + keyHeight + legendSpacing;
const legendWidth = (legendPadding * 2) + 24 + keyWidth;
const legendHeight = (legendPadding * 2) + (keyHeight * 2) + legendSpacing;
const legendOffset = (this.chartWidth + margin.right) - legendWidth - 1;
const legendWidth = legendPadding * 2 + 24 + keyWidth;
const legendHeight = legendPadding * 2 + keyHeight * 2 + legendSpacing;
const legendOffset = this.chartWidth + margin.right - legendWidth - 1;
this.chartLegendGroup.select('rect')
this.chartLegendGroup
.select('rect')
.attr('width', legendWidth)
.attr('height', legendHeight);
this.chartLegendGroup.selectAll('text')
this.chartLegendGroup
.selectAll('text')
.attr('x', 24)
.attr('dy', '1em');
this.chartLegendGroup.selectAll('line')
this.chartLegendGroup
.selectAll('line')
.attr('y1', keyHeight / 2)
.attr('y2', keyHeight / 2)
.attr('x1', 0)
......@@ -298,15 +331,19 @@ export default class BurndownChart {
const x = this.xScale(datum.date);
const y = this.yScale(datum.value);
const textSize = this.tooltipGroup.select('text').text(tooltip).node().getBBox();
const width = textSize.width + (tooltipPadding.x * 2);
const height = textSize.height + (tooltipPadding.y * 2);
const textSize = this.tooltipGroup
.select('text')
.text(tooltip)
.node()
.getBBox();
const width = textSize.width + tooltipPadding.x * 2;
const height = textSize.height + tooltipPadding.y * 2;
// calculate bounraries
const xMin = 0 - x - margin.left;
const yMin = 0 - y - margin.top;
const xMax = (this.chartWidth + margin.right) - x - width;
const yMax = (this.chartHeight + margin.bottom) - y - height;
const xMax = this.chartWidth + margin.right - x - width;
const yMax = this.chartHeight + margin.bottom - y - height;
// try to fit tooltip above point
let xOffset = 0 - Math.floor(width / 2);
......@@ -331,12 +368,14 @@ export default class BurndownChart {
this.chartFocus.attr('transform', `translate(${x}, ${y})`);
this.tooltipGroup.attr('transform', `translate(${xOffset}, ${yOffset})`);
this.tooltipGroup.select('text')
this.tooltipGroup
.select('text')
.attr('dy', '1em')
.attr('x', tooltipPadding.x)
.attr('y', tooltipPadding.y);
this.tooltipGroup.select('rect')
this.tooltipGroup
.select('rect')
.attr('width', width)
.attr('height', height);
}
......@@ -357,7 +396,10 @@ export default class BurndownChart {
static animateLinePath(path, duration = 1000, cb) {
const lineLength = path.node().getTotalLength();
const linearTransition = d3.transition().duration(duration).ease(d3.easeLinear);
const linearTransition = d3
.transition()
.duration(duration)
.ease(d3.easeLinear);
path
.attr('stroke-dasharray', `${lineLength} ${lineLength}`)
.attr('stroke-dashoffset', lineLength)
......
......@@ -31,7 +31,10 @@ export default () => {
const show = $this.data('show');
if (currentView !== show) {
currentView = show;
$this.addClass('active').siblings().removeClass('active');
$this
.addClass('active')
.siblings()
.removeClass('active');
switch (show) {
case 'count':
chart.setData(openIssuesCount, { label: 'Open issues', animate: true });
......
<script>
/**
/**
* Renders a deploy board.
*
* A deploy board is composed by:
......@@ -8,13 +8,13 @@
* - Button Actions.
* [Mockup](https://gitlab.com/gitlab-org/gitlab-ce/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png)
*/
import _ from 'underscore';
import { n__ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import deployBoardSvg from 'ee_empty_states/icons/_deploy_board.svg';
import instanceComponent from './deploy_board_instance_component.vue';
import _ from 'underscore';
import { n__ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import deployBoardSvg from 'ee_empty_states/icons/_deploy_board.svg';
import instanceComponent from './deploy_board_instance_component.vue';
export default {
export default {
components: {
instanceComponent,
},
......@@ -73,7 +73,7 @@
return deployBoardSvg;
},
},
};
};
</script>
<template>
<div class="js-deploy-board deploy-board">
......
<script>
/**
/**
* An instance in deploy board is represented by a square in this mockup:
* https://gitlab.com/gitlab-org/gitlab-ce/uploads/2f655655c0eadf655d0ae7467b53002a/environments__deploy-graphic.png
*
......@@ -12,9 +12,9 @@
* this information in the tooltip and the colors.
* Mockup is https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1551#note_26595150
*/
import tooltip from '~/vue_shared/directives/tooltip';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
......@@ -71,7 +71,7 @@
return `${this.logsPath}?pod_name=${this.podName}`;
},
},
};
};
</script>
<template>
<a
......
<script>
import $ from 'jquery';
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import timeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import Icon from '~/vue_shared/components/icon.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import { __, s__ } from '~/locale';
import eventHub from '../../event_hub';
import { stateEvent } from '../../constants';
import $ from 'jquery';
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import timeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import Icon from '~/vue_shared/components/icon.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import { __, s__ } from '~/locale';
import eventHub from '../../event_hub';
import { stateEvent } from '../../constants';
export default {
export default {
name: 'EpicHeader',
directives: {
tooltip,
......@@ -54,7 +54,9 @@
return this.isEpicOpen ? __('Open') : __('Closed');
},
actionButtonClass() {
return `btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button ${this.isEpicOpen ? 'btn-close' : 'btn-open'}`;
return `btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button ${
this.isEpicOpen ? 'btn-close' : 'btn-open'
}`;
},
actionButtonText() {
return this.isEpicOpen ? __('Close epic') : __('Reopen epic');
......@@ -68,7 +70,8 @@
},
methods: {
deleteEpic() {
if (window.confirm(s__('Epic will be removed! Are you sure?'))) { // eslint-disable-line no-alert
if (window.confirm(s__('Epic will be removed! Are you sure?'))) {
// eslint-disable-line no-alert
this.deleteLoading = true;
this.$emit('deleteEpic');
}
......@@ -81,7 +84,7 @@
this.$emit('toggleEpicStatus', this.isEpicOpen ? stateEvent.close : stateEvent.reopen);
},
},
};
};
</script>
<template>
......
......@@ -7,7 +7,9 @@ export default class SidebarContext {
constructor() {
const $issuableSidebar = $('.js-issuable-update');
Mousetrap.bind('l', () => SidebarContext.openSidebarDropdown($issuableSidebar.find('.js-labels-block')));
Mousetrap.bind('l', () =>
SidebarContext.openSidebarDropdown($issuableSidebar.find('.js-labels-block')),
);
$issuableSidebar
.off('click', '.js-sidebar-dropdown-toggle')
......
<script>
import Flash from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import loadingButton from '~/vue_shared/components/loading_button.vue';
import NewEpicService from '../services/new_epic_service';
import Flash from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import loadingButton from '~/vue_shared/components/loading_button.vue';
import NewEpicService from '../services/new_epic_service';
export default {
export default {
name: 'NewEpic',
components: {
loadingButton,
......@@ -39,7 +39,8 @@
methods: {
createEpic() {
this.creating = true;
this.service.createEpic(this.title)
this.service
.createEpic(this.title)
.then(({ data }) => {
visitUrl(data.web_url);
})
......@@ -55,7 +56,7 @@
}, 25);
},
},
};
};
</script>
<template>
......
......@@ -7,12 +7,14 @@ export default () => {
if (el) {
const props = el.dataset;
new Vue({ // eslint-disable-line no-new
new Vue({
// eslint-disable-line no-new
el,
components: {
'new-epic-app': NewEpicApp,
},
render: createElement => createElement('new-epic-app', {
render: createElement =>
createElement('new-epic-app', {
props,
}),
});
......
......@@ -119,7 +119,9 @@ export default {
},
popoverOptions() {
return this.getPopoverConfig({
title: s__('Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely.'),
title: s__(
'Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely.',
),
content: `
<a
href="${gon.gitlab_url}/help/user/group/epics/index.md#start-date-and-due-date"
......@@ -304,4 +306,3 @@ export default {
</div>
</div>
</template>
<script>
import Participants from '~/sidebar/components/participants/participants.vue';
import Participants from '~/sidebar/components/participants/participants.vue';
export default {
export default {
components: {
Participants,
},
......@@ -16,7 +16,7 @@
this.$emit('toggleCollapse');
},
},
};
};
</script>
<template>
......
<script>
import Subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue';
import Subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue';
export default {
export default {
components: {
Subscriptions,
},
......@@ -23,7 +23,7 @@
this.$emit('toggleCollapse');
},
},
};
};
</script>
<template>
......
<script>
import { __, s__ } from '~/locale';
import eventHub from '../event_hub';
import { NODE_ACTIONS } from '../constants';
import Icon from '~/vue_shared/components/icon.vue';
import { __, s__ } from '~/locale';
import eventHub from '../event_hub';
import { NODE_ACTIONS } from '../constants';
import Icon from '~/vue_shared/components/icon.vue';
export default {
export default {
components: {
Icon,
},
......@@ -59,7 +59,7 @@
eventHub.$emit('repairNode', this.node);
},
},
};
};
</script>
<template>
......
<script>
import { s__ } from '~/locale';
import popover from '~/vue_shared/directives/popover';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import StackedProgressBar from '~/vue_shared/components/stacked_progress_bar.vue';
import { s__ } from '~/locale';
import popover from '~/vue_shared/directives/popover';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import StackedProgressBar from '~/vue_shared/components/stacked_progress_bar.vue';
import { VALUE_TYPE, CUSTOM_TYPE } from '../constants';
import { VALUE_TYPE, CUSTOM_TYPE } from '../constants';
import GeoNodeSyncSettings from './geo_node_sync_settings.vue';
import GeoNodeEventStatus from './geo_node_event_status.vue';
import GeoNodeSyncSettings from './geo_node_sync_settings.vue';
import GeoNodeEventStatus from './geo_node_event_status.vue';
export default {
export default {
components: {
Icon,
StackedProgressBar,
......@@ -117,7 +117,7 @@
};
},
},
};
};
</script>
<template>
......
<script>
/* eslint-disable vue/no-side-effects-in-computed-properties */
import { s__ } from '~/locale';
/* eslint-disable vue/no-side-effects-in-computed-properties */
import { s__ } from '~/locale';
import NodeDetailsSectionMain from './node_detail_sections/node_details_section_main.vue';
import NodeDetailsSectionSync from './node_detail_sections/node_details_section_sync.vue';
import NodeDetailsSectionVerification from './node_detail_sections/node_details_section_verification.vue';
import NodeDetailsSectionOther from './node_detail_sections/node_details_section_other.vue';
import NodeDetailsSectionMain from './node_detail_sections/node_details_section_main.vue';
import NodeDetailsSectionSync from './node_detail_sections/node_details_section_sync.vue';
import NodeDetailsSectionVerification from './node_detail_sections/node_details_section_verification.vue';
import NodeDetailsSectionOther from './node_detail_sections/node_details_section_other.vue';
export default {
export default {
components: {
NodeDetailsSectionMain,
NodeDetailsSectionSync,
......@@ -46,15 +46,17 @@
return !this.nodeDetails.healthy;
},
hasVersionMismatch() {
if (this.nodeDetails.version !== this.nodeDetails.primaryVersion ||
this.nodeDetails.revision !== this.nodeDetails.primaryRevision) {
if (
this.nodeDetails.version !== this.nodeDetails.primaryVersion ||
this.nodeDetails.revision !== this.nodeDetails.primaryRevision
) {
this.errorMessage = s__('GeoNodes|GitLab version does not match the primary node version');
return true;
}
return false;
},
},
};
};
</script>
<template>
......
<script>
import { formatDate } from '~/lib/utils/datetime_utility';
import timeAgoMixin from '~/vue_shared/mixins/timeago';
import tooltip from '~/vue_shared/directives/tooltip';
import { formatDate } from '~/lib/utils/datetime_utility';
import timeAgoMixin from '~/vue_shared/mixins/timeago';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
mixins: [
timeAgoMixin,
],
mixins: [timeAgoMixin],
props: {
eventId: {
type: Number,
......@@ -37,7 +35,7 @@
return this.eventId;
},
},
};
};
</script>
<template>
......
<script>
import { s__ } from '~/locale';
import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import { s__ } from '~/locale';
import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
components: {
icon,
},
......@@ -56,10 +56,12 @@
if (this.nodeDetailsFailed) {
return '';
}
return s__('GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS.');
return s__(
'GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS.',
);
},
},
};
};
</script>
<template>
......
<script>
import icon from '~/vue_shared/components/icon.vue';
import { HEALTH_STATUS_ICON } from '../constants';
import icon from '~/vue_shared/components/icon.vue';
import { HEALTH_STATUS_ICON } from '../constants';
export default {
export default {
components: {
icon,
},
......@@ -20,7 +20,7 @@
return HEALTH_STATUS_ICON[this.status.toLowerCase()];
},
},
};
};
</script>
<template>
......
<script>
import { s__ } from '~/locale';
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
import icon from '~/vue_shared/components/icon.vue';
import { s__ } from '~/locale';
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
import icon from '~/vue_shared/components/icon.vue';
import { TIME_DIFF } from '../constants';
import { TIME_DIFF } from '../constants';
export default {
export default {
directives: {
tooltip,
},
......@@ -80,8 +80,7 @@
statusIcon(syncLag) {
if (syncLag <= TIME_DIFF.FIVE_MINS) {
return 'retry';
} else if (syncLag > TIME_DIFF.FIVE_MINS &&
syncLag <= TIME_DIFF.HOUR) {
} else if (syncLag > TIME_DIFF.FIVE_MINS && syncLag <= TIME_DIFF.HOUR) {
return 'warning';
}
return 'status_failed';
......@@ -92,17 +91,17 @@
return `${timeAgoStr} (${pendingEvents} events)`;
},
statusTooltip(lagInSeconds) {
if (this.eventTimestampEmpty ||
lagInSeconds <= TIME_DIFF.FIVE_MINS) {
if (this.eventTimestampEmpty || lagInSeconds <= TIME_DIFF.FIVE_MINS) {
return '';
} else if (lagInSeconds > TIME_DIFF.FIVE_MINS &&
lagInSeconds <= TIME_DIFF.HOUR) {
return s__('GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage.');
} else if (lagInSeconds > TIME_DIFF.FIVE_MINS && lagInSeconds <= TIME_DIFF.HOUR) {
return s__(
'GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage.',
);
}
return s__('GeoNodeSyncStatus|Node is failing or broken.');
},
},
};
};
</script>
<template>
......
<script>
import { __ } from '~/locale';
import { __ } from '~/locale';
import GeoNodeHealthStatus from '../geo_node_health_status.vue';
import GeoNodeActions from '../geo_node_actions.vue';
import GeoNodeHealthStatus from '../geo_node_health_status.vue';
import GeoNodeActions from '../geo_node_actions.vue';
export default {
export default {
components: {
GeoNodeHealthStatus,
GeoNodeActions,
......@@ -33,8 +33,7 @@
},
computed: {
nodeVersion() {
if (this.nodeDetails.version == null &&
this.nodeDetails.revision == null) {
if (this.nodeDetails.version == null && this.nodeDetails.revision == null) {
return __('Unknown');
}
return `${this.nodeDetails.version} (${this.nodeDetails.revision})`;
......@@ -43,7 +42,7 @@
return this.nodeDetails.healthy ? this.nodeDetails.health : this.nodeDetails.healthStatus;
},
},
};
};
</script>
<template>
......
<script>
import { s__, __ } from '~/locale';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { s__, __ } from '~/locale';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { VALUE_TYPE } from '../../constants';
import { VALUE_TYPE } from '../../constants';
import DetailsSectionMixin from '../../mixins/details_section_mixin';
import DetailsSectionMixin from '../../mixins/details_section_mixin';
import GeoNodeDetailItem from '../geo_node_detail_item.vue';
import SectionRevealButton from './section_reveal_button.vue';
import GeoNodeDetailItem from '../geo_node_detail_item.vue';
import SectionRevealButton from './section_reveal_button.vue';
export default {
export default {
valueType: VALUE_TYPE,
components: {
SectionRevealButton,
GeoNodeDetailItem,
},
mixins: [
DetailsSectionMixin,
],
mixins: [DetailsSectionMixin],
props: {
nodeDetails: {
type: Object,
......@@ -48,14 +46,12 @@
];
if (this.nodeDetails.replicationSlots.totalCount) {
primaryNodeDetailItems.push(
{
primaryNodeDetailItems.push({
itemTitle: s__('GeoNodes|Replication slot WAL'),
itemValue: numberToHumanSize(this.nodeDetails.replicationSlotWAL),
itemValueType: VALUE_TYPE.PLAIN,
cssClass: 'node-detail-value-bold',
},
);
});
}
return primaryNodeDetailItems;
......@@ -75,11 +71,15 @@
if (this.nodeDetails.storageShardsMatch == null) {
return __('Unknown');
}
return this.nodeDetails.storageShardsMatch ? __('OK') : s__('GeoNodes|Does not match the primary storage configuration');
return this.nodeDetails.storageShardsMatch
? __('OK')
: s__('GeoNodes|Does not match the primary storage configuration');
},
storageShardsCssClass() {
const cssClass = 'node-detail-value-bold';
return !this.nodeDetails.storageShardsMatch ? `${cssClass} node-detail-value-error` : cssClass;
return !this.nodeDetails.storageShardsMatch
? `${cssClass} node-detail-value-error`
: cssClass;
},
},
methods: {
......@@ -87,7 +87,7 @@
this.showSectionItems = toggleState;
},
},
};
};
</script>
<template>
......
<script>
import { s__ } from '~/locale';
import { s__ } from '~/locale';
import { VALUE_TYPE, HELP_INFO_URL } from '../../constants';
import { VALUE_TYPE, HELP_INFO_URL } from '../../constants';
import DetailsSectionMixin from '../../mixins/details_section_mixin';
import DetailsSectionMixin from '../../mixins/details_section_mixin';
import GeoNodeDetailItem from '../geo_node_detail_item.vue';
import SectionRevealButton from './section_reveal_button.vue';
import GeoNodeDetailItem from '../geo_node_detail_item.vue';
import SectionRevealButton from './section_reveal_button.vue';
export default {
export default {
components: {
GeoNodeDetailItem,
SectionRevealButton,
},
mixins: [
DetailsSectionMixin,
],
mixins: [DetailsSectionMixin],
props: {
nodeDetails: {
type: Object,
......@@ -35,9 +33,9 @@
},
computed: {
nodeDetailItems() {
return this.nodeTypePrimary ?
this.getPrimaryNodeDetailItems() :
this.getSecondaryNodeDetailItems();
return this.nodeTypePrimary
? this.getPrimaryNodeDetailItems()
: this.getSecondaryNodeDetailItems();
},
},
methods: {
......@@ -51,7 +49,9 @@
neutraLabel: s__('GeoNodes|Not checksummed'),
failureLabel: s__('GeoNodes|Failed'),
helpInfo: {
title: s__('GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes'),
title: s__(
'GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes',
),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Repository checksum progress'),
},
......@@ -64,7 +64,9 @@
neutraLabel: s__('GeoNodes|Not checksummed'),
failureLabel: s__('GeoNodes|Failed'),
helpInfo: {
title: s__('GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes'),
title: s__(
'GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes',
),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Wiki checksum progress'),
},
......@@ -81,7 +83,9 @@
neutraLabel: s__('GeoNodes|Unverified'),
failureLabel: s__('GeoNodes|Failed'),
helpInfo: {
title: s__('GeoNodes|Repositories verified with their counterparts on the Primary node'),
title: s__(
'GeoNodes|Repositories verified with their counterparts on the Primary node',
),
url: HELP_INFO_URL,
urlText: s__('GeoNodes|Learn more about Repository verification'),
},
......@@ -105,7 +109,7 @@
this.showSectionItems = toggleState;
},
},
};
};
</script>
<template>
......
<script>
import icon from '~/vue_shared/components/icon.vue';
import icon from '~/vue_shared/components/icon.vue';
export default {
export default {
components: {
icon,
},
......@@ -27,7 +27,7 @@
this.$emit('toggleButton', this.toggleState);
},
},
};
};
</script>
<template>
......
......@@ -30,4 +30,5 @@ export const TIME_DIFF = {
export const STATUS_DELAY_THRESHOLD_MS = 60000;
export const HELP_INFO_URL = 'https://docs.gitlab.com/ee/administration/geo/disaster_recovery/background_verification.html#repository-verification';
export const HELP_INFO_URL =
'https://docs.gitlab.com/ee/administration/geo/disaster_recovery/background_verification.html#repository-verification';
......@@ -13,9 +13,7 @@ export default {
},
statusInfoStaleMessage() {
return sprintf(s__('GeoNodes|Data is out of date from %{timeago}'), {
timeago: this.timeFormated(
this.nodeDetails.statusCheckTimestamp,
),
timeago: this.timeFormated(this.nodeDetails.statusCheckTimestamp),
});
},
},
......
......@@ -8,9 +8,7 @@ export default class GeoNodesStore {
}
setNodes(nodes) {
this.state.nodes = nodes.map(
node => GeoNodesStore.formatNode(node),
);
this.state.nodes = nodes.map(node => GeoNodesStore.formatNode(node));
}
getNodes() {
......
......@@ -19,7 +19,7 @@ const setupAutoCompleteEpics = ($input, defaultCallbacks) => {
callbacks: {
...defaultCallbacks,
beforeSave(merges) {
return $.map(merges, (m) => {
return $.map(merges, m => {
if (m.title == null) {
return m;
}
......
......@@ -11,18 +11,16 @@ export default () => {
modal: true,
show: false,
})
.on('show.bs.modal', (e) => {
const {
cloneUrlPrimary,
cloneUrlSecondary,
} = $(e.currentTarget).data();
.on('show.bs.modal', e => {
const { cloneUrlPrimary, cloneUrlSecondary } = $(e.currentTarget).data();
$('#geo-info-1').val(
`git clone ${(cloneUrlSecondary || '<clone url for secondary repository>')}`,
`git clone ${cloneUrlSecondary || '<clone url for secondary repository>'}`,
);
$('#geo-info-2').val(
`git remote set-url --push origin ${(cloneUrlPrimary || '<clone url for primary repository>')}`,
`git remote set-url --push origin ${cloneUrlPrimary ||
'<clone url for primary repository>'}`,
);
});
};
......@@ -78,11 +78,15 @@ export default class KubernetesPodLogs extends LogOutputBehaviours {
this.$podDropdown
.find('.dropdown-menu-toggle')
.html(`<span class="dropdown-toggle-text">${this.podName}</span><i class="fa fa-chevron-down"></i>`);
.html(
`<span class="dropdown-toggle-text">${
this.podName
}</span><i class="fa fa-chevron-down"></i>`,
);
$podDropdownMenu.off('click');
$podDropdownMenu.empty();
pods.forEach((pod) => {
pods.forEach(pod => {
$podDropdownMenu.append(`
<button class='dropdown-item'>
${_.escape(pod)}
......
......@@ -16,7 +16,7 @@ export default function initLDAPGroupsSelect() {
id: function(group) {
return group.cn;
},
placeholder: "Search for a LDAP group",
placeholder: 'Search for a LDAP group',
minimumInputLength: 1,
query: function(query) {
var provider;
......@@ -24,7 +24,7 @@ export default function initLDAPGroupsSelect() {
return Api.ldap_groups(query.term, provider, function(groups) {
var data;
data = {
results: groups
results: groups,
};
return query.callback(data);
});
......@@ -32,18 +32,18 @@ export default function initLDAPGroupsSelect() {
initSelection: function(element, callback) {
var id;
id = $(element).val();
if (id !== "") {
if (id !== '') {
return callback({
cn: id
cn: id,
});
}
},
formatResult: ldapGroupResult,
formatSelection: groupFormatSelection,
dropdownCssClass: "ajax-groups-dropdown",
dropdownCssClass: 'ajax-groups-dropdown',
formatNoMatches: function(nomatch) {
return "Match not found; try refining your search query.";
}
return 'Match not found; try refining your search query.';
},
});
});
return $('#ldap_group_link_provider').on('change', function() {
......
......@@ -96,7 +96,11 @@ export default class MirrorPull {
// Make backOff polling to get data
backOff((next, stop) => {
axios
.get(`${projectMirrorSSHEndpoint}?ssh_url=${repositoryUrl}&compare_host_keys=${encodeURIComponent(currentKnownHosts)}`)
.get(
`${projectMirrorSSHEndpoint}?ssh_url=${repositoryUrl}&compare_host_keys=${encodeURIComponent(
currentKnownHosts,
)}`,
)
.then(({ data, status }) => {
if (status === 204) {
this.backOffRequestCounter += 1;
......
......@@ -97,9 +97,7 @@ export default {
this.isLoading = true;
return Promise.all(
this.alerts.map(alertPath =>
this.service
.readAlert(alertPath)
.then(alertData => {
this.service.readAlert(alertPath).then(alertData => {
this.$emit('setAlerts', this.customMetricId, {
...this.alertData,
[alertPath]: alertData,
......
......@@ -26,17 +26,15 @@ export default {
const [xMin, xMax] = this.graphDrawData.xDom;
const [yMin, yMax] = this.graphDrawData.yDom;
const outOfRange = (this.operator === '>' && this.threshold > yMax) ||
const outOfRange =
(this.operator === '>' && this.threshold > yMax) ||
(this.operator === '<' && this.threshold < yMin);
if (outOfRange) {
return [];
}
return [
{ time: xMin, value: this.threshold },
{ time: xMax, value: this.threshold },
];
return [{ time: xMin, value: this.threshold }, { time: xMax, value: this.threshold }];
},
linePath() {
if (!this.graphDrawData.lineFunction) {
......
......@@ -4,38 +4,39 @@ import $ from 'jquery';
import Api from '~/api';
function AdminEmailSelect() {
$('.ajax-admin-email-select').each((function(_this) {
$('.ajax-admin-email-select').each(
(function(_this) {
return function(i, select) {
var skip_ldap;
skip_ldap = $(select).hasClass('skip_ldap');
return $(select).select2({
placeholder: "Select group or project",
placeholder: 'Select group or project',
multiple: $(select).hasClass('multiselect'),
minimumInputLength: 0,
query: function(query) {
const groupsFetch = Api.groups(query.term, {});
const projectsFetch = Api.projects(query.term, {
order_by: 'id',
membership: false
membership: false,
});
return Promise.all([projectsFetch, groupsFetch]).then(function([projects, groups]) {
var all, data;
all = {
id: "all"
id: 'all',
};
data = [all].concat(groups, projects);
return query.callback({
results: data
results: data,
});
});
},
id: function(object) {
if (object.path_with_namespace) {
return "project-" + object.id;
return 'project-' + object.id;
} else if (object.path) {
return "group-" + object.id;
return 'group-' + object.id;
} else {
return "all";
return 'all';
}
},
formatResult(...args) {
......@@ -44,20 +45,33 @@ function AdminEmailSelect() {
formatSelection(...args) {
return _this.formatSelection(...args);
},
dropdownCssClass: "ajax-admin-email-dropdown",
dropdownCssClass: 'ajax-admin-email-dropdown',
escapeMarkup: function(m) {
return m;
}
},
});
};
})(this));
})(this),
);
}
AdminEmailSelect.prototype.formatResult = function(object) {
if (object.path_with_namespace) {
return "<div class='project-result'> <div class='project-name'>" + object.name + "</div> <div class='project-path'>" + object.path_with_namespace + "</div> </div>";
return (
"<div class='project-result'> <div class='project-name'>" +
object.name +
"</div> <div class='project-path'>" +
object.path_with_namespace +
'</div> </div>'
);
} else if (object.path) {
return "<div class='group-result'> <div class='group-name'>" + object.name + "</div> <div class='group-path'>" + object.path + "</div> </div>";
return (
"<div class='group-result'> <div class='group-name'>" +
object.name +
"</div> <div class='group-path'>" +
object.path +
'</div> </div>'
);
} else {
return "<div class='group-result'> <div class='group-name'>All</div> <div class='group-path'>All groups and projects</div> </div>";
}
......@@ -65,11 +79,11 @@ AdminEmailSelect.prototype.formatResult = function(object) {
AdminEmailSelect.prototype.formatSelection = function(object) {
if (object.path_with_namespace) {
return "Project: " + object.name;
return 'Project: ' + object.name;
} else if (object.path) {
return "Group: " + object.name;
return 'Group: ' + object.name;
} else {
return "All groups and projects";
return 'All groups and projects';
}
};
......
......@@ -24,11 +24,11 @@ export default function geoNodeForm() {
const $syncByNamespaces = $('.js-sync-by-namespace', $container);
const $syncByShards = $('.js-sync-by-shard', $container);
$primaryCheckbox.on('change', e =>
onPrimaryCheckboxChange(e, $namespaces));
$primaryCheckbox.on('change', e => onPrimaryCheckboxChange(e, $namespaces));
$selectiveSyncTypeSelect.on('change', e =>
onSelectiveSyncTypeChange(e, $syncByNamespaces, $syncByShards));
onSelectiveSyncTypeChange(e, $syncByNamespaces, $syncByShards),
);
$select2Dropdown.select2({
placeholder: s__('Geo|Select groups to replicate.'),
......
......@@ -25,7 +25,7 @@ document.addEventListener('DOMContentLoaded', () => {
merge_requests_created: [],
};
outputElIds.forEach((id) => {
outputElIds.forEach(id => {
data[id].data.forEach((d, index) => {
formattedData[id].push({
name: data.labels[index],
......
......@@ -107,8 +107,7 @@ export default class EEMirrorRepos extends MirrorRepos {
};
}
return super.deleteMirror(event, payload)
.then(() => {
return super.deleteMirror(event, payload).then(() => {
if (isPullMirror) this.$mirrorDirectionSelect.removeAttr('disabled');
});
}
......
......@@ -4,10 +4,7 @@ export default () => {
const dataEl = document.getElementById('js-file-lock');
if (dataEl) {
const {
toggle_path,
path,
} = JSON.parse(dataEl.innerHTML);
const { toggle_path, path } = JSON.parse(dataEl.innerHTML);
initPathLocks(toggle_path, path);
}
......
......@@ -4,13 +4,16 @@ import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
export default function initPathLocks(url, path) {
$('a.path-lock').on('click', (e) => {
$('a.path-lock').on('click', e => {
e.preventDefault();
axios.post(url, {
axios
.post(url, {
path,
}).then(() => {
})
.then(() => {
window.location.reload();
}).catch(() => flash(__('An error occurred while initializing path locks')));
})
.catch(() => flash(__('An error occurred while initializing path locks')));
});
}
<script>
import ciStatus from '~/vue_shared/components/ci_icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import ciStatus from '~/vue_shared/components/ci_icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
......@@ -32,7 +32,7 @@
return `${this.projectName} - ${this.pipelineStatus.label}`;
},
},
};
};
</script>
<template>
......
<script>
import linkedPipeline from './linked_pipeline.vue';
import linkedPipeline from './linked_pipeline.vue';
export default {
export default {
components: {
linkedPipeline,
},
......@@ -25,7 +25,7 @@
return `graph-position-${this.graphPosition}`;
},
},
};
};
</script>
<template>
......
......@@ -46,8 +46,9 @@ const bindEvents = () => {
const $activeTabProjectName = $('.tab-pane.active #project_name');
const $activeTabProjectPath = $('.tab-pane.active #project_path');
$activeTabProjectName.focus();
$activeTabProjectName
.keyup(() => projectNew.onProjectNameChange($activeTabProjectName, $activeTabProjectPath));
$activeTabProjectName.keyup(() =>
projectNew.onProjectNameChange($activeTabProjectName, $activeTabProjectPath),
);
}
$useCustomTemplateBtn.on('change', chooseTemplate);
......@@ -60,7 +61,6 @@ const bindEvents = () => {
};
export default () => {
const $navElement = $('.nav-link[href="#custom-templates"]');
const $tabContent = $('.project-templates-buttons#custom-templates');
......
<script>
import Flash from '~/flash';
import serviceDeskSetting from './service_desk_setting.vue';
import ServiceDeskStore from '../stores/service_desk_store';
import ServiceDeskService from '../services/service_desk_service';
import eventHub from '../event_hub';
import Flash from '~/flash';
import serviceDeskSetting from './service_desk_setting.vue';
import ServiceDeskStore from '../stores/service_desk_store';
import ServiceDeskService from '../services/service_desk_service';
import eventHub from '../event_hub';
export default {
export default {
name: 'ServiceDeskRoot',
components: {
......@@ -59,18 +59,23 @@
this.flash.innerHTML = '';
}
this.service.fetchIncomingEmail()
this.service
.fetchIncomingEmail()
.then(res => res.json())
.then((data) => {
.then(data => {
const email = data.service_desk_address;
if (!email) {
throw new Error('Response didn\'t include `service_desk_address`');
throw new Error("Response didn't include `service_desk_address`");
}
this.store.setIncomingEmail(email);
})
.catch(() => {
this.flash = new Flash('An error occurred while fetching the Service Desk address.', 'alert', this.$el);
this.flash = new Flash(
'An error occurred while fetching the Service Desk address.',
'alert',
this.$el,
);
});
},
......@@ -81,23 +86,28 @@
this.flash.destroy();
}
this.service.toggleServiceDesk(isChecked)
this.service
.toggleServiceDesk(isChecked)
.then(res => res.json())
.then((data) => {
.then(data => {
const email = data.service_desk_address;
if (isChecked && !email) {
throw new Error('Response didn\'t include `service_desk_address`');
throw new Error("Response didn't include `service_desk_address`");
}
this.store.setIncomingEmail(email);
})
.catch(() => {
const verb = isChecked ? 'enabling' : 'disabling';
this.flash = new Flash(`An error occurred while ${verb} Service Desk.`, 'alert', this.$el);
this.flash = new Flash(
`An error occurred while ${verb} Service Desk.`,
'alert',
this.$el,
);
});
},
},
};
};
</script>
<template>
......
<script>
import tooltip from '~/vue_shared/directives/tooltip';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import eventHub from '../event_hub';
import tooltip from '~/vue_shared/directives/tooltip';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import eventHub from '../event_hub';
export default {
export default {
name: 'ServiceDeskSetting',
directives: {
tooltip,
......@@ -30,7 +30,7 @@
eventHub.$emit('serviceDeskEnabledCheckboxToggled', isChecked);
},
},
};
};
</script>
<template>
......
......@@ -14,9 +14,7 @@ export default () => {
data() {
const { dataset } = serviceDeskRootElement;
return {
initialIsEnabled: convertPermissionToBoolean(
dataset.enabled,
),
initialIsEnabled: convertPermissionToBoolean(dataset.enabled),
endpoint: dataset.endpoint,
incomingEmail: dataset.incomingEmail,
};
......
class ServiceDeskStore {
constructor(initialState = {}) {
this.state = Object.assign({
this.state = Object.assign(
{
incomingEmail: '',
}, initialState);
},
initialState,
);
}
setIncomingEmail(value) {
......
import Stats from 'ee/stats';
const bindTrackEvents = (container) => {
const bindTrackEvents = container => {
Stats.bindTrackableContainer(container);
};
......
......@@ -11,18 +11,32 @@ export default class EEPrometheusMetrics extends PrometheusMetrics {
super(wrapperSelector);
this.$wrapperCustomMetrics = $(wrapperSelector);
this.$monitoredCustomMetricsPanel = this.$wrapperCustomMetrics.find('.js-panel-custom-monitored-metrics');
this.$monitoredCustomMetricsCount = this.$monitoredCustomMetricsPanel.find('.js-custom-monitored-count');
this.$monitoredCustomMetricsLoading = this.$monitoredCustomMetricsPanel.find('.js-loading-custom-metrics');
this.$monitoredCustomMetricsEmpty = this.$monitoredCustomMetricsPanel.find('.js-empty-custom-metrics');
this.$monitoredCustomMetricsList = this.$monitoredCustomMetricsPanel.find('.js-custom-metrics-list');
this.$monitoredCustomMetricsPanel = this.$wrapperCustomMetrics.find(
'.js-panel-custom-monitored-metrics',
);
this.$monitoredCustomMetricsCount = this.$monitoredCustomMetricsPanel.find(
'.js-custom-monitored-count',
);
this.$monitoredCustomMetricsLoading = this.$monitoredCustomMetricsPanel.find(
'.js-loading-custom-metrics',
);
this.$monitoredCustomMetricsEmpty = this.$monitoredCustomMetricsPanel.find(
'.js-empty-custom-metrics',
);
this.$monitoredCustomMetricsList = this.$monitoredCustomMetricsPanel.find(
'.js-custom-metrics-list',
);
this.$newCustomMetricButton = this.$monitoredCustomMetricsPanel.find('.js-new-metric-button');
this.$flashCustomMetricsContainer = this.$wrapperCustomMetrics.find('.flash-container');
this.customMetrics = [];
this.environmentsData = [];
this.activeCustomMetricsEndpoint = this.$monitoredCustomMetricsPanel.data('active-custom-metrics');
this.environmentsDataEndpoint = this.$monitoredCustomMetricsPanel.data('environments-data-endpoint');
this.activeCustomMetricsEndpoint = this.$monitoredCustomMetricsPanel.data(
'active-custom-metrics',
);
this.environmentsDataEndpoint = this.$monitoredCustomMetricsPanel.data(
'environments-data-endpoint',
);
}
showMonitoringCustomMetricsPanelState(stateName) {
......@@ -49,20 +63,25 @@ export default class EEPrometheusMetrics extends PrometheusMetrics {
}
populateCustomMetrics() {
const sortedMetrics = _(this.customMetrics).chain()
const sortedMetrics = _(this.customMetrics)
.chain()
.map(metric => ({ ...metric, group: capitalizeFirstCharacter(metric.group) }))
.sortBy('title')
.sortBy('group')
.value();
sortedMetrics.forEach((metric) => {
sortedMetrics.forEach(metric => {
this.$monitoredCustomMetricsList.append(EEPrometheusMetrics.customMetricTemplate(metric));
});
this.$monitoredCustomMetricsCount.text(this.customMetrics.length);
this.showMonitoringCustomMetricsPanelState(PANEL_STATE.LIST);
if (!this.environmentsData) {
this.showFlashMessage(s__('PrometheusService|These metrics will only be monitored after your first deployment to an environment'));
this.showFlashMessage(
s__(
'PrometheusService|These metrics will only be monitored after your first deployment to an environment',
),
);
}
}
......@@ -86,7 +105,7 @@ export default class EEPrometheusMetrics extends PrometheusMetrics {
this.populateCustomMetrics(customMetrics.data.metrics);
}
})
.catch((customMetricError) => {
.catch(customMetricError => {
this.showFlashMessage(customMetricError);
this.showMonitoringCustomMetricsPanelState(PANEL_STATE.EMPTY);
});
......
......@@ -17,4 +17,3 @@ export default class ProtectedEnvironmentEditList {
});
}
}
......@@ -43,8 +43,9 @@ export default {
return `Paste issue link${this.allowAutoComplete ? ' or <#issue id>' : ''}`;
},
isSubmitButtonDisabled() {
return (this.inputValue.length === 0 && this.pendingReferences.length === 0)
|| this.isSubmitting;
return (
(this.inputValue.length === 0 && this.pendingReferences.length === 0) || this.isSubmitting
);
},
allowAutoComplete() {
return Object.keys(this.autoCompleteSources).length > 0;
......
......@@ -113,10 +113,10 @@ export default {
if (issueToRemove) {
RelatedIssuesService.remove(issueToRemove.relation_path)
.then(res => res.json())
.then((data) => {
.then(data => {
this.store.setRelatedIssues(data.issues);
})
.catch((res) => {
.catch(res => {
if (res && res.status !== 404) {
Flash('An error occurred while removing issues.');
}
......@@ -136,9 +136,10 @@ export default {
if (this.state.pendingReferences.length > 0) {
this.isSubmitting = true;
this.service.addRelatedIssues(this.state.pendingReferences)
this.service
.addRelatedIssues(this.state.pendingReferences)
.then(res => res.json())
.then((data) => {
.then(data => {
// We could potentially lose some pending issues in the interim here
this.store.setPendingReferences([]);
this.store.setRelatedIssues(data.issues);
......@@ -147,9 +148,9 @@ export default {
// Close the form on submission
this.isFormVisible = false;
})
.catch((res) => {
.catch(res => {
this.isSubmitting = false;
let errorMessage = 'We can\'t find an issue that matches what you are looking for.';
let errorMessage = "We can't find an issue that matches what you are looking for.";
if (res.data && res.data.message) {
errorMessage = res.data.message;
}
......@@ -164,9 +165,10 @@ export default {
},
fetchRelatedIssues() {
this.isFetching = true;
this.service.fetchRelatedIssues()
this.service
.fetchRelatedIssues()
.then(res => res.json())
.then((issues) => {
.then(issues => {
this.store.setRelatedIssues(issues);
this.isFetching = false;
})
......@@ -186,7 +188,7 @@ export default {
move_after_id: afterId,
})
.then(res => res.json())
.then((res) => {
.then(res => {
if (!res.message) {
this.store.updateIssueOrder(oldIndex, newIndex);
}
......@@ -197,15 +199,14 @@ export default {
}
},
onInput(newValue, caretPos) {
const rawReferences = newValue
.split(/\s/);
const rawReferences = newValue.split(/\s/);
let touchedReference;
let iteratingPos = 0;
const untouchedRawReferences = rawReferences
.filter((reference) => {
.filter(reference => {
let isTouched = false;
if (caretPos >= iteratingPos && caretPos <= (iteratingPos + reference.length)) {
if (caretPos >= iteratingPos && caretPos <= iteratingPos + reference.length) {
touchedReference = reference;
isTouched = true;
}
......@@ -216,22 +217,16 @@ export default {
})
.filter(reference => reference.trim().length > 0);
this.store.setPendingReferences(
this.state.pendingReferences.concat(untouchedRawReferences),
);
this.store.setPendingReferences(this.state.pendingReferences.concat(untouchedRawReferences));
this.inputValue = `${touchedReference}`;
},
onBlur(newValue) {
this.processAllReferences(newValue);
},
processAllReferences(value = '') {
const rawReferences = value
.split(/\s+/)
.filter(reference => reference.trim().length > 0);
const rawReferences = value.split(/\s+/).filter(reference => reference.trim().length > 0);
this.store.setPendingReferences(
this.state.pendingReferences.concat(rawReferences),
);
this.store.setPendingReferences(this.state.pendingReferences.concat(rawReferences));
this.inputValue = '';
},
},
......
......@@ -11,7 +11,8 @@ export default function initRelatedIssues() {
components: {
relatedIssuesRoot: RelatedIssuesRoot,
},
render: createElement => createElement('related-issues-root', {
render: createElement =>
createElement('related-issues-root', {
props: {
endpoint: relatedIssuesRootElement.dataset.endpoint,
canAdmin: convertPermissionToBoolean(
......
......@@ -13,9 +13,12 @@ class RelatedIssuesService {
}
addRelatedIssues(newIssueReferences) {
return this.relatedIssuesResource.save({}, {
return this.relatedIssuesResource.save(
{},
{
issue_references: newIssueReferences,
});
},
);
}
static saveOrder({ endpoint, move_before_id, move_after_id }) {
......
......@@ -28,10 +28,10 @@ class RelatedIssuesStore {
}
removePendingRelatedIssue(indexToRemove) {
this.state.pendingReferences =
this.state.pendingReferences.filter((reference, index) => index !== indexToRemove);
this.state.pendingReferences = this.state.pendingReferences.filter(
(reference, index) => index !== indexToRemove,
);
}
}
export default RelatedIssuesStore;
<script>
import _ from 'underscore';
import Flash from '~/flash';
import { s__ } from '~/locale';
import _ from 'underscore';
import Flash from '~/flash';
import { s__ } from '~/locale';
import epicsListEmpty from './epics_list_empty.vue';
import roadmapShell from './roadmap_shell.vue';
import epicsListEmpty from './epics_list_empty.vue';
import roadmapShell from './roadmap_shell.vue';
export default {
export default {
components: {
epicsListEmpty,
roadmapShell,
......@@ -77,9 +77,10 @@
methods: {
fetchEpics() {
this.hasError = false;
this.service.getEpics()
this.service
.getEpics()
.then(res => res.data)
.then((epics) => {
.then(epics => {
this.isLoading = false;
if (epics.length) {
this.store.setEpics(epics);
......@@ -115,7 +116,7 @@
}, 200)();
},
},
};
};
</script>
<template>
......
<script>
import epicItemDetails from './epic_item_details.vue';
import epicItemTimeline from './epic_item_timeline.vue';
import epicItemDetails from './epic_item_details.vue';
import epicItemTimeline from './epic_item_timeline.vue';
export default {
export default {
components: {
epicItemDetails,
epicItemTimeline,
......@@ -33,7 +33,7 @@
required: true,
},
},
};
};
</script>
<template>
......
<script>
import { s__, sprintf } from '~/locale';
import { dateInWords } from '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
import { s__, sprintf } from '~/locale';
import { dateInWords } from '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
......@@ -68,7 +68,7 @@
return `${startDateInWords} &ndash; ${dateInWords(this.endDate, true)}`;
},
},
};
};
</script>
<template>
......
......@@ -17,11 +17,7 @@ export default {
directives: {
tooltip,
},
mixins: [
QuartersPresetMixin,
MonthsPresetMixin,
WeeksPresetMixin,
],
mixins: [QuartersPresetMixin, MonthsPresetMixin, WeeksPresetMixin],
props: {
presetType: {
type: String,
......
<script>
import eventHub from '../event_hub';
import eventHub from '../event_hub';
import SectionMixin from '../mixins/section_mixin';
import SectionMixin from '../mixins/section_mixin';
import epicItem from './epic_item.vue';
import epicItem from './epic_item.vue';
export default {
export default {
components: {
epicItem,
},
mixins: [
SectionMixin,
],
mixins: [SectionMixin],
props: {
presetType: {
type: String,
......@@ -114,14 +112,14 @@
if (approxChildrenHeight < this.shellHeight) {
// reset approximate height and recalculate actual height
approxChildrenHeight = 0;
children.forEach((child) => {
children.forEach(child => {
// accumulate children height
// compensate for bottom border
approxChildrenHeight += child.$el.clientHeight;
});
// set height and show empty row reducing horizontal scrollbar size
this.emptyRowHeight = (this.shellHeight - approxChildrenHeight);
this.emptyRowHeight = this.shellHeight - approxChildrenHeight;
this.showEmptyRow = true;
} else {
this.showBottomShadow = true;
......@@ -138,10 +136,10 @@
this.$el.scrollTo(uptoTodayIndicator, 0);
},
handleEpicsListScroll({ scrollTop, clientHeight, scrollHeight }) {
this.showBottomShadow = (Math.ceil(scrollTop) + clientHeight) < scrollHeight;
this.showBottomShadow = Math.ceil(scrollTop) + clientHeight < scrollHeight;
},
},
};
};
</script>
<template>
......
<script>
import { monthInWords } from '~/lib/utils/datetime_utility';
import { monthInWords } from '~/lib/utils/datetime_utility';
import MonthsHeaderSubItem from './months_header_sub_item.vue';
import MonthsHeaderSubItem from './months_header_sub_item.vue';
export default {
export default {
components: {
MonthsHeaderSubItem,
},
......@@ -51,8 +51,10 @@
//
// End result of doing this is;
// 2017 Nov, Dec, 2018 Jan, Feb, Mar
if (this.timeframeIndex !== 0 &&
this.timeframe[this.timeframeIndex - 1].getFullYear() === year) {
if (
this.timeframeIndex !== 0 &&
this.timeframe[this.timeframeIndex - 1].getFullYear() === year
) {
return month;
}
......@@ -66,22 +68,20 @@
// Show dark color text only if timeframe item year & month
// are greater than current year.
if (timeframeYear >= this.currentYear &&
timeframeMonth >= this.currentMonth) {
if (timeframeYear >= this.currentYear && timeframeMonth >= this.currentMonth) {
itemLabelClass += 'label-dark';
}
// Show bold text only if timeframe item year & month
// is current year & month
if (timeframeYear === this.currentYear &&
timeframeMonth === this.currentMonth) {
if (timeframeYear === this.currentYear && timeframeMonth === this.currentMonth) {
itemLabelClass += ' label-bold';
}
return itemLabelClass;
},
},
};
};
</script>
<template>
......
<script>
import { getSundays } from '~/lib/utils/datetime_utility';
import { getSundays } from '~/lib/utils/datetime_utility';
import { PRESET_TYPES } from '../../constants';
import { PRESET_TYPES } from '../../constants';
import timelineTodayIndicator from '../timeline_today_indicator.vue';
import timelineTodayIndicator from '../timeline_today_indicator.vue';
export default {
export default {
presetType: PRESET_TYPES.MONTHS,
components: {
timelineTodayIndicator,
......@@ -37,8 +37,10 @@
const timeframeYear = this.timeframeItem.getFullYear();
const timeframeMonth = this.timeframeItem.getMonth();
return this.currentDate.getMonth() === timeframeMonth &&
this.currentDate.getFullYear() === timeframeYear;
return (
this.currentDate.getMonth() === timeframeMonth &&
this.currentDate.getFullYear() === timeframeYear
);
},
},
methods: {
......@@ -46,10 +48,12 @@
const daysToClosestWeek = this.currentDate.getDate() - subItem.getDate();
// Show dark color text only for upcoming dates
// and current week date
if (daysToClosestWeek <= 6 &&
if (
daysToClosestWeek <= 6 &&
this.currentDate.getDate() >= subItem.getDate() &&
this.currentDate.getFullYear() === subItem.getFullYear() &&
this.currentDate.getMonth() === subItem.getMonth()) {
this.currentDate.getMonth() === subItem.getMonth()
) {
return 'label-dark label-bold';
} else if (subItem >= this.currentDate) {
return 'label-dark';
......@@ -57,7 +61,7 @@
return '';
},
},
};
};
</script>
<template>
......
<script>
import QuartersHeaderSubItem from './quarters_header_sub_item.vue';
import QuartersHeaderSubItem from './quarters_header_sub_item.vue';
export default {
export default {
components: {
QuartersHeaderSubItem,
},
......@@ -41,8 +41,7 @@
},
timelineHeaderLabel() {
const { quarterSequence } = this.timeframeItem;
if (quarterSequence === 1 ||
this.timeframeIndex === 0 && quarterSequence !== 1) {
if (quarterSequence === 1 || (this.timeframeIndex === 0 && quarterSequence !== 1)) {
return `${this.timeframeItem.year} Q${quarterSequence}`;
}
......@@ -50,8 +49,7 @@
},
timelineHeaderClass() {
let headerClass = '';
if (this.currentDate >= this.quarterBeginDate &&
this.currentDate <= this.quarterEndDate) {
if (this.currentDate >= this.quarterBeginDate && this.currentDate <= this.quarterEndDate) {
headerClass = 'label-dark label-bold';
} else if (this.currentDate < this.quarterBeginDate) {
headerClass = 'label-dark';
......@@ -60,7 +58,7 @@
return headerClass;
},
},
};
};
</script>
<template>
......
<script>
import { monthInWords } from '~/lib/utils/datetime_utility';
import { monthInWords } from '~/lib/utils/datetime_utility';
import { PRESET_TYPES } from '../../constants';
import { PRESET_TYPES } from '../../constants';
import timelineTodayIndicator from '../timeline_today_indicator.vue';
import timelineTodayIndicator from '../timeline_today_indicator.vue';
export default {
export default {
presetType: PRESET_TYPES.QUARTERS,
components: {
timelineTodayIndicator,
......@@ -31,16 +31,17 @@
return this.timeframeItem.range;
},
hasToday() {
return this.currentDate >= this.quarterBeginDate &&
this.currentDate <= this.quarterEndDate;
return this.currentDate >= this.quarterBeginDate && this.currentDate <= this.quarterEndDate;
},
},
methods: {
getSubItemValueClass(subItem) {
let itemValueClass = '';
if (this.currentDate.getFullYear() === subItem.getFullYear() &&
this.currentDate.getMonth() === subItem.getMonth()) {
if (
this.currentDate.getFullYear() === subItem.getFullYear() &&
this.currentDate.getMonth() === subItem.getMonth()
) {
itemValueClass = 'label-dark label-bold';
} else if (this.currentDate < subItem) {
itemValueClass = 'label-dark';
......@@ -51,7 +52,7 @@
return monthInWords(subItem, true);
},
},
};
};
</script>
<template>
......
<script>
import { monthInWords } from '~/lib/utils/datetime_utility';
import { monthInWords } from '~/lib/utils/datetime_utility';
import WeeksHeaderSubItem from './weeks_header_sub_item.vue';
import WeeksHeaderSubItem from './weeks_header_sub_item.vue';
export default {
export default {
components: {
WeeksHeaderSubItem,
},
......@@ -45,13 +45,15 @@
},
timelineHeaderLabel() {
if (this.timeframeIndex === 0) {
return `${this.timeframeItem.getFullYear()} ${monthInWords(this.timeframeItem, true)} ${this.timeframeItem.getDate()}`;
return `${this.timeframeItem.getFullYear()} ${monthInWords(
this.timeframeItem,
true,
)} ${this.timeframeItem.getDate()}`;
}
return `${monthInWords(this.timeframeItem, true)} ${this.timeframeItem.getDate()}`;
},
timelineHeaderClass() {
if (this.currentDate >= this.timeframeItem &&
this.currentDate <= this.lastDayOfCurrentWeek) {
if (this.currentDate >= this.timeframeItem && this.currentDate <= this.lastDayOfCurrentWeek) {
return 'label-dark label-bold';
} else if (this.currentDate < this.lastDayOfCurrentWeek) {
return 'label-dark';
......@@ -59,7 +61,7 @@
return '';
},
},
};
};
</script>
<template>
......
......@@ -23,7 +23,8 @@ export default {
const headerSubItems = new Array(7)
.fill()
.map(
(val, i) => new Date(
(val, i) =>
new Date(
timeframeItem.getFullYear(),
timeframeItem.getMonth(),
timeframeItem.getDate() + i,
......
<script>
import bp from '~/breakpoints';
import { SCROLL_BAR_SIZE, EPIC_ITEM_HEIGHT, SHELL_MIN_WIDTH } from '../constants';
import eventHub from '../event_hub';
import bp from '~/breakpoints';
import { SCROLL_BAR_SIZE, EPIC_ITEM_HEIGHT, SHELL_MIN_WIDTH } from '../constants';
import eventHub from '../event_hub';
import epicsListSection from './epics_list_section.vue';
import roadmapTimelineSection from './roadmap_timeline_section.vue';
import epicsListSection from './epics_list_section.vue';
import roadmapTimelineSection from './roadmap_timeline_section.vue';
export default {
export default {
components: {
epicsListSection,
roadmapTimelineSection,
......@@ -38,9 +38,10 @@
},
computed: {
containerStyles() {
const width = bp.windowWidth() > SHELL_MIN_WIDTH ?
this.shellWidth + this.getWidthOffset() :
this.shellWidth;
const width =
bp.windowWidth() > SHELL_MIN_WIDTH
? this.shellWidth + this.getWidthOffset()
: this.shellWidth;
return {
width: `${width}px`,
......@@ -58,7 +59,7 @@
// see https://vuejs.org/v2/api/#Vue-nextTick
if (this.$el.parentElement) {
this.shellHeight = window.innerHeight - this.$el.offsetTop;
this.noScroll = this.shellHeight > (EPIC_ITEM_HEIGHT * (this.epics.length + 1));
this.noScroll = this.shellHeight > EPIC_ITEM_HEIGHT * (this.epics.length + 1);
this.shellWidth = this.$el.parentElement.clientWidth + this.getWidthOffset();
}
});
......@@ -72,7 +73,7 @@
eventHub.$emit('epicsListScrolled', { scrollTop, scrollLeft, clientHeight, scrollHeight });
},
},
};
};
</script>
<template>
......
<script>
import eventHub from '../event_hub';
import eventHub from '../event_hub';
import { PRESET_TYPES } from '../constants';
import { PRESET_TYPES } from '../constants';
import SectionMixin from '../mixins/section_mixin';
import SectionMixin from '../mixins/section_mixin';
import QuartersHeaderItem from './preset_quarters/quarters_header_item.vue';
import MonthsHeaderItem from './preset_months/months_header_item.vue';
import WeeksHeaderItem from './preset_weeks/weeks_header_item.vue';
import QuartersHeaderItem from './preset_quarters/quarters_header_item.vue';
import MonthsHeaderItem from './preset_months/months_header_item.vue';
import WeeksHeaderItem from './preset_weeks/weeks_header_item.vue';
export default {
export default {
components: {
QuartersHeaderItem,
MonthsHeaderItem,
WeeksHeaderItem,
},
mixins: [
SectionMixin,
],
mixins: [SectionMixin],
props: {
presetType: {
type: String,
......@@ -66,10 +64,10 @@
methods: {
handleEpicsListScroll({ scrollTop }) {
// Add class only when epics list is scrolled at 1% the height of header
this.scrolledHeaderClass = (scrollTop > this.$el.clientHeight / 100) ? 'scroll-top-shadow' : '';
this.scrolledHeaderClass = scrollTop > this.$el.clientHeight / 100 ? 'scroll-top-shadow' : '';
},
},
};
};
</script>
<template>
......
......@@ -48,14 +48,16 @@ export default {
// based on the current presetType
if (this.presetType === PRESET_TYPES.QUARTERS) {
left = Math.floor(
dayInQuarter(this.currentDate, this.timeframeItem.range) /
totalDaysInQuarter(this.timeframeItem.range) *
(dayInQuarter(this.currentDate, this.timeframeItem.range) /
totalDaysInQuarter(this.timeframeItem.range)) *
100,
);
} else if (this.presetType === PRESET_TYPES.MONTHS) {
left = Math.floor(this.currentDate.getDate() / totalDaysInMonth(this.timeframeItem) * 100);
left = Math.floor(
(this.currentDate.getDate() / totalDaysInMonth(this.timeframeItem)) * 100,
);
} else if (this.presetType === PRESET_TYPES.WEEKS) {
left = Math.floor(((this.currentDate.getDay() + 1) / 7 * 100) - 7);
left = Math.floor(((this.currentDate.getDay() + 1) / 7) * 100 - 7);
}
// We add 20 to height to ensure that
......@@ -73,7 +75,7 @@ export default {
const rootOffsetLeft = this.$root.$el.offsetLeft;
// 3px to compensate size of bubble on top of Indicator
this.todayBarReady = (indicatorX - rootOffsetLeft) >= (EPIC_DETAILS_CELL_WIDTH + 3);
this.todayBarReady = indicatorX - rootOffsetLeft >= EPIC_DETAILS_CELL_WIDTH + 3;
},
},
};
......
......@@ -25,17 +25,29 @@ export const PRESET_TYPES = {
export const PRESET_DEFAULTS = {
QUARTERS: {
TIMEFRAME_LENGTH: 18,
emptyStateDefault: s__('GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateWithFilters: s__('GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateDefault: s__(
'GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}.',
),
emptyStateWithFilters: s__(
'GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}.',
),
},
MONTHS: {
TIMEFRAME_LENGTH: 7,
emptyStateDefault: s__('GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateWithFilters: s__('GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateDefault: s__(
'GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}.',
),
emptyStateWithFilters: s__(
'GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}.',
),
},
WEEKS: {
TIMEFRAME_LENGTH: 42,
emptyStateDefault: s__('GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateWithFilters: s__('GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}.'),
emptyStateDefault: s__(
'GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}.',
),
emptyStateWithFilters: s__(
'GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}.',
),
},
};
......@@ -73,7 +73,7 @@ export default {
}
// Calculate proportional offset based on startDate and total days in
// current month.
return `left: ${startDate / daysInMonth * 100}%;`;
return `left: ${(startDate / daysInMonth) * 100}%;`;
},
/**
* This method is externally only called when current timeframe cell has timeline
......
......@@ -65,7 +65,7 @@ export default {
return `right: ${TIMELINE_END_OFFSET_HALF}px;`;
}
return `left: ${startDay / daysInQuarter * 100}%;`;
return `left: ${(startDay / daysInQuarter) * 100}%;`;
},
/**
* This method is externally only called when current timeframe cell has timeline
......
......@@ -23,7 +23,7 @@ export default {
return Math.max(width, TIMELINE_CELL_MIN_WIDTH);
},
sectionContainerStyles() {
const width = EPIC_DETAILS_CELL_WIDTH + (this.sectionItemWidth * this.timeframe.length);
const width = EPIC_DETAILS_CELL_WIDTH + this.sectionItemWidth * this.timeframe.length;
return {
width: `${width}px`,
};
......
......@@ -43,7 +43,7 @@ export default {
*/
getTimelineBarEndOffsetHalfForWeek() {
const dayWidth = this.getCellWidth() / 7;
return TIMELINE_END_OFFSET_HALF + (dayWidth * 0.5);
return TIMELINE_END_OFFSET_HALF + dayWidth * 0.5;
},
/**
* In case startDate for any epic is undefined or is out of range
......@@ -82,7 +82,7 @@ export default {
return `right: ${TIMELINE_END_OFFSET_HALF}px;`;
}
return `left: ${(startDate * dayWidth) - (dayWidth / 2)}px;`;
return `left: ${startDate * dayWidth - dayWidth / 2}px;`;
},
/**
* This method is externally only called when current timeframe cell has timeline
......
......@@ -4,8 +4,9 @@ import vulnerabilities from './modules/vulnerabilities/index';
Vue.use(Vuex);
export default () => new Vuex.Store({
export default () =>
new Vuex.Store({
modules: {
vulnerabilities,
},
});
});
<script>
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import { spriteIcon } from '~/lib/utils/common_utils';
import Store from '../stores/sidebar_store';
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import { spriteIcon } from '~/lib/utils/common_utils';
import Store from '../stores/sidebar_store';
export default {
export default {
name: 'SidebarItemEpic',
directives: {
tooltip,
......@@ -41,14 +41,18 @@
if (this.store.epic.human_readable_end_date || this.store.epic.human_readable_timestamp) {
tooltipTitle += '<br />';
tooltipTitle += this.store.epic.human_readable_end_date ? `${this.store.epic.human_readable_end_date} ` : '';
tooltipTitle += this.store.epic.human_readable_timestamp ? `(${this.store.epic.human_readable_timestamp})` : '';
tooltipTitle += this.store.epic.human_readable_end_date
? `${this.store.epic.human_readable_end_date} `
: '';
tooltipTitle += this.store.epic.human_readable_timestamp
? `(${this.store.epic.human_readable_timestamp})`
: '';
}
return tooltipTitle;
},
},
};
};
</script>
<template>
......
......@@ -14,7 +14,8 @@ function mountWeightComponent(mediator) {
components: {
sidebarWeight,
},
render: createElement => createElement('sidebar-weight', {
render: createElement =>
createElement('sidebar-weight', {
props: {
mediator,
},
......
......@@ -15,13 +15,14 @@ export default class SidebarMediator extends CESidebarMediator {
updateWeight(newWeight) {
this.store.setLoadingState('weight', true);
return this.service.update('issue[weight]', newWeight)
return this.service
.update('issue[weight]', newWeight)
.then(res => res.json())
.then((data) => {
.then(data => {
this.store.setWeight(data.weight);
this.store.setLoadingState('weight', false);
})
.catch((err) => {
.catch(err => {
this.store.setLoadingState('weight', false);
throw err;
});
......
......@@ -2,7 +2,11 @@ import $ from 'jquery';
const snowPlowEnabled = () => typeof window.snowplow === 'function';
const trackEvent = (category, eventName, additionalData = { label: '', property: '', value: '' }) => {
const trackEvent = (
category,
eventName,
additionalData = { label: '', property: '', value: '' },
) => {
if (!snowPlowEnabled()) {
return;
}
......@@ -14,14 +18,7 @@ const trackEvent = (category, eventName, additionalData = { label: '', property:
const { label, property, value } = additionalData;
try {
window.snowplow(
'trackStructEvent',
category,
eventName,
label,
property,
value,
);
window.snowplow('trackStructEvent', category, eventName, label, property, value);
} catch (e) {
// do nothing
}
......@@ -32,7 +29,7 @@ const bindTrackableContainer = (container = '', category = document.body.dataset
return;
}
const clickHandler = (e) => {
const clickHandler = e => {
const target = e.currentTarget;
const label = target.getAttribute('data-track-label');
const property = target.getAttribute('data-track-property') || '';
......@@ -45,7 +42,10 @@ const bindTrackableContainer = (container = '', category = document.body.dataset
}
// overrides value if data-track_value is set
if (typeof target.getAttribute('data-track-value') !== 'undefined' && target.getAttribute('data-track-value') !== null) {
if (
typeof target.getAttribute('data-track-value') !== 'undefined' &&
target.getAttribute('data-track-value') !== null
) {
value = target.getAttribute('data-track-value');
}
......@@ -54,12 +54,12 @@ const bindTrackableContainer = (container = '', category = document.body.dataset
const trackableElements = document.querySelectorAll(`${container} [data-track-label]`);
trackableElements.forEach(element => {
element.addEventListener('click', (e) => clickHandler(e));
element.addEventListener('click', e => clickHandler(e));
});
// jquery required for select2 events
// see: https://github.com/select2/select2/issues/4686#issuecomment-264747428
$(`${container} .select2[data-track-label]`).on('click', (e) => clickHandler(e));
$(`${container} .select2[data-track-label]`).on('click', e => clickHandler(e));
};
export default {
......
......@@ -71,9 +71,9 @@ export default {
}
if (this.approvalsLeft === 0) {
return this.userCanApprove ?
s__('mrWidget|Merge request approved; you can approve additionally') :
s__('mrWidget|Merge request approved');
return this.userCanApprove
? s__('mrWidget|Merge request approved; you can approve additionally')
: s__('mrWidget|Merge request approved');
}
if (this.suggestedApprovers.length >= 1) {
......
<script>
import icon from '~/vue_shared/components/icon.vue';
import ciStatus from '~/vue_shared/components/ci_icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import icon from '~/vue_shared/components/icon.vue';
import ciStatus from '~/vue_shared/components/ci_icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
export default {
directives: {
tooltip,
},
......@@ -48,9 +48,9 @@
return this.linkedPipelines.length;
},
linkedPipelinesTrimmed() {
return (this.totalPipelineCount > this.maxRenderedPipelines) ?
this.linkedPipelines.slice(0, this.maxRenderedPipelines) :
this.linkedPipelines;
return this.totalPipelineCount > this.maxRenderedPipelines
? this.linkedPipelines.slice(0, this.maxRenderedPipelines)
: this.linkedPipelines;
},
shouldRenderCounter() {
return this.isDownstream && this.linkedPipelines.length > this.maxRenderedPipelines;
......@@ -73,7 +73,7 @@
return `ci-status-icon-${group}`;
},
},
};
};
</script>
<template>
......
......@@ -9,9 +9,7 @@ export const licenseReport = state =>
export const licenseSummaryText = (state, getters) => {
const hasReportItems = getters.licenseReport && getters.licenseReport.length;
const baseReportHasLicenses =
state.baseReport
&& state.baseReport.licenses
&& state.baseReport.licenses.length;
state.baseReport && state.baseReport.licenses && state.baseReport.licenses.length;
if (getters.isLoading) {
return sprintf(s__('ciReport|Loading %{reportName} report'), {
......
import { n__, sprintf } from '~/locale';
import {
STATUS_FAILED,
STATUS_NEUTRAL,
STATUS_SUCCESS,
} from '~/reports/constants';
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
import { LICENSE_APPROVAL_STATUS } from 'ee/vue_shared/license_management/constants';
/**
......
import {
LOADING,
ERROR,
SUCCESS,
} from '../store/constants';
import { LOADING, ERROR, SUCCESS } from '../store/constants';
export default {
methods: {
......
......@@ -4,7 +4,9 @@ export default {
computed: {
sastPopover() {
return {
title: s__('ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code.'),
title: s__(
'ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code.',
),
content: sprintf(
s__('ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}'),
{
......@@ -17,7 +19,9 @@ export default {
},
sastContainerPopover() {
return {
title: s__('ciReport|Container scanning detects known vulnerabilities in your docker images.'),
title: s__(
'ciReport|Container scanning detects known vulnerabilities in your docker images.',
),
content: sprintf(
s__('ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}'),
{
......@@ -30,7 +34,9 @@ export default {
},
dastPopover() {
return {
title: s__('ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application.'),
title: s__(
'ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application.',
),
content: sprintf(
s__('ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}'),
{
......@@ -43,7 +49,9 @@ export default {
},
dependencyScanningPopover() {
return {
title: s__('ciReport|Dependency Scanning detects known vulnerabilities in your source code\'s dependencies.'),
title: s__(
"ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies.",
),
content: sprintf(
s__('ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}'),
{
......
......@@ -7,9 +7,10 @@ import state from './state';
Vue.use(Vuex);
export default () => new Vuex.Store({
export default () =>
new Vuex.Store({
actions,
getters,
mutations,
state: state(),
});
});
......@@ -230,10 +230,16 @@ export default {
[types.RECEIVE_DEPENDENCY_SCANNING_REPORTS](state, reports) {
if (reports.base && reports.head) {
const filterKey = 'cve';
const parsedHead = parseDependencyScanningIssues(reports.head, reports.enrichData,
state.blobPath.head);
const parsedBase = parseDependencyScanningIssues(reports.base, reports.enrichData,
state.blobPath.base);
const parsedHead = parseDependencyScanningIssues(
reports.head,
reports.enrichData,
state.blobPath.head,
);
const parsedBase = parseDependencyScanningIssues(
reports.base,
reports.enrichData,
state.blobPath.base,
);
const newIssues = filterByKey(parsedHead, parsedBase, filterKey);
const resolvedIssues = filterByKey(parsedBase, parsedHead, filterKey);
......@@ -250,8 +256,11 @@ export default {
}
if (reports.head && !reports.base) {
const newIssues = parseDependencyScanningIssues(reports.head, reports.enrichData,
state.blobPath.head);
const newIssues = parseDependencyScanningIssues(
reports.head,
reports.enrichData,
state.blobPath.head,
);
Vue.set(state.dependencyScanning, 'newIssues', newIssues);
Vue.set(state.dependencyScanning, 'isLoading', false);
......
......@@ -18,9 +18,9 @@ export const findIssueIndex = (issues, issue) =>
* @param {Array} feedback
*/
function enrichVulnerabilityWithfeedback(vulnerability, feedback = []) {
return feedback.filter(
fb => fb.project_fingerprint === vulnerability.project_fingerprint,
).reduce((vuln, fb) => {
return feedback
.filter(fb => fb.project_fingerprint === vulnerability.project_fingerprint)
.reduce((vuln, fb) => {
if (fb.feedback_type === 'dismissal') {
return {
...vuln,
......@@ -155,24 +155,30 @@ export const parseSastContainer = (issues = [], feedback = []) =>
const parsed = {
...issue,
category: 'container_scanning',
project_fingerprint: sha1(`${issue.namespace}:${issue.vulnerability}:${issue.featurename}:${issue.featureversion}`),
project_fingerprint: sha1(
`${issue.namespace}:${issue.vulnerability}:${issue.featurename}:${issue.featureversion}`,
),
title: issue.vulnerability,
description: !_.isEmpty(issue.description) ? issue.description :
sprintf(s__('ciReport|%{namespace} is affected by %{vulnerability}.'), {
description: !_.isEmpty(issue.description)
? issue.description
: sprintf(s__('ciReport|%{namespace} is affected by %{vulnerability}.'), {
namespace: issue.namespace,
vulnerability: issue.vulnerability,
}),
path: issue.namespace,
identifiers: [{
identifiers: [
{
type: 'CVE',
name: issue.vulnerability,
value: issue.vulnerability,
url: `https://cve.mitre.org/cgi-bin/cvename.cgi?name=${issue.vulnerability}`,
}],
},
],
};
// Generate solution
if (!_.isEmpty(issue.fixedby) &&
if (
!_.isEmpty(issue.fixedby) &&
!_.isEmpty(issue.featurename) &&
!_.isEmpty(issue.featureversion)
) {
......@@ -213,12 +219,14 @@ export const parseDastIssues = (issues = [], feedback = []) =>
if (!_.isEmpty(issue.cweid)) {
Object.assign(parsed, {
identifiers: [{
identifiers: [
{
type: 'CWE',
name: `CWE-${issue.cweid}`,
value: issue.cweid,
url: `https://cwe.mitre.org/data/definitions/${issue.cweid}.html`,
}],
},
],
});
}
......
......@@ -6,7 +6,15 @@ function WeightSelect(els, options = {}) {
const $els = $(els || '.js-weight-select');
$els.each(function(i, dropdown) {
var $block, $dropdown, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, updateUrl, updateWeight;
var $block,
$dropdown,
$loading,
$selectbox,
$sidebarCollapsedValue,
$value,
abilityName,
updateUrl,
updateWeight;
$dropdown = $(dropdown);
updateUrl = $dropdown.data('issueUpdate');
$selectbox = $dropdown.closest('.selectbox');
......@@ -15,7 +23,7 @@ function WeightSelect(els, options = {}) {
$value = $block.find('.value');
abilityName = $dropdown.data('abilityName');
$loading = $block.find('.block-loading').fadeOut();
const fieldName = options.fieldName || $dropdown.data("fieldName");
const fieldName = options.fieldName || $dropdown.data('fieldName');
const inputField = $dropdown.closest('.selectbox').find(`input[name='${fieldName}']`);
if (Object.keys(options).includes('selected')) {
......@@ -25,16 +33,16 @@ function WeightSelect(els, options = {}) {
return $dropdown.glDropdown({
selectable: true,
fieldName,
toggleLabel: function (selected, el) {
return $(el).data("id");
toggleLabel: function(selected, el) {
return $(el).data('id');
},
hidden: function(e) {
$selectbox.hide();
return $value.css('display', '');
},
id: function(obj, el) {
if ($(el).data("none") == null) {
return $(el).data("id");
if ($(el).data('none') == null) {
return $(el).data('id');
} else {
return '';
}
......@@ -51,7 +59,7 @@ function WeightSelect(els, options = {}) {
} else if ($dropdown.is('.js-issuable-form-weight')) {
e.preventDefault();
}
}
},
});
});
}
......
......@@ -11,13 +11,16 @@ describe('AddGitlabSlackApplication', () => {
const docsPath = '//docsPath';
const gitlabLogoPath = '//gitlabLogoPath';
const slackLogoPath = '//slackLogoPath';
const projects = [{
const projects = [
{
id: 4,
name: 'test',
}, {
},
{
id: 6,
name: 'nope',
}];
},
];
const DEFAULT_PROPS = {
projects,
gitlabForSlackGifPath,
......@@ -31,20 +34,20 @@ describe('AddGitlabSlackApplication', () => {
const AddGitlabSlackApplication = Vue.extend(addGitlabSlackApplication);
it('opens popup when button is clicked', (done) => {
it('opens popup when button is clicked', done => {
const vm = mountComponent(AddGitlabSlackApplication, DEFAULT_PROPS);
vm.$el.querySelector('.js-popup-button').click();
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.js-popup')).toBeDefined()
expect(vm.$el.querySelector('.js-popup')).toBeDefined();
})
.then(done)
.catch(done.fail);
});
it('hides popup when button is clicked', (done) => {
it('hides popup when button is clicked', done => {
const vm = mountComponent(AddGitlabSlackApplication, DEFAULT_PROPS);
vm.popupOpen = true;
......@@ -53,13 +56,13 @@ describe('AddGitlabSlackApplication', () => {
.then(() => vm.$el.querySelector('.js-popup-button').click())
.then(vm.$nextTick)
.then(() => {
expect(vm.$el.querySelector('.js-popup')).toBeNull()
expect(vm.$el.querySelector('.js-popup')).toBeNull();
})
.then(done)
.catch(done.fail);
});
it('popup has a project select when signed in', (done) => {
it('popup has a project select when signed in', done => {
const vm = mountComponent(AddGitlabSlackApplication, {
...DEFAULT_PROPS,
isSignedIn: true,
......@@ -69,13 +72,13 @@ describe('AddGitlabSlackApplication', () => {
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.js-project-select')).toBeDefined()
expect(vm.$el.querySelector('.js-project-select')).toBeDefined();
})
.then(done)
.catch(done.fail);
});
it('popup has a message when there is no projects', (done) => {
it('popup has a message when there is no projects', done => {
const vm = mountComponent(AddGitlabSlackApplication, {
...DEFAULT_PROPS,
projects: [],
......@@ -86,14 +89,15 @@ describe('AddGitlabSlackApplication', () => {
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.js-no-projects').textContent)
.toMatch("You don't have any projects available.");
expect(vm.$el.querySelector('.js-no-projects').textContent).toMatch(
"You don't have any projects available.",
);
})
.then(done)
.catch(done.fail);
});
it('popup has a sign in link when logged out', (done) => {
it('popup has a sign in link when logged out', done => {
const vm = mountComponent(AddGitlabSlackApplication, {
...DEFAULT_PROPS,
});
......@@ -103,14 +107,15 @@ describe('AddGitlabSlackApplication', () => {
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.js-gitlab-slack-sign-in-link').href)
.toMatch(new RegExp(signInPath, 'i'));
expect(vm.$el.querySelector('.js-gitlab-slack-sign-in-link').href).toMatch(
new RegExp(signInPath, 'i'),
);
})
.then(done)
.catch(done.fail);
});
it('redirects user to external link when submitted', (done) => {
it('redirects user to external link when submitted', done => {
const vm = mountComponent(AddGitlabSlackApplication, {
...DEFAULT_PROPS,
isSignedIn: true,
......@@ -127,7 +132,7 @@ describe('AddGitlabSlackApplication', () => {
.then(vm.$nextTick)
.then(addToSlackPromise)
.then(() => {
expect(redirectTo).toHaveBeenCalledWith(redirectLink)
expect(redirectTo).toHaveBeenCalledWith(redirectLink);
})
.then(done)
.catch(done.fail);
......
......@@ -98,8 +98,9 @@ describe('Approvals Body Component', () => {
vm.userCanApprove = true;
Vue.nextTick(() => {
expect(vm.approvalsRequiredStringified)
.toBe('Merge request approved; you can approve additionally');
expect(vm.approvalsRequiredStringified).toBe(
'Merge request approved; you can approve additionally',
);
done();
});
});
......
......@@ -114,8 +114,7 @@ describe('Batch comments draft note component', () => {
it('dispatches updateDraft', done => {
vm.$el.querySelector('.js-note-edit').click();
vm
.$nextTick()
vm.$nextTick()
.then(() => {
vm.$el.querySelector('.js-vue-issue-save').click();
......
......@@ -30,7 +30,7 @@ const assignee2 = {
};
describe('Assignee select component', () => {
beforeEach((done) => {
beforeEach(done => {
setFixtures('<div class="test-container"></div>');
gl.boardService = mockBoardService();
boardsStore.create();
......@@ -55,7 +55,7 @@ describe('Assignee select component', () => {
});
describe('canEdit', () => {
it('hides Edit button', (done) => {
it('hides Edit button', done => {
vm.canEdit = false;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.edit-link')).toBeFalsy();
......@@ -63,7 +63,7 @@ describe('Assignee select component', () => {
});
});
it('shows Edit button if true', (done) => {
it('shows Edit button if true', done => {
vm.canEdit = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.edit-link')).toBeTruthy();
......@@ -77,7 +77,7 @@ describe('Assignee select component', () => {
expect(selectedText()).toContain('Any assignee');
});
it('shows selected assignee', (done) => {
it('shows selected assignee', done => {
vm.selected = assignee;
Vue.nextTick(() => {
expect(selectedText()).toContain('first assignee');
......@@ -90,17 +90,14 @@ describe('Assignee select component', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet('/autocomplete/users.json').reply(200, [
assignee,
assignee2,
]);
mock.onGet('/autocomplete/users.json').reply(200, [assignee, assignee2]);
});
afterEach(() => {
mock.restore();
});
it('sets assignee', (done) => {
it('sets assignee', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
......
......@@ -59,7 +59,7 @@ describe('board_form.vue', () => {
});
describe('cancel', () => {
it('resets currentPage', (done) => {
it('resets currentPage', done => {
vm.cancel();
Vue.nextTick()
......@@ -73,7 +73,7 @@ describe('board_form.vue', () => {
});
describe('buttons', () => {
it('cancel button triggers cancel()', (done) => {
it('cancel button triggers cancel()', done => {
spyOn(vm, 'cancel');
Vue.nextTick()
......
......@@ -49,8 +49,7 @@ describe('BoardListSelector', () => {
mock.onGet(dummyEndpoint).reply(200, mockAssigneesList);
boardsStore.state.assignees = [];
vm
.loadList()
vm.loadList()
.then(() => {
expect(vm.loading).toBe(false);
expect(vm.store.state.assignees.length).toBe(mockAssigneesList.length);
......@@ -63,8 +62,7 @@ describe('BoardListSelector', () => {
spyOn(axios, 'get');
boardsStore.state.assignees = mockAssigneesList;
vm
.loadList()
vm.loadList()
.then(() => {
expect(axios.get).not.toHaveBeenCalled();
})
......@@ -76,8 +74,7 @@ describe('BoardListSelector', () => {
mock.onGet(dummyEndpoint).replyOnce(500, {});
boardsStore.state.assignees = [];
vm
.loadList()
vm.loadList()
.then(() => {
expect(vm.loading).toBe(false);
expect(document.querySelector('.flash-text').innerText.trim()).toBe(
......
......@@ -81,7 +81,7 @@ describe('ListContainer', () => {
expect(vm.$el.classList.contains('dropdown-assignees-list')).toBe(true);
});
it('renders loading animation when prop `loading` is true', (done) => {
it('renders loading animation when prop `loading` is true', done => {
vm.loading = true;
Vue.nextTick()
.then(() => {
......
......@@ -51,7 +51,7 @@ describe('ListFilter', () => {
expect(vm.$el.classList.contains('dropdown-input')).toBe(true);
});
it('renders class `has-value` on container element when prop `query` is not empty', (done) => {
it('renders class `has-value` on container element when prop `query` is not empty', done => {
vm.query = 'foobar';
Vue.nextTick()
.then(() => {
......@@ -61,7 +61,7 @@ describe('ListFilter', () => {
.catch(done.fail);
});
it('removes class `has-value` from container element when prop `query` is empty', (done) => {
it('removes class `has-value` from container element when prop `query` is empty', done => {
vm.query = '';
Vue.nextTick()
.then(() => {
......
......@@ -17,8 +17,7 @@ describe('BoardsSelector', () => {
let scrollContainer;
let scrollFade;
let boardServiceResponse;
const boards = new Array(20).fill()
.map((board, id) => {
const boards = new Array(20).fill().map((board, id) => {
const name = `board${id}`;
return {
......@@ -27,7 +26,7 @@ describe('BoardsSelector', () => {
};
});
beforeEach((done) => {
beforeEach(done => {
loadFixtures('boards/show.html.raw');
window.gl = window.gl || {};
......@@ -45,11 +44,15 @@ describe('BoardsSelector', () => {
spyOn(BoardService.prototype, 'allBoards').and.returnValue(boardServiceResponse);
vm = mountComponent(BoardsSelector, {
vm = mountComponent(
BoardsSelector,
{
throttleDuration,
currentBoard: {},
milestonePath: '',
}, document.querySelector('.js-boards-selector'));
},
document.querySelector('.js-boards-selector'),
);
vm.$el.querySelector('.js-dropdown-toggle').click();
......@@ -71,7 +74,7 @@ describe('BoardsSelector', () => {
window.gl.boardService = undefined;
});
it('shows the scroll fade if isScrolledUp', (done) => {
it('shows the scroll fade if isScrolledUp', done => {
scrollContainer.scrollTop = 0;
waitForScroll()
......@@ -82,7 +85,7 @@ describe('BoardsSelector', () => {
.catch(done.fail);
});
it('hides the scroll fade if not isScrolledUp', (done) => {
it('hides the scroll fade if not isScrolledUp', done => {
scrollContainer.scrollTop = scrollContainer.scrollHeight;
waitForScroll()
......
......@@ -15,7 +15,7 @@ function activeDropdownItem() {
}
describe('WeightSelect', () => {
beforeEach((done) => {
beforeEach(done => {
setFixtures('<div class="test-container"></div>');
board = {
......@@ -43,7 +43,7 @@ describe('WeightSelect', () => {
expect(getSelectedText()).toBe('Any Weight');
});
it('displays Any Weight for value -1', (done) => {
it('displays Any Weight for value -1', done => {
vm.value = -1;
Vue.nextTick(() => {
expect(getSelectedText()).toEqual('Any Weight');
......@@ -51,7 +51,7 @@ describe('WeightSelect', () => {
});
});
it('displays No Weight', (done) => {
it('displays No Weight', done => {
vm.value = 0;
Vue.nextTick(() => {
expect(getSelectedText()).toEqual('No Weight');
......@@ -59,7 +59,7 @@ describe('WeightSelect', () => {
});
});
it('weight 1', (done) => {
it('weight 1', done => {
vm.value = 1;
Vue.nextTick(() => {
expect(getSelectedText()).toEqual('1');
......@@ -69,7 +69,7 @@ describe('WeightSelect', () => {
});
describe('active item in dropdown', () => {
it('defaults to Any Weight', (done) => {
it('defaults to Any Weight', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
......@@ -78,7 +78,7 @@ describe('WeightSelect', () => {
});
});
it('shows No Weight', (done) => {
it('shows No Weight', done => {
vm.value = 0;
vm.$el.querySelector('.edit-link').click();
......@@ -88,7 +88,7 @@ describe('WeightSelect', () => {
});
});
it('shows correct weight', (done) => {
it('shows correct weight', done => {
vm.value = 1;
vm.$el.querySelector('.edit-link').click();
......@@ -100,7 +100,7 @@ describe('WeightSelect', () => {
});
describe('changing weight', () => {
it('sets value', (done) => {
it('sets value', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
......@@ -114,7 +114,7 @@ describe('WeightSelect', () => {
});
});
it('sets Any Weight', (done) => {
it('sets Any Weight', done => {
vm.value = 2;
vm.$el.querySelector('.edit-link').click();
......@@ -129,7 +129,7 @@ describe('WeightSelect', () => {
});
});
it('sets No Weight', (done) => {
it('sets No Weight', done => {
vm.value = 2;
vm.$el.querySelector('.edit-link').click();
......
......@@ -31,9 +31,7 @@ describe('Issue card component', () => {
groupId: null,
});
expect(
vm.$el.querySelector('.board-card-weight'),
).toBeNull();
expect(vm.$el.querySelector('.board-card-weight')).toBeNull();
});
it('renders issue weight if specified', () => {
......
......@@ -30,7 +30,7 @@ const milestone2 = {
};
describe('Milestone select component', () => {
beforeEach((done) => {
beforeEach(done => {
setFixtures('<div class="test-container"></div>');
// eslint-disable-next-line no-new
......@@ -49,7 +49,7 @@ describe('Milestone select component', () => {
});
describe('canEdit', () => {
it('hides Edit button', (done) => {
it('hides Edit button', done => {
vm.canEdit = false;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.edit-link')).toBeFalsy();
......@@ -57,7 +57,7 @@ describe('Milestone select component', () => {
});
});
it('shows Edit button if true', (done) => {
it('shows Edit button if true', done => {
vm.canEdit = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.edit-link')).toBeTruthy();
......@@ -71,7 +71,7 @@ describe('Milestone select component', () => {
expect(selectedText()).toContain('Any Milestone');
});
it('shows No Milestone', (done) => {
it('shows No Milestone', done => {
vm.board.milestone_id = 0;
Vue.nextTick(() => {
expect(selectedText()).toContain('No Milestone');
......@@ -79,7 +79,7 @@ describe('Milestone select component', () => {
});
});
it('shows selected milestone title', (done) => {
it('shows selected milestone title', done => {
vm.board.milestone_id = 20;
vm.board.milestone = {
id: 20,
......@@ -96,17 +96,14 @@ describe('Milestone select component', () => {
beforeEach(() => {
mock = new MockAdapater(axios);
mock.onGet('/test/issue-boards/milestones.json').reply(200, [
milestone,
milestone2,
]);
mock.onGet('/test/issue-boards/milestones.json').reply(200, [milestone, milestone2]);
});
afterEach(() => {
mock.restore();
});
it('sets Any Milestone', (done) => {
it('sets Any Milestone', done => {
vm.board.milestone_id = 0;
vm.$el.querySelector('.edit-link').click();
......@@ -121,7 +118,7 @@ describe('Milestone select component', () => {
});
});
it('sets No Milestone', (done) => {
it('sets No Milestone', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
......@@ -135,7 +132,7 @@ describe('Milestone select component', () => {
});
});
it('sets milestone', (done) => {
it('sets milestone', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
......
......@@ -28,7 +28,8 @@ describe('VariableList (EE features)', () => {
$row.find('.js-variable-environment-toggle').click();
// Filter for the new item
$row.find('.js-variable-environment-dropdown-wrapper .dropdown-input-field')
$row
.find('.js-variable-environment-dropdown-wrapper .dropdown-input-field')
.val(newEnv)
.trigger('input');
......@@ -36,7 +37,7 @@ describe('VariableList (EE features)', () => {
$row.find('.js-variable-environment-dropdown-wrapper .js-dropdown-create-new-item').click();
}
it('should add another row when editing the last rows environment dropdown', (done) => {
it('should add another row when editing the last rows environment dropdown', done => {
addRowByNewEnvironment('someenv');
getSetTimeoutPromise()
......@@ -44,7 +45,9 @@ describe('VariableList (EE features)', () => {
expect($wrapper.find('.js-row').length).toBe(2);
// Check for the correct default in the new row
const $environmentInput = $wrapper.find('.js-row:last-child').find('input[name="variables[variables_attributes][][environment_scope]"]');
const $environmentInput = $wrapper
.find('.js-row:last-child')
.find('input[name="variables[variables_attributes][][environment_scope]"]');
expect($environmentInput.val()).toBe('*');
})
......@@ -52,7 +55,7 @@ describe('VariableList (EE features)', () => {
.catch(done.fail);
});
it('should update dropdown with new environment values and remove values when row is removed', (done) => {
it('should update dropdown with new environment values and remove values when row is removed', done => {
addRowByNewEnvironment('someenv');
const $row = $wrapper.find('.js-row:last-child');
......@@ -60,7 +63,9 @@ describe('VariableList (EE features)', () => {
getSetTimeoutPromise()
.then(() => {
const $dropdownItemsBeforeRemove = $row.find('.js-variable-environment-dropdown-wrapper .dropdown-content a');
const $dropdownItemsBeforeRemove = $row.find(
'.js-variable-environment-dropdown-wrapper .dropdown-content a',
);
expect($dropdownItemsBeforeRemove.length).toBe(2);
expect($dropdownItemsBeforeRemove[0].textContent.trim()).toBe('someenv');
......@@ -71,7 +76,9 @@ describe('VariableList (EE features)', () => {
expect($wrapper.find('.js-row').length).toBe(0);
})
.then(() => {
const $dropdownItemsAfterRemove = $row.find('.js-variable-environment-dropdown-wrapper .dropdown-content a');
const $dropdownItemsAfterRemove = $row.find(
'.js-variable-environment-dropdown-wrapper .dropdown-content a',
);
expect($dropdownItemsAfterRemove.length).toBe(1);
expect($dropdownItemsAfterRemove[0].textContent.trim()).toBe('* (All environments)');
......
......@@ -33,9 +33,7 @@ describe('Deploy Board', () => {
const renderedTotal = component.$el.querySelector('.deploy-board-instances .total-instances');
const actualTotal = deployBoardMockData.instances.length;
expect(
renderedTotal.textContent,
).toEqual(`(${actualTotal})`);
expect(renderedTotal.textContent).toEqual(`(${actualTotal})`);
});
it('should render all instances', () => {
......@@ -44,7 +42,9 @@ describe('Deploy Board', () => {
expect(instances.length).toEqual(deployBoardMockData.instances.length);
expect(
instances[2].classList.contains(`deploy-board-instance-${deployBoardMockData.instances[2].status}`),
instances[2].classList.contains(
`deploy-board-instance-${deployBoardMockData.instances[2].status}`,
),
).toBe(true);
});
......@@ -72,7 +72,9 @@ describe('Deploy Board', () => {
it('should render the empty state', () => {
expect(component.$el.querySelector('.deploy-board-empty-state-svg svg')).toBeDefined();
expect(component.$el.querySelector('.deploy-board-empty-state-text .title').textContent).toContain('Kubernetes deployment not found');
expect(
component.$el.querySelector('.deploy-board-empty-state-text .title').textContent,
).toContain('Kubernetes deployment not found');
});
});
......
......@@ -56,6 +56,8 @@ describe('Deploy Board Instance', () => {
},
}).$mount();
expect(component.computedLogPath).toEqual('/root/review-app/environments/12/logs?pod_name=tanuki-1');
expect(component.computedLogPath).toEqual(
'/root/review-app/environments/12/logs?pod_name=tanuki-1',
);
});
});
......@@ -89,13 +89,17 @@ describe('epicHeader', () => {
it('returns classes `btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button` & `btn-close` when `isEpicOpen` prop is true', () => {
vm.isEpicOpen = true;
expect(vm.actionButtonClass).toContain('btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button btn-close');
expect(vm.actionButtonClass).toContain(
'btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button btn-close',
);
});
it('returns classes `btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button` & `btn-open` when `isEpicOpen` prop is false', () => {
vm.isEpicOpen = false;
expect(vm.actionButtonClass).toContain('btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button btn-open');
expect(vm.actionButtonClass).toContain(
'btn btn-grouped js-btn-epic-action qa-close-reopen-epic-button btn-open',
);
});
});
......
......@@ -15,7 +15,7 @@ describe('EpicShowApp', () => {
let headerVm;
let issuableAppVm;
beforeEach((done) => {
beforeEach(done => {
mock = new MockAdapter(axios);
mock.onGet(`${gl.TEST_HOST}/realtime_changes`).reply(200, issueShowData.initialRequest);
......
......@@ -80,7 +80,7 @@ export const headerProps = {
username: '@root',
name: 'Administrator',
},
created: (new Date()).toISOString(),
created: new Date().toISOString(),
open: true,
canUpdate: true,
canDelete: true,
......
......@@ -25,20 +25,24 @@ describe('newEpic', () => {
describe('alignRight', () => {
it('should not add dropdown-menu-right by default', () => {
expect(vm.$el.querySelector('.dropdown-menu').classList.contains('dropdown-menu-right')).toEqual(false);
expect(
vm.$el.querySelector('.dropdown-menu').classList.contains('dropdown-menu-right'),
).toEqual(false);
});
it('should add dropdown-menu-right when alignRight', (done) => {
it('should add dropdown-menu-right when alignRight', done => {
vm.alignRight = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.dropdown-menu').classList.contains('dropdown-menu-right')).toEqual(true);
expect(
vm.$el.querySelector('.dropdown-menu').classList.contains('dropdown-menu-right'),
).toEqual(true);
done();
});
});
});
describe('creating epic', () => {
it('should call createEpic service', (done) => {
it('should call createEpic service', done => {
spyOnDependency(newEpic, 'visitUrl').and.callFake(done);
spyOn(vm.service, 'createEpic').and.callThrough();
......@@ -51,8 +55,8 @@ describe('newEpic', () => {
});
});
it('should redirect to epic url after epic creation', (done) => {
spyOnDependency(newEpic, 'visitUrl').and.callFake((url) => {
it('should redirect to epic url after epic creation', done => {
spyOnDependency(newEpic, 'visitUrl').and.callFake(url => {
expect(url).toEqual(gl.TEST_HOST);
done();
});
......@@ -64,7 +68,7 @@ describe('newEpic', () => {
});
});
it('should toggle loading button while creating', (done) => {
it('should toggle loading button while creating', done => {
spyOnDependency(newEpic, 'visitUrl').and.callFake(done);
vm.title = 'test';
......
......@@ -93,29 +93,39 @@ describe('epicSidebar', () => {
it('should render both sidebar-date-picker', () => {
const startDate = '2017-01-01';
const endDate = '2018-01-01';
vm = mountComponent(EpicSidebar, Object.assign({}, defaultPropsData, {
vm = mountComponent(
EpicSidebar,
Object.assign({}, defaultPropsData, {
initialStartDate: startDate,
initialStartDateFixed: startDate,
initialEndDate: endDate,
initialDueDateFixed: endDate,
}));
}),
);
const startDatePicker = vm.$el.querySelector('.block.start-date');
const endDatePicker = vm.$el.querySelector('.block.end-date');
expect(startDatePicker.querySelector('.value-type-fixed .value-content').innerText.trim()).toEqual('Jan 1, 2017');
expect(endDatePicker.querySelector('.value-type-fixed .value-content').innerText.trim()).toEqual('Jan 1, 2018');
expect(
startDatePicker.querySelector('.value-type-fixed .value-content').innerText.trim(),
).toEqual('Jan 1, 2017');
expect(
endDatePicker.querySelector('.value-type-fixed .value-content').innerText.trim(),
).toEqual('Jan 1, 2018');
});
describe('computed prop', () => {
const getComponent = (customPropsData = {
const getComponent = (
customPropsData = {
initialStartDateIsFixed: true,
startDateFromMilestones: '2018-01-01',
initialStartDate: '2017-01-01',
initialDueDateIsFixed: true,
dueDateFromMilestones: '2018-11-31',
initialEndDate: '2018-01-01',
}) => new EpicSidebar({
},
) =>
new EpicSidebar({
propsData: Object.assign({}, defaultPropsData, customPropsData),
});
......@@ -158,7 +168,10 @@ describe('epicSidebar', () => {
describe('when collapsed', () => {
beforeEach(() => {
Cookies.set('collapsed_gutter', 'true');
vm = mountComponent(EpicSidebar, Object.assign({}, defaultPropsData, { initialStartDate: '2017-01-01' }));
vm = mountComponent(
EpicSidebar,
Object.assign({}, defaultPropsData, { initialStartDate: '2017-01-01' }),
);
});
it('should render right-sidebar-collapsed class', () => {
......@@ -166,17 +179,23 @@ describe('epicSidebar', () => {
});
it('should render collapsed grouped date picker', () => {
expect(vm.$el.querySelector('.sidebar-grouped-item .sidebar-collapsed-icon span').innerText.trim()).toEqual('From Jan 1 2017');
expect(
vm.$el.querySelector('.sidebar-grouped-item .sidebar-collapsed-icon span').innerText.trim(),
).toEqual('From Jan 1 2017');
});
it('should render collapsed labels picker', () => {
expect(vm.$el.querySelector('.js-labels-block .sidebar-collapsed-icon span').innerText.trim()).toEqual('1');
expect(
vm.$el.querySelector('.js-labels-block .sidebar-collapsed-icon span').innerText.trim(),
).toEqual('1');
});
});
describe('getDateFromMilestonesTooltip', () => {
it('returns tooltip string for milestone', () => {
expect(vm.getDateFromMilestonesTooltip('start')).toBe('To schedule your epic\'s start date based on milestones, assign a milestone with a start date to any issue in the epic.');
expect(vm.getDateFromMilestonesTooltip('start')).toBe(
"To schedule your epic's start date based on milestones, assign a milestone with a start date to any issue in the epic.",
);
});
it('returns tooltip string with milestone dates', () => {
......@@ -256,11 +275,12 @@ describe('epicSidebar', () => {
mock.restore();
});
it('should save startDate', (done) => {
it('should save startDate', done => {
const date = '2017-01-01';
expect(component.store.startDate).toBeUndefined();
component.saveStartDate(date)
component
.saveStartDate(date)
.then(() => {
expect(component.store.startDate).toEqual(date);
done();
......@@ -268,11 +288,12 @@ describe('epicSidebar', () => {
.catch(done.fail);
});
it('should save endDate', (done) => {
it('should save endDate', done => {
const date = '2017-01-01';
expect(component.store.endDate).toBeUndefined();
component.saveEndDate(date)
component
.saveEndDate(date)
.then(() => {
expect(component.store.endDate).toEqual(date);
done();
......@@ -280,7 +301,7 @@ describe('epicSidebar', () => {
.catch(done.fail);
});
it('should change start date type as from milestones', (done) => {
it('should change start date type as from milestones', done => {
spyOn(component.service, 'updateStartDate').and.callThrough();
const dateValue = '2017-01-01';
component.saveDate('start', dateValue, false);
......@@ -295,7 +316,7 @@ describe('epicSidebar', () => {
.catch(done.fail);
});
it('should change start date type as fixed', (done) => {
it('should change start date type as fixed', done => {
spyOn(component.service, 'updateStartDate').and.callThrough();
const dateValue = '2017-04-01';
component.saveDate('start', dateValue, true);
......@@ -312,7 +333,7 @@ describe('epicSidebar', () => {
}, 0);
});
it('should change end date type as from milestones', (done) => {
it('should change end date type as from milestones', done => {
spyOn(component.service, 'updateEndDate').and.callThrough();
const dateValue = '2017-01-01';
component.saveDate('end', dateValue, false);
......@@ -327,7 +348,7 @@ describe('epicSidebar', () => {
.catch(done.fail);
});
it('should change end date type as fixed', (done) => {
it('should change end date type as fixed', done => {
spyOn(component.service, 'updateEndDate').and.callThrough();
const dateValue = '2017-04-01';
component.saveDate('end', dateValue, true);
......@@ -448,7 +469,9 @@ describe('epicSidebar', () => {
vm.handleToggleTodo();
setTimeout(() => {
expect(vm.savingTodoAction).toBe(false);
expect(document.querySelector('.flash-text').innerText.trim()).toBe('There was an error adding a todo.');
expect(document.querySelector('.flash-text').innerText.trim()).toBe(
'There was an error adding a todo.',
);
done();
}, 0);
});
......@@ -487,7 +510,9 @@ describe('epicSidebar', () => {
vm.handleToggleTodo();
setTimeout(() => {
expect(vm.savingTodoAction).toBe(false);
expect(document.querySelector('.flash-text').innerText.trim()).toBe('There was an error deleting the todo.');
expect(document.querySelector('.flash-text').innerText.trim()).toBe(
'There was an error deleting the todo.',
);
done();
}, 0);
});
......@@ -499,9 +524,11 @@ describe('epicSidebar', () => {
beforeEach(() => {
interceptor = (request, next) => {
next(request.respondWith(JSON.stringify({}), {
next(
request.respondWith(JSON.stringify({}), {
status: 500,
}));
}),
);
};
Vue.http.interceptors.push(interceptor);
component = new EpicSidebar({
......@@ -513,11 +540,12 @@ describe('epicSidebar', () => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
});
it('should handle errors gracefully', (done) => {
it('should handle errors gracefully', done => {
const date = '2017-01-01';
expect(component.store.startDate).toBeUndefined();
component.saveDate('start', date)
component
.saveDate('start', date)
.then(() => {
expect(component.store.startDate).toBeUndefined();
done();
......
......@@ -99,13 +99,17 @@ describe('SidebarParticipants', () => {
describe('popoverOptions', () => {
it('returns popover config object containing title with appropriate string', () => {
expect(vm.popoverOptions.title).toBe('These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely.');
expect(vm.popoverOptions.title).toBe(
'These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely.',
);
});
it('returns popover config object containing `content` with href pointing to correct documentation', () => {
const hrefContent = vm.popoverOptions.content.trim();
expect(hrefContent).toContain(`${gon.gitlab_url}/help/user/group/epics/index.md#start-date-and-due-date`);
expect(hrefContent).toContain(
`${gon.gitlab_url}/help/user/group/epics/index.md#start-date-and-due-date`,
);
expect(hrefContent).toContain('More information');
});
});
......@@ -118,7 +122,9 @@ describe('SidebarParticipants', () => {
it('returns popover config object containing `content` with href pointing to correct documentation', () => {
const hrefContent = vm.dateInvalidPopoverOptions.content.trim();
expect(hrefContent).toContain(`${gon.gitlab_url}/help/user/group/epics/index.md#start-date-and-due-date`);
expect(hrefContent).toContain(
`${gon.gitlab_url}/help/user/group/epics/index.md#start-date-and-due-date`,
);
expect(hrefContent).toContain('How can I solve this?');
});
});
......@@ -140,7 +146,7 @@ describe('SidebarParticipants', () => {
content,
};
Object.keys(popoverConfig).forEach((key) => {
Object.keys(popoverConfig).forEach(key => {
if (key === 'template') {
expect(popoverConfig[key]).toContain(expectedPopoverConfig[key]);
} else {
......@@ -277,7 +283,9 @@ describe('SidebarParticipants', () => {
expect(warningIconEl).not.toBe(null);
expect(warningIconEl.getAttribute('tabindex')).toBe('0');
expect(warningIconEl.querySelector('use').getAttribute('xlink:href')).toContain('warning');
expect(warningIconEl.querySelector('use').getAttribute('xlink:href')).toContain(
'warning',
);
})
.then(done)
.catch(done.fail);
......
......@@ -41,7 +41,9 @@ describe('SidebarParticipants', () => {
it('renders participants list element', () => {
expect(vm.$el.querySelector('.participants-list')).not.toBeNull();
expect(vm.$el.querySelectorAll('.js-participants-author').length).toBe(mockParticipants.length);
expect(vm.$el.querySelectorAll('.js-participants-author').length).toBe(
mockParticipants.length,
);
});
});
});
......@@ -135,16 +135,18 @@ describe('Filtered Search Token Keys (Issues EE)', () => {
it('should return tokenKey when found by key param', () => {
const tokenKeys = IssuesFilteredSearchTokenKeysEE.get();
const result = IssuesFilteredSearchTokenKeysEE
.searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
const result = IssuesFilteredSearchTokenKeysEE.searchByKeyParam(
`${tokenKeys[0].key}_${tokenKeys[0].param}`,
);
expect(result).toEqual(tokenKeys[0]);
});
it('should return alternative tokenKey when found by key param', () => {
const tokenKeys = IssuesFilteredSearchTokenKeysEE.getAlternatives();
const result = IssuesFilteredSearchTokenKeysEE
.searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
const result = IssuesFilteredSearchTokenKeysEE.searchByKeyParam(
`${tokenKeys[0].key}_${tokenKeys[0].param}`,
);
expect(result).toEqual(tokenKeys[0]);
});
......@@ -167,8 +169,7 @@ describe('Filtered Search Token Keys (Issues EE)', () => {
it('should return condition when found by url', () => {
const conditions = IssuesFilteredSearchTokenKeysEE.getConditions();
const result = IssuesFilteredSearchTokenKeysEE
.searchByConditionUrl(conditions[0].url);
const result = IssuesFilteredSearchTokenKeysEE.searchByConditionUrl(conditions[0].url);
expect(result).toBe(conditions[0]);
});
......@@ -176,8 +177,7 @@ describe('Filtered Search Token Keys (Issues EE)', () => {
it('should return weight condition when found by weight url', () => {
const conditions = IssuesFilteredSearchTokenKeysEE.getConditions();
const weightConditions = conditions.filter(c => c.tokenKey === 'weight');
const result = IssuesFilteredSearchTokenKeysEE
.searchByConditionUrl(weightConditions[0].url);
const result = IssuesFilteredSearchTokenKeysEE.searchByConditionUrl(weightConditions[0].url);
expect(result).toBe(weightConditions[0]);
});
......@@ -185,16 +185,17 @@ describe('Filtered Search Token Keys (Issues EE)', () => {
describe('searchByConditionKeyValue', () => {
it('should return null when condition tokenKey and value not found', () => {
const condition = IssuesFilteredSearchTokenKeysEE
.searchByConditionKeyValue(null, null);
const condition = IssuesFilteredSearchTokenKeysEE.searchByConditionKeyValue(null, null);
expect(condition).toBeNull();
});
it('should return condition when found by tokenKey and value', () => {
const conditions = IssuesFilteredSearchTokenKeysEE.getConditions();
const result = IssuesFilteredSearchTokenKeysEE
.searchByConditionKeyValue(conditions[0].tokenKey, conditions[0].value);
const result = IssuesFilteredSearchTokenKeysEE.searchByConditionKeyValue(
conditions[0].tokenKey,
conditions[0].value,
);
expect(result).toEqual(conditions[0]);
});
......@@ -202,8 +203,10 @@ describe('Filtered Search Token Keys (Issues EE)', () => {
it('should return weight condition when found by weight tokenKey and value', () => {
const conditions = IssuesFilteredSearchTokenKeysEE.getConditions();
const weightConditions = conditions.filter(c => c.tokenKey === 'weight');
const result = IssuesFilteredSearchTokenKeysEE
.searchByConditionKeyValue(weightConditions[0].tokenKey, weightConditions[0].value);
const result = IssuesFilteredSearchTokenKeysEE.searchByConditionKeyValue(
weightConditions[0].tokenKey,
weightConditions[0].value,
);
expect(result).toEqual(weightConditions[0]);
});
......
......@@ -97,8 +97,7 @@ describe('AppComponent', () => {
it('calls service.getGeoNodes and sets response to the store on success', done => {
spyOn(vm.store, 'setNodes');
vm
.fetchGeoNodes()
vm.fetchGeoNodes()
.then(() => {
expect(vm.store.setNodes).toHaveBeenCalledWith(mockNodes);
expect(vm.isLoading).toBe(false);
......@@ -111,8 +110,7 @@ describe('AppComponent', () => {
response = 'Something went wrong';
statusCode = 500;
vm
.fetchGeoNodes()
vm.fetchGeoNodes()
.then(() => {
expect(vm.isLoading).toBe(false);
expect(document.querySelector('.flash-text').innerText.trim()).toBe(
......@@ -129,8 +127,7 @@ describe('AppComponent', () => {
mock.onGet(mockNode.statusPath).reply(200, rawMockNodeDetails);
spyOn(vm.service, 'getGeoNodeDetails').and.callThrough();
vm
.fetchNodeDetails(mockNode)
vm.fetchNodeDetails(mockNode)
.then(() => {
expect(vm.service.getGeoNodeDetails).toHaveBeenCalled();
expect(Object.keys(vm.store.state.nodeDetails).length).not.toBe(0);
......@@ -145,8 +142,7 @@ describe('AppComponent', () => {
mock.onGet(mockNode.statusPath).reply(404, {});
spyOn(vm.service, 'getGeoNodeDetails').and.callThrough();
vm
.fetchNodeDetails(mockNode)
vm.fetchNodeDetails(mockNode)
.then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('nodeDetailsLoaded', jasmine.any(Object));
const nodeDetails = vm.store.state.nodeDetails['1'];
......@@ -164,8 +160,7 @@ describe('AppComponent', () => {
mock.onGet(mockNode.statusPath).networkError();
spyOn(vm.service, 'getGeoNodeDetails').and.callThrough();
vm
.fetchNodeDetails(mockNode)
vm.fetchNodeDetails(mockNode)
.then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('nodeDetailsLoaded', jasmine.any(Object));
const nodeDetails = vm.store.state.nodeDetails['1'];
......@@ -183,8 +178,7 @@ describe('AppComponent', () => {
mock.onGet(mockNode.statusPath).timeout();
spyOn(vm.service, 'getGeoNodeDetails').and.callThrough();
vm
.fetchNodeDetails(mockNode)
vm.fetchNodeDetails(mockNode)
.then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('nodeDetailsLoaded', jasmine.any(Object));
const nodeDetails = vm.store.state.nodeDetails['1'];
......@@ -207,8 +201,7 @@ describe('AppComponent', () => {
});
spyOn(vm.service, 'repairNode').and.callThrough();
vm
.repairNode(node)
vm.repairNode(node)
.then(() => {
expect(vm.service.repairNode).toHaveBeenCalledWith(node);
expect(document.querySelector('.flash-text').innerText.trim()).toBe(
......@@ -229,8 +222,7 @@ describe('AppComponent', () => {
});
spyOn(vm.service, 'repairNode').and.callThrough();
vm
.repairNode(node)
vm.repairNode(node)
.then(() => {
expect(vm.service.repairNode).toHaveBeenCalledWith(node);
expect(document.querySelector('.flash-text').innerText.trim()).toBe(
......@@ -259,8 +251,7 @@ describe('AppComponent', () => {
spyOn(vm.service, 'toggleNode').and.callThrough();
node.enabled = false;
vm
.toggleNode(node)
vm.toggleNode(node)
.then(() => {
expect(vm.service.toggleNode).toHaveBeenCalledWith(node);
expect(node.enabled).toBe(true);
......@@ -279,8 +270,7 @@ describe('AppComponent', () => {
spyOn(vm.service, 'toggleNode').and.callThrough();
node.enabled = false;
vm
.toggleNode(node)
vm.toggleNode(node)
.then(() => {
expect(vm.service.toggleNode).toHaveBeenCalledWith(node);
expect(document.querySelector('.flash-text').innerText.trim()).toBe(
......@@ -304,8 +294,7 @@ describe('AppComponent', () => {
spyOn(vm.service, 'removeNode').and.callThrough();
spyOn(vm.store, 'removeNode').and.stub();
vm
.removeNode(node)
vm.removeNode(node)
.then(() => {
expect(vm.service.removeNode).toHaveBeenCalledWith(node);
expect(vm.store.removeNode).toHaveBeenCalledWith(node);
......@@ -326,8 +315,7 @@ describe('AppComponent', () => {
spyOn(vm.service, 'removeNode').and.callThrough();
spyOn(vm.store, 'removeNode').and.stub();
vm
.removeNode(node)
vm.removeNode(node)
.then(() => {
expect(vm.service.removeNode).toHaveBeenCalledWith(node);
expect(vm.store.removeNode).not.toHaveBeenCalled();
......
......@@ -6,8 +6,12 @@ import eventHub from 'ee/geo_nodes/event_hub';
import { NODE_ACTIONS } from 'ee/geo_nodes/constants';
import { mockNodes } from '../mock_data';
const createComponent = (node = mockNodes[0], nodeEditAllowed = true,
nodeActionsAllowed = true, nodeMissingOauth = false) => {
const createComponent = (
node = mockNodes[0],
nodeEditAllowed = true,
nodeActionsAllowed = true,
nodeMissingOauth = false,
) => {
const Component = Vue.extend(geoNodeActionsComponent);
return mountComponent(Component, {
......
......@@ -5,9 +5,10 @@ import { VALUE_TYPE, CUSTOM_TYPE } from 'ee/geo_nodes/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { rawMockNodeDetails } from '../mock_data';
const createComponent = (config) => {
const createComponent = config => {
const Component = Vue.extend(geoNodeDetailItemComponent);
const defaultConfig = Object.assign({
const defaultConfig = Object.assign(
{
itemTitle: 'GitLab version',
cssClass: 'node-version',
itemValue: '10.4.0-pre',
......@@ -15,7 +16,9 @@ const createComponent = (config) => {
failureLabel: 'Failed',
neutralLabel: 'Out of sync',
itemValueType: VALUE_TYPE.PLAIN,
}, config);
},
config,
);
return mountComponent(Component, defaultConfig);
};
......@@ -40,7 +43,11 @@ describe('GeoNodeDetailItemComponent', () => {
});
it('renders item title help info icon and popover with help info', () => {
const helpInfo = { title: 'Foo title tooltip', url: 'https://docs.gitlab.com', urlText: 'Help' };
const helpInfo = {
title: 'Foo title tooltip',
url: 'https://docs.gitlab.com',
urlText: 'Help',
};
const vm = createComponent({ helpInfo });
const helpTextIconEl = vm.$el.querySelector('.node-detail-help-text');
......
......@@ -60,7 +60,9 @@ describe('GeoNodeEventStatus', () => {
it('renders container elements correctly', () => {
expect(vm.$el.classList.contains('node-detail-value')).toBeTruthy();
expect(vm.$el.querySelectorAll('strong').length).not.toBe(0);
expect(vm.$el.querySelector('strong').innerText.trim()).toBe(`${mockNodeDetails.lastEvent.id}`);
expect(vm.$el.querySelector('strong').innerText.trim()).toBe(
`${mockNodeDetails.lastEvent.id}`,
);
expect(vm.$el.querySelector('.event-status-timestamp').innerText).toContain('ago');
});
......
......@@ -37,7 +37,7 @@ describe('GeoNodeHeader', () => {
expect(vm.isNodeHTTP).toBe(true);
});
it('returns `false` when Node URL protocol is HTTPS', (done) => {
it('returns `false` when Node URL protocol is HTTPS', done => {
vm.node.url = 'https://127.0.0.1:3001/';
Vue.nextTick()
.then(() => {
......@@ -49,7 +49,7 @@ describe('GeoNodeHeader', () => {
});
describe('showNodeStatusIcon', () => {
it('returns `false` when Node details are still loading', (done) => {
it('returns `false` when Node details are still loading', done => {
vm.nodeDetailsLoading = true;
Vue.nextTick()
.then(() => {
......@@ -59,7 +59,7 @@ describe('GeoNodeHeader', () => {
.catch(done.fail);
});
it('returns `true` when Node details failed to load', (done) => {
it('returns `true` when Node details failed to load', done => {
vm.nodeDetailsFailed = true;
Vue.nextTick()
.then(() => {
......@@ -69,7 +69,7 @@ describe('GeoNodeHeader', () => {
.catch(done.fail);
});
it('returns `true` when Node details loaded and Node URL is non-HTTPS', (done) => {
it('returns `true` when Node details loaded and Node URL is non-HTTPS', done => {
vm.nodeDetailsLoading = false;
vm.nodeDetailsFailed = false;
vm.node.url = mockNode.url;
......@@ -81,7 +81,7 @@ describe('GeoNodeHeader', () => {
.catch(done.fail);
});
it('returns `false` when Node details loaded and Node URL is HTTPS', (done) => {
it('returns `false` when Node details loaded and Node URL is HTTPS', done => {
vm.node.url = 'https://127.0.0.1:3001/';
Vue.nextTick()
.then(() => {
......
......@@ -63,7 +63,9 @@ describe('GeoNodeHealthStatusComponent', () => {
const iconContainerEl = vm.$el.querySelector('.node-detail-value.node-health-status');
expect(iconContainerEl).not.toBeNull();
expect(iconContainerEl.querySelector('svg use').getAttribute('xlink:href')).toContain('#status_success');
expect(iconContainerEl.querySelector('svg use').getAttribute('xlink:href')).toContain(
'#status_success',
);
expect(iconContainerEl.querySelector('.status-text').innerText.trim()).toBe('Healthy');
vm.$destroy();
});
......
......@@ -142,7 +142,7 @@ describe('GeoNodeItemComponent', () => {
expect(vm.$el.classList.contains('card', 'geo-node-item')).toBe(true);
});
it('renders node error message', (done) => {
it('renders node error message', done => {
const err = 'Something error message';
vm.isNodeDetailsFailed = true;
vm.errorMessage = err;
......
......@@ -8,7 +8,8 @@ const createComponent = (
syncStatusUnavailable = false,
selectiveSyncType = mockNodeDetails.selectiveSyncType,
lastEvent = mockNodeDetails.lastEvent,
cursorLastEvent = mockNodeDetails.cursorLastEvent) => {
cursorLastEvent = mockNodeDetails.cursorLastEvent,
) => {
const Component = Vue.extend(geoNodeSyncSettingsComponent);
return mountComponent(Component, {
......@@ -32,13 +33,18 @@ describe('GeoNodeSyncSettingsComponent', () => {
describe('eventTimestampEmpty', () => {
it('returns `true` if one of the event timestamp is empty', () => {
const vmEmptyTimestamp = createComponent(false, mockNodeDetails.namespaces, {
const vmEmptyTimestamp = createComponent(
false,
mockNodeDetails.namespaces,
{
id: 0,
timeStamp: 0,
}, {
},
{
id: 0,
timeStamp: 0,
});
},
);
expect(vmEmptyTimestamp.eventTimestampEmpty).toBeTruthy();
vmEmptyTimestamp.$destroy();
......@@ -87,7 +93,9 @@ describe('GeoNodeSyncSettingsComponent', () => {
describe('statusTooltip', () => {
it('returns string representing status lag message', () => {
expect(vm.statusTooltip(250)).toBe('');
expect(vm.statusTooltip(1000)).toBe('Node is slow, overloaded, or it just recovered after an outage.');
expect(vm.statusTooltip(1000)).toBe(
'Node is slow, overloaded, or it just recovered after an outage.',
);
expect(vm.statusTooltip(4000)).toBe('Node is failing or broken.');
});
});
......
......@@ -35,7 +35,7 @@ describe('NodeDetailsSectionMain', () => {
describe('computed', () => {
describe('nodeVersion', () => {
it('returns `Unknown` when `version` and `revision` are null', (done) => {
it('returns `Unknown` when `version` and `revision` are null', done => {
vm.nodeDetails.version = null;
vm.nodeDetails.revision = null;
Vue.nextTick()
......@@ -52,7 +52,7 @@ describe('NodeDetailsSectionMain', () => {
});
describe('nodeHealthStatus', () => {
it('returns health status string', (done) => {
it('returns health status string', done => {
// With default mock data
expect(vm.nodeHealthStatus).toBe('Healthy');
......@@ -76,7 +76,9 @@ describe('NodeDetailsSectionMain', () => {
it('renders node version element', () => {
expect(vm.$el.querySelector('.node-detail-title').innerText.trim()).toBe('GitLab version');
expect(vm.$el.querySelector('.node-detail-value').innerText.trim()).toBe('10.4.0-pre (b93c51849b)');
expect(vm.$el.querySelector('.node-detail-value').innerText.trim()).toBe(
'10.4.0-pre (b93c51849b)',
);
});
});
});
......@@ -59,7 +59,7 @@ describe('NodeDetailsSectionOther', () => {
});
describe('storageShardsStatus', () => {
it('returns `Unknown` when `nodeDetails.storageShardsMatch` is null', (done) => {
it('returns `Unknown` when `nodeDetails.storageShardsMatch` is null', done => {
vm.nodeDetails.storageShardsMatch = null;
Vue.nextTick()
.then(() => {
......@@ -69,7 +69,7 @@ describe('NodeDetailsSectionOther', () => {
.catch(done.fail);
});
it('returns `OK` when `nodeDetails.storageShardsMatch` is true', (done) => {
it('returns `OK` when `nodeDetails.storageShardsMatch` is true', done => {
vm.nodeDetails.storageShardsMatch = true;
Vue.nextTick()
.then(() => {
......@@ -85,7 +85,7 @@ describe('NodeDetailsSectionOther', () => {
});
describe('storageShardsCssClass', () => {
it('returns CSS class `node-detail-value-bold` when `nodeDetails.storageShardsMatch` is true', (done) => {
it('returns CSS class `node-detail-value-bold` when `nodeDetails.storageShardsMatch` is true', done => {
vm.nodeDetails.storageShardsMatch = true;
Vue.nextTick()
.then(() => {
......@@ -108,7 +108,9 @@ describe('NodeDetailsSectionOther', () => {
it('renders show section button element', () => {
expect(vm.$el.querySelector('.btn-show-section')).not.toBeNull();
expect(vm.$el.querySelector('.btn-show-section > span').innerText.trim()).toBe('Other information');
expect(vm.$el.querySelector('.btn-show-section > span').innerText.trim()).toBe(
'Other information',
);
});
it('renders section items container element', () => {
......
......@@ -4,9 +4,7 @@ import NodeDetailsSectionSyncComponent from 'ee/geo_nodes/components/node_detail
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockNodeDetails } from 'ee_spec/geo_nodes/mock_data';
const createComponent = (
nodeDetails = Object.assign({}, mockNodeDetails),
) => {
const createComponent = (nodeDetails = Object.assign({}, mockNodeDetails)) => {
const Component = Vue.extend(NodeDetailsSectionSyncComponent);
return mountComponent(Component, {
......@@ -35,7 +33,7 @@ describe('NodeDetailsSectionSync', () => {
describe('methods', () => {
describe('syncSettings', () => {
it('returns sync settings object', (done) => {
it('returns sync settings object', done => {
vm.nodeDetails.syncStatusUnavailable = true;
Vue.nextTick()
.then(() => {
......@@ -56,7 +54,7 @@ describe('NodeDetailsSectionSync', () => {
expect(vm.dbReplicationLag()).toBe('0m');
});
it('returns `Unknown` when `dbReplicationLag` is null', (done) => {
it('returns `Unknown` when `dbReplicationLag` is null', done => {
vm.nodeDetails.dbReplicationLag = null;
Vue.nextTick()
.then(() => {
......@@ -77,8 +75,9 @@ describe('NodeDetailsSectionSync', () => {
describe('cursorLastEventStatus', () => {
it('returns event status object', () => {
expect(vm.cursorLastEventStatus().eventId).toBe(mockNodeDetails.cursorLastEvent.id);
expect(vm.cursorLastEventStatus().eventTimeStamp)
.toBe(mockNodeDetails.cursorLastEvent.timeStamp);
expect(vm.cursorLastEventStatus().eventTimeStamp).toBe(
mockNodeDetails.cursorLastEvent.timeStamp,
);
});
});
});
......@@ -90,7 +89,9 @@ describe('NodeDetailsSectionSync', () => {
it('renders show section button element', () => {
expect(vm.$el.querySelector('.btn-show-section')).not.toBeNull();
expect(vm.$el.querySelector('.btn-show-section > span').innerText.trim()).toBe('Sync information');
expect(vm.$el.querySelector('.btn-show-section > span').innerText.trim()).toBe(
'Sync information',
);
});
it('renders section items container element', () => {
......
......@@ -4,10 +4,7 @@ import NodeDetailsSectionVerificationComponent from 'ee/geo_nodes/components/nod
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockNodeDetails } from 'ee_spec/geo_nodes/mock_data';
const createComponent = ({
nodeDetails = mockNodeDetails,
nodeTypePrimary = false,
}) => {
const createComponent = ({ nodeDetails = mockNodeDetails, nodeTypePrimary = false }) => {
const Component = Vue.extend(NodeDetailsSectionVerificationComponent);
return mountComponent(Component, {
......@@ -86,7 +83,7 @@ describe('NodeDetailsSectionVerification', () => {
expect(vm.$el.classList.contains('verification-section')).toBe(true);
});
it('renders section items container element', (done) => {
it('renders section items container element', done => {
vm.showSectionItems = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.section-items-container')).not.toBeNull();
......
......@@ -40,7 +40,7 @@ describe('GeoNodesStore', () => {
store.setNodes(mockNodes);
const nodeToBeRemoved = store.getNodes()[1];
store.removeNode(nodeToBeRemoved);
store.getNodes().forEach((node) => {
store.getNodes().forEach(node => {
expect(node.id).not.toBe(nodeToBeRemoved);
});
});
......@@ -63,8 +63,9 @@ describe('GeoNodesStore', () => {
const nodeDetails = GeoNodesStore.formatNodeDetails(rawMockNodeDetails);
expect(nodeDetails.healthStatus).toBe(rawMockNodeDetails.health_status);
expect(nodeDetails.replicationSlotWAL)
.toBe(rawMockNodeDetails.replication_slots_max_retained_wal_bytes);
expect(nodeDetails.replicationSlotWAL).toBe(
rawMockNodeDetails.replication_slots_max_retained_wal_bytes,
);
});
});
});
......@@ -102,8 +102,7 @@ describe('AppComponent', () => {
it('shows loading icon when isLoading prop is true', done => {
vm.isLoading = true;
vm
.$nextTick()
vm.$nextTick()
.then(() => {
const loadingEl = vm.$el.querySelector('.loading-animation');
......@@ -118,8 +117,7 @@ describe('AppComponent', () => {
it('renders table container element', done => {
vm.isLoading = false;
vm
.$nextTick()
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('table.table.gl-sortable')).not.toBeNull();
})
......
......@@ -44,7 +44,7 @@ describe('GroupMemberStore', () => {
expect(firstMember.fullname).toBe('Administrator');
store.sortMembers('fullname');
([firstMember] = store.state.members);
[firstMember] = store.state.members;
expect(firstMember.fullname).toBe('Terrell Graham');
});
......
......@@ -80,10 +80,7 @@ describe('AddIssuableForm', () => {
vm = new AddIssuableForm({
propsData: {
inputValue,
pendingReferences: [
issuable1.reference,
issuable2.reference,
],
pendingReferences: [issuable1.reference, issuable2.reference],
},
}).$mount();
});
......@@ -106,10 +103,7 @@ describe('AddIssuableForm', () => {
vm = new AddIssuableForm({
propsData: {
inputValue: '',
pendingReferences: [
issuable1.reference,
issuable2.reference,
],
pendingReferences: [issuable1.reference, issuable2.reference],
isSubmitting: true,
},
}).$mount();
......@@ -187,9 +181,7 @@ describe('AddIssuableForm', () => {
vm = new AddIssuableForm({
propsData: {
inputValue: '',
pendingIssuables: [
issuable1,
],
pendingIssuables: [issuable1],
autoCompleteSources: {
issues: '/fake/issues/path',
},
......@@ -204,7 +196,7 @@ describe('AddIssuableForm', () => {
eventHub.$off('addIssuableFormCancel', addIssuableFormCancelSpy);
});
it('when clicking somewhere on the input wrapper should focus the input', (done) => {
it('when clicking somewhere on the input wrapper should focus the input', done => {
vm.onInputWrapperClick();
setTimeout(() => {
......@@ -227,7 +219,7 @@ describe('AddIssuableForm', () => {
expect(addIssuableFormInputSpy).toHaveBeenCalledWith(newInputValue, newInputValue.length);
});
it('when blurring the input', (done) => {
it('when blurring the input', done => {
expect(addIssuableFormInputSpy).not.toHaveBeenCalled();
const newInputValue = 'filling in things';
......@@ -244,14 +236,16 @@ describe('AddIssuableForm', () => {
});
});
it('when using the autocomplete', (done) => {
it('when using the autocomplete', done => {
const $input = $(vm.$refs.input);
vm.gfmAutoComplete.loadData($input, '#', [{
vm.gfmAutoComplete.loadData($input, '#', [
{
id: 1,
iid: 111,
title: 'foo',
}]);
},
]);
$input
.val('#')
......
......@@ -23,7 +23,9 @@ describe('issueItem', () => {
});
it('renders displayReference', () => {
expect(vm.$el.querySelector('.text-secondary').innerText.trim()).toEqual(props.displayReference);
expect(vm.$el.querySelector('.text-secondary').innerText.trim()).toEqual(
props.displayReference,
);
});
it('does not render token state', () => {
......@@ -47,7 +49,7 @@ describe('issueItem', () => {
describe('token state', () => {
let tokenState;
beforeEach((done) => {
beforeEach(done => {
vm.state = 'opened';
Vue.nextTick(() => {
tokenState = vm.$el.querySelector('.text-secondary svg');
......@@ -71,7 +73,7 @@ describe('issueItem', () => {
expect(tokenState.classList.contains('issue-token-state-icon-open')).toEqual(true);
});
it('renders close icon when close state', (done) => {
it('renders close icon when close state', done => {
vm.state = 'closed';
Vue.nextTick(() => {
......@@ -84,7 +86,7 @@ describe('issueItem', () => {
describe('remove button', () => {
let removeBtn;
beforeEach((done) => {
beforeEach(done => {
vm.canRemove = true;
Vue.nextTick(() => {
removeBtn = vm.$refs.removeButton;
......@@ -96,7 +98,7 @@ describe('issueItem', () => {
expect(removeBtn).toBeDefined();
});
it('renders disabled button when removeDisabled', (done) => {
it('renders disabled button when removeDisabled', done => {
vm.removeDisabled = true;
Vue.nextTick(() => {
expect(removeBtn.hasAttribute('disabled')).toEqual(true);
......
......@@ -75,7 +75,7 @@ describe('IssueToken', () => {
});
describe('with state supplied', () => {
describe('`state: \'opened\'`', () => {
describe("`state: 'opened'`", () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
......@@ -91,7 +91,7 @@ describe('IssueToken', () => {
});
});
describe('`state: \'reopened\'`', () => {
describe("`state: 'reopened'`", () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
......@@ -107,7 +107,7 @@ describe('IssueToken', () => {
});
});
describe('`state: \'closed\'`', () => {
describe("`state: 'closed'`", () => {
beforeEach(() => {
vm = new IssueToken({
propsData: {
......
......@@ -86,10 +86,7 @@ describe('RelatedIssuesBlock', () => {
beforeEach(() => {
vm = new RelatedIssuesBlock({
propsData: {
relatedIssues: [
issuable1,
issuable2,
],
relatedIssues: [issuable1, issuable2],
},
}).$mount();
});
......@@ -105,13 +102,7 @@ describe('RelatedIssuesBlock', () => {
beforeEach(() => {
vm = new RelatedIssuesBlock({
propsData: {
relatedIssues: [
issuable1,
issuable2,
issuable3,
issuable4,
issuable5,
],
relatedIssues: [issuable1, issuable2, issuable3, issuable4, issuable5],
},
}).$mount();
toggleAddRelatedIssuesFormSpy = jasmine.createSpy('spy');
......
......@@ -21,8 +21,10 @@ describe('RelatedIssuesRoot', () => {
describe('methods', () => {
describe('onRelatedIssueRemoveRequest', () => {
beforeEach((done) => {
spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues').and.returnValue(Promise.reject());
beforeEach(done => {
spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues').and.returnValue(
Promise.reject(),
);
vm = new RelatedIssuesRoot({
propsData: defaultProps,
......@@ -34,13 +36,18 @@ describe('RelatedIssuesRoot', () => {
});
});
it('remove related issue and succeeds', (done) => {
it('remove related issue and succeeds', done => {
const interceptor = (request, next) => {
next(request.respondWith(JSON.stringify({
next(
request.respondWith(
JSON.stringify({
issues: [],
}), {
}),
{
status: 200,
}));
},
),
);
};
Vue.http.interceptors.push(interceptor);
......@@ -55,11 +62,13 @@ describe('RelatedIssuesRoot', () => {
});
});
it('remove related issue, fails, and restores to related issues', (done) => {
it('remove related issue, fails, and restores to related issues', done => {
const interceptor = (request, next) => {
next(request.respondWith(JSON.stringify({}), {
next(
request.respondWith(JSON.stringify({}), {
status: 422,
}));
}),
);
};
Vue.http.interceptors.push(interceptor);
......@@ -117,7 +126,9 @@ describe('RelatedIssuesRoot', () => {
describe('onPendingFormSubmit', () => {
beforeEach(() => {
spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues').and.returnValue(Promise.reject());
spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues').and.returnValue(
Promise.reject(),
);
vm = new RelatedIssuesRoot({
propsData: defaultProps,
}).$mount();
......@@ -135,7 +146,7 @@ describe('RelatedIssuesRoot', () => {
expect(vm.service.addRelatedIssues).toHaveBeenCalledWith([input]);
});
it('submit zero pending issue as related issue', (done) => {
it('submit zero pending issue as related issue', done => {
vm.store.setPendingReferences([]);
vm.onPendingFormSubmit();
......@@ -147,17 +158,22 @@ describe('RelatedIssuesRoot', () => {
});
});
it('submit pending issue as related issue', (done) => {
it('submit pending issue as related issue', done => {
const interceptor = (request, next) => {
next(request.respondWith(JSON.stringify({
next(
request.respondWith(
JSON.stringify({
issues: [issuable1],
result: {
message: 'something was successfully related',
status: 'success',
},
}), {
}),
{
status: 200,
}));
},
),
);
};
Vue.http.interceptors.push(interceptor);
......@@ -175,17 +191,22 @@ describe('RelatedIssuesRoot', () => {
});
});
it('submit multiple pending issues as related issues', (done) => {
it('submit multiple pending issues as related issues', done => {
const interceptor = (request, next) => {
next(request.respondWith(JSON.stringify({
next(
request.respondWith(
JSON.stringify({
issues: [issuable1, issuable2],
result: {
message: 'something was successfully related',
status: 'success',
},
}), {
}),
{
status: 200,
}));
},
),
);
};
Vue.http.interceptors.push(interceptor);
......@@ -225,12 +246,14 @@ describe('RelatedIssuesRoot', () => {
describe('fetchRelatedIssues', () => {
const interceptor = (request, next) => {
next(request.respondWith(JSON.stringify([issuable1, issuable2]), {
next(
request.respondWith(JSON.stringify([issuable1, issuable2]), {
status: 200,
}));
}),
);
};
beforeEach((done) => {
beforeEach(done => {
Vue.http.interceptors.push(interceptor);
vm = new RelatedIssuesRoot({
......@@ -245,7 +268,7 @@ describe('RelatedIssuesRoot', () => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
});
it('sets isFetching while fetching', (done) => {
it('sets isFetching while fetching', done => {
vm.fetchRelatedIssues();
expect(vm.isFetching).toEqual(true);
......@@ -257,7 +280,7 @@ describe('RelatedIssuesRoot', () => {
});
});
it('should fetch related issues', (done) => {
it('should fetch related issues', done => {
Vue.nextTick(() => {
expect(vm.state.relatedIssues.length).toEqual(2);
expect(vm.state.relatedIssues[0].id).toEqual(issuable1.id);
......
......@@ -30,7 +30,7 @@ describe('Kubernetes Logs', () => {
mock.restore();
});
it('has the pod name placed on the dropdown', (done) => {
it('has the pod name placed on the dropdown', done => {
kubernetesLog = new KubernetesLogs(kubernetesLogContainer);
kubernetesLog.getPodLogs();
......@@ -44,7 +44,7 @@ describe('Kubernetes Logs', () => {
}, 0);
});
it('queries the pod log data and sets the dom elements', (done) => {
it('queries the pod log data and sets the dom elements', done => {
const scrollSpy = spyOnDependency(KubernetesLogs, 'scrollDown').and.callThrough();
const toggleDisableSpy = spyOnDependency(KubernetesLogs, 'toggleDisableButton').and.stub();
kubernetesLog = new KubernetesLogs(kubernetesLogContainer);
......@@ -59,7 +59,7 @@ describe('Kubernetes Logs', () => {
}, 0);
});
it('asks for the pod logs from another pod', (done) => {
it('asks for the pod logs from another pod', done => {
const changePodLogSpy = spyOn(KubernetesLogs.prototype, 'getPodLogs').and.callThrough();
kubernetesLog = new KubernetesLogs(kubernetesLogContainer);
......@@ -75,7 +75,7 @@ describe('Kubernetes Logs', () => {
}, 0);
});
it('clears the pod dropdown contents when pod logs are requested', (done) => {
it('clears the pod dropdown contents when pod logs are requested', done => {
const emptySpy = spyOn($.prototype, 'empty').and.callThrough();
kubernetesLog = new KubernetesLogs(kubernetesLogContainer);
......@@ -109,7 +109,9 @@ describe('Kubernetes Logs', () => {
it('escapes the pod name', () => {
kubernetesLog = new KubernetesLogs(kubernetesLogContainer);
expect(kubernetesLog.podName).toContain('&quot;&gt;&amp;lt;img src=x onerror=alert(document.domain)&amp;gt; production');
expect(kubernetesLog.podName).toContain(
'&quot;&gt;&amp;lt;img src=x onerror=alert(document.domain)&amp;gt; production',
);
});
});
......
......@@ -2,105 +2,105 @@ export const logMockData = [
'[2018-05-17 16:31:10] INFO WEBrick 1.3.1',
'[2018-05-17 16:31:10] INFO ruby 2.4.1 (2017-03-22) [x86_64-linux-musl]',
'[2018-05-17 16:31:10] INFO WEBrick::HTTPServer#start: pid=5 port=5000',
'172.17.0.1 - - [17/May/2018:16:31:14 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:31:14 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:31:24 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:31:24 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:31:32 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:31:32 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:31:34 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:31:34 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:31:42 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:31:42 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:31:44 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:31:44 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:31:52 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:31:52 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:31:54 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:31:54 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:02 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:02 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:04 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:04 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:12 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:12 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:14 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:14 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:22 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:22 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:24 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:24 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:32 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:32 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:34 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:34 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:42 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:42 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:44 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:44 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:52 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:52 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:32:54 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:32:54 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:02 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:02 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:04 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:04 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:12 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:12 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:14 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:14 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:22 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:22 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:24 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:24 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:32 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:32 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:34 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:34 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:42 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:42 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:44 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:44 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:52 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:52 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:33:54 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:33:54 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:02 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:02 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:04 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:04 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:12 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:12 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:14 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:14 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:22 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:22 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:24 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:24 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:32 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:32 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:34 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:34 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:42 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:42 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:44 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:44 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:52 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:52 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:34:54 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:34:54 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:35:02 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:35:02 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:35:04 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:35:04 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:35:12 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:35:12 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:35:14 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:35:14 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:35:22 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:35:22 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
'172.17.0.1 - - [17/May/2018:16:35:24 UTC] \'GET / HTTP/1.1\' 200 13',
"172.17.0.1 - - [17/May/2018:16:35:24 UTC] 'GET / HTTP/1.1' 200 13",
'- -> /',
];
......
......@@ -38,7 +38,8 @@ describe('LicenseManagement', () => {
it('should render the form if the form is open', done => {
vm.formIsOpen = true;
return Vue.nextTick().then(() => {
return Vue.nextTick()
.then(() => {
const formEl = vm.$el.querySelector('.js-add-license-form');
expect(formEl).not.toBeNull();
......@@ -46,13 +47,15 @@ describe('LicenseManagement', () => {
expect(buttonEl).toBeNull();
done();
}).catch(done.fail);
})
.catch(done.fail);
});
it('should render the button if the form is closed', done => {
vm.formIsOpen = false;
return Vue.nextTick().then(() => {
return Vue.nextTick()
.then(() => {
const formEl = vm.$el.querySelector('.js-add-license-form');
expect(formEl).toBeNull();
......@@ -60,7 +63,8 @@ describe('LicenseManagement', () => {
expect(buttonEl).not.toBeNull();
done();
}).catch(done.fail);
})
.catch(done.fail);
});
it('clicking the Add a license button opens the form', () => {
......@@ -77,42 +81,50 @@ describe('LicenseManagement', () => {
it('should render loading icon', done => {
store.replaceState({ ...store.state, isLoadingManagedLicenses: true });
return Vue.nextTick().then(() => {
return Vue.nextTick()
.then(() => {
expect(vm.$el.querySelector('.loading-container')).not.toBeNull();
done();
}).catch(done.fail);
})
.catch(done.fail);
});
it('should render callout if no licenses are managed', done => {
store.replaceState({ ...store.state, managedLicenses: [], isLoadingManagedLicenses: false });
return Vue.nextTick().then(() => {
return Vue.nextTick()
.then(() => {
const callout = vm.$el.querySelector('.bs-callout');
expect(callout).not.toBeNull();
expect(trimText(callout.innerText)).toBe(vm.$options.emptyMessage);
done();
}).catch(done.fail);
})
.catch(done.fail);
});
it('should render delete confirmation modal', done => {
store.replaceState({ ...store.state });
return Vue.nextTick().then(() => {
return Vue.nextTick()
.then(() => {
expect(vm.$el.querySelector('#modal-license-delete-confirmation')).not.toBeNull();
done();
}).catch(done.fail);
})
.catch(done.fail);
});
it('should render list of managed licenses', done => {
store.replaceState({ ...store.state, isLoadingManagedLicenses: false });
return Vue.nextTick().then(() => {
return Vue.nextTick()
.then(() => {
expect(vm.$el.querySelector('.list-group')).not.toBeNull();
expect(vm.$el.querySelector('.list-group .list-group-item')).not.toBeNull();
expect(vm.$el.querySelectorAll('.list-group .list-group-item').length).toBe(2);
done();
}).catch(done.fail);
})
.catch(done.fail);
});
it('should set api settings after mount and init API calls', () =>
......
......@@ -6,11 +6,7 @@ import {
getIssueStatusFromLicenseStatus,
} from 'ee/vue_shared/license_management/store/utils';
import { LICENSE_APPROVAL_STATUS } from 'ee/vue_shared/license_management/constants';
import {
STATUS_FAILED,
STATUS_NEUTRAL,
STATUS_SUCCESS,
} from '~/reports/constants';
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
import {
approvedLicense,
blacklistedLicense,
......
......@@ -24,7 +24,7 @@ describe('Dashboard', () => {
});
describe('metrics without alerts', () => {
it('does not show threshold lines', (done) => {
it('does not show threshold lines', done => {
vm = new Component({
el: document.querySelector('.prometheus-graphs'),
propsData: {
......@@ -59,7 +59,7 @@ describe('Dashboard', () => {
});
});
it('shows single threshold line', (done) => {
it('shows single threshold line', done => {
vm.setAlerts(metricId, {
alertName: alertParams,
});
......@@ -70,7 +70,7 @@ describe('Dashboard', () => {
});
});
it('shows multiple threshold lines', (done) => {
it('shows multiple threshold lines', done => {
vm.setAlerts(metricId, {
someAlert: alertParams,
otherAlert: alertParams,
......
......@@ -2,7 +2,10 @@ import Vue from 'vue';
import ThresholdLines from 'ee/monitoring/components/threshold_lines.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { generateGraphDrawData } from '~/monitoring/utils/multiple_time_series';
import { singleRowMetricsMultipleSeries, convertDatesMultipleSeries } from 'spec/monitoring/mock_data';
import {
singleRowMetricsMultipleSeries,
convertDatesMultipleSeries,
} from 'spec/monitoring/mock_data';
const width = 500;
const height = 200;
......
......@@ -20,4 +20,3 @@ const metrics = [
];
export default metrics;
......@@ -6,7 +6,8 @@ import metrics from './mock_data';
describe('PrometheusMetrics EE', () => {
const FIXTURE = 'services/prometheus/prometheus_service.html.raw';
const customMetricsEndpoint = 'http://test.host/frontend-fixtures/services-project/prometheus/metrics';
const customMetricsEndpoint =
'http://test.host/frontend-fixtures/services-project/prometheus/metrics';
let mock;
preloadFixtures(FIXTURE);
......
......@@ -10,7 +10,14 @@ import RoadmapService from 'ee/roadmap/service/roadmap_service';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeMonths, mockGroupId, epicsPath, mockNewEpicEndpoint, rawEpics, mockSvgPath } from '../mock_data';
import {
mockTimeframeMonths,
mockGroupId,
epicsPath,
mockNewEpicEndpoint,
rawEpics,
mockSvgPath,
} from '../mock_data';
const createComponent = () => {
const Component = Vue.extend(appComponent);
......@@ -123,7 +130,7 @@ describe('AppComponent', () => {
document.querySelector('.flash-container').remove();
});
it('calls service.getEpics and sets response to the store on success', (done) => {
it('calls service.getEpics and sets response to the store on success', done => {
mock.onGet(vm.service.epicsPath).reply(200, rawEpics);
spyOn(vm.store, 'setEpics');
......@@ -137,7 +144,7 @@ describe('AppComponent', () => {
}, 0);
});
it('calls service.getEpics and sets `isEpicsListEmpty` to true if response is empty', (done) => {
it('calls service.getEpics and sets `isEpicsListEmpty` to true if response is empty', done => {
mock.onGet(vm.service.epicsPath).reply(200, []);
spyOn(vm.store, 'setEpics');
......@@ -151,7 +158,7 @@ describe('AppComponent', () => {
}, 0);
});
it('calls service.getEpics and sets `hasError` to true and shows flash message if request failed', (done) => {
it('calls service.getEpics and sets `hasError` to true and shows flash message if request failed', done => {
mock.onGet(vm.service.epicsPath).reply(500, {});
vm.fetchEpics();
......@@ -159,7 +166,9 @@ describe('AppComponent', () => {
expect(vm.hasError).toBe(false);
setTimeout(() => {
expect(vm.hasError).toBe(true);
expect(document.querySelector('.flash-text').innerText.trim()).toBe('Something went wrong while fetching epics');
expect(document.querySelector('.flash-text').innerText.trim()).toBe(
'Something went wrong while fetching epics',
);
done();
}, 0);
});
......@@ -172,7 +181,11 @@ describe('AppComponent', () => {
const vmX = createComponent();
expect(vmX.handleResizeThrottled).toBeDefined();
expect(window.addEventListener).toHaveBeenCalledWith('resize', vmX.handleResizeThrottled, false);
expect(window.addEventListener).toHaveBeenCalledWith(
'resize',
vmX.handleResizeThrottled,
false,
);
vmX.$destroy();
});
});
......@@ -183,7 +196,11 @@ describe('AppComponent', () => {
const vmX = createComponent();
vmX.$destroy();
expect(window.removeEventListener).toHaveBeenCalledWith('resize', vmX.handleResizeThrottled, false);
expect(window.removeEventListener).toHaveBeenCalledWith(
'resize',
vmX.handleResizeThrottled,
false,
);
});
});
......@@ -192,7 +209,7 @@ describe('AppComponent', () => {
expect(vm.$el.classList.contains('roadmap-container')).toBe(true);
});
it('renders roadmap container with classes `roadmap-container overflow-reset` when isEpicsListEmpty prop is true', (done) => {
it('renders roadmap container with classes `roadmap-container overflow-reset` when isEpicsListEmpty prop is true', done => {
vm.isEpicsListEmpty = true;
Vue.nextTick()
.then(() => {
......
......@@ -5,7 +5,13 @@ import epicItemComponent from 'ee/roadmap/components/epic_item.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeMonths, mockEpic, mockGroupId, mockShellWidth, mockItemWidth } from '../mock_data';
import {
mockTimeframeMonths,
mockEpic,
mockGroupId,
mockShellWidth,
mockItemWidth,
} from '../mock_data';
const createComponent = ({
presetType = PRESET_TYPES.MONTHS,
......
......@@ -48,7 +48,7 @@ describe('EpicsListEmptyComponent', () => {
expect(vm.message).toBe('The roadmap shows the progress of your epics along a timeline');
});
it('returns empty state message when `hasFiltersApplied` prop is true', (done) => {
it('returns empty state message when `hasFiltersApplied` prop is true', done => {
vm.hasFiltersApplied = true;
Vue.nextTick()
.then(() => {
......@@ -70,7 +70,9 @@ describe('EpicsListEmptyComponent', () => {
it('returns default empty state sub-message when `hasFiltersApplied` props is false', done => {
Vue.nextTick()
.then(() => {
expect(vm.subMessage).toBe('To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from Oct 1, 2017 to Mar 31, 2019.');
expect(vm.subMessage).toBe(
'To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from Oct 1, 2017 to Mar 31, 2019.',
);
})
.then(done)
.catch(done.fail);
......@@ -80,7 +82,9 @@ describe('EpicsListEmptyComponent', () => {
vm.hasFiltersApplied = true;
Vue.nextTick()
.then(() => {
expect(vm.subMessage).toBe('To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from Oct 1, 2017 to Mar 31, 2019.');
expect(vm.subMessage).toBe(
'To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from Oct 1, 2017 to Mar 31, 2019.',
);
})
.then(done)
.catch(done.fail);
......@@ -95,7 +99,9 @@ describe('EpicsListEmptyComponent', () => {
it('returns default empty state sub-message when `hasFiltersApplied` props is false', done => {
Vue.nextTick()
.then(() => {
expect(vm.subMessage).toBe('To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from Dec 1, 2017 to Jun 30, 2018.');
expect(vm.subMessage).toBe(
'To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from Dec 1, 2017 to Jun 30, 2018.',
);
})
.then(done)
.catch(done.fail);
......@@ -105,7 +111,9 @@ describe('EpicsListEmptyComponent', () => {
vm.hasFiltersApplied = true;
Vue.nextTick()
.then(() => {
expect(vm.subMessage).toBe('To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from Dec 1, 2017 to Jun 30, 2018.');
expect(vm.subMessage).toBe(
'To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from Dec 1, 2017 to Jun 30, 2018.',
);
})
.then(done)
.catch(done.fail);
......@@ -125,7 +133,9 @@ describe('EpicsListEmptyComponent', () => {
it('returns default empty state sub-message when `hasFiltersApplied` props is false', done => {
Vue.nextTick()
.then(() => {
expect(vm.subMessage).toBe('To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from Dec 24, 2017 to Feb 9, 2018.');
expect(vm.subMessage).toBe(
'To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from Dec 24, 2017 to Feb 9, 2018.',
);
})
.then(done)
.catch(done.fail);
......@@ -135,7 +145,9 @@ describe('EpicsListEmptyComponent', () => {
vm.hasFiltersApplied = true;
Vue.nextTick()
.then(() => {
expect(vm.subMessage).toBe('To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from Dec 24, 2017 to Feb 15, 2018.');
expect(vm.subMessage).toBe(
'To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from Dec 24, 2017 to Feb 15, 2018.',
);
})
.then(done)
.catch(done.fail);
......@@ -153,7 +165,9 @@ describe('EpicsListEmptyComponent', () => {
describe('template', () => {
it('renders empty state illustration in image element with provided `emptyStateIllustrationPath`', () => {
expect(vm.$el.querySelector('.svg-content img').getAttribute('src')).toBe(vm.emptyStateIllustrationPath);
expect(vm.$el.querySelector('.svg-content img').getAttribute('src')).toBe(
vm.emptyStateIllustrationPath,
);
});
it('renders new epic button element', () => {
......
......@@ -80,14 +80,14 @@ describe('EpicsListSectionComponent', () => {
});
describe('initMounted', () => {
it('initializes shellHeight based on window.innerHeight and component element position', (done) => {
it('initializes shellHeight based on window.innerHeight and component element position', done => {
vm.$nextTick(() => {
expect(vm.shellHeight).toBe(600);
done();
});
});
it('calls initEmptyRow() when there are Epics to render', (done) => {
it('calls initEmptyRow() when there are Epics to render', done => {
spyOn(vm, 'initEmptyRow').and.callThrough();
vm.$nextTick(() => {
......@@ -96,7 +96,7 @@ describe('EpicsListSectionComponent', () => {
});
});
it('emits `epicsListRendered` via eventHub', (done) => {
it('emits `epicsListRendered` via eventHub', done => {
spyOn(eventHub, '$emit');
vm.$nextTick(() => {
......@@ -107,7 +107,7 @@ describe('EpicsListSectionComponent', () => {
});
describe('initEmptyRow', () => {
it('sets `emptyRowHeight` and `showEmptyRow` props when shellHeight is greater than approximate height of epics list', (done) => {
it('sets `emptyRowHeight` and `showEmptyRow` props when shellHeight is greater than approximate height of epics list', done => {
vm.$nextTick(() => {
expect(vm.emptyRowHeight).toBe(600);
expect(vm.showEmptyRow).toBe(true);
......@@ -115,7 +115,7 @@ describe('EpicsListSectionComponent', () => {
});
});
it('does not set `emptyRowHeight` and `showEmptyRow` props when shellHeight is less than approximate height of epics list', (done) => {
it('does not set `emptyRowHeight` and `showEmptyRow` props when shellHeight is less than approximate height of epics list', done => {
const initialHeight = window.innerHeight;
window.innerHeight = 0;
const vmMoreEpics = createComponent({
......@@ -145,21 +145,21 @@ describe('EpicsListSectionComponent', () => {
vm = createComponent({});
});
it('renders component container element with class `epics-list-section`', (done) => {
it('renders component container element with class `epics-list-section`', done => {
vm.$nextTick(() => {
expect(vm.$el.classList.contains('epics-list-section')).toBe(true);
done();
});
});
it('renders component container element with `width` property applied via style attribute', (done) => {
it('renders component container element with `width` property applied via style attribute', done => {
vm.$nextTick(() => {
expect(vm.$el.getAttribute('style')).toBe(`width: ${mockShellWidth}px;`);
done();
});
});
it('renders bottom shadow element when `showBottomShadow` prop is true', (done) => {
it('renders bottom shadow element when `showBottomShadow` prop is true', done => {
vm.showBottomShadow = true;
vm.$nextTick(() => {
expect(vm.$el.querySelector('.scroll-bottom-shadow')).not.toBe(null);
......
......@@ -8,19 +8,22 @@ import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockEpic, mockTimeframeMonths, mockGroupId, mockScrollBarSize } from '../mock_data';
const createComponent = ({
epics = [mockEpic],
timeframe = mockTimeframeMonths,
currentGroupId = mockGroupId,
}, el) => {
const createComponent = (
{ epics = [mockEpic], timeframe = mockTimeframeMonths, currentGroupId = mockGroupId },
el,
) => {
const Component = Vue.extend(roadmapShellComponent);
return mountComponent(Component, {
return mountComponent(
Component,
{
presetType: PRESET_TYPES.MONTHS,
epics,
timeframe,
currentGroupId,
}, el);
},
el,
);
};
describe('RoadmapShellComponent', () => {
......@@ -45,14 +48,15 @@ describe('RoadmapShellComponent', () => {
describe('computed', () => {
describe('containerStyles', () => {
beforeEach(() => {
document.body.innerHTML += '<div class="roadmap-container"><div id="roadmap-shell"></div></div>';
document.body.innerHTML +=
'<div class="roadmap-container"><div id="roadmap-shell"></div></div>';
});
afterEach(() => {
document.querySelector('.roadmap-container').remove();
});
it('returns style object based on shellWidth and current Window width with Scollbar size offset', (done) => {
it('returns style object based on shellWidth and current Window width with Scollbar size offset', done => {
const vmWithParentEl = createComponent({}, document.getElementById('roadmap-shell'));
Vue.nextTick(() => {
const stylesObj = vmWithParentEl.containerStyles;
......@@ -101,7 +105,7 @@ describe('RoadmapShellComponent', () => {
expect(vm.$el.classList.contains('roadmap-shell')).toBe(true);
});
it('adds `prevent-vertical-scroll` class on component container element', (done) => {
it('adds `prevent-vertical-scroll` class on component container element', done => {
vm.noScroll = true;
Vue.nextTick(() => {
expect(vm.$el.classList.contains('prevent-vertical-scroll')).toBe(true);
......
......@@ -80,7 +80,7 @@ describe('TimelineTodayIndicatorComponent', () => {
});
describe('template', () => {
it('renders component container element with class `today-bar`', (done) => {
it('renders component container element with class `today-bar`', done => {
vm = createComponent({});
vm.handleEpicsListRender({
height: 100,
......@@ -92,4 +92,3 @@ describe('TimelineTodayIndicatorComponent', () => {
});
});
});
......@@ -25,8 +25,10 @@ export const mockTimeframeWeeks = getTimeframeForWeeksView(new Date(2018, 0, 1))
export const mockEpic = {
id: 1,
iid: 1,
description: 'Explicabo et soluta minus praesentium minima ab et voluptatem. Quas architecto vero corrupti voluptatibus labore accusantium consectetur. Aliquam aut impedit voluptates illum molestias aut harum. Aut non odio praesentium aut.\n\nQuo asperiores aliquid sed nobis. Omnis sint iste provident numquam. Qui voluptatem tempore aut aut voluptas dolorem qui.\n\nEst est nemo quod est. Odit modi eos natus cum illo aut. Expedita nostrum ea est omnis magnam ut eveniet maxime. Itaque ipsam provident minima et occaecati ut. Dicta est perferendis sequi perspiciatis rerum voluptatum deserunt.',
title: 'Cupiditate exercitationem unde harum reprehenderit maxime eius velit recusandae incidunt quia.',
description:
'Explicabo et soluta minus praesentium minima ab et voluptatem. Quas architecto vero corrupti voluptatibus labore accusantium consectetur. Aliquam aut impedit voluptates illum molestias aut harum. Aut non odio praesentium aut.\n\nQuo asperiores aliquid sed nobis. Omnis sint iste provident numquam. Qui voluptatem tempore aut aut voluptas dolorem qui.\n\nEst est nemo quod est. Odit modi eos natus cum illo aut. Expedita nostrum ea est omnis magnam ut eveniet maxime. Itaque ipsam provident minima et occaecati ut. Dicta est perferendis sequi perspiciatis rerum voluptatum deserunt.',
title:
'Cupiditate exercitationem unde harum reprehenderit maxime eius velit recusandae incidunt quia.',
groupId: 2,
groupName: 'Gitlab Org',
groupFullName: 'Gitlab Org',
......@@ -123,7 +125,8 @@ export const rawEpics = [
{
id: 4,
iid: 4,
description: 'Animi dolorem error ipsam assumenda. Dolor reprehenderit sit soluta molestias id. Explicabo vel dolores numquam earum ut aliquid. Quisquam aliquam a totam laborum quia.\n\nEt voluptatem reiciendis qui cum. Labore ratione delectus minus et voluptates. Dolor voluptatem nisi neque fugiat ut ullam dicta odit. Aut quaerat provident ducimus aut molestiae hic esse.\n\nSuscipit non repellat laudantium quaerat. Voluptatum dolor explicabo vel illo earum. Laborum vero occaecati qui autem cumque dolorem autem. Enim voluptatibus a dolorem et.',
description:
'Animi dolorem error ipsam assumenda. Dolor reprehenderit sit soluta molestias id. Explicabo vel dolores numquam earum ut aliquid. Quisquam aliquam a totam laborum quia.\n\nEt voluptatem reiciendis qui cum. Labore ratione delectus minus et voluptates. Dolor voluptatem nisi neque fugiat ut ullam dicta odit. Aut quaerat provident ducimus aut molestiae hic esse.\n\nSuscipit non repellat laudantium quaerat. Voluptatum dolor explicabo vel illo earum. Laborum vero occaecati qui autem cumque dolorem autem. Enim voluptatibus a dolorem et.',
title: 'Et repellendus quo et laboriosam corrupti ex nisi qui.',
group_id: 2,
group_name: 'Gitlab Org',
......@@ -135,7 +138,8 @@ export const rawEpics = [
{
id: 3,
iid: 3,
description: 'Magnam placeat ut esse aut vel. Et sit ab soluta ut eos et et. Nesciunt expedita sit et optio maiores quas facilis. Provident ut aut et nihil. Nesciunt ipsum fuga labore dolor quia.\n\nSit suscipit impedit aut dolore non provident. Nesciunt nemo excepturi voluptatem natus veritatis. Vel ut possimus reiciendis dolorem et. Recusandae voluptatem voluptatum aut iure. Sapiente quia est iste similique quidem quia omnis et.\n\nId aut assumenda beatae iusto est dicta consequatur. Tempora voluptatem pariatur ab velit vero ut reprehenderit fuga. Dolor modi aspernatur eos atque eveniet harum sed voluptatem. Dolore iusto voluptas dolor enim labore dolorum consequatur dolores.',
description:
'Magnam placeat ut esse aut vel. Et sit ab soluta ut eos et et. Nesciunt expedita sit et optio maiores quas facilis. Provident ut aut et nihil. Nesciunt ipsum fuga labore dolor quia.\n\nSit suscipit impedit aut dolore non provident. Nesciunt nemo excepturi voluptatem natus veritatis. Vel ut possimus reiciendis dolorem et. Recusandae voluptatem voluptatum aut iure. Sapiente quia est iste similique quidem quia omnis et.\n\nId aut assumenda beatae iusto est dicta consequatur. Tempora voluptatem pariatur ab velit vero ut reprehenderit fuga. Dolor modi aspernatur eos atque eveniet harum sed voluptatem. Dolore iusto voluptas dolor enim labore dolorum consequatur dolores.',
title: 'Nostrum ut nisi fugiat accusantium qui velit dignissimos.',
group_id: 2,
group_name: 'Gitlab Org',
......@@ -147,7 +151,8 @@ export const rawEpics = [
{
id: 2,
iid: 2,
description: 'Deleniti id facere numquam cum consectetur sint ipsum consequatur. Odit nihil harum consequuntur est nemo adipisci. Incidunt suscipit voluptatem et culpa at voluptatem consequuntur. Rerum aliquam earum quia consequatur ipsam quae ut.\n\nQuod molestias ducimus quia ratione nostrum ut adipisci. Fugiat officiis reiciendis repellendus quia ut ipsa. Voluptatum ut dolor perferendis nostrum. Porro a ducimus sequi qui quos ea. Earum velit architecto necessitatibus at dicta.\n\nModi aut non fugiat autem doloribus nobis ea. Sit quam corrupti blanditiis nihil tempora ratione enim ex. Aliquam quia ut impedit ut velit reprehenderit quae amet. Unde quod at dolorum eligendi in ducimus perspiciatis accusamus.',
description:
'Deleniti id facere numquam cum consectetur sint ipsum consequatur. Odit nihil harum consequuntur est nemo adipisci. Incidunt suscipit voluptatem et culpa at voluptatem consequuntur. Rerum aliquam earum quia consequatur ipsam quae ut.\n\nQuod molestias ducimus quia ratione nostrum ut adipisci. Fugiat officiis reiciendis repellendus quia ut ipsa. Voluptatum ut dolor perferendis nostrum. Porro a ducimus sequi qui quos ea. Earum velit architecto necessitatibus at dicta.\n\nModi aut non fugiat autem doloribus nobis ea. Sit quam corrupti blanditiis nihil tempora ratione enim ex. Aliquam quia ut impedit ut velit reprehenderit quae amet. Unde quod at dolorum eligendi in ducimus perspiciatis accusamus.',
title: 'Sit beatae amet quaerat consequatur non repudiandae qui.',
group_id: 2,
group_name: 'Gitlab Org',
......@@ -159,8 +164,10 @@ export const rawEpics = [
{
id: 1,
iid: 1,
description: 'Explicabo et soluta minus praesentium minima ab et voluptatem. Quas architecto vero corrupti voluptatibus labore accusantium consectetur. Aliquam aut impedit voluptates illum molestias aut harum. Aut non odio praesentium aut.\n\nQuo asperiores aliquid sed nobis. Omnis sint iste provident numquam. Qui voluptatem tempore aut aut voluptas dolorem qui.\n\nEst est nemo quod est. Odit modi eos natus cum illo aut. Expedita nostrum ea est omnis magnam ut eveniet maxime. Itaque ipsam provident minima et occaecati ut. Dicta est perferendis sequi perspiciatis rerum voluptatum deserunt.',
title: 'Cupiditate exercitationem unde harum reprehenderit maxime eius velit recusandae incidunt quia.',
description:
'Explicabo et soluta minus praesentium minima ab et voluptatem. Quas architecto vero corrupti voluptatibus labore accusantium consectetur. Aliquam aut impedit voluptates illum molestias aut harum. Aut non odio praesentium aut.\n\nQuo asperiores aliquid sed nobis. Omnis sint iste provident numquam. Qui voluptatem tempore aut aut voluptas dolorem qui.\n\nEst est nemo quod est. Odit modi eos natus cum illo aut. Expedita nostrum ea est omnis magnam ut eveniet maxime. Itaque ipsam provident minima et occaecati ut. Dicta est perferendis sequi perspiciatis rerum voluptatum deserunt.',
title:
'Cupiditate exercitationem unde harum reprehenderit maxime eius velit recusandae incidunt quia.',
group_id: 2,
group_name: 'Gitlab Org',
group_full_name: 'Gitlab Org',
......
......@@ -38,7 +38,7 @@ describe('sidebarItemEpic', () => {
const epicTitle = 'epic title';
const url = 'https://gitlab.com/';
beforeEach((done) => {
beforeEach(done => {
sidebarStore.setEpicData({
epic: {
title: epicTitle,
......@@ -60,11 +60,13 @@ describe('sidebarItemEpic', () => {
it('shows epic title as collapsed title tooltip', () => {
expect(vm.$el.querySelector('.sidebar-collapsed-icon').getAttribute('title')).toBeDefined();
expect(vm.$el.querySelector('.sidebar-collapsed-icon').getAttribute('data-original-title')).toEqual(epicTitle);
expect(
vm.$el.querySelector('.sidebar-collapsed-icon').getAttribute('data-original-title'),
).toEqual(epicTitle);
});
describe('no epic', () => {
beforeEach((done) => {
beforeEach(done => {
sidebarStore.epic = {};
Vue.nextTick(done);
});
......
......@@ -7,7 +7,7 @@ import eventHub from '~/sidebar/event_hub';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import Mock from './ee_mock_data';
describe('Sidebar Weight', function () {
describe('Sidebar Weight', function() {
let vm;
let sidebarMediator;
let SidebarWeight;
......
......@@ -83,8 +83,7 @@ describe('Weight', function() {
vm.$el.querySelector('.js-weight-collapsed-block').click();
vm
.$nextTick()
vm.$nextTick()
.then(() => {
expect(vm.$el.classList.contains('collapse-after-update')).toEqual(true);
})
......@@ -102,8 +101,7 @@ describe('Weight', function() {
vm.$el.querySelector('.js-weight-edit-link').click();
vm
.$nextTick()
vm.$nextTick()
.then(() => {
expect(vm.shouldShowEditField).toEqual(true);
})
......
import Vue from 'vue';
import component from 'ee/vue_merge_request_widget/components/codequality_issue_body.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import {
STATUS_FAILED,
STATUS_NEUTRAL,
STATUS_SUCCESS,
} from '~/reports/constants';
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
describe('code quality issue body issue body', () => {
let vm;
......
......@@ -34,13 +34,18 @@ describe('Report issues', () => {
});
it('should render a list of resolved issues', () => {
expect(vm.$el.querySelectorAll('.report-block-list li').length).toEqual(codequalityParsedIssues.length);
expect(vm.$el.querySelectorAll('.report-block-list li').length).toEqual(
codequalityParsedIssues.length,
);
});
it('should render "Fixed" keyword', () => {
expect(vm.$el.querySelector('.report-block-list li').textContent).toContain('Fixed');
expect(
vm.$el.querySelector('.report-block-list li').textContent.replace(/\s+/g, ' ').trim(),
vm.$el
.querySelector('.report-block-list li')
.textContent.replace(/\s+/g, ' ')
.trim(),
).toEqual('Fixed: Insecure Dependency in Gemfile.lock:12');
});
});
......@@ -55,7 +60,9 @@ describe('Report issues', () => {
});
it('should render a list of unresolved issues', () => {
expect(vm.$el.querySelectorAll('.report-block-list li').length).toEqual(codequalityParsedIssues.length);
expect(vm.$el.querySelectorAll('.report-block-list li').length).toEqual(
codequalityParsedIssues.length,
);
});
it('should not render "Fixed" keyword', () => {
......@@ -74,7 +81,9 @@ describe('Report issues', () => {
});
it('should render a list of unresolved issues', () => {
expect(vm.$el.querySelectorAll('.report-block-list li').length).toEqual(sastParsedIssues.length);
expect(vm.$el.querySelectorAll('.report-block-list li').length).toEqual(
sastParsedIssues.length,
);
});
});
......@@ -87,16 +96,20 @@ describe('Report issues', () => {
});
expect(vm.$el.querySelector('.report-block-list li').textContent).toContain('in');
expect(vm.$el.querySelector('.report-block-list li a').getAttribute('href')).toEqual(sastParsedIssues[0].urlPath);
expect(vm.$el.querySelector('.report-block-list li a').getAttribute('href')).toEqual(
sastParsedIssues[0].urlPath,
);
});
});
describe('without location', () => {
it('should not render location', () => {
vm = mountComponent(ReportIssues, {
issues: [{
issues: [
{
title: 'foo',
}],
},
],
component: componentNames.SastIssueBody,
status: STATUS_SUCCESS,
});
......@@ -116,31 +129,30 @@ describe('Report issues', () => {
});
it('renders severity', () => {
expect(
vm.$el.querySelector('.report-block-list li').textContent.trim(),
).toContain(dockerReportParsed.unapproved[0].severity);
expect(vm.$el.querySelector('.report-block-list li').textContent.trim()).toContain(
dockerReportParsed.unapproved[0].severity,
);
});
it('renders CVE name', () => {
expect(
vm.$el.querySelector('.report-block-list button').textContent.trim(),
).toEqual(dockerReportParsed.unapproved[0].title);
expect(vm.$el.querySelector('.report-block-list button').textContent.trim()).toEqual(
dockerReportParsed.unapproved[0].title,
);
});
it('renders namespace', () => {
expect(
vm.$el.querySelector('.report-block-list li').textContent.trim(),
).toContain(dockerReportParsed.unapproved[0].path);
expect(vm.$el.querySelector('.report-block-list li').textContent.trim()).toContain(
dockerReportParsed.unapproved[0].path,
);
expect(
vm.$el.querySelector('.report-block-list li').textContent.trim(),
).toContain('in');
expect(vm.$el.querySelector('.report-block-list li').textContent.trim()).toContain('in');
});
});
describe('for dast issues', () => {
beforeEach(() => {
vm = mountComponentWithStore(ReportIssues, { store,
vm = mountComponentWithStore(ReportIssues, {
store,
props: {
issues: parsedDast,
component: componentNames.DastIssueBody,
......@@ -151,7 +163,9 @@ describe('Report issues', () => {
it('renders severity (confidence) and title', () => {
expect(vm.$el.textContent).toContain(parsedDast[0].title);
expect(vm.$el.textContent).toContain(`${parsedDast[0].severity} (${parsedDast[0].confidence})`);
expect(vm.$el.textContent).toContain(
`${parsedDast[0].severity} (${parsedDast[0].confidence})`,
);
});
});
});
......@@ -12,8 +12,7 @@ describe('dast issue body', () => {
confidence: 'Medium',
count: '17',
cweid: '16',
desc:
'<p>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to "nosniff". </p>',
desc: '<p>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to "nosniff". </p>',
title: 'X-Content-Type-Options Header Missing',
reference:
'<p>http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx</p><p>https://www.owasp.org/index.php/List_of_useful_HTTP_headers</p>',
......@@ -35,7 +34,9 @@ describe('dast issue body', () => {
status,
});
expect(vm.$el.textContent.trim()).toContain(`${dastIssue.severity} (${dastIssue.confidence})`);
expect(vm.$el.textContent.trim()).toContain(
`${dastIssue.severity} (${dastIssue.confidence})`,
);
});
});
......
......@@ -17,8 +17,7 @@ describe('sast issue body', () => {
solution:
'upgrade to >= 5.0.0.beta1.1, >= 4.2.5.1, ~> 4.2.5, >= 4.1.14.1, ~> 4.1.14, ~> 3.2.22.1',
tool: 'bundler_audit',
url:
'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
urlPath: '/Gemfile.lock',
severity: 'Medium',
confidence: 'Low',
......@@ -37,7 +36,9 @@ describe('sast issue body', () => {
status,
});
expect(vm.$el.textContent.trim()).toContain(`${sastIssue.severity} (${sastIssue.confidence}):`);
expect(vm.$el.textContent.trim()).toContain(
`${sastIssue.severity} (${sastIssue.confidence}):`,
);
});
});
......@@ -93,9 +94,7 @@ describe('sast issue body', () => {
status,
});
expect(vm.$el.textContent.trim()).not.toContain(
sastIssue.priority,
);
expect(vm.$el.textContent.trim()).not.toContain(sastIssue.priority);
});
});
......@@ -106,9 +105,7 @@ describe('sast issue body', () => {
status,
});
expect(vm.$el.textContent.trim()).toContain(
sastIssue.title,
);
expect(vm.$el.textContent.trim()).toContain(sastIssue.title);
});
});
......@@ -119,13 +116,9 @@ describe('sast issue body', () => {
status,
});
expect(vm.$el.querySelector('a').getAttribute('href')).toEqual(
sastIssue.urlPath,
);
expect(vm.$el.querySelector('a').getAttribute('href')).toEqual(sastIssue.urlPath);
expect(vm.$el.querySelector('a').textContent.trim()).toEqual(
sastIssue.path,
);
expect(vm.$el.querySelector('a').textContent.trim()).toEqual(sastIssue.path);
});
});
});
......@@ -49,15 +49,19 @@ export const sastIssues = [
start_line: 5,
end_line: 10,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2014-7829',
value: 'CVE-2014-7829',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7829',
}],
},
],
},
{
tool: 'bundler_audit',
......@@ -69,15 +73,19 @@ export const sastIssues = [
location: {
file: 'Gemfile.lock',
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2016-0752',
value: 'CVE-2016-0752',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0752',
}],
},
],
},
{
tool: 'bundler_audit',
......@@ -89,15 +97,19 @@ export const sastIssues = [
location: {
file: 'Gemfile.lock',
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/9oLY_FCzvoc',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2016-0751',
value: 'CVE-2016-0751',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0751',
}],
},
],
},
];
......@@ -126,15 +138,19 @@ export const sastIssuesBase = [
start_line: 5,
end_line: 10,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2016-9999',
value: 'CVE-2016-9999',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9999',
}],
},
],
},
{
tool: 'bundler_audit',
......@@ -146,15 +162,19 @@ export const sastIssuesBase = [
location: {
file: 'Gemfile.lock',
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2016-0752',
value: 'CVE-2016-0752',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0752',
}],
},
],
},
];
......@@ -174,15 +194,19 @@ export const parsedSastIssuesStore = [
start_line: 5,
end_line: 10,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2014-7829',
value: 'CVE-2014-7829',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7829',
}],
},
],
},
{
tool: 'bundler_audit',
......@@ -198,15 +222,19 @@ export const parsedSastIssuesStore = [
location: {
file: 'Gemfile.lock',
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2016-0752',
value: 'CVE-2016-0752',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0752',
}],
},
],
},
{
tool: 'bundler_audit',
......@@ -222,15 +250,19 @@ export const parsedSastIssuesStore = [
location: {
file: 'Gemfile.lock',
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/9oLY_FCzvoc',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2016-0751',
value: 'CVE-2016-0751',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0751',
}],
},
],
},
];
......@@ -250,15 +282,19 @@ export const parsedSastIssuesHead = [
start_line: 5,
end_line: 10,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2014-7829',
value: 'CVE-2014-7829',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7829',
}],
},
],
},
{
tool: 'bundler_audit',
......@@ -274,15 +310,19 @@ export const parsedSastIssuesHead = [
location: {
file: 'Gemfile.lock',
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/9oLY_FCzvoc',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2016-0751',
value: 'CVE-2016-0751',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0751',
}],
},
],
},
];
......@@ -303,15 +343,19 @@ export const parsedSastBaseStore = [
start_line: 5,
end_line: 10,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2016-9999',
value: 'CVE-2016-9999',
link: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9999',
}],
},
],
},
];
......@@ -384,9 +428,11 @@ export const parsedDependencyScanningIssuesStore = [
file: 'Gemfile.lock',
start_line: 5,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
}],
},
],
},
{
tool: 'bundler_audit',
......@@ -405,9 +451,11 @@ export const parsedDependencyScanningIssuesStore = [
file: 'Gemfile.lock',
start_line: undefined,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
}],
},
],
},
{
tool: 'bundler_audit',
......@@ -426,9 +474,11 @@ export const parsedDependencyScanningIssuesStore = [
file: 'Gemfile.lock',
start_line: undefined,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/9oLY_FCzvoc',
}],
},
],
},
];
......@@ -450,9 +500,11 @@ export const parsedDependencyScanningIssuesHead = [
file: 'Gemfile.lock',
start_line: 5,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
}],
},
],
},
{
tool: 'bundler_audit',
......@@ -471,9 +523,11 @@ export const parsedDependencyScanningIssuesHead = [
file: 'Gemfile.lock',
start_line: undefined,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/9oLY_FCzvoc',
}],
},
],
},
];
......@@ -495,9 +549,11 @@ export const parsedDependencyScanningBaseStore = [
file: 'Gemfile.lock',
start_line: undefined,
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
}],
},
],
},
];
......@@ -565,12 +621,14 @@ export const dockerNewIssues = [
severity: 'Negligible',
title: 'CVE-2017-16232',
path: 'debian:8',
identifiers: [{
identifiers: [
{
type: 'CVE',
name: 'CVE-2017-16232',
value: 'CVE-2017-16232',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16232',
}],
},
],
category: 'container_scanning',
project_fingerprint: '4e010f6d292364a42c6bb05dbd2cc788c2e5e408',
description: 'debian:8 is affected by CVE-2017-16232.',
......@@ -584,12 +642,14 @@ export const dockerOnlyHeadParsed = [
severity: 'Medium',
title: 'CVE-2017-12944',
path: 'debian:8',
identifiers: [{
identifiers: [
{
type: 'CVE',
name: 'CVE-2017-12944',
value: 'CVE-2017-12944',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12944',
}],
},
],
category: 'container_scanning',
project_fingerprint: '0693a82ef93c5e9d98c23a35ddcd8ed2cbd047d9',
description: 'debian:8 is affected by CVE-2017-12944.',
......@@ -600,12 +660,14 @@ export const dockerOnlyHeadParsed = [
severity: 'Negligible',
title: 'CVE-2017-16232',
path: 'debian:8',
identifiers: [{
identifiers: [
{
type: 'CVE',
name: 'CVE-2017-16232',
value: 'CVE-2017-16232',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16232',
}],
},
],
category: 'container_scanning',
project_fingerprint: '4e010f6d292364a42c6bb05dbd2cc788c2e5e408',
description: 'debian:8 is affected by CVE-2017-16232.',
......@@ -620,12 +682,14 @@ export const dockerReportParsed = {
severity: 'Medium',
title: 'CVE-2017-12944',
path: 'debian:8',
identifiers: [{
identifiers: [
{
type: 'CVE',
name: 'CVE-2017-12944',
value: 'CVE-2017-12944',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12944',
}],
},
],
},
{
vulnerability: 'CVE-2017-16232',
......@@ -633,12 +697,14 @@ export const dockerReportParsed = {
severity: 'Negligible',
title: 'CVE-2017-16232',
path: 'debian:8',
identifiers: [{
identifiers: [
{
type: 'CVE',
name: 'CVE-2017-16232',
value: 'CVE-2017-16232',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16232',
}],
},
],
},
],
approved: [
......@@ -648,12 +714,14 @@ export const dockerReportParsed = {
severity: 'Negligible',
title: 'CVE-2014-8130',
path: 'debian:8',
identifiers: [{
identifiers: [
{
type: 'CVE',
name: 'CVE-2017-8130',
value: 'CVE-2017-8130',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8130',
}],
},
],
},
],
vulnerabilities: [
......@@ -663,12 +731,14 @@ export const dockerReportParsed = {
severity: 'Medium',
title: 'CVE-2017-12944',
path: 'debian:8',
identifiers: [{
identifiers: [
{
type: 'CVE',
name: 'CVE-2017-12944',
value: 'CVE-2017-12944',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-v',
}],
},
],
},
{
vulnerability: 'CVE-2017-16232',
......@@ -676,12 +746,14 @@ export const dockerReportParsed = {
severity: 'Negligible',
title: 'CVE-2017-16232',
path: 'debian:8',
identifiers: [{
identifiers: [
{
type: 'CVE',
name: 'CVE-2017-16232',
value: 'CVE-2017-16232',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16232',
}],
},
],
},
{
vulnerability: 'CVE-2014-8130',
......@@ -689,12 +761,14 @@ export const dockerReportParsed = {
severity: 'Negligible',
title: 'CVE-2014-8130',
path: 'debian:8',
identifiers: [{
identifiers: [
{
type: 'CVE',
name: 'CVE-2017-8130',
value: 'CVE-2017-8130',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8130',
}],
},
],
},
],
};
......@@ -789,12 +863,14 @@ export const parsedDast = [
cweid: '3',
desc: '<p>No Anti-CSRF tokens were found in a HTML submission form.</p>',
pluginid: '123',
identifiers: [{
identifiers: [
{
type: 'CWE',
name: 'CWE-3',
value: '3',
url: 'https://cwe.mitre.org/data/definitions/3.html',
}],
},
],
instances: [
{
uri: 'http://192.168.32.236:3001/explore?sort=latest_activity_desc',
......@@ -817,12 +893,14 @@ export const parsedDast = [
name: 'X-Content-Type-Options Header Missing',
title: 'X-Content-Type-Options Header Missing',
riskdesc: 'Low (Medium)',
identifiers: [{
identifiers: [
{
type: 'CWE',
name: 'CWE-4',
value: '4',
url: 'https://cwe.mitre.org/data/definitions/4.html',
}],
},
],
severity: 'Low',
confidence: 'Medium',
cweid: '4',
......@@ -848,12 +926,14 @@ export const parsedDastNewIssues = [
name: 'X-Content-Type-Options Header Missing',
title: 'X-Content-Type-Options Header Missing',
riskdesc: 'Low (Medium)',
identifiers: [{
identifiers: [
{
type: 'CWE',
name: 'CWE-4',
value: '4',
url: 'https://cwe.mitre.org/data/definitions/4.html',
}],
},
],
severity: 'Low',
confidence: 'Medium',
cweid: '4',
......
......@@ -414,21 +414,26 @@ describe('security reports mutations', () => {
class: 'User',
method: 'do_something',
},
links: [{
links: [
{
url: 'https://groups.google.com/forum/#!topic/rubyonrails-security/rMTQy4oRCGk',
}],
identifiers: [{
},
],
identifiers: [
{
type: 'CVE',
name: 'CVE-2014-9999',
value: 'CVE-2014-9999',
url: 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-9999',
}],
instances: [{
},
],
instances: [
{
param: 'X-Content-Type-Options',
method: 'GET',
uri: 'http://example.com/some-path',
}],
},
],
isDismissed: true,
};
const status = 'success';
......
......@@ -82,11 +82,7 @@ describe('security reports utils', () => {
});
it('includes vulnerability feedbacks', () => {
const parsed = parseSastIssues(
sastIssues,
sastFeedbacks,
'path',
)[0];
const parsed = parseSastIssues(sastIssues, sastFeedbacks, 'path')[0];
expect(parsed.hasIssue).toEqual(true);
expect(parsed.isDismissed).toEqual(true);
......@@ -144,15 +140,20 @@ describe('security reports utils', () => {
expect(parsed.title).toEqual(issue.vulnerability);
expect(parsed.path).toEqual(issue.namespace);
expect(parsed.identifiers).toEqual([{
expect(parsed.identifiers).toEqual([
{
type: 'CVE',
name: issue.vulnerability,
value: issue.vulnerability,
url: `https://cve.mitre.org/cgi-bin/cvename.cgi?name=${issue.vulnerability}`,
}]);
},
]);
expect(parsed.project_fingerprint).toEqual(
sha1(`${issue.namespace}:${issue.vulnerability}:${issue.featurename}:${issue.featureversion}`));
sha1(
`${issue.namespace}:${issue.vulnerability}:${issue.featurename}:${issue.featureversion}`,
),
);
});
it('includes vulnerability feedbacks', () => {
......@@ -174,10 +175,7 @@ describe('security reports utils', () => {
});
it('includes vulnerability feedbacks', () => {
const parsed = parseDastIssues(
dast.site.alerts,
dastFeedbacks,
)[0];
const parsed = parseDastIssues(dast.site.alerts, dastFeedbacks)[0];
expect(parsed.hasIssue).toEqual(true);
expect(parsed.isDismissed).toEqual(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