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 {
<template>
<div class="mt-2 detail-section-item">
<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" />
<span class="status-text ml-2"> {{ status }} </span>
<span class="status-text ml-1 bold"> {{ status }} </span>
</div>
</div>
</template>
......@@ -19,16 +19,16 @@ export const HEALTH_STATUS_ICON = {
healthy: 'status_success',
unhealthy: 'status_failed',
disabled: 'status_canceled',
unknown: 'status_warning',
unknown: 'status_notfound',
offline: 'status_canceled',
};
export const HEALTH_STATUS_CLASS = {
healthy: 'text-success-500',
unhealthy: 'text-danger-500',
disabled: 'text-secondary-950',
unknown: 'cdark',
offline: 'cdark',
healthy: 'text-success-600 bg-success-100',
unhealthy: 'text-danger-600 bg-danger-100',
disabled: 'text-secondary-800 bg-secondary-100',
unknown: 'text-secondary-800 bg-secondary-100',
offline: 'text-secondary-800 bg-secondary-100',
};
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 { HEALTH_STATUS_ICON, HEALTH_STATUS_CLASS } from 'ee/geo_nodes/constants';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockNodeDetails } from '../mock_data';
const createComponent = (status = mockNodeDetails.health) => {
const Component = Vue.extend(geoNodeHealthStatusComponent);
return mountComponent(Component, {
status,
});
};
describe('GeoNodeHealthStatusComponent', () => {
describe('computed', () => {
describe('healthCssClass', () => {
it('returns CSS class representing `status` prop value', () => {
const vm = createComponent('healthy');
expect(vm.healthCssClass).toBe(HEALTH_STATUS_CLASS.healthy);
vm.$destroy();
});
let wrapper;
const defaultProps = {
status: mockNodeDetails.health,
};
const createComponent = (props = {}) => {
wrapper = shallowMount(geoNodeHealthStatusComponent, {
propsData: {
...defaultProps,
...props,
},
});
};
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);
vm.$destroy();
vm = createComponent('disabled');
expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.disabled);
vm.$destroy();
vm = createComponent('unknown');
expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.unknown);
vm.$destroy();
vm = createComponent('offline');
expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.offline);
vm.$destroy();
});
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('template', () => {
it('renders container elements correctly', () => {
const vm = createComponent('Healthy');
const findStatusPill = () => wrapper.find('.rounded-pill');
const findStatusIcon = () => findStatusPill().find(Icon);
describe.each`
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 });
});
expect(vm.$el.classList.contains('detail-section-item')).toBe(true);
expect(vm.$el.querySelector('.node-detail-title').innerText.trim()).toBe('Health status');
it(`sets background of StatusPill to ${healthCssClass} when status is ${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();
expect(iconContainerEl.querySelector('svg use').getAttribute('xlink:href')).toContain(
'#status_success',
);
it(`sets StatusIcon to ${statusIconName} when status is ${status}`, () => {
expect(findStatusIcon().attributes('name')).toBe(statusIconName);
});
expect(iconContainerEl.querySelector('.status-text').innerText.trim()).toBe('Healthy');
vm.$destroy();
it('renders Icon correctly', () => {
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