Commit d2fcec7d authored by Phil Hughes's avatar Phil Hughes

Merge branch 'cleanup-geo_node-nodes-css' into 'master'

Cleanup styles for Geo Node Items

See merge request gitlab-org/gitlab!21269
parents c7fc256d 079d4b89
...@@ -79,53 +79,49 @@ export default { ...@@ -79,53 +79,49 @@ export default {
</script> </script>
<template> <template>
<div class="geo-node-actions"> <div class="d-flex align-items-center justify-content-end geo-node-actions">
<div v-if="isSecondaryNode" class="node-action-container"> <a v-if="isSecondaryNode" :href="node.geoProjectsUrl" class="btn btn-sm mx-1 " target="_blank">
<a :href="node.geoProjectsUrl" class="btn btn-sm btn-node-action" target="_blank"> <icon v-if="!node.current" name="external-link" /> {{ __('Open projects') }}
<icon v-if="!node.current" name="external-link" /> {{ __('Open projects') }} </a>
</a>
</div>
<template v-if="nodeActionsAllowed"> <template v-if="nodeActionsAllowed">
<div v-if="nodeMissingOauth" class="node-action-container"> <button
<button type="button" class="btn btn-default btn-sm btn-node-action" @click="onRepairNode"> v-if="nodeMissingOauth"
{{ s__('Repair authentication') }} type="button"
</button> class="btn btn-sm btn-default mx-1"
</div> @click="onRepairNode"
<div v-if="isToggleAllowed" class="node-action-container"> >
<button {{ s__('Repair authentication') }}
:class="{ </button>
'btn-warning': node.enabled, <button
'btn-success': !node.enabled, v-if="isToggleAllowed"
}" :class="{
type="button" 'btn-warning': node.enabled,
class="btn btn-sm btn-node-action" 'btn-success': !node.enabled,
@click="onToggleNode" }"
> type="button"
<icon :name="nodeToggleIcon" /> class="btn btn-sm mx-1"
{{ nodeToggleLabel }} @click="onToggleNode"
</button> >
</div> <icon :name="nodeToggleIcon" />
<div v-if="nodeEditAllowed" class="node-action-container"> {{ nodeToggleLabel }}
<a :href="node.editPath" class="btn btn-sm btn-node-action"> {{ __('Edit') }} </a> </button>
</div> <a v-if="nodeEditAllowed" :href="node.editPath" class="btn btn-sm mx-1"> {{ __('Edit') }} </a>
<div class="node-action-container"> <button
<button v-if="isSecondaryNode"
v-if="isSecondaryNode" type="button"
type="button" class="btn btn-sm btn-danger mx-1"
class="btn btn-sm btn-node-action btn-danger" @click="onRemoveSecondaryNode"
@click="onRemoveSecondaryNode" >
> {{ __('Remove') }}
{{ __('Remove') }} </button>
</button> <button
<button v-if="!isSecondaryNode"
v-else type="button"
type="button" class="btn btn-sm btn-danger mx-1"
class="btn btn-sm btn-node-action btn-danger" @click="onRemovePrimaryNode"
@click="onRemovePrimaryNode" >
> {{ __('Remove') }}
{{ __('Remove') }} </button>
</button>
</div>
</template> </template>
</div> </div>
</template> </template>
...@@ -126,19 +126,21 @@ export default { ...@@ -126,19 +126,21 @@ export default {
</script> </script>
<template> <template>
<div v-if="!featureDisabled" class="prepend-top-15 prepend-left-10 node-detail-item"> <div v-if="!featureDisabled" class="mt-2 ml-2 node-detail-item">
<div class="node-detail-title"> <div class="d-flex align-items-center text-secondary-700">
<span>{{ itemTitle }}</span> <span class="node-detail-title">{{ itemTitle }}</span>
<icon <icon
v-if="hasHelpInfo" v-if="hasHelpInfo"
v-popover="popoverConfig" v-popover="popoverConfig"
:size="12" :size="12"
class="node-detail-help-text prepend-left-5" class="text-primary-600 ml-1 node-detail-help-text"
name="question" name="question"
/> />
</div> </div>
<div v-if="isValueTypePlain" :class="cssClass" class="node-detail-value">{{ itemValue }}</div> <div v-if="isValueTypePlain" :class="cssClass" class="mt-1 node-detail-value">
<div v-if="isValueTypeGraph" :class="{ 'd-flex': itemValueStale }" class="node-detail-value"> {{ itemValue }}
</div>
<div v-if="isValueTypeGraph" :class="{ 'd-flex': itemValueStale }" class="mt-1">
<stacked-progress-bar <stacked-progress-bar
:css-class="itemValueStale ? 'flex-fill' : ''" :css-class="itemValueStale ? 'flex-fill' : ''"
:success-label="successLabel" :success-label="successLabel"
...@@ -153,7 +155,7 @@ export default { ...@@ -153,7 +155,7 @@ export default {
v-tooltip v-tooltip
:title="itemValueStaleTooltip" :title="itemValueStaleTooltip"
name="time-out" name="time-out"
class="prepend-left-10 detail-value-stale-icon" class="ml-2 text-warning-500"
data-container="body" data-container="body"
/> />
</div> </div>
......
...@@ -66,7 +66,7 @@ export default { ...@@ -66,7 +66,7 @@ export default {
</script> </script>
<template> <template>
<div class="card-body"> <div class="card-body p-0">
<node-details-section-main <node-details-section-main
:node="node" :node="node"
:node-details="nodeDetails" :node-details="nodeDetails"
...@@ -85,8 +85,8 @@ export default { ...@@ -85,8 +85,8 @@ export default {
:node-details="nodeDetails" :node-details="nodeDetails"
:node-type-primary="node.primary" :node-type-primary="node.primary"
/> />
<div v-if="hasError || hasVersionMismatch" class="node-health-message-container"> <div v-if="hasError || hasVersionMismatch">
<p class="node-health-message"> <p class="p-3 mb-0 bg-danger-100 text-danger-500">
{{ errorMessage }} {{ errorMessage }}
<gl-link :href="geoTroubleshootingHelpPath">{{ <gl-link :href="geoTroubleshootingHelpPath">{{
s__('Geo|Please refer to Geo Troubleshooting.') s__('Geo|Please refer to Geo Troubleshooting.')
......
...@@ -39,7 +39,7 @@ export default { ...@@ -39,7 +39,7 @@ export default {
</script> </script>
<template> <template>
<div class="node-detail-value"> <div class="mt-1 node-detail-value">
<template v-if="eventTimeStamp"> <template v-if="eventTimeStamp">
<strong> {{ eventString }} </strong> <strong> {{ eventString }} </strong>
<span <span
......
...@@ -42,11 +42,10 @@ export default { ...@@ -42,11 +42,10 @@ export default {
return this.isNodeHTTP || this.nodeDetailsFailed; return this.isNodeHTTP || this.nodeDetailsFailed;
}, },
nodeStatusIconClass() { nodeStatusIconClass() {
const iconClasses = 'prepend-left-10 node-status-icon'; return [
if (this.nodeDetailsFailed) { 'ml-2',
return `${iconClasses} status-icon-failure`; { 'text-danger-500': this.nodeDetailsFailed, 'text-warning-500': !this.nodeDetailsFailed },
} ];
return `${iconClasses} status-icon-warning`;
}, },
nodeStatusIconName() { nodeStatusIconName() {
if (this.nodeDetailsFailed) { if (this.nodeDetailsFailed) {
...@@ -70,7 +69,7 @@ export default { ...@@ -70,7 +69,7 @@ export default {
<div class="card-header"> <div class="card-header">
<div class="row"> <div class="row">
<div class="col-md-8 clearfix"> <div class="col-md-8 clearfix">
<span class="d-flex float-left append-right-10"> <span class="d-flex align-items-center float-left append-right-10">
<strong class="node-url"> {{ node.url }} </strong> <strong class="node-url"> {{ node.url }} </strong>
<gl-loading-icon <gl-loading-icon
v-if="nodeDetailsLoading || node.nodeActionActive" v-if="nodeDetailsLoading || node.nodeActionActive"
...@@ -87,11 +86,17 @@ export default { ...@@ -87,11 +86,17 @@ export default {
data-placement="bottom" data-placement="bottom"
/> />
</span> </span>
<span class="inline node-type-badges"> <span class="inline">
<span v-if="node.current" class="node-badge current-node"> <span
v-if="node.current"
class="rounded-pill gl-font-size-12 p-1 text-white bg-success-400"
>
{{ s__('Current node') }} {{ s__('Current node') }}
</span> </span>
<span v-if="node.primary" class="prepend-left-5 node-badge primary-node"> <span
v-if="node.primary"
class="ml-1 rounded-pill gl-font-size-12 p-1 text-white bg-primary-600"
>
{{ s__('Primary') }} {{ s__('Primary') }}
</span> </span>
</span> </span>
......
<script> <script>
import icon from '~/vue_shared/components/icon.vue'; import icon from '~/vue_shared/components/icon.vue';
import { HEALTH_STATUS_ICON } from '../constants'; import { HEALTH_STATUS_ICON, HEALTH_STATUS_CLASS } from '../constants';
export default { export default {
components: { components: {
...@@ -14,7 +14,7 @@ export default { ...@@ -14,7 +14,7 @@ export default {
}, },
computed: { computed: {
healthCssClass() { healthCssClass() {
return `geo-node-${this.status.toLowerCase()}`; return HEALTH_STATUS_CLASS[this.status.toLowerCase()];
}, },
statusIconName() { statusIconName() {
return HEALTH_STATUS_ICON[this.status.toLowerCase()]; return HEALTH_STATUS_ICON[this.status.toLowerCase()];
...@@ -24,11 +24,11 @@ export default { ...@@ -24,11 +24,11 @@ export default {
</script> </script>
<template> <template>
<div class="prepend-top-15 detail-section-item"> <div class="mt-2 detail-section-item">
<div class="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="node-detail-value node-health-status"> <div :class="healthCssClass" class="mt-1 d-flex align-items-center node-health-status">
<icon :size="16" :name="statusIconName" /> <icon :size="16" :name="statusIconName" />
<span class="status-text prepend-left-5"> {{ status }} </span> <span class="status-text ml-2"> {{ status }} </span>
</div> </div>
</div> </div>
</template> </template>
...@@ -78,7 +78,7 @@ export default { ...@@ -78,7 +78,7 @@ export default {
</script> </script>
<template> <template>
<div :class="{ 'node-action-active': node.nodeActionActive }" class="card geo-node-item"> <div :class="{ 'node-action-active': node.nodeActionActive }" class="card">
<geo-node-header <geo-node-header
:node="node" :node="node"
:node-details="nodeDetails" :node-details="nodeDetails"
...@@ -93,8 +93,8 @@ export default { ...@@ -93,8 +93,8 @@ export default {
:node-actions-allowed="nodeActionsAllowed" :node-actions-allowed="nodeActionsAllowed"
:geo-troubleshooting-help-path="geoTroubleshootingHelpPath" :geo-troubleshooting-help-path="geoTroubleshootingHelpPath"
/> />
<div v-if="isNodeDetailsFailed" class="node-health-message-container"> <div v-if="isNodeDetailsFailed">
<p class="node-health-message"> <p class="p-3 mb-0 bg-danger-100 text-danger-500">
{{ errorMessage {{ errorMessage
}}<gl-link :href="geoTroubleshootingHelpPath">{{ }}<gl-link :href="geoTroubleshootingHelpPath">{{
s__('Geo|Please refer to Geo Troubleshooting.') s__('Geo|Please refer to Geo Troubleshooting.')
......
...@@ -108,18 +108,18 @@ export default { ...@@ -108,18 +108,18 @@ export default {
</script> </script>
<template> <template>
<div class="node-detail-value"> <div class="mt-1 node-sync-settings">
<span v-if="syncStatusUnavailable" class="node-detail-value-bold"> {{ __('Unknown') }} </span> <strong v-if="syncStatusUnavailable"> {{ __('Unknown') }} </strong>
<span <span
v-else v-else
v-tooltip v-tooltip
:title="syncStatusTooltip" :title="syncStatusTooltip"
class="node-sync-settings" class="d-flex align-items-center"
data-placement="bottom" data-placement="bottom"
> >
<strong>{{ syncType }}</strong> <strong>{{ syncType }}</strong>
<icon name="retry" class="sync-status-icon prepend-left-5" /> <icon name="retry" class="ml-2" />
<span v-if="!eventTimestampEmpty" class="sync-status-event-info prepend-left-5"> <span v-if="!eventTimestampEmpty" class="ml-2">
{{ syncStatusEventInfo }} {{ syncStatusEventInfo }}
</span> </span>
</span> </span>
......
...@@ -46,13 +46,13 @@ export default { ...@@ -46,13 +46,13 @@ export default {
</script> </script>
<template> <template>
<div class="row-fluid clearfix node-detail-section primary-section"> <div class="row-fluid clearfix py-3 primary-section">
<div class="col-md-8 section-items-container"> <div class="col-md-8">
<div class="detail-section-item node-version"> <div>
<div class="node-detail-title">{{ s__('GeoNodes|GitLab version') }}</div> <div class="text-secondary-700 node-detail-title">{{ s__('GeoNodes|GitLab version') }}</div>
<div <div
:class="{ 'node-detail-value-error': versionMismatch }" :class="{ 'text-danger-500': versionMismatch }"
class="node-detail-value node-detail-value-bold" class="mt-1 font-weight-bold node-detail-value"
> >
{{ nodeVersion }} {{ nodeVersion }}
</div> </div>
......
...@@ -54,7 +54,7 @@ export default { ...@@ -54,7 +54,7 @@ export default {
itemTitle: s__('GeoNodes|Replication slot WAL'), itemTitle: s__('GeoNodes|Replication slot WAL'),
itemValue: numberToHumanSize(this.nodeDetails.replicationSlotWAL), itemValue: numberToHumanSize(this.nodeDetails.replicationSlotWAL),
itemValueType: VALUE_TYPE.PLAIN, itemValueType: VALUE_TYPE.PLAIN,
cssClass: 'node-detail-value-bold', cssClass: 'font-weight-bold',
}); });
} }
...@@ -63,7 +63,7 @@ export default { ...@@ -63,7 +63,7 @@ export default {
itemTitle: s__('GeoNodes|Internal URL'), itemTitle: s__('GeoNodes|Internal URL'),
itemValue: this.node.internalUrl, itemValue: this.node.internalUrl,
itemValueType: VALUE_TYPE.PLAIN, itemValueType: VALUE_TYPE.PLAIN,
cssClass: 'node-detail-value-bold', cssClass: 'font-weight-bold',
}); });
} }
...@@ -76,7 +76,7 @@ export default { ...@@ -76,7 +76,7 @@ export default {
itemTitle: s__('GeoNodes|Storage config'), itemTitle: s__('GeoNodes|Storage config'),
itemValue: this.storageShardsStatus, itemValue: this.storageShardsStatus,
itemValueType: VALUE_TYPE.PLAIN, itemValueType: VALUE_TYPE.PLAIN,
cssClass: this.storageShardsCssClass, cssClass: this.storageShardsCssClass.join(' '),
}, },
]; ];
}, },
...@@ -89,10 +89,7 @@ export default { ...@@ -89,10 +89,7 @@ export default {
: s__('GeoNodes|Does not match the primary storage configuration'); : s__('GeoNodes|Does not match the primary storage configuration');
}, },
storageShardsCssClass() { storageShardsCssClass() {
const cssClass = 'node-detail-value-bold'; return ['font-weight-bold', { 'text-danger-500': !this.nodeDetails.storageShardsMatch }];
return !this.nodeDetails.storageShardsMatch
? `${cssClass} node-detail-value-error`
: cssClass;
}, },
}, },
methods: { methods: {
...@@ -104,17 +101,14 @@ export default { ...@@ -104,17 +101,14 @@ export default {
</script> </script>
<template> <template>
<div class="row-fluid clearfix node-detail-section other-section"> <div class="row-fluid clearfix py-3 border-top border-color-default other-section">
<div class="col-md-12"> <div class="col-md-12">
<section-reveal-button <section-reveal-button
:button-title="__('Other information')" :button-title="__('Other information')"
@toggleButton="handleSectionToggle" @toggleButton="handleSectionToggle"
/> />
</div> </div>
<div <div v-if="showSectionItems" class="col-md-6 ml-2 mt-2 section-items-container">
v-show="showSectionItems"
class="col-md-6 prepend-left-15 prepend-top-10 section-items-container"
>
<geo-node-detail-item <geo-node-detail-item
v-for="(nodeDetailItem, index) in nodeDetailItems" v-for="(nodeDetailItem, index) in nodeDetailItems"
:key="index" :key="index"
......
...@@ -130,17 +130,14 @@ export default { ...@@ -130,17 +130,14 @@ export default {
</script> </script>
<template> <template>
<div class="row-fluid clearfix node-detail-section sync-section"> <div class="row-fluid clearfix py-3 border-top border-color-default sync-section">
<div class="col-md-12"> <div class="col-md-12">
<section-reveal-button <section-reveal-button
:button-title="__('Sync information')" :button-title="__('Sync information')"
@toggleButton="handleSectionToggle" @toggleButton="handleSectionToggle"
/> />
</div> </div>
<div <div v-if="showSectionItems" class="col-md-6 ml-2 mt-2 section-items-container">
v-show="showSectionItems"
class="col-md-6 prepend-left-15 prepend-top-10 section-items-container"
>
<geo-node-detail-item <geo-node-detail-item
v-for="(nodeDetailItem, index) in nodeDetailItems" v-for="(nodeDetailItem, index) in nodeDetailItems"
:key="index" :key="index"
......
...@@ -113,7 +113,7 @@ export default { ...@@ -113,7 +113,7 @@ export default {
</script> </script>
<template> <template>
<div class="row-fluid clearfix node-detail-section verification-section"> <div class="row-fluid clearfix py-3 border-top border-color-default verification-section">
<div class="col-md-12"> <div class="col-md-12">
<section-reveal-button <section-reveal-button
:button-title="__('Verification information')" :button-title="__('Verification information')"
...@@ -121,7 +121,7 @@ export default { ...@@ -121,7 +121,7 @@ export default {
/> />
</div> </div>
<template v-if="showSectionItems"> <template v-if="showSectionItems">
<div class="col-md-6 prepend-left-15 prepend-top-10 section-items-container"> <div class="col-md-6 ml-2 mt-2 section-items-container">
<geo-node-detail-item <geo-node-detail-item
v-for="(nodeDetailItem, index) in nodeDetailItems" v-for="(nodeDetailItem, index) in nodeDetailItems"
:key="index" :key="index"
......
...@@ -31,7 +31,7 @@ export default { ...@@ -31,7 +31,7 @@ export default {
</script> </script>
<template> <template>
<button class="btn-link btn-show-section" type="button" @click="onClickButton"> <button class="btn-link d-flex align-items-center" type="button" @click="onClickButton">
<icon :size="16" :name="toggleButtonIcon" /> <icon :size="16" :name="toggleButtonIcon" />
<span class="prepend-left-8">{{ buttonTitle }}</span> <span class="prepend-left-8">{{ buttonTitle }}</span>
</button> </button>
......
...@@ -23,6 +23,14 @@ export const HEALTH_STATUS_ICON = { ...@@ -23,6 +23,14 @@ export const HEALTH_STATUS_ICON = {
offline: 'status_canceled', offline: 'status_canceled',
}; };
export const HEALTH_STATUS_CLASS = {
healthy: 'text-success-500',
unhealthy: 'text-danger-500',
disabled: 'text-secondary-950',
unknown: 'cdark',
offline: 'cdark',
};
export const TIME_DIFF = { export const TIME_DIFF = {
FIVE_MINS: 300, FIVE_MINS: 300,
HOUR: 3600, HOUR: 3600,
......
.node-badge { @media (max-width: map-get($grid-breakpoints, sm)) {
color: $white-light; .geo-node-actions {
padding: 1px $gl-padding-8; flex-direction: column;
font-size: $label-font-size; margin: 0 1rem;
border-radius: $label-border-radius;
&.primary-node { .btn-sm {
background-color: $blue-600;
}
&.current-node {
background-color: $green-400;
}
}
.geo-node-healthy {
color: $green-500;
}
.geo-node-unhealthy {
color: $red-500;
}
.geo-node-offline {
color: $gray-950;
}
.geo-node-disabled {
color: $gray-darkest;
}
.geo-node-unknown {
color: $gray-darkest;
}
.geo-node-item {
.node-status-icon {
height: 35px;
}
.status-icon-warning {
fill: $orange-500;
}
.status-icon-failure {
fill: $red-500;
}
.card-body {
padding: 0;
.node-detail-section {
padding: $gl-padding 0;
&.sync-section,
&.verification-section,
&.other-section {
border-top: 1px solid $border-color;
}
.btn-show-section {
padding: 0;
}
}
}
.node-health-message-container {
max-height: $dropdown-max-height;
overflow-y: auto;
.node-health-message {
margin-bottom: 0;
padding: $gl-padding;
background-color: $red-100;
color: $red-500;
}
}
}
.node-detail-section {
.detail-section-item,
.section-items-container {
.node-detail-title {
color: $gray-700;
.node-detail-help-text {
color: $blue-600;
}
.tooltip .tooltip-inner {
text-align: left;
}
}
.node-detail-value {
margin-top: 4px;
}
.detail-value-stale-icon {
color: $orange-500;
}
.node-detail-value-bold {
font-weight: $gl-font-weight-bold;
}
.node-detail-value-error {
color: $red-500;
}
}
.section-items-container {
display: inline-block;
.node-detail-item {
&:first-child {
margin-top: 0;
}
}
@include media-breakpoint-down(sm) {
width: 95%;
}
}
}
.node-detail-title,
.node-health-status,
.node-sync-settings,
.node-detail-section .btn-show-section {
display: flex;
align-items: center;
}
.geo-node-actions {
display: inline-flex;
justify-content: center;
float: right;
.node-action-container {
margin: 0 5px;
&:last-child {
margin-right: $gl-padding;
}
}
@include media-breakpoint-down(sm) {
display: block;
width: 100%;
.node-action-container {
width: 100%;
margin: 0;
margin-top: 10px;
padding: 0 10px;
}
.btn-node-action {
width: 100%; width: 100%;
margin-top: 1rem;
} }
} }
} }
......
...@@ -16,7 +16,7 @@ describe 'admin Geo Nodes', :js, :geo do ...@@ -16,7 +16,7 @@ describe 'admin Geo Nodes', :js, :geo do
wait_for_requests wait_for_requests
expect(page).to have_link('New node', href: new_admin_geo_node_path) expect(page).to have_link('New node', href: new_admin_geo_node_path)
page.within(find('.geo-node-item', match: :first)) do page.within(find('.card', match: :first)) do
expect(page).to have_content(geo_node.url) expect(page).to have_content(geo_node.url)
end end
end end
...@@ -86,7 +86,7 @@ describe 'admin Geo Nodes', :js, :geo do ...@@ -86,7 +86,7 @@ describe 'admin Geo Nodes', :js, :geo do
expect(current_path).to eq admin_geo_nodes_path expect(current_path).to eq admin_geo_nodes_path
wait_for_requests wait_for_requests
page.within(find('.geo-node-item', match: :first)) do page.within(find('.card', match: :first)) do
expect(page).to have_content(geo_node.url) expect(page).to have_content(geo_node.url)
end end
end end
...@@ -167,7 +167,7 @@ describe 'admin Geo Nodes', :js, :geo do ...@@ -167,7 +167,7 @@ describe 'admin Geo Nodes', :js, :geo do
expect(current_path).to eq admin_geo_nodes_path expect(current_path).to eq admin_geo_nodes_path
wait_for_requests wait_for_requests
page.within(find('.geo-node-item', match: :first)) do page.within(find('.card', match: :first)) do
expect(page).to have_content('http://newsite.com') expect(page).to have_content('http://newsite.com')
expect(page).to have_content('Primary') expect(page).to have_content('Primary')
...@@ -196,7 +196,7 @@ describe 'admin Geo Nodes', :js, :geo do ...@@ -196,7 +196,7 @@ describe 'admin Geo Nodes', :js, :geo do
expect(current_path).to eq admin_geo_nodes_path expect(current_path).to eq admin_geo_nodes_path
wait_for_requests wait_for_requests
expect(page).not_to have_css('.geo-node-item') expect(page).not_to have_css('.card')
end end
end end
end end
...@@ -125,8 +125,7 @@ describe('GeoNodeActionsComponent', () => { ...@@ -125,8 +125,7 @@ describe('GeoNodeActionsComponent', () => {
describe('template', () => { describe('template', () => {
it('renders container elements correctly', () => { it('renders container elements correctly', () => {
expect(vm.$el.classList.contains('geo-node-actions')).toBe(true); expect(vm.$el.classList.contains('geo-node-actions')).toBe(true);
expect(vm.$el.querySelectorAll('.node-action-container').length).not.toBe(0); expect(vm.$el.querySelectorAll('.btn-sm').length).not.toBe(0);
expect(vm.$el.querySelectorAll('.btn-node-action').length).not.toBe(0);
}); });
}); });
}); });
...@@ -75,7 +75,7 @@ describe('GeoNodeDetailItemComponent', () => { ...@@ -75,7 +75,7 @@ describe('GeoNodeDetailItemComponent', () => {
itemValueStaleTooltip, itemValueStaleTooltip,
}); });
const iconEl = vm.$el.querySelector('.detail-value-stale-icon'); const iconEl = vm.$el.querySelector('.text-warning-500');
expect(iconEl).not.toBeNull(); expect(iconEl).not.toBeNull();
expect(iconEl.dataset.originalTitle).toBe(itemValueStaleTooltip); expect(iconEl.dataset.originalTitle).toBe(itemValueStaleTooltip);
......
...@@ -87,9 +87,7 @@ describe('GeoNodeDetailsComponent', () => { ...@@ -87,9 +87,7 @@ describe('GeoNodeDetailsComponent', () => {
vm.errorMessage = 'Foobar'; vm.errorMessage = 'Foobar';
vm.$nextTick(() => { vm.$nextTick(() => {
expect(vm.$el.querySelector('.node-health-message-container a').getAttribute('href')).toBe( expect(vm.$el.querySelector('.bg-danger-100 a').getAttribute('href')).toBe('/foo/bar');
'/foo/bar',
);
done(); done();
}); });
}); });
......
import Vue from 'vue'; import Vue from '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 mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockNodeDetails } from '../mock_data'; import { mockNodeDetails } from '../mock_data';
...@@ -16,38 +17,38 @@ describe('GeoNodeHealthStatusComponent', () => { ...@@ -16,38 +17,38 @@ describe('GeoNodeHealthStatusComponent', () => {
describe('computed', () => { describe('computed', () => {
describe('healthCssClass', () => { describe('healthCssClass', () => {
it('returns CSS class representing `status` prop value', () => { it('returns CSS class representing `status` prop value', () => {
const vm = createComponent('Healthy'); const vm = createComponent('healthy');
expect(vm.healthCssClass).toBe('geo-node-healthy'); expect(vm.healthCssClass).toBe(HEALTH_STATUS_CLASS.healthy);
vm.$destroy(); vm.$destroy();
}); });
}); });
describe('statusIconName', () => { describe('statusIconName', () => {
it('returns icon name representing `status` prop value', () => { it('returns icon name representing `status` prop value', () => {
let vm = createComponent('Healthy'); let vm = createComponent('healthy');
expect(vm.statusIconName).toBe('status_success'); expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.healthy);
vm.$destroy(); vm.$destroy();
vm = createComponent('Unhealthy'); vm = createComponent('unhealthy');
expect(vm.statusIconName).toBe('status_failed'); expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.unhealthy);
vm.$destroy(); vm.$destroy();
vm = createComponent('Disabled'); vm = createComponent('disabled');
expect(vm.statusIconName).toBe('status_canceled'); expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.disabled);
vm.$destroy(); vm.$destroy();
vm = createComponent('Unknown'); vm = createComponent('unknown');
expect(vm.statusIconName).toBe('status_warning'); expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.unknown);
vm.$destroy(); vm.$destroy();
vm = createComponent('Offline'); vm = createComponent('offline');
expect(vm.statusIconName).toBe('status_canceled'); expect(vm.statusIconName).toBe(HEALTH_STATUS_ICON.offline);
vm.$destroy(); vm.$destroy();
}); });
}); });
...@@ -60,7 +61,7 @@ describe('GeoNodeHealthStatusComponent', () => { ...@@ -60,7 +61,7 @@ describe('GeoNodeHealthStatusComponent', () => {
expect(vm.$el.classList.contains('detail-section-item')).toBe(true); expect(vm.$el.classList.contains('detail-section-item')).toBe(true);
expect(vm.$el.querySelector('.node-detail-title').innerText.trim()).toBe('Health status'); expect(vm.$el.querySelector('.node-detail-title').innerText.trim()).toBe('Health status');
const iconContainerEl = vm.$el.querySelector('.node-detail-value.node-health-status'); const iconContainerEl = vm.$el.querySelector('.node-health-status');
expect(iconContainerEl).not.toBeNull(); expect(iconContainerEl).not.toBeNull();
expect(iconContainerEl.querySelector('svg use').getAttribute('xlink:href')).toContain( expect(iconContainerEl.querySelector('svg use').getAttribute('xlink:href')).toContain(
......
...@@ -148,11 +148,9 @@ describe('GeoNodeItemComponent', () => { ...@@ -148,11 +148,9 @@ describe('GeoNodeItemComponent', () => {
vm.isNodeDetailsFailed = true; vm.isNodeDetailsFailed = true;
vm.errorMessage = err; vm.errorMessage = err;
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$el.querySelectorAll('p.node-health-message').length).not.toBe(0); expect(vm.$el.querySelectorAll('p.bg-danger-100').length).not.toBe(0);
expect(vm.$el.querySelector('p.node-health-message').innerText.trim()).toContain(err); expect(vm.$el.querySelector('p.bg-danger-100').innerText.trim()).toContain(err);
expect(vm.$el.querySelector('p.node-health-message a').getAttribute('href')).toBe( expect(vm.$el.querySelector('p.bg-danger-100 a').getAttribute('href')).toBe('/foo/bar');
'/foo/bar',
);
done(); done();
}); });
}); });
......
...@@ -89,18 +89,20 @@ describe('NodeDetailsSectionOther', () => { ...@@ -89,18 +89,20 @@ describe('NodeDetailsSectionOther', () => {
}); });
describe('storageShardsCssClass', () => { describe('storageShardsCssClass', () => {
it('returns CSS class `node-detail-value-bold` when `nodeDetails.storageShardsMatch` is true', done => { it('returns CSS class `font-weight-bold` when `nodeDetails.storageShardsMatch` is true', done => {
vm.nodeDetails.storageShardsMatch = true; vm.nodeDetails.storageShardsMatch = true;
Vue.nextTick() Vue.nextTick()
.then(() => { .then(() => {
expect(vm.storageShardsCssClass).toBe('node-detail-value-bold'); expect(vm.storageShardsCssClass[0]).toBe('font-weight-bold');
expect(vm.storageShardsCssClass[1]['text-danger-500']).toBeFalsy();
}) })
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
}); });
it('returns CSS class `node-detail-value-bold node-detail-value-error` when `nodeDetails.storageShardsMatch` is false', () => { it('returns CSS class `font-weight-bold text-danger-500` when `nodeDetails.storageShardsMatch` is false', () => {
expect(vm.storageShardsCssClass).toBe('node-detail-value-bold node-detail-value-error'); expect(vm.storageShardsCssClass[0]).toBe('font-weight-bold');
expect(vm.storageShardsCssClass[1]['text-danger-500']).toBeTruthy();
}); });
}); });
}); });
...@@ -111,14 +113,16 @@ describe('NodeDetailsSectionOther', () => { ...@@ -111,14 +113,16 @@ describe('NodeDetailsSectionOther', () => {
}); });
it('renders show section button element', () => { it('renders show section button element', () => {
expect(vm.$el.querySelector('.btn-show-section')).not.toBeNull(); expect(vm.$el.querySelector('.btn-link')).not.toBeNull();
expect(vm.$el.querySelector('.btn-show-section > span').innerText.trim()).toBe( expect(vm.$el.querySelector('.btn-link > span').innerText.trim()).toBe('Other information');
'Other information',
);
}); });
it('renders section items container element', () => { it('renders section items container element', done => {
expect(vm.$el.querySelector('.section-items-container')).not.toBeNull(); vm.showSectionItems = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.section-items-container')).not.toBeNull();
done();
});
}); });
}); });
}); });
...@@ -89,14 +89,16 @@ describe('NodeDetailsSectionSync', () => { ...@@ -89,14 +89,16 @@ describe('NodeDetailsSectionSync', () => {
}); });
it('renders show section button element', () => { it('renders show section button element', () => {
expect(vm.$el.querySelector('.btn-show-section')).not.toBeNull(); expect(vm.$el.querySelector('.btn-link')).not.toBeNull();
expect(vm.$el.querySelector('.btn-show-section > span').innerText.trim()).toBe( expect(vm.$el.querySelector('.btn-link > span').innerText.trim()).toBe('Sync information');
'Sync information',
);
}); });
it('renders section items container element', () => { it('renders section items container element', done => {
expect(vm.$el.querySelector('.section-items-container')).not.toBeNull(); vm.showSectionItems = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.section-items-container')).not.toBeNull();
done();
});
}); });
}); });
}); });
...@@ -83,6 +83,13 @@ describe('NodeDetailsSectionVerification', () => { ...@@ -83,6 +83,13 @@ describe('NodeDetailsSectionVerification', () => {
expect(vm.$el.classList.contains('verification-section')).toBe(true); expect(vm.$el.classList.contains('verification-section')).toBe(true);
}); });
it('renders show section button element', () => {
expect(vm.$el.querySelector('.btn-link')).not.toBeNull();
expect(vm.$el.querySelector('.btn-link > span').innerText.trim()).toBe(
'Verification information',
);
});
it('renders section items container element', done => { it('renders section items container element', done => {
vm.showSectionItems = true; vm.showSectionItems = true;
Vue.nextTick(() => { Vue.nextTick(() => {
......
...@@ -62,7 +62,7 @@ describe('SectionRevealButton', () => { ...@@ -62,7 +62,7 @@ describe('SectionRevealButton', () => {
describe('template', () => { describe('template', () => {
it('renders button element', () => { it('renders button element', () => {
expect(vm.$el.classList.contains('btn-show-section')).toBe(true); expect(vm.$el.classList.contains('btn-link')).toBe(true);
expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('#angle-down'); expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('#angle-down');
expect(vm.$el.querySelector('span').innerText.trim()).toBe('Foo button'); expect(vm.$el.querySelector('span').innerText.trim()).toBe('Foo button');
}); });
......
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