Commit ad4222b6 authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '344857-relocate-the-number-of-online-runners-text-in-toolbar' into 'master'

Relocate online runners count in search bar

See merge request gitlab-org/gitlab!74877
parents 5dcaeeee 2bd69e20
...@@ -3,12 +3,12 @@ import { GlBadge, GlLink } from '@gitlab/ui'; ...@@ -3,12 +3,12 @@ import { GlBadge, GlLink } from '@gitlab/ui';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { fetchPolicies } from '~/lib/graphql'; import { fetchPolicies } from '~/lib/graphql';
import { updateHistory } from '~/lib/utils/url_utility'; import { updateHistory } from '~/lib/utils/url_utility';
import { sprintf, __ } from '~/locale';
import RegistrationDropdown from '../components/registration/registration_dropdown.vue'; import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue'; import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
import RunnerList from '../components/runner_list.vue'; import RunnerList from '../components/runner_list.vue';
import RunnerName from '../components/runner_name.vue'; import RunnerName from '../components/runner_name.vue';
import RunnerOnlineStat from '../components/stat/runner_online_stat.vue';
import RunnerPagination from '../components/runner_pagination.vue'; import RunnerPagination from '../components/runner_pagination.vue';
import RunnerTypeTabs from '../components/runner_type_tabs.vue'; import RunnerTypeTabs from '../components/runner_type_tabs.vue';
...@@ -38,6 +38,7 @@ export default { ...@@ -38,6 +38,7 @@ export default {
RunnerFilteredSearchBar, RunnerFilteredSearchBar,
RunnerList, RunnerList,
RunnerName, RunnerName,
RunnerOnlineStat,
RunnerPagination, RunnerPagination,
RunnerTypeTabs, RunnerTypeTabs,
}, },
...@@ -110,11 +111,6 @@ export default { ...@@ -110,11 +111,6 @@ export default {
noRunnersFound() { noRunnersFound() {
return !this.runnersLoading && !this.runners.items.length; return !this.runnersLoading && !this.runners.items.length;
}, },
activeRunnersMessage() {
return sprintf(__('Runners currently online: %{active_runners_count}'), {
active_runners_count: this.activeRunnersCount,
});
},
searchTokens() { searchTokens() {
return [ return [
statusTokenConfig, statusTokenConfig,
...@@ -165,6 +161,8 @@ export default { ...@@ -165,6 +161,8 @@ export default {
</script> </script>
<template> <template>
<div> <div>
<runner-online-stat class="gl-py-6 gl-px-5" :value="activeRunnersCount" />
<div <div
class="gl-display-flex gl-align-items-center gl-flex-direction-column-reverse gl-md-flex-direction-row gl-mt-3 gl-md-mt-0" class="gl-display-flex gl-align-items-center gl-flex-direction-column-reverse gl-md-flex-direction-row gl-mt-3 gl-md-mt-0"
> >
...@@ -194,11 +192,7 @@ export default { ...@@ -194,11 +192,7 @@ export default {
v-model="search" v-model="search"
:tokens="searchTokens" :tokens="searchTokens"
:namespace="$options.filteredSearchNamespace" :namespace="$options.filteredSearchNamespace"
> />
<template #runner-count>
{{ activeRunnersMessage }}
</template>
</runner-filtered-search-bar>
<div v-if="noRunnersFound" class="gl-text-center gl-p-5"> <div v-if="noRunnersFound" class="gl-text-center gl-p-5">
{{ __('No runners found') }} {{ __('No runners found') }}
......
...@@ -76,24 +76,18 @@ export default { ...@@ -76,24 +76,18 @@ export default {
}; };
</script> </script>
<template> <template>
<div <filtered-search
class="gl-bg-gray-10 gl-p-5 gl-border-solid gl-border-gray-100 gl-border-0 gl-border-t-1 gl-border-b-1" class="gl-bg-gray-10 gl-p-5 gl-border-solid gl-border-gray-100 gl-border-0 gl-border-t-1 gl-border-b-1"
> v-bind="$attrs"
<filtered-search :namespace="namespace"
v-bind="$attrs" recent-searches-storage-key="runners-search"
:namespace="namespace" :sort-options="$options.sortOptions"
recent-searches-storage-key="runners-search" :initial-filter-value="initialFilterValue"
:sort-options="$options.sortOptions" :tokens="tokens"
:initial-filter-value="initialFilterValue" :initial-sort-by="initialSortBy"
:tokens="tokens" :search-input-placeholder="__('Search or filter results...')"
:initial-sort-by="initialSortBy" data-testid="runners-filtered-search"
:search-input-placeholder="__('Search or filter results...')" @onFilter="onFilter"
data-testid="runners-filtered-search" @onSort="onSort"
@onFilter="onFilter" />
@onSort="onSort"
/>
<div class="gl-text-right" data-testid="runner-count">
<slot name="runner-count"></slot>
</div>
</div>
</template> </template>
<script>
import { GlSingleStat } from '@gitlab/ui/dist/charts';
export default {
components: {
GlSingleStat,
},
};
</script>
<template>
<gl-single-stat
v-bind="$attrs"
variant="success"
:title="s__('Runners|Online Runners')"
:meta-text="s__('Runners|online')"
/>
</template>
...@@ -9,6 +9,7 @@ import RegistrationDropdown from '../components/registration/registration_dropdo ...@@ -9,6 +9,7 @@ import RegistrationDropdown from '../components/registration/registration_dropdo
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue'; import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
import RunnerList from '../components/runner_list.vue'; import RunnerList from '../components/runner_list.vue';
import RunnerName from '../components/runner_name.vue'; import RunnerName from '../components/runner_name.vue';
import RunnerOnlineStat from '../components/stat/runner_online_stat.vue';
import RunnerPagination from '../components/runner_pagination.vue'; import RunnerPagination from '../components/runner_pagination.vue';
import RunnerTypeTabs from '../components/runner_type_tabs.vue'; import RunnerTypeTabs from '../components/runner_type_tabs.vue';
...@@ -35,6 +36,7 @@ export default { ...@@ -35,6 +36,7 @@ export default {
RunnerFilteredSearchBar, RunnerFilteredSearchBar,
RunnerList, RunnerList,
RunnerName, RunnerName,
RunnerOnlineStat,
RunnerPagination, RunnerPagination,
RunnerTypeTabs, RunnerTypeTabs,
}, },
...@@ -145,6 +147,8 @@ export default { ...@@ -145,6 +147,8 @@ export default {
<template> <template>
<div> <div>
<runner-online-stat class="gl-py-6 gl-px-5" :value="groupRunnersCount" />
<div class="gl-display-flex gl-align-items-center"> <div class="gl-display-flex gl-align-items-center">
<runner-type-tabs <runner-type-tabs
v-model="search" v-model="search"
...@@ -164,11 +168,7 @@ export default { ...@@ -164,11 +168,7 @@ export default {
v-model="search" v-model="search"
:tokens="searchTokens" :tokens="searchTokens"
:namespace="filteredSearchNamespace" :namespace="filteredSearchNamespace"
> />
<template #runner-count>
{{ runnerCountMessage }}
</template>
</runner-filtered-search-bar>
<div v-if="noRunnersFound" class="gl-text-center gl-p-5"> <div v-if="noRunnersFound" class="gl-text-center gl-p-5">
{{ __('No runners found') }} {{ __('No runners found') }}
......
...@@ -29959,6 +29959,9 @@ msgstr "" ...@@ -29959,6 +29959,9 @@ msgstr ""
msgid "Runners|Online" msgid "Runners|Online"
msgstr "" msgstr ""
msgid "Runners|Online Runners"
msgstr ""
msgid "Runners|Paused" msgid "Runners|Paused"
msgstr "" msgstr ""
......
...@@ -26,7 +26,7 @@ RSpec.describe "Admin Runners" do ...@@ -26,7 +26,7 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path visit admin_runners_path
expect(page).to have_text "Register an instance runner" expect(page).to have_text "Register an instance runner"
expect(page).to have_text "Runners currently online: 1" expect(page).to have_text "Online Runners 1"
end end
it 'with an instance runner shows an instance badge' do it 'with an instance runner shows an instance badge' do
...@@ -324,7 +324,7 @@ RSpec.describe "Admin Runners" do ...@@ -324,7 +324,7 @@ RSpec.describe "Admin Runners" do
it 'has all necessary texts including no runner message' do it 'has all necessary texts including no runner message' do
expect(page).to have_text "Register an instance runner" expect(page).to have_text "Register an instance runner"
expect(page).to have_text "Runners currently online: 0" expect(page).to have_text "Online Runners 0"
expect(page).to have_text 'No runners found' expect(page).to have_text 'No runners found'
end end
end end
......
...@@ -155,9 +155,7 @@ describe('AdminRunnersApp', () => { ...@@ -155,9 +155,7 @@ describe('AdminRunnersApp', () => {
it('shows the active runner count', () => { it('shows the active runner count', () => {
createComponent({ mountFn: mount }); createComponent({ mountFn: mount });
expect(findRunnerFilteredSearchBar().text()).toMatch( expect(wrapper.text()).toMatch(new RegExp(`Online Runners ${mockActiveRunnersCount}`));
`Runners currently online: ${mockActiveRunnersCount}`,
);
}); });
describe('when a filter is preselected', () => { describe('when a filter is preselected', () => {
......
...@@ -15,7 +15,6 @@ describe('RunnerList', () => { ...@@ -15,7 +15,6 @@ describe('RunnerList', () => {
const findFilteredSearch = () => wrapper.findComponent(FilteredSearch); const findFilteredSearch = () => wrapper.findComponent(FilteredSearch);
const findGlFilteredSearch = () => wrapper.findComponent(GlFilteredSearch); const findGlFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
const findSortOptions = () => wrapper.findAllComponents(GlDropdownItem); const findSortOptions = () => wrapper.findAllComponents(GlDropdownItem);
const findActiveRunnersMessage = () => wrapper.findByTestId('runner-count');
const mockDefaultSort = 'CREATED_DESC'; const mockDefaultSort = 'CREATED_DESC';
const mockOtherSort = 'CONTACTED_DESC'; const mockOtherSort = 'CONTACTED_DESC';
...@@ -23,7 +22,6 @@ describe('RunnerList', () => { ...@@ -23,7 +22,6 @@ describe('RunnerList', () => {
{ type: PARAM_KEY_STATUS, value: { data: STATUS_ACTIVE, operator: '=' } }, { type: PARAM_KEY_STATUS, value: { data: STATUS_ACTIVE, operator: '=' } },
{ type: 'filtered-search-term', value: { data: '' } }, { type: 'filtered-search-term', value: { data: '' } },
]; ];
const mockActiveRunnersCount = 2;
const expectToHaveLastEmittedInput = (value) => { const expectToHaveLastEmittedInput = (value) => {
const inputs = wrapper.emitted('input'); const inputs = wrapper.emitted('input');
...@@ -43,9 +41,6 @@ describe('RunnerList', () => { ...@@ -43,9 +41,6 @@ describe('RunnerList', () => {
}, },
...props, ...props,
}, },
slots: {
'runner-count': `Runners currently online: ${mockActiveRunnersCount}`,
},
stubs: { stubs: {
FilteredSearch, FilteredSearch,
GlFilteredSearch, GlFilteredSearch,
...@@ -69,12 +64,6 @@ describe('RunnerList', () => { ...@@ -69,12 +64,6 @@ describe('RunnerList', () => {
expect(findFilteredSearch().props('namespace')).toBe('runners'); expect(findFilteredSearch().props('namespace')).toBe('runners');
}); });
it('Displays an active runner count', () => {
expect(findActiveRunnersMessage().text()).toBe(
`Runners currently online: ${mockActiveRunnersCount}`,
);
});
it('sets sorting options', () => { it('sets sorting options', () => {
const SORT_OPTIONS_COUNT = 2; const SORT_OPTIONS_COUNT = 2;
......
import { GlSingleStat } from '@gitlab/ui/dist/charts';
import { shallowMount, mount } from '@vue/test-utils';
import RunnerOnlineBadge from '~/runner/components/stat/runner_online_stat.vue';
describe('RunnerOnlineBadge', () => {
let wrapper;
const findSingleStat = () => wrapper.findComponent(GlSingleStat);
const createComponent = ({ props = {} } = {}, mountFn = shallowMount) => {
wrapper = mountFn(RunnerOnlineBadge, {
propsData: {
value: '99',
...props,
},
});
};
afterEach(() => {
wrapper.destroy();
});
it('Uses a success appearance', () => {
createComponent({}, shallowMount);
expect(findSingleStat().props('variant')).toBe('success');
});
it('Renders a value', () => {
createComponent({}, mount);
expect(wrapper.text()).toMatch(new RegExp(`Online Runners 99\\s+online`));
});
});
...@@ -130,24 +130,24 @@ describe('GroupRunnersApp', () => { ...@@ -130,24 +130,24 @@ describe('GroupRunnersApp', () => {
}); });
describe('shows the active runner count', () => { describe('shows the active runner count', () => {
const expectedOnlineCount = (count) => new RegExp(`Online Runners ${count}`);
it('with a regular value', () => { it('with a regular value', () => {
createComponent({ mountFn: mount }); createComponent({ mountFn: mount });
expect(findRunnerFilteredSearchBar().text()).toMatch( expect(wrapper.text()).toMatch(expectedOnlineCount(mockGroupRunnersLimitedCount));
`Runners in this group: ${mockGroupRunnersLimitedCount}`,
);
}); });
it('at the limit', () => { it('at the limit', () => {
createComponent({ props: { groupRunnersLimitedCount: 1000 }, mountFn: mount }); createComponent({ props: { groupRunnersLimitedCount: 1000 }, mountFn: mount });
expect(findRunnerFilteredSearchBar().text()).toMatch(`Runners in this group: 1,000`); expect(wrapper.text()).toMatch(expectedOnlineCount('1,000'));
}); });
it('over the limit', () => { it('over the limit', () => {
createComponent({ props: { groupRunnersLimitedCount: 1001 }, mountFn: mount }); createComponent({ props: { groupRunnersLimitedCount: 1001 }, mountFn: mount });
expect(findRunnerFilteredSearchBar().text()).toMatch(`Runners in this group: 1,000+`); expect(wrapper.text()).toMatch(expectedOnlineCount('1,000\\+'));
}); });
}); });
......
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