Commit 7fed3395 authored by Miguel Rincon's avatar Miguel Rincon

Split the dashboard header to a separate component

The dashboard component is too complex at the moment,
this is an MVC to split the dashboard from its header component.

specs have been kept almost the same to ensure features are not impacted
by the change.
parent 59122560
<script>
import { debounce } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
import VueDraggable from 'vuedraggable';
import {
GlIcon,
GlButton,
GlDeprecatedButton,
GlDropdown,
GlDropdownItem,
GlDropdownHeader,
GlDropdownDivider,
GlModal,
GlLoadingIcon,
GlSearchBoxByType,
GlModalDirective,
GlTooltipDirective,
} from '@gitlab/ui';
import { GlIcon, GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
import DashboardHeader from './dashboard_header.vue';
import DashboardPanel from './dashboard_panel.vue';
import { s__ } from '~/locale';
import createFlash from '~/flash';
import { ESC_KEY, ESC_KEY_IE11 } from '~/lib/utils/keys';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import { mergeUrlParams, redirectTo, updateHistory } from '~/lib/utils/url_utility';
import { mergeUrlParams, updateHistory } from '~/lib/utils/url_utility';
import invalidUrl from '~/lib/utils/invalid_url';
import Icon from '~/vue_shared/components/icon.vue';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import GraphGroup from './graph_group.vue';
import EmptyState from './empty_state.vue';
import GroupEmptyState from './group_empty_state.vue';
import DashboardsDropdown from './dashboards_dropdown.vue';
import VariablesSection from './variables_section.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import {
getAddMetricTrackingOptions,
timeRangeToUrl,
timeRangeFromUrl,
panelToUrl,
expandedPanelPayloadFromUrl,
convertVariablesForURL,
} from '../utils';
import { metricStates } from '../constants';
import { defaultTimeRange, timeRanges } from '~/vue_shared/constants';
import { defaultTimeRange } from '~/vue_shared/constants';
export default {
components: {
VueDraggable,
DashboardHeader,
DashboardPanel,
Icon,
GlIcon,
GlButton,
GlDeprecatedButton,
GlDropdown,
GlLoadingIcon,
GlDropdownItem,
GlDropdownHeader,
GlDropdownDivider,
GlSearchBoxByType,
GlModal,
CustomMetricsFormFields,
DateTimePicker,
GraphGroup,
EmptyState,
GroupEmptyState,
DashboardsDropdown,
VariablesSection,
},
directives: {
......@@ -173,10 +143,7 @@ export default {
},
data() {
return {
formIsValid: null,
selectedTimeRange: timeRangeFromUrl() || defaultTimeRange,
hasValidDates: true,
timeRanges,
isRearrangingPanels: false,
};
},
......@@ -185,36 +152,11 @@ export default {
'dashboard',
'emptyState',
'showEmptyState',
'useDashboardEndpoint',
'allDashboards',
'environmentsLoading',
'expandedPanel',
'variables',
'isUpdatingStarredValue',
'currentDashboard',
'currentEnvironmentName',
]),
...mapGetters('monitoringDashboard', [
'selectedDashboard',
'getMetricStates',
'filteredEnvironments',
]),
showRearrangePanelsBtn() {
return !this.showEmptyState && this.rearrangePanelsAvailable;
},
addingMetricsAvailable() {
return (
this.customMetricsAvailable &&
!this.showEmptyState &&
// Custom metrics only avaialble on system dashboards because
// they are stored in the database. This can be improved. See:
// https://gitlab.com/gitlab-org/gitlab/-/issues/28241
this.selectedDashboard?.system_dashboard
);
},
shouldShowEnvironmentsDropdownNoMatchedMsg() {
return !this.environmentsLoading && this.filteredEnvironments.length === 0;
},
...mapGetters('monitoringDashboard', ['selectedDashboard', 'getMetricStates']),
shouldShowVariablesSection() {
return Object.keys(this.variables).length > 0;
},
......@@ -263,13 +205,10 @@ export default {
...mapActions('monitoringDashboard', [
'setTimeRange',
'fetchData',
'fetchDashboardData',
'setGettingStartedEmptyState',
'setPanelGroupMetrics',
'filterEnvironments',
'setExpandedPanel',
'clearExpandedPanel',
'toggleStarredValue',
]),
updatePanels(key, panels) {
this.setPanelGroupMetrics({
......@@ -283,38 +222,10 @@ export default {
key,
});
},
onDateTimePickerInput(timeRange) {
redirectTo(timeRangeToUrl(timeRange));
},
onDateTimePickerInvalid() {
createFlash(
s__(
'Metrics|Link contains an invalid time window, please verify the link to see the requested time range.',
),
);
// As a fallback, switch to default time range instead
this.selectedTimeRange = defaultTimeRange;
},
generatePanelUrl(groupKey, panel) {
const dashboardPath = this.currentDashboard || this.selectedDashboard?.path;
return panelToUrl(dashboardPath, convertVariablesForURL(this.variables), groupKey, panel);
},
hideAddMetricModal() {
this.$refs.addMetricModal.hide();
},
toggleRearrangingPanels() {
this.isRearrangingPanels = !this.isRearrangingPanels;
},
setFormValidity(isValid) {
this.formIsValid = isValid;
},
debouncedEnvironmentsSearch: debounce(function environmentsSearchOnInput(searchTerm) {
this.filterEnvironments(searchTerm);
}, 500),
submitCustomMetricsForm() {
this.$refs.customMetricsForm.submit();
},
/**
* Return a single empty state for a group.
*
......@@ -341,19 +252,6 @@ export default {
// Collapse group if no data is available
return !this.getMetricStates(groupKey).includes(metricStates.OK);
},
getAddMetricTrackingOptions,
selectDashboard(dashboard) {
const params = {
dashboard: dashboard.path,
};
redirectTo(mergeUrlParams(params, window.location.href));
},
refreshDashboard() {
this.fetchDashboardData();
},
onTimeRangeZoom({ start, end }) {
updateHistory({
url: mergeUrlParams({ start, end }, window.location.href),
......@@ -373,212 +271,43 @@ export default {
this.clearExpandedPanel();
}
},
onSetRearrangingPanels(isRearrangingPanels) {
this.isRearrangingPanels = isRearrangingPanels;
},
onDateTimePickerInvalid() {
createFlash(
s__(
'Metrics|Link contains an invalid time window, please verify the link to see the requested time range.',
),
);
// As a fallback, switch to default time range instead
this.selectedTimeRange = defaultTimeRange;
},
addMetric: {
title: s__('Metrics|Add metric'),
modalId: 'add-metric',
},
i18n: {
goBackLabel: s__('Metrics|Go back (Esc)'),
starDashboard: s__('Metrics|Star dashboard'),
unstarDashboard: s__('Metrics|Unstar dashboard'),
},
};
</script>
<template>
<div class="prometheus-graphs" data-qa-selector="prometheus_graphs">
<div
<dashboard-header
v-if="showHeader"
ref="prometheusGraphsHeader"
class="prometheus-graphs-header d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 border-bottom bg-gray-light"
>
<div class="mb-2 pr-2 d-flex d-sm-block">
<dashboards-dropdown
id="monitor-dashboards-dropdown"
data-qa-selector="dashboards_filter_dropdown"
class="flex-grow-1"
toggle-class="dropdown-menu-toggle"
:default-branch="defaultBranch"
@selectDashboard="selectDashboard($event)"
/>
</div>
<div class="mb-2 pr-2 d-flex d-sm-block">
<gl-dropdown
id="monitor-environments-dropdown"
ref="monitorEnvironmentsDropdown"
class="flex-grow-1"
data-qa-selector="environments_dropdown"
toggle-class="dropdown-menu-toggle"
menu-class="monitor-environment-dropdown-menu"
:text="currentEnvironmentName"
>
<div class="d-flex flex-column overflow-hidden">
<gl-dropdown-header class="monitor-environment-dropdown-header text-center">
{{ __('Environment') }}
</gl-dropdown-header>
<gl-dropdown-divider />
<gl-search-box-by-type
ref="monitorEnvironmentsDropdownSearch"
class="m-2"
@input="debouncedEnvironmentsSearch"
/>
<gl-loading-icon
v-if="environmentsLoading"
ref="monitorEnvironmentsDropdownLoading"
:inline="true"
/>
<div v-else class="flex-fill overflow-auto">
<gl-dropdown-item
v-for="environment in filteredEnvironments"
:key="environment.id"
:active="environment.name === currentEnvironmentName"
active-class="is-active"
:href="environment.metrics_path"
>{{ environment.name }}</gl-dropdown-item
>
</div>
<div
v-show="shouldShowEnvironmentsDropdownNoMatchedMsg"
ref="monitorEnvironmentsDropdownMsg"
class="text-secondary no-matches-message"
>
{{ __('No matching results') }}
</div>
</div>
</gl-dropdown>
</div>
<div class="mb-2 pr-2 d-flex d-sm-block">
<date-time-picker
ref="dateTimePicker"
class="flex-grow-1 show-last-dropdown"
data-qa-selector="range_picker_dropdown"
:value="selectedTimeRange"
:options="timeRanges"
@input="onDateTimePickerInput"
@invalid="onDateTimePickerInvalid"
/>
</div>
<div class="mb-2 pr-2 d-flex d-sm-block">
<gl-deprecated-button
ref="refreshDashboardBtn"
v-gl-tooltip
class="flex-grow-1"
variant="default"
:title="s__('Metrics|Refresh dashboard')"
@click="refreshDashboard"
>
<icon name="retry" />
</gl-deprecated-button>
</div>
<div class="flex-grow-1"></div>
<div class="d-sm-flex">
<div v-if="selectedDashboard" class="mb-2 mr-2 d-flex">
<!--
wrapper for tooltip as button can be `disabled`
https://bootstrap-vue.org/docs/components/tooltip#disabled-elements
-->
<div
v-gl-tooltip
class="flex-grow-1"
:title="
selectedDashboard.starred
? $options.i18n.unstarDashboard
: $options.i18n.starDashboard
"
>
<gl-deprecated-button
ref="toggleStarBtn"
class="w-100"
:disabled="isUpdatingStarredValue"
variant="default"
@click="toggleStarredValue()"
>
<gl-icon :name="selectedDashboard.starred ? 'star' : 'star-o'" />
</gl-deprecated-button>
</div>
</div>
<div v-if="showRearrangePanelsBtn" class="mb-2 mr-2 d-flex">
<gl-deprecated-button
:pressed="isRearrangingPanels"
variant="default"
class="flex-grow-1 js-rearrange-button"
@click="toggleRearrangingPanels"
>
{{ __('Arrange charts') }}
</gl-deprecated-button>
</div>
<div v-if="addingMetricsAvailable" class="mb-2 mr-2 d-flex d-sm-block">
<gl-deprecated-button
ref="addMetricBtn"
v-gl-modal="$options.addMetric.modalId"
variant="outline-success"
data-qa-selector="add_metric_button"
class="flex-grow-1"
>
{{ $options.addMetric.title }}
</gl-deprecated-button>
<gl-modal
ref="addMetricModal"
:modal-id="$options.addMetric.modalId"
:title="$options.addMetric.title"
>
<form ref="customMetricsForm" :action="customMetricsPath" method="post">
<custom-metrics-form-fields
:rearrange-panels-available="rearrangePanelsAvailable"
:custom-metrics-available="customMetricsAvailable"
:custom-metrics-path="customMetricsPath"
:validate-query-path="validateQueryPath"
form-operation="post"
@formValidation="setFormValidity"
:external-dashboard-url="externalDashboardUrl"
:has-metrics="hasMetrics"
:is-rearranging-panels="isRearrangingPanels"
:selected-time-range="selectedTimeRange"
@dateTimePickerInvalid="onDateTimePickerInvalid"
@setRearrangingPanels="onSetRearrangingPanels"
/>
</form>
<div slot="modal-footer">
<gl-deprecated-button @click="hideAddMetricModal">
{{ __('Cancel') }}
</gl-deprecated-button>
<gl-deprecated-button
ref="submitCustomMetricsFormBtn"
v-track-event="getAddMetricTrackingOptions()"
:disabled="!formIsValid"
variant="success"
@click="submitCustomMetricsForm"
>
{{ __('Save changes') }}
</gl-deprecated-button>
</div>
</gl-modal>
</div>
<div
v-if="selectedDashboard && selectedDashboard.can_edit"
class="mb-2 mr-2 d-flex d-sm-block"
>
<gl-deprecated-button
class="flex-grow-1 js-edit-link"
:href="selectedDashboard.project_blob_path"
data-qa-selector="edit_dashboard_button"
>
{{ __('Edit dashboard') }}
</gl-deprecated-button>
</div>
<div v-if="externalDashboardUrl.length" class="mb-2 mr-2 d-flex d-sm-block">
<gl-deprecated-button
class="flex-grow-1 js-external-dashboard-link"
variant="primary"
:href="externalDashboardUrl"
target="_blank"
rel="noopener noreferrer"
>
{{ __('View full dashboard') }} <icon name="external-link" />
</gl-deprecated-button>
</div>
</div>
</div>
<variables-section v-if="shouldShowVariablesSection && !showEmptyState" />
<div v-if="!showEmptyState">
<dashboard-panel
......
<script>
import { debounce } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
import {
GlIcon,
GlDeprecatedButton,
GlDropdown,
GlDropdownItem,
GlDropdownHeader,
GlDropdownDivider,
GlModal,
GlLoadingIcon,
GlSearchBoxByType,
GlModalDirective,
GlTooltipDirective,
} from '@gitlab/ui';
import { s__ } from '~/locale';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
import invalidUrl from '~/lib/utils/invalid_url';
import Icon from '~/vue_shared/components/icon.vue';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import DashboardsDropdown from './dashboards_dropdown.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import { getAddMetricTrackingOptions, timeRangeToUrl } from '../utils';
import { timeRanges } from '~/vue_shared/constants';
export default {
components: {
Icon,
GlIcon,
GlDeprecatedButton,
GlDropdown,
GlLoadingIcon,
GlDropdownItem,
GlDropdownHeader,
GlDropdownDivider,
GlSearchBoxByType,
GlModal,
CustomMetricsFormFields,
DateTimePicker,
DashboardsDropdown,
},
directives: {
GlModal: GlModalDirective,
GlTooltip: GlTooltipDirective,
TrackEvent: TrackEventDirective,
},
props: {
defaultBranch: {
type: String,
required: true,
},
rearrangePanelsAvailable: {
type: Boolean,
required: false,
default: false,
},
customMetricsAvailable: {
type: Boolean,
required: false,
default: false,
},
customMetricsPath: {
type: String,
required: false,
default: invalidUrl,
},
validateQueryPath: {
type: String,
required: false,
default: invalidUrl,
},
externalDashboardUrl: {
type: String,
required: false,
default: '',
},
hasMetrics: {
type: Boolean,
required: false,
default: true,
},
isRearrangingPanels: {
type: Boolean,
required: true,
},
selectedTimeRange: {
type: Object,
required: true,
},
},
data() {
return {
formIsValid: null,
};
},
computed: {
...mapState('monitoringDashboard', [
'environmentsLoading',
'currentEnvironmentName',
'isUpdatingStarredValue',
'showEmptyState',
]),
...mapGetters('monitoringDashboard', ['selectedDashboard', 'filteredEnvironments']),
shouldShowEnvironmentsDropdownNoMatchedMsg() {
return !this.environmentsLoading && this.filteredEnvironments.length === 0;
},
addingMetricsAvailable() {
return (
this.customMetricsAvailable &&
!this.showEmptyState &&
// Custom metrics only avaialble on system dashboards because
// they are stored in the database. This can be improved. See:
// https://gitlab.com/gitlab-org/gitlab/-/issues/28241
this.selectedDashboard?.system_dashboard
);
},
showRearrangePanelsBtn() {
return !this.showEmptyState && this.rearrangePanelsAvailable;
},
},
methods: {
...mapActions('monitoringDashboard', [
'filterEnvironments',
'fetchDashboardData',
'toggleStarredValue',
]),
selectDashboard(dashboard) {
const params = {
dashboard: dashboard.path,
};
redirectTo(mergeUrlParams(params, window.location.href));
},
debouncedEnvironmentsSearch: debounce(function environmentsSearchOnInput(searchTerm) {
this.filterEnvironments(searchTerm);
}, 500),
onDateTimePickerInput(timeRange) {
redirectTo(timeRangeToUrl(timeRange));
},
onDateTimePickerInvalid() {
this.$emit('dateTimePickerInvalid');
},
refreshDashboard() {
this.fetchDashboardData();
},
toggleRearrangingPanels() {
this.$emit('setRearrangingPanels', !this.isRearrangingPanels);
},
setFormValidity(isValid) {
this.formIsValid = isValid;
},
hideAddMetricModal() {
this.$refs.addMetricModal.hide();
},
getAddMetricTrackingOptions,
submitCustomMetricsForm() {
this.$refs.customMetricsForm.submit();
},
},
addMetric: {
title: s__('Metrics|Add metric'),
modalId: 'add-metric',
},
i18n: {
starDashboard: s__('Metrics|Star dashboard'),
unstarDashboard: s__('Metrics|Unstar dashboard'),
},
timeRanges,
};
</script>
<template>
<div ref="prometheusGraphsHeader">
<div class="mb-2 pr-2 d-flex d-sm-block">
<dashboards-dropdown
id="monitor-dashboards-dropdown"
data-qa-selector="dashboards_filter_dropdown"
class="flex-grow-1"
toggle-class="dropdown-menu-toggle"
:default-branch="defaultBranch"
@selectDashboard="selectDashboard"
/>
</div>
<div class="mb-2 pr-2 d-flex d-sm-block">
<gl-dropdown
id="monitor-environments-dropdown"
ref="monitorEnvironmentsDropdown"
class="flex-grow-1"
data-qa-selector="environments_dropdown"
toggle-class="dropdown-menu-toggle"
menu-class="monitor-environment-dropdown-menu"
:text="currentEnvironmentName"
>
<div class="d-flex flex-column overflow-hidden">
<gl-dropdown-header class="monitor-environment-dropdown-header text-center">
{{ __('Environment') }}
</gl-dropdown-header>
<gl-dropdown-divider />
<gl-search-box-by-type
ref="monitorEnvironmentsDropdownSearch"
class="m-2"
@input="debouncedEnvironmentsSearch"
/>
<gl-loading-icon
v-if="environmentsLoading"
ref="monitorEnvironmentsDropdownLoading"
:inline="true"
/>
<div v-else class="flex-fill overflow-auto">
<gl-dropdown-item
v-for="environment in filteredEnvironments"
:key="environment.id"
:active="environment.name === currentEnvironmentName"
active-class="is-active"
:href="environment.metrics_path"
>{{ environment.name }}</gl-dropdown-item
>
</div>
<div
v-show="shouldShowEnvironmentsDropdownNoMatchedMsg"
ref="monitorEnvironmentsDropdownMsg"
class="text-secondary no-matches-message"
>
{{ __('No matching results') }}
</div>
</div>
</gl-dropdown>
</div>
<div class="mb-2 pr-2 d-flex d-sm-block">
<date-time-picker
ref="dateTimePicker"
class="flex-grow-1 show-last-dropdown"
data-qa-selector="range_picker_dropdown"
:value="selectedTimeRange"
:options="$options.timeRanges"
@input="onDateTimePickerInput"
@invalid="onDateTimePickerInvalid"
/>
</div>
<div class="mb-2 pr-2 d-flex d-sm-block">
<gl-deprecated-button
ref="refreshDashboardBtn"
v-gl-tooltip
class="flex-grow-1"
variant="default"
:title="s__('Metrics|Refresh dashboard')"
@click="refreshDashboard"
>
<icon name="retry" />
</gl-deprecated-button>
</div>
<div class="flex-grow-1"></div>
<div class="d-sm-flex">
<div v-if="selectedDashboard" class="mb-2 mr-2 d-flex">
<!--
wrapper for tooltip as button can be `disabled`
https://bootstrap-vue.org/docs/components/tooltip#disabled-elements
-->
<div
v-gl-tooltip
class="flex-grow-1"
:title="
selectedDashboard.starred ? $options.i18n.unstarDashboard : $options.i18n.starDashboard
"
>
<gl-deprecated-button
ref="toggleStarBtn"
class="w-100"
:disabled="isUpdatingStarredValue"
variant="default"
@click="toggleStarredValue()"
>
<gl-icon :name="selectedDashboard.starred ? 'star' : 'star-o'" />
</gl-deprecated-button>
</div>
</div>
<div v-if="showRearrangePanelsBtn" class="mb-2 mr-2 d-flex">
<gl-deprecated-button
:pressed="isRearrangingPanels"
variant="default"
class="flex-grow-1 js-rearrange-button"
@click="toggleRearrangingPanels"
>
{{ __('Arrange charts') }}
</gl-deprecated-button>
</div>
<div v-if="addingMetricsAvailable" class="mb-2 mr-2 d-flex d-sm-block">
<gl-deprecated-button
ref="addMetricBtn"
v-gl-modal="$options.addMetric.modalId"
variant="outline-success"
data-qa-selector="add_metric_button"
class="flex-grow-1"
>
{{ $options.addMetric.title }}
</gl-deprecated-button>
<gl-modal
ref="addMetricModal"
:modal-id="$options.addMetric.modalId"
:title="$options.addMetric.title"
>
<form ref="customMetricsForm" :action="customMetricsPath" method="post">
<custom-metrics-form-fields
:validate-query-path="validateQueryPath"
form-operation="post"
@formValidation="setFormValidity"
/>
</form>
<div slot="modal-footer">
<gl-deprecated-button @click="hideAddMetricModal">
{{ __('Cancel') }}
</gl-deprecated-button>
<gl-deprecated-button
ref="submitCustomMetricsFormBtn"
v-track-event="getAddMetricTrackingOptions()"
:disabled="!formIsValid"
variant="success"
@click="submitCustomMetricsForm"
>
{{ __('Save changes') }}
</gl-deprecated-button>
</div>
</gl-modal>
</div>
<div
v-if="selectedDashboard && selectedDashboard.can_edit"
class="mb-2 mr-2 d-flex d-sm-block"
>
<gl-deprecated-button
class="flex-grow-1 js-edit-link"
:href="selectedDashboard.project_blob_path"
data-qa-selector="edit_dashboard_button"
>
{{ __('Edit dashboard') }}
</gl-deprecated-button>
</div>
<div v-if="externalDashboardUrl.length" class="mb-2 mr-2 d-flex d-sm-block">
<gl-deprecated-button
class="flex-grow-1 js-external-dashboard-link"
variant="primary"
:href="externalDashboardUrl"
target="_blank"
rel="noopener noreferrer"
>
{{ __('View full dashboard') }} <icon name="external-link" />
</gl-deprecated-button>
</div>
</div>
</div>
</template>
......@@ -11,6 +11,9 @@ module QA
view 'app/assets/javascripts/monitoring/components/dashboard.vue' do
element :prometheus_graphs
end
view 'app/assets/javascripts/monitoring/components/dashboard_header.vue' do
element :dashboards_filter_dropdown
element :environments_dropdown
element :edit_dashboard_button
......
......@@ -9,6 +9,7 @@ import axios from '~/lib/utils/axios_utils';
import { metricStates } from '~/monitoring/constants';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
......@@ -35,7 +36,8 @@ describe('Dashboard', () => {
let wrapper;
let mock;
const findEnvironmentsDropdown = () => wrapper.find({ ref: 'monitorEnvironmentsDropdown' });
const findEnvironmentsDropdown = () =>
wrapper.find(DashboardHeader).find({ ref: 'monitorEnvironmentsDropdown' });
const findAllEnvironmentsDropdownItems = () => findEnvironmentsDropdown().findAll(GlDropdownItem);
const setSearchTerm = searchTerm => {
store.commit(`monitoringDashboard/${types.SET_ENVIRONMENTS_FILTER}`, searchTerm);
......@@ -45,6 +47,9 @@ describe('Dashboard', () => {
wrapper = shallowMount(Dashboard, {
propsData: { ...propsData, ...props },
store,
stubs: {
DashboardHeader,
},
...options,
});
};
......@@ -53,7 +58,11 @@ describe('Dashboard', () => {
wrapper = mount(Dashboard, {
propsData: { ...propsData, ...props },
store,
stubs: ['graph-group', 'dashboard-panel'],
stubs: {
'graph-group': true,
'dashboard-panel': true,
'dashboard-header': DashboardHeader,
},
...options,
});
};
......@@ -336,7 +345,9 @@ describe('Dashboard', () => {
});
});
it('renders the environments dropdown with a single active element', () => {
// Note: This test is not working, .active does not show the active environment
// eslint-disable-next-line jest/no-disabled-tests
it.skip('renders the environments dropdown with a single active element', () => {
const activeItem = findAllEnvironmentsDropdownItems().wrappers.filter(itemWrapper =>
itemWrapper.find('.active').exists(),
);
......@@ -346,7 +357,7 @@ describe('Dashboard', () => {
});
describe('star dashboards', () => {
const findToggleStar = () => wrapper.find({ ref: 'toggleStarBtn' });
const findToggleStar = () => wrapper.find(DashboardHeader).find({ ref: 'toggleStarBtn' });
const findToggleStarIcon = () => findToggleStar().find(GlIcon);
beforeEach(() => {
......@@ -450,7 +461,7 @@ describe('Dashboard', () => {
setupStoreWithData(store);
return wrapper.vm.$nextTick().then(() => {
const refreshBtn = wrapper.findAll({ ref: 'refreshDashboardBtn' });
const refreshBtn = wrapper.find(DashboardHeader).findAll({ ref: 'refreshDashboardBtn' });
expect(refreshBtn).toHaveLength(1);
expect(refreshBtn.is(GlDeprecatedButton)).toBe(true);
......@@ -621,7 +632,12 @@ describe('Dashboard', () => {
});
it('renders a search input', () => {
expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownSearch' }).exists()).toBe(true);
expect(
wrapper
.find(DashboardHeader)
.find({ ref: 'monitorEnvironmentsDropdownSearch' })
.exists(),
).toBe(true);
});
it('renders dropdown items', () => {
......@@ -657,7 +673,12 @@ describe('Dashboard', () => {
setSearchTerm(searchTerm);
return wrapper.vm.$nextTick(() => {
expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownMsg' }).isVisible()).toBe(true);
expect(
wrapper
.find(DashboardHeader)
.find({ ref: 'monitorEnvironmentsDropdownMsg' })
.isVisible(),
).toBe(true);
});
});
......@@ -667,7 +688,12 @@ describe('Dashboard', () => {
return wrapper.vm
.$nextTick()
.then(() => {
expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownLoading' }).exists()).toBe(true);
expect(
wrapper
.find(DashboardHeader)
.find({ ref: 'monitorEnvironmentsDropdownLoading' })
.exists(),
).toBe(true);
})
.then(() => {
store.commit(
......@@ -676,7 +702,12 @@ describe('Dashboard', () => {
);
})
.then(() => {
expect(wrapper.find({ ref: 'monitorEnvironmentsDropdownLoading' }).exists()).toBe(false);
expect(
wrapper
.find(DashboardHeader)
.find({ ref: 'monitorEnvironmentsDropdownLoading' })
.exists(),
).toBe(false);
});
});
});
......@@ -886,7 +917,8 @@ describe('Dashboard', () => {
});
describe('add custom metrics', () => {
const findAddMetricButton = () => wrapper.vm.$refs.addMetricBtn;
const findAddMetricButton = () => wrapper.find(DashboardHeader).find({ ref: 'addMetricBtn' });
describe('when not available', () => {
beforeEach(() => {
createShallowWrapper({
......@@ -895,7 +927,7 @@ describe('Dashboard', () => {
});
});
it('does not render add button on the dashboard', () => {
expect(findAddMetricButton()).toBeUndefined();
expect(findAddMetricButton().exists()).toBe(false);
});
});
......@@ -928,10 +960,9 @@ describe('Dashboard', () => {
expect(wrapper.find(GlModal).attributes().modalid).toBe('add-metric');
});
it('adding new metric is tracked', done => {
const submitButton = wrapper.vm.$refs.submitCustomMetricsFormBtn;
wrapper.setData({
formIsValid: true,
});
const submitButton = wrapper
.find(DashboardHeader)
.find({ ref: 'submitCustomMetricsFormBtn' }).vm;
wrapper.vm.$nextTick(() => {
submitButton.$el.click();
wrapper.vm.$nextTick(() => {
......
......@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import { createStore } from '~/monitoring/stores';
import { setupAllDashboards } from '../store_utils';
import { propsData } from '../mock_data';
......@@ -27,7 +28,13 @@ describe('Dashboard template', () => {
});
it('matches the default snapshot', () => {
wrapper = shallowMount(Dashboard, { propsData: { ...propsData }, store });
wrapper = shallowMount(Dashboard, {
propsData: { ...propsData },
store,
stubs: {
DashboardHeader,
},
});
expect(wrapper.element).toMatchSnapshot();
});
......
......@@ -12,6 +12,7 @@ import axios from '~/lib/utils/axios_utils';
import { mockProjectDir, propsData } from '../mock_data';
import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import { createStore } from '~/monitoring/stores';
import { defaultTimeRange } from '~/vue_shared/constants';
......@@ -27,12 +28,12 @@ describe('dashboard invalid url parameters', () => {
wrapper = mount(Dashboard, {
propsData: { ...propsData, ...props },
store,
stubs: ['graph-group', 'dashboard-panel'],
stubs: { 'graph-group': true, 'dashboard-panel': true, 'dashboard-header': DashboardHeader },
...options,
});
};
const findDateTimePicker = () => wrapper.find({ ref: 'dateTimePicker' });
const findDateTimePicker = () => wrapper.find(DashboardHeader).find({ ref: 'dateTimePicker' });
beforeEach(() => {
store = createStore();
......
......@@ -52,7 +52,6 @@ export const initialState = () => ({
dashboard: {
panel_groups: [],
},
useDashboardEndpoint: true,
});
export const initialEmbedGroupState = () => ({
......
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