Commit e015edfc authored by svistas's avatar svistas

Expand the dashbord fixture to include metrics data

Prior to this change, the dashboard fixture
was only generating the dashboard json
to feed to the integration specs.

This change allows to make the tests
more dynamic by introducing the metrics data
too and avoid a hardcoded fixture to mantain.

Apply diff and update snapshot

Rename to dashboardProps

Fix CI issues
parent 4a8e1e7a
...@@ -353,7 +353,10 @@ export default { ...@@ -353,7 +353,10 @@ export default {
</gl-deprecated-button> </gl-deprecated-button>
</div> </div>
<div v-if="externalDashboardUrl.length" class="mb-2 mr-2 d-flex d-sm-block"> <div
v-if="externalDashboardUrl && externalDashboardUrl.length"
class="mb-2 mr-2 d-flex d-sm-block"
>
<gl-deprecated-button <gl-deprecated-button
class="flex-grow-1 js-external-dashboard-link" class="flex-grow-1 js-external-dashboard-link"
variant="primary" variant="primary"
......
import Vue from 'vue'; import Vue from 'vue';
import { GlToast } from '@gitlab/ui'; import { GlToast } from '@gitlab/ui';
import { parseBoolean } from '~/lib/utils/common_utils';
import { getParameterValues } from '~/lib/utils/url_utility'; import { getParameterValues } from '~/lib/utils/url_utility';
import { createStore } from './stores'; import { createStore } from './stores';
import createRouter from './router'; import createRouter from './router';
import { stateAndPropsFromDataset } from './utils';
Vue.use(GlToast); Vue.use(GlToast);
...@@ -12,37 +12,10 @@ export default (props = {}) => { ...@@ -12,37 +12,10 @@ export default (props = {}) => {
if (el && el.dataset) { if (el && el.dataset) {
const [currentDashboard] = getParameterValues('dashboard'); const [currentDashboard] = getParameterValues('dashboard');
const { metricsDashboardBasePath, ...dataset } = el.dataset;
const { const { initState, dataProps } = stateAndPropsFromDataset({ currentDashboard, ...dataset });
deploymentsEndpoint, const store = createStore(initState);
dashboardEndpoint,
dashboardsEndpoint,
projectPath,
logsPath,
currentEnvironmentName,
dashboardTimezone,
metricsDashboardBasePath,
customDashboardBasePath,
...dataProps
} = el.dataset;
const store = createStore({
currentDashboard,
deploymentsEndpoint,
dashboardEndpoint,
dashboardsEndpoint,
dashboardTimezone,
projectPath,
logsPath,
currentEnvironmentName,
customDashboardBasePath,
});
// HTML attributes are always strings, parse other types.
dataProps.hasMetrics = parseBoolean(dataProps.hasMetrics);
dataProps.customMetricsAvailable = parseBoolean(dataProps.customMetricsAvailable);
dataProps.prometheusAlertsAvailable = parseBoolean(dataProps.prometheusAlertsAvailable);
const router = createRouter(metricsDashboardBasePath); const router = createRouter(metricsDashboardBasePath);
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
......
...@@ -5,6 +5,7 @@ import { ...@@ -5,6 +5,7 @@ import {
removeParams, removeParams,
updateHistory, updateHistory,
} from '~/lib/utils/url_utility'; } from '~/lib/utils/url_utility';
import { parseBoolean } from '~/lib/utils/common_utils';
import { import {
timeRangeParamNames, timeRangeParamNames,
timeRangeFromParams, timeRangeFromParams,
...@@ -12,6 +13,46 @@ import { ...@@ -12,6 +13,46 @@ import {
} from '~/lib/utils/datetime_range'; } from '~/lib/utils/datetime_range';
import { VARIABLE_PREFIX } from './constants'; import { VARIABLE_PREFIX } from './constants';
/**
* Extracts the initial state and props from HTML dataset
* and places them in separate objects to setup bundle.
* @param {*} dataset
*/
export const stateAndPropsFromDataset = (dataset = {}) => {
const {
currentDashboard,
deploymentsEndpoint,
dashboardEndpoint,
dashboardsEndpoint,
dashboardTimezone,
projectPath,
logsPath,
currentEnvironmentName,
customDashboardBasePath,
...dataProps
} = dataset;
// HTML attributes are always strings, parse other types.
dataProps.hasMetrics = parseBoolean(dataProps.hasMetrics);
dataProps.customMetricsAvailable = parseBoolean(dataProps.customMetricsAvailable);
dataProps.prometheusAlertsAvailable = parseBoolean(dataProps.prometheusAlertsAvailable);
return {
initState: {
currentDashboard,
deploymentsEndpoint,
dashboardEndpoint,
dashboardsEndpoint,
dashboardTimezone,
projectPath,
logsPath,
currentEnvironmentName,
customDashboardBasePath,
},
dataProps,
};
};
/** /**
* List of non time range url parameters * List of non time range url parameters
* This will be removed once we add support for free text variables * This will be removed once we add support for free text variables
......
...@@ -6,10 +6,11 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do ...@@ -6,10 +6,11 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers include JavaScriptFixturesHelpers
include MetricsDashboardHelpers include MetricsDashboardHelpers
let(:user) { create(:user) } let_it_be(:user) { create(:user) }
let(:project) { project_with_dashboard('.gitlab/dashboards/test.yml') } let_it_be(:namespace) { create(:namespace, name: 'monitoring' )}
let(:environment) { create(:environment, project: project) } let_it_be(:project) { project_with_dashboard_namespace('.gitlab/dashboards/test.yml', namespace: namespace) }
let(:params) { { environment: environment } } let_it_be(:environment) { create(:environment, id: 1, project: project) }
let_it_be(:params) { { environment: environment } }
before(:all) do before(:all) do
clean_frontend_fixtures('metrics_dashboard/') clean_frontend_fixtures('metrics_dashboard/')
...@@ -24,6 +25,7 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do ...@@ -24,6 +25,7 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do
project.add_maintainer(user) project.add_maintainer(user)
allow(controller).to receive(:project).and_return(project) allow(controller).to receive(:project).and_return(project)
allow(controller).to receive(:environment).and_return(environment)
allow(controller) allow(controller)
.to receive(:metrics_dashboard_params) .to receive(:metrics_dashboard_params)
.and_return(params) .and_return(params)
...@@ -35,7 +37,9 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do ...@@ -35,7 +37,9 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do
it 'metrics_dashboard/environment_metrics_dashboard.json' do it 'metrics_dashboard/environment_metrics_dashboard.json' do
routes.draw { get "metrics_dashboard" => "anonymous#metrics_dashboard" } routes.draw { get "metrics_dashboard" => "anonymous#metrics_dashboard" }
response = get :metrics_dashboard, format: :json response = get :metrics_dashboard, format: :json
expect(response).to be_successful expect(response).to be_successful
end end
end end
...@@ -4,6 +4,10 @@ exports[`Dashboard template matches the default snapshot 1`] = ` ...@@ -4,6 +4,10 @@ exports[`Dashboard template matches the default snapshot 1`] = `
<div <div
class="prometheus-graphs" class="prometheus-graphs"
data-qa-selector="prometheus_graphs" data-qa-selector="prometheus_graphs"
environmentstate="available"
metricsdashboardbasepath="/monitoring/monitor-project/-/environments/1/metrics"
metricsendpoint="/monitoring/monitor-project/-/environments/1/additional_metrics.json"
prometheusstatus=""
> >
<div <div
class="prometheus-graphs-header d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 border-bottom bg-gray-light" class="prometheus-graphs-header d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 border-bottom bg-gray-light"
...@@ -135,15 +139,15 @@ exports[`Dashboard template matches the default snapshot 1`] = ` ...@@ -135,15 +139,15 @@ exports[`Dashboard template matches the default snapshot 1`] = `
<!----> <!---->
<empty-state-stub <empty-state-stub
clusterspath="/path/to/clusters" clusterspath="/monitoring/monitor-project/-/clusters"
documentationpath="/path/to/docs" documentationpath="/help/administration/monitoring/prometheus/index.md"
emptygettingstartedsvgpath="/path/to/getting-started.svg" emptygettingstartedsvgpath="/images/illustrations/monitoring/getting_started.svg"
emptyloadingsvgpath="/path/to/loading.svg" emptyloadingsvgpath="/images/illustrations/monitoring/loading.svg"
emptynodatasmallsvgpath="/path/to/no-data-small.svg" emptynodatasmallsvgpath="/images/illustrations/chart-empty-state-small.svg"
emptynodatasvgpath="/path/to/no-data.svg" emptynodatasvgpath="/images/illustrations/monitoring/no_data.svg"
emptyunabletoconnectsvgpath="/path/to/unable-to-connect.svg" emptyunabletoconnectsvgpath="/images/illustrations/monitoring/unable_to_connect.svg"
selectedstate="gettingStarted" selectedstate="gettingStarted"
settingspath="/path/to/settings" settingspath="/monitoring/monitor-project/-/services/prometheus/edit"
/> />
</div> </div>
`; `;
...@@ -18,8 +18,8 @@ import { ...@@ -18,8 +18,8 @@ import {
singleStatMetricsResult, singleStatMetricsResult,
graphDataPrometheusQueryRangeMultiTrack, graphDataPrometheusQueryRangeMultiTrack,
barMockData, barMockData,
propsData,
} from '../mock_data'; } from '../mock_data';
import { dashboardProps, graphData, graphDataEmpty } from '../fixture_data';
import { panelTypes } from '~/monitoring/constants'; import { panelTypes } from '~/monitoring/constants';
...@@ -32,7 +32,6 @@ import MonitorColumnChart from '~/monitoring/components/charts/column.vue'; ...@@ -32,7 +32,6 @@ import MonitorColumnChart from '~/monitoring/components/charts/column.vue';
import MonitorBarChart from '~/monitoring/components/charts/bar.vue'; import MonitorBarChart from '~/monitoring/components/charts/bar.vue';
import MonitorStackedColumnChart from '~/monitoring/components/charts/stacked_column.vue'; import MonitorStackedColumnChart from '~/monitoring/components/charts/stacked_column.vue';
import { graphData, graphDataEmpty } from '../fixture_data';
import { createStore, monitoringDashboard } from '~/monitoring/stores'; import { createStore, monitoringDashboard } from '~/monitoring/stores';
import { createStore as createEmbedGroupStore } from '~/monitoring/stores/embed_group'; import { createStore as createEmbedGroupStore } from '~/monitoring/stores/embed_group';
...@@ -63,7 +62,7 @@ describe('Dashboard Panel', () => { ...@@ -63,7 +62,7 @@ describe('Dashboard Panel', () => {
wrapper = shallowMount(DashboardPanel, { wrapper = shallowMount(DashboardPanel, {
propsData: { propsData: {
graphData, graphData,
settingsPath: propsData.settingsPath, settingsPath: dashboardProps.settingsPath,
...props, ...props,
}, },
store, store,
...@@ -316,7 +315,7 @@ describe('Dashboard Panel', () => { ...@@ -316,7 +315,7 @@ describe('Dashboard Panel', () => {
return wrapper.vm.$nextTick(() => { return wrapper.vm.$nextTick(() => {
expect(findEditCustomMetricLink().text()).toBe('Edit metrics'); expect(findEditCustomMetricLink().text()).toBe('Edit metrics');
expect(findEditCustomMetricLink().attributes('href')).toBe(propsData.settingsPath); expect(findEditCustomMetricLink().attributes('href')).toBe(dashboardProps.settingsPath);
}); });
}); });
}); });
...@@ -433,7 +432,7 @@ describe('Dashboard Panel', () => { ...@@ -433,7 +432,7 @@ describe('Dashboard Panel', () => {
wrapper = shallowMount(DashboardPanel, { wrapper = shallowMount(DashboardPanel, {
propsData: { propsData: {
clipboardText: exampleText, clipboardText: exampleText,
settingsPath: propsData.settingsPath, settingsPath: dashboardProps.settingsPath,
graphData: { graphData: {
y_label: 'metric', y_label: 'metric',
...graphData, ...graphData,
...@@ -483,7 +482,7 @@ describe('Dashboard Panel', () => { ...@@ -483,7 +482,7 @@ describe('Dashboard Panel', () => {
wrapper = shallowMount(DashboardPanel, { wrapper = shallowMount(DashboardPanel, {
propsData: { propsData: {
graphData, graphData,
settingsPath: propsData.settingsPath, settingsPath: dashboardProps.settingsPath,
namespace: mockNamespace, namespace: mockNamespace,
}, },
store, store,
......
...@@ -29,8 +29,12 @@ import { ...@@ -29,8 +29,12 @@ import {
setupStoreWithVariable, setupStoreWithVariable,
setupStoreWithLinks, setupStoreWithLinks,
} from '../store_utils'; } from '../store_utils';
import { environmentData, dashboardGitResponse, propsData } from '../mock_data'; import { environmentData, dashboardGitResponse } from '../mock_data';
import { metricsDashboardViewModel, metricsDashboardPanelCount } from '../fixture_data'; import {
metricsDashboardViewModel,
metricsDashboardPanelCount,
dashboardProps,
} from '../fixture_data';
import createFlash from '~/flash'; import createFlash from '~/flash';
jest.mock('~/flash'); jest.mock('~/flash');
...@@ -50,7 +54,7 @@ describe('Dashboard', () => { ...@@ -50,7 +54,7 @@ describe('Dashboard', () => {
const createShallowWrapper = (props = {}, options = {}) => { const createShallowWrapper = (props = {}, options = {}) => {
wrapper = shallowMount(Dashboard, { wrapper = shallowMount(Dashboard, {
propsData: { ...propsData, ...props }, propsData: { ...dashboardProps, ...props },
store, store,
stubs: { stubs: {
DashboardHeader, DashboardHeader,
...@@ -61,7 +65,7 @@ describe('Dashboard', () => { ...@@ -61,7 +65,7 @@ describe('Dashboard', () => {
const createMountedWrapper = (props = {}, options = {}) => { const createMountedWrapper = (props = {}, options = {}) => {
wrapper = mount(Dashboard, { wrapper = mount(Dashboard, {
propsData: { ...propsData, ...props }, propsData: { ...dashboardProps, ...props },
store, store,
stubs: { stubs: {
'graph-group': true, 'graph-group': true,
......
...@@ -5,7 +5,7 @@ import Dashboard from '~/monitoring/components/dashboard.vue'; ...@@ -5,7 +5,7 @@ import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue'; import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import { createStore } from '~/monitoring/stores'; import { createStore } from '~/monitoring/stores';
import { setupAllDashboards } from '../store_utils'; import { setupAllDashboards } from '../store_utils';
import { propsData } from '../mock_data'; import { dashboardProps } from '../fixture_data';
jest.mock('~/lib/utils/url_utility'); jest.mock('~/lib/utils/url_utility');
...@@ -29,7 +29,7 @@ describe('Dashboard template', () => { ...@@ -29,7 +29,7 @@ describe('Dashboard template', () => {
it('matches the default snapshot', () => { it('matches the default snapshot', () => {
wrapper = shallowMount(Dashboard, { wrapper = shallowMount(Dashboard, {
propsData: { ...propsData }, propsData: { ...dashboardProps },
store, store,
stubs: { stubs: {
DashboardHeader, DashboardHeader,
......
...@@ -9,7 +9,8 @@ import { ...@@ -9,7 +9,8 @@ import {
updateHistory, updateHistory,
} from '~/lib/utils/url_utility'; } from '~/lib/utils/url_utility';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { mockProjectDir, propsData } from '../mock_data'; import { mockProjectDir } from '../mock_data';
import { dashboardProps } from '../fixture_data';
import Dashboard from '~/monitoring/components/dashboard.vue'; import Dashboard from '~/monitoring/components/dashboard.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue'; import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
...@@ -26,7 +27,7 @@ describe('dashboard invalid url parameters', () => { ...@@ -26,7 +27,7 @@ describe('dashboard invalid url parameters', () => {
const createMountedWrapper = (props = { hasMetrics: true }, options = {}) => { const createMountedWrapper = (props = { hasMetrics: true }, options = {}) => {
wrapper = mount(Dashboard, { wrapper = mount(Dashboard, {
propsData: { ...propsData, ...props }, propsData: { ...dashboardProps, ...props },
store, store,
stubs: { 'graph-group': true, 'dashboard-panel': true, 'dashboard-header': DashboardHeader }, stubs: { 'graph-group': true, 'dashboard-panel': true, 'dashboard-header': DashboardHeader },
...options, ...options,
......
import { stateAndPropsFromDataset } from '~/monitoring/utils';
import { mapToDashboardViewModel } from '~/monitoring/stores/utils'; import { mapToDashboardViewModel } from '~/monitoring/stores/utils';
import { metricStates } from '~/monitoring/constants'; import { metricStates } from '~/monitoring/constants';
import { convertObjectProps } from '~/lib/utils/common_utils';
import { convertToCamelCase } from '~/lib/utils/text_utility';
import { metricsResult } from './mock_data'; import { metricsResult } from './mock_data';
...@@ -8,6 +11,19 @@ export const metricsDashboardResponse = getJSONFixture( ...@@ -8,6 +11,19 @@ export const metricsDashboardResponse = getJSONFixture(
'metrics_dashboard/environment_metrics_dashboard.json', 'metrics_dashboard/environment_metrics_dashboard.json',
); );
export const metricsDashboardPayload = metricsDashboardResponse.dashboard; export const metricsDashboardPayload = metricsDashboardResponse.dashboard;
const datasetState = stateAndPropsFromDataset(
// It's preferable to have props in snake_case, this will be addressed at:
// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33574
convertObjectProps(
// Some props use kebab-case, convert to snake_case first
key => convertToCamelCase(key.replace(/-/g, '_')),
metricsDashboardResponse.metrics_data,
),
);
export const dashboardProps = datasetState.dataProps;
export const metricsDashboardViewModel = mapToDashboardViewModel(metricsDashboardPayload); export const metricsDashboardViewModel = mapToDashboardViewModel(metricsDashboardPayload);
export const metricsDashboardPanelCount = 22; export const metricsDashboardPanelCount = 22;
......
...@@ -11,8 +11,8 @@ import MockAdapter from 'axios-mock-adapter'; ...@@ -11,8 +11,8 @@ import MockAdapter from 'axios-mock-adapter';
import Dashboard from '~/monitoring/components/dashboard.vue'; import Dashboard from '~/monitoring/components/dashboard.vue';
import { createStore } from '~/monitoring/stores'; import { createStore } from '~/monitoring/stores';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { mockApiEndpoint, propsData } from '../mock_data'; import { mockApiEndpoint } from '../mock_data';
import { metricsDashboardPayload } from '../fixture_data'; import { metricsDashboardPayload, dashboardProps } from '../fixture_data';
import { setupStoreWithData } from '../store_utils'; import { setupStoreWithData } from '../store_utils';
const localVue = createLocalVue(); const localVue = createLocalVue();
...@@ -56,7 +56,7 @@ describe('Dashboard', () => { ...@@ -56,7 +56,7 @@ describe('Dashboard', () => {
component = new DashboardComponent({ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'), el: document.querySelector('.prometheus-graphs'),
propsData: { propsData: {
...propsData, ...dashboardProps,
hasMetrics: true, hasMetrics: true,
showPanels: true, showPanels: true,
}, },
......
...@@ -7,6 +7,12 @@ module MetricsDashboardHelpers ...@@ -7,6 +7,12 @@ module MetricsDashboardHelpers
create(:project, :custom_repo, files: { dashboard_path => dashboard_yml }) create(:project, :custom_repo, files: { dashboard_path => dashboard_yml })
end end
def project_with_dashboard_namespace(dashboard_path, dashboard_yml = nil)
dashboard_yml ||= fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')
create(:project, :custom_repo, namespace: namespace, path: 'monitor-project', files: { dashboard_path => dashboard_yml })
end
def delete_project_dashboard(project, user, dashboard_path) def delete_project_dashboard(project, user, dashboard_path)
project.repository.delete_file( project.repository.delete_file(
user, user,
......
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