Commit fa237c9a authored by Zack Cuddy's avatar Zack Cuddy

Update Geo Status Design

This change updates the UI for the
Geo Node Status.

Adds light backround and darker text.

Also re-writes the spec for Geo Node Health.
parent 57bfac17
...@@ -26,9 +26,12 @@ export default { ...@@ -26,9 +26,12 @@ export default {
<template> <template>
<div class="mt-2 detail-section-item"> <div class="mt-2 detail-section-item">
<div class="text-secondary-700 node-detail-title">{{ s__('GeoNodes|Health status') }}</div> <div class="text-secondary-700 node-detail-title">{{ s__('GeoNodes|Health status') }}</div>
<div :class="healthCssClass" class="mt-1 d-flex align-items-center node-health-status"> <div
:class="healthCssClass"
class="rounded-pill d-inline-flex align-items-center px-2 py-1 mt-1"
>
<icon :size="16" :name="statusIconName" /> <icon :size="16" :name="statusIconName" />
<span class="status-text ml-2"> {{ status }} </span> <span class="status-text ml-1 bold"> {{ status }} </span>
</div> </div>
</div> </div>
</template> </template>
...@@ -19,16 +19,16 @@ export const HEALTH_STATUS_ICON = { ...@@ -19,16 +19,16 @@ export const HEALTH_STATUS_ICON = {
healthy: 'status_success', healthy: 'status_success',
unhealthy: 'status_failed', unhealthy: 'status_failed',
disabled: 'status_canceled', disabled: 'status_canceled',
unknown: 'status_warning', unknown: 'status_notfound',
offline: 'status_canceled', offline: 'status_canceled',
}; };
export const HEALTH_STATUS_CLASS = { export const HEALTH_STATUS_CLASS = {
healthy: 'text-success-500', healthy: 'text-success-600 bg-success-100',
unhealthy: 'text-danger-500', unhealthy: 'text-danger-600 bg-danger-100',
disabled: 'text-secondary-950', disabled: 'text-secondary-800 bg-secondary-100',
unknown: 'cdark', unknown: 'text-secondary-800 bg-secondary-100',
offline: 'cdark', offline: 'text-secondary-800 bg-secondary-100',
}; };
export const TIME_DIFF = { export const TIME_DIFF = {
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`GeoNodeHealthStatusComponent computed properties renders Icon correctly 1`] = `"<icon-stub name=\\"status_success\\" size=\\"16\\"></icon-stub>"`;
exports[`GeoNodeHealthStatusComponent computed properties renders Icon correctly 2`] = `"<icon-stub name=\\"status_failed\\" size=\\"16\\"></icon-stub>"`;
exports[`GeoNodeHealthStatusComponent computed properties renders Icon correctly 3`] = `"<icon-stub name=\\"status_canceled\\" size=\\"16\\"></icon-stub>"`;
exports[`GeoNodeHealthStatusComponent computed properties renders Icon correctly 4`] = `"<icon-stub name=\\"status_notfound\\" size=\\"16\\"></icon-stub>"`;
exports[`GeoNodeHealthStatusComponent computed properties renders Icon correctly 5`] = `"<icon-stub name=\\"status_canceled\\" size=\\"16\\"></icon-stub>"`;
exports[`GeoNodeHealthStatusComponent computed properties renders StatusPill correctly 1`] = `
"<div class=\\"rounded-pill d-inline-flex align-items-center px-2 py-1 mt-1 text-success-600 bg-success-100\\">
<icon-stub name=\\"status_success\\" size=\\"16\\"></icon-stub> <span class=\\"status-text ml-1 bold\\"> Healthy </span>
</div>"
`;
exports[`GeoNodeHealthStatusComponent computed properties renders StatusPill correctly 2`] = `
"<div class=\\"rounded-pill d-inline-flex align-items-center px-2 py-1 mt-1 text-danger-600 bg-danger-100\\">
<icon-stub name=\\"status_failed\\" size=\\"16\\"></icon-stub> <span class=\\"status-text ml-1 bold\\"> Unhealthy </span>
</div>"
`;
exports[`GeoNodeHealthStatusComponent computed properties renders StatusPill correctly 3`] = `
"<div class=\\"rounded-pill d-inline-flex align-items-center px-2 py-1 mt-1 text-secondary-800 bg-secondary-100\\">
<icon-stub name=\\"status_canceled\\" size=\\"16\\"></icon-stub> <span class=\\"status-text ml-1 bold\\"> Disabled </span>
</div>"
`;
exports[`GeoNodeHealthStatusComponent computed properties renders StatusPill correctly 4`] = `
"<div class=\\"rounded-pill d-inline-flex align-items-center px-2 py-1 mt-1 text-secondary-800 bg-secondary-100\\">
<icon-stub name=\\"status_notfound\\" size=\\"16\\"></icon-stub> <span class=\\"status-text ml-1 bold\\"> Unknown </span>
</div>"
`;
exports[`GeoNodeHealthStatusComponent computed properties renders StatusPill correctly 5`] = `
"<div class=\\"rounded-pill d-inline-flex align-items-center px-2 py-1 mt-1 text-secondary-800 bg-secondary-100\\">
<icon-stub name=\\"status_canceled\\" size=\\"16\\"></icon-stub> <span class=\\"status-text ml-1 bold\\"> Offline </span>
</div>"
`;
import Vue from 'vue'; import { shallowMount } from '@vue/test-utils';
import Icon from '~/vue_shared/components/icon.vue';
import geoNodeHealthStatusComponent from 'ee/geo_nodes/components/geo_node_health_status.vue'; import geoNodeHealthStatusComponent from 'ee/geo_nodes/components/geo_node_health_status.vue';
import { HEALTH_STATUS_ICON, HEALTH_STATUS_CLASS } from 'ee/geo_nodes/constants'; import { HEALTH_STATUS_ICON, HEALTH_STATUS_CLASS } from 'ee/geo_nodes/constants';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockNodeDetails } from '../mock_data'; import { mockNodeDetails } from '../mock_data';
const createComponent = (status = mockNodeDetails.health) => {
const Component = Vue.extend(geoNodeHealthStatusComponent);
return mountComponent(Component, {
status,
});
};
describe('GeoNodeHealthStatusComponent', () => { describe('GeoNodeHealthStatusComponent', () => {
describe('computed', () => { let wrapper;
describe('healthCssClass', () => {
it('returns CSS class representing `status` prop value', () => {
const vm = createComponent('healthy');
expect(vm.healthCssClass).toBe(HEALTH_STATUS_CLASS.healthy);
vm.$destroy();
});
});
describe('statusIconName', () => {
it('returns icon name representing `status` prop value', () => {
let vm = createComponent('healthy');
expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.healthy);
vm.$destroy();
vm = createComponent('unhealthy');
expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.unhealthy); const defaultProps = {
vm.$destroy(); status: mockNodeDetails.health,
};
vm = createComponent('disabled'); const createComponent = (props = {}) => {
wrapper = shallowMount(geoNodeHealthStatusComponent, {
expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.disabled); propsData: {
vm.$destroy(); ...defaultProps,
...props,
vm = createComponent('unknown'); },
});
};
expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.unknown); afterEach(() => {
vm.$destroy(); wrapper.destroy();
wrapper = null;
});
vm = createComponent('offline'); const findStatusPill = () => wrapper.find('.rounded-pill');
const findStatusIcon = () => findStatusPill().find(Icon);
expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.offline); describe.each`
vm.$destroy(); status | healthCssClass | statusIconName
}); ${'Healthy'} | ${HEALTH_STATUS_CLASS.healthy} | ${HEALTH_STATUS_ICON.healthy}
${'Unhealthy'} | ${HEALTH_STATUS_CLASS.unhealthy} | ${HEALTH_STATUS_ICON.unhealthy}
${'Disabled'} | ${HEALTH_STATUS_CLASS.disabled} | ${HEALTH_STATUS_ICON.disabled}
${'Unknown'} | ${HEALTH_STATUS_CLASS.unknown} | ${HEALTH_STATUS_ICON.unknown}
${'Offline'} | ${HEALTH_STATUS_CLASS.offline} | ${HEALTH_STATUS_ICON.offline}
`(`computed properties`, ({ status, healthCssClass, statusIconName }) => {
beforeEach(() => {
createComponent({ status });
}); });
});
describe('template', () => {
it('renders container elements correctly', () => {
const vm = createComponent('Healthy');
expect(vm.$el.classList.contains('detail-section-item')).toBe(true); it(`sets background of StatusPill to ${healthCssClass} when status is ${status}`, () => {
expect(vm.$el.querySelector('.node-detail-title').innerText.trim()).toBe('Health status'); expect(
findStatusPill()
.classes()
.join(' '),
).toContain(healthCssClass);
});
const iconContainerEl = vm.$el.querySelector('.node-health-status'); it('renders StatusPill correctly', () => {
expect(findStatusPill().html()).toMatchSnapshot();
});
expect(iconContainerEl).not.toBeNull(); it(`sets StatusIcon to ${statusIconName} when status is ${status}`, () => {
expect(iconContainerEl.querySelector('svg use').getAttribute('xlink:href')).toContain( expect(findStatusIcon().attributes('name')).toBe(statusIconName);
'#status_success', });
);
expect(iconContainerEl.querySelector('.status-text').innerText.trim()).toBe('Healthy'); it('renders Icon correctly', () => {
vm.$destroy(); expect(findStatusIcon().html()).toMatchSnapshot();
}); });
}); });
}); });
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