Commit b852ba5b authored by Miguel Rincon's avatar Miguel Rincon

Add total counters in each runner type tab

In order for admin users to have a more comprehensive view of their
runner resources, this change adds a counter badge next to each runner
tab with the total number of runners.

Changelog: added
parent 9a1eeb7c
<script> <script>
import { GlLink } from '@gitlab/ui'; 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 { formatNumber, sprintf, __ } from '~/locale'; 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';
...@@ -14,7 +14,13 @@ import RunnerTypeTabs from '../components/runner_type_tabs.vue'; ...@@ -14,7 +14,13 @@ import RunnerTypeTabs from '../components/runner_type_tabs.vue';
import { statusTokenConfig } from '../components/search_tokens/status_token_config'; import { statusTokenConfig } from '../components/search_tokens/status_token_config';
import { tagTokenConfig } from '../components/search_tokens/tag_token_config'; import { tagTokenConfig } from '../components/search_tokens/tag_token_config';
import { ADMIN_FILTERED_SEARCH_NAMESPACE, INSTANCE_TYPE, I18N_FETCH_ERROR } from '../constants'; import {
ADMIN_FILTERED_SEARCH_NAMESPACE,
INSTANCE_TYPE,
GROUP_TYPE,
PROJECT_TYPE,
I18N_FETCH_ERROR,
} from '../constants';
import getRunnersQuery from '../graphql/get_runners.query.graphql'; import getRunnersQuery from '../graphql/get_runners.query.graphql';
import { import {
fromUrlQueryToSearch, fromUrlQueryToSearch,
...@@ -26,6 +32,7 @@ import { captureException } from '../sentry_utils'; ...@@ -26,6 +32,7 @@ import { captureException } from '../sentry_utils';
export default { export default {
name: 'AdminRunnersApp', name: 'AdminRunnersApp',
components: { components: {
GlBadge,
GlLink, GlLink,
RegistrationDropdown, RegistrationDropdown,
RunnerFilteredSearchBar, RunnerFilteredSearchBar,
...@@ -35,11 +42,27 @@ export default { ...@@ -35,11 +42,27 @@ export default {
RunnerTypeTabs, RunnerTypeTabs,
}, },
props: { props: {
registrationToken: {
type: String,
required: true,
},
activeRunnersCount: { activeRunnersCount: {
type: Number, type: String,
required: true, required: true,
}, },
registrationToken: { allRunnersCount: {
type: String,
required: true,
},
instanceRunnersCount: {
type: String,
required: true,
},
groupRunnersCount: {
type: String,
required: true,
},
projectRunnersCount: {
type: String, type: String,
required: true, required: true,
}, },
...@@ -89,7 +112,7 @@ export default { ...@@ -89,7 +112,7 @@ export default {
}, },
activeRunnersMessage() { activeRunnersMessage() {
return sprintf(__('Runners currently online: %{active_runners_count}'), { return sprintf(__('Runners currently online: %{active_runners_count}'), {
active_runners_count: formatNumber(this.activeRunnersCount), active_runners_count: this.activeRunnersCount,
}); });
}, },
searchTokens() { searchTokens() {
...@@ -118,6 +141,20 @@ export default { ...@@ -118,6 +141,20 @@ export default {
this.reportToSentry(error); this.reportToSentry(error);
}, },
methods: { methods: {
tabCount({ runnerType }) {
switch (runnerType) {
case null:
return this.allRunnersCount;
case INSTANCE_TYPE:
return this.instanceRunnersCount;
case GROUP_TYPE:
return this.groupRunnersCount;
case PROJECT_TYPE:
return this.projectRunnersCount;
default:
return null;
}
},
reportToSentry(error) { reportToSentry(error) {
captureException({ error, component: this.$options.name }); captureException({ error, component: this.$options.name });
}, },
...@@ -128,15 +165,25 @@ export default { ...@@ -128,15 +165,25 @@ export default {
</script> </script>
<template> <template>
<div> <div>
<div class="gl-display-flex gl-align-items-center"> <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"
>
<runner-type-tabs <runner-type-tabs
v-model="search" v-model="search"
class="gl-w-full"
content-class="gl-display-none" content-class="gl-display-none"
nav-class="gl-border-none!" nav-class="gl-border-none!"
/> >
<template #title="{ tab }">
{{ tab.title }}
<gl-badge v-if="tabCount(tab)" class="gl-ml-1" size="sm">
{{ tabCount(tab) }}
</gl-badge>
</template>
</runner-type-tabs>
<registration-dropdown <registration-dropdown
class="gl-ml-auto" class="gl-w-full gl-sm-w-auto gl-mr-auto"
:registration-token="registrationToken" :registration-token="registrationToken"
:type="$options.INSTANCE_TYPE" :type="$options.INSTANCE_TYPE"
right right
......
...@@ -16,7 +16,16 @@ export const initAdminRunners = (selector = '#js-admin-runners') => { ...@@ -16,7 +16,16 @@ export const initAdminRunners = (selector = '#js-admin-runners') => {
// TODO `activeRunnersCount` should be implemented using a GraphQL API // TODO `activeRunnersCount` should be implemented using a GraphQL API
// https://gitlab.com/gitlab-org/gitlab/-/issues/333806 // https://gitlab.com/gitlab-org/gitlab/-/issues/333806
const { activeRunnersCount, registrationToken, runnerInstallHelpPage } = el.dataset; const {
runnerInstallHelpPage,
registrationToken,
activeRunnersCount,
allRunnersCount,
instanceRunnersCount,
groupRunnersCount,
projectRunnersCount,
} = el.dataset;
const apolloProvider = new VueApollo({ const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(), defaultClient: createDefaultClient(),
...@@ -31,8 +40,15 @@ export const initAdminRunners = (selector = '#js-admin-runners') => { ...@@ -31,8 +40,15 @@ export const initAdminRunners = (selector = '#js-admin-runners') => {
render(h) { render(h) {
return h(AdminRunnersApp, { return h(AdminRunnersApp, {
props: { props: {
activeRunnersCount: parseInt(activeRunnersCount, 10),
registrationToken, registrationToken,
// All runner counts are returned as formatted
// strings, we do not use `parseInt`.
activeRunnersCount,
allRunnersCount,
instanceRunnersCount,
groupRunnersCount,
projectRunnersCount,
}, },
}); });
}, },
......
...@@ -51,13 +51,16 @@ export default { ...@@ -51,13 +51,16 @@ export default {
}; };
</script> </script>
<template> <template>
<gl-tabs v-bind="$attrs"> <gl-tabs v-bind="$attrs" data-testid="runner-type-tabs">
<gl-tab <gl-tab
v-for="tab in $options.tabs" v-for="tab in $options.tabs"
:key="`${tab.runnerType}`" :key="`${tab.runnerType}`"
:active="isTabActive(tab)" :active="isTabActive(tab)"
:title="tab.title"
@click="onTabSelected(tab)" @click="onTabSelected(tab)"
/> >
<template #title>
<slot name="title" :tab="tab">{{ tab.title }}</slot>
</template>
</gl-tab>
</gl-tabs> </gl-tabs>
</template> </template>
...@@ -8,7 +8,6 @@ class Admin::RunnersController < Admin::ApplicationController ...@@ -8,7 +8,6 @@ class Admin::RunnersController < Admin::ApplicationController
feature_category :runner feature_category :runner
def index def index
@active_runners_count = Ci::Runner.online.count
end end
def show def show
......
...@@ -60,6 +60,22 @@ module Ci ...@@ -60,6 +60,22 @@ module Ci
end end
end end
def admin_runners_data_attributes
{
# Runner install help page is external, located at
# https://gitlab.com/gitlab-org/gitlab-runner
runner_install_help_page: 'https://docs.gitlab.com/runner/install/',
registration_token: Gitlab::CurrentSettings.runners_registration_token,
# All runner counts are returned as formatted strings
active_runners_count: Ci::Runner.online.count.to_s,
all_runners_count: limited_counter_with_delimiter(Ci::Runner),
instance_runners_count: limited_counter_with_delimiter(Ci::Runner.instance_type),
group_runners_count: limited_counter_with_delimiter(Ci::Runner.group_type),
project_runners_count: limited_counter_with_delimiter(Ci::Runner.project_type)
}
end
def group_shared_runners_settings_data(group) def group_shared_runners_settings_data(group)
{ {
update_path: api_v4_groups_path(id: group.id), update_path: api_v4_groups_path(id: group.id),
......
- breadcrumb_title _('Runners') - breadcrumb_title _('Runners')
- page_title _('Runners') - page_title _('Runners')
#js-admin-runners{ data: { registration_token: Gitlab::CurrentSettings.runners_registration_token, runner_install_help_page: 'https://docs.gitlab.com/runner/install/', active_runners_count: @active_runners_count } } #js-admin-runners{ data: admin_runners_data_attributes }
...@@ -12,9 +12,11 @@ RSpec.describe Admin::RunnersController do ...@@ -12,9 +12,11 @@ RSpec.describe Admin::RunnersController do
describe '#index' do describe '#index' do
render_views render_views
it 'lists all runners' do before do
get :index get :index
end
it 'renders index template' do
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:index) expect(response).to render_template(:index)
end end
......
...@@ -66,11 +66,11 @@ RSpec.describe "Admin Runners" do ...@@ -66,11 +66,11 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path visit admin_runners_path
end end
it 'runner type can be selected' do it 'runner types tabs have total counts and can be selected' do
expect(page).to have_link('All') expect(page).to have_link('All 2')
expect(page).to have_link('Instance') expect(page).to have_link('Instance 2')
expect(page).to have_link('Group') expect(page).to have_link('Group 0')
expect(page).to have_link('Project') expect(page).to have_link('Project 0')
end end
it 'shows runners' do it 'shows runners' do
...@@ -162,10 +162,12 @@ RSpec.describe "Admin Runners" do ...@@ -162,10 +162,12 @@ RSpec.describe "Admin Runners" do
create(:ci_runner, :group, description: 'runner-group', groups: [group]) create(:ci_runner, :group, description: 'runner-group', groups: [group])
end end
it 'shows correct runner when type matches' do it '"All" tab is selected by default' do
visit admin_runners_path visit admin_runners_path
expect(page).to have_link('All', class: 'active') page.within('[data-testid="runner-type-tabs"]') do
expect(page).to have_link('All', class: 'active')
end
end end
it 'shows correct runner when type matches' do it 'shows correct runner when type matches' do
...@@ -174,9 +176,11 @@ RSpec.describe "Admin Runners" do ...@@ -174,9 +176,11 @@ RSpec.describe "Admin Runners" do
expect(page).to have_content 'runner-project' expect(page).to have_content 'runner-project'
expect(page).to have_content 'runner-group' expect(page).to have_content 'runner-group'
click_on 'Project' page.within('[data-testid="runner-type-tabs"]') do
click_on('Project')
expect(page).to have_link('Project', class: 'active') expect(page).to have_link('Project', class: 'active')
end
expect(page).to have_content 'runner-project' expect(page).to have_content 'runner-project'
expect(page).not_to have_content 'runner-group' expect(page).not_to have_content 'runner-group'
...@@ -185,9 +189,11 @@ RSpec.describe "Admin Runners" do ...@@ -185,9 +189,11 @@ RSpec.describe "Admin Runners" do
it 'shows no runner when type does not match' do it 'shows no runner when type does not match' do
visit admin_runners_path visit admin_runners_path
click_on 'Instance' page.within('[data-testid="runner-type-tabs"]') do
click_on 'Instance'
expect(page).to have_link('Instance', class: 'active') expect(page).to have_link('Instance', class: 'active')
end
expect(page).not_to have_content 'runner-project' expect(page).not_to have_content 'runner-project'
expect(page).not_to have_content 'runner-group' expect(page).not_to have_content 'runner-group'
...@@ -200,7 +206,9 @@ RSpec.describe "Admin Runners" do ...@@ -200,7 +206,9 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path visit admin_runners_path
click_on 'Project' page.within('[data-testid="runner-type-tabs"]') do
click_on 'Project'
end
expect(page).to have_content 'runner-project' expect(page).to have_content 'runner-project'
expect(page).to have_content 'runner-2-project' expect(page).to have_content 'runner-2-project'
...@@ -224,7 +232,9 @@ RSpec.describe "Admin Runners" do ...@@ -224,7 +232,9 @@ RSpec.describe "Admin Runners" do
expect(page).to have_content 'runner-group' expect(page).to have_content 'runner-group'
expect(page).not_to have_content 'runner-paused-project' expect(page).not_to have_content 'runner-paused-project'
click_on 'Project' page.within('[data-testid="runner-type-tabs"]') do
click_on 'Project'
end
expect(page).to have_content 'runner-project' expect(page).to have_content 'runner-project'
expect(page).not_to have_content 'runner-group' expect(page).not_to have_content 'runner-group'
......
...@@ -10,6 +10,7 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils'; ...@@ -10,6 +10,7 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { updateHistory } from '~/lib/utils/url_utility'; import { updateHistory } from '~/lib/utils/url_utility';
import AdminRunnersApp from '~/runner/admin_runners/admin_runners_app.vue'; import AdminRunnersApp from '~/runner/admin_runners/admin_runners_app.vue';
import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue'; import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
import RunnerList from '~/runner/components/runner_list.vue'; import RunnerList from '~/runner/components/runner_list.vue';
import RegistrationDropdown from '~/runner/components/registration/registration_dropdown.vue'; import RegistrationDropdown from '~/runner/components/registration/registration_dropdown.vue';
...@@ -33,7 +34,11 @@ import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered ...@@ -33,7 +34,11 @@ import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered
import { runnersData, runnersDataPaginated } from '../mock_data'; import { runnersData, runnersDataPaginated } from '../mock_data';
const mockRegistrationToken = 'MOCK_REGISTRATION_TOKEN'; const mockRegistrationToken = 'MOCK_REGISTRATION_TOKEN';
const mockActiveRunnersCount = 2; const mockActiveRunnersCount = '2';
const mockAllRunnersCount = '6';
const mockInstanceRunnersCount = '3';
const mockGroupRunnersCount = '2';
const mockProjectRunnersCount = '1';
jest.mock('~/flash'); jest.mock('~/flash');
jest.mock('~/runner/sentry_utils'); jest.mock('~/runner/sentry_utils');
...@@ -50,6 +55,7 @@ describe('AdminRunnersApp', () => { ...@@ -50,6 +55,7 @@ describe('AdminRunnersApp', () => {
let mockRunnersQuery; let mockRunnersQuery;
const findRegistrationDropdown = () => wrapper.findComponent(RegistrationDropdown); const findRegistrationDropdown = () => wrapper.findComponent(RegistrationDropdown);
const findRunnerTypeTabs = () => wrapper.findComponent(RunnerTypeTabs);
const findRunnerList = () => wrapper.findComponent(RunnerList); const findRunnerList = () => wrapper.findComponent(RunnerList);
const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination)); const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination));
const findRunnerPaginationPrev = () => const findRunnerPaginationPrev = () =>
...@@ -65,8 +71,12 @@ describe('AdminRunnersApp', () => { ...@@ -65,8 +71,12 @@ describe('AdminRunnersApp', () => {
localVue, localVue,
apolloProvider: createMockApollo(handlers), apolloProvider: createMockApollo(handlers),
propsData: { propsData: {
activeRunnersCount: mockActiveRunnersCount,
registrationToken: mockRegistrationToken, registrationToken: mockRegistrationToken,
activeRunnersCount: mockActiveRunnersCount,
allRunnersCount: mockAllRunnersCount,
instanceRunnersCount: mockInstanceRunnersCount,
groupRunnersCount: mockGroupRunnersCount,
projectRunnersCount: mockProjectRunnersCount,
...props, ...props,
}, },
}); });
...@@ -85,6 +95,16 @@ describe('AdminRunnersApp', () => { ...@@ -85,6 +95,16 @@ describe('AdminRunnersApp', () => {
wrapper.destroy(); wrapper.destroy();
}); });
it('shows the runner tabs with a runner count', async () => {
createComponent({ mountFn: mount });
await waitForPromises();
expect(findRunnerTypeTabs().text()).toMatchInterpolatedText(
`All ${mockAllRunnersCount} Instance ${mockInstanceRunnersCount} Group ${mockGroupRunnersCount} Project ${mockProjectRunnersCount}`,
);
});
it('shows the runner setup instructions', () => { it('shows the runner setup instructions', () => {
expect(findRegistrationDropdown().props('registrationToken')).toBe(mockRegistrationToken); expect(findRegistrationDropdown().props('registrationToken')).toBe(mockRegistrationToken);
expect(findRegistrationDropdown().props('type')).toBe(INSTANCE_TYPE); expect(findRegistrationDropdown().props('type')).toBe(INSTANCE_TYPE);
......
...@@ -14,11 +14,16 @@ describe('RunnerTypeTabs', () => { ...@@ -14,11 +14,16 @@ describe('RunnerTypeTabs', () => {
.filter((tab) => tab.attributes('active') === 'true') .filter((tab) => tab.attributes('active') === 'true')
.at(0); .at(0);
const createComponent = ({ value = mockSearch } = {}) => { const createComponent = ({ props, ...options } = {}) => {
wrapper = shallowMount(RunnerTypeTabs, { wrapper = shallowMount(RunnerTypeTabs, {
propsData: { propsData: {
value, value: mockSearch,
...props,
}, },
stubs: {
GlTab,
},
...options,
}); });
}; };
...@@ -31,7 +36,7 @@ describe('RunnerTypeTabs', () => { ...@@ -31,7 +36,7 @@ describe('RunnerTypeTabs', () => {
}); });
it('Renders options to filter runners', () => { it('Renders options to filter runners', () => {
expect(findTabs().wrappers.map((tab) => tab.attributes('title'))).toEqual([ expect(findTabs().wrappers.map((tab) => tab.text())).toEqual([
'All', 'All',
'Instance', 'Instance',
'Group', 'Group',
...@@ -40,18 +45,20 @@ describe('RunnerTypeTabs', () => { ...@@ -40,18 +45,20 @@ describe('RunnerTypeTabs', () => {
}); });
it('"All" is selected by default', () => { it('"All" is selected by default', () => {
expect(findActiveTab().attributes('title')).toBe('All'); expect(findActiveTab().text()).toBe('All');
}); });
it('Another tab can be preselected by the user', () => { it('Another tab can be preselected by the user', () => {
createComponent({ createComponent({
value: { props: {
...mockSearch, value: {
runnerType: INSTANCE_TYPE, ...mockSearch,
runnerType: INSTANCE_TYPE,
},
}, },
}); });
expect(findActiveTab().attributes('title')).toBe('Instance'); expect(findActiveTab().text()).toBe('Instance');
}); });
describe('When the user selects a tab', () => { describe('When the user selects a tab', () => {
...@@ -72,7 +79,31 @@ describe('RunnerTypeTabs', () => { ...@@ -72,7 +79,31 @@ describe('RunnerTypeTabs', () => {
const newValue = emittedValue(); const newValue = emittedValue();
await wrapper.setProps({ value: newValue }); await wrapper.setProps({ value: newValue });
expect(findActiveTab().attributes('title')).toBe('Group'); expect(findActiveTab().text()).toBe('Group');
});
});
describe('When using a custom slot', () => {
const mockContent = 'content';
beforeEach(() => {
createComponent({
scopedSlots: {
title: `
<span>
{{props.tab.title}} ${mockContent}
</span>`,
},
});
});
it('Renders tabs with additional information', () => {
expect(findTabs().wrappers.map((tab) => tab.text())).toEqual([
`All ${mockContent}`,
`Instance ${mockContent}`,
`Group ${mockContent}`,
`Project ${mockContent}`,
]);
}); });
}); });
}); });
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Ci::RunnersHelper do RSpec.describe Ci::RunnersHelper do
let_it_be(:user, refind: true) { create(:user) } let_it_be(:user) { create(:user) }
before do before do
allow(helper).to receive(:current_user).and_return(user) allow(helper).to receive(:current_user).and_return(user)
...@@ -12,22 +12,22 @@ RSpec.describe Ci::RunnersHelper do ...@@ -12,22 +12,22 @@ RSpec.describe Ci::RunnersHelper do
describe '#runner_status_icon', :clean_gitlab_redis_cache do describe '#runner_status_icon', :clean_gitlab_redis_cache do
it "returns - not contacted yet" do it "returns - not contacted yet" do
runner = create(:ci_runner) runner = create(:ci_runner)
expect(runner_status_icon(runner)).to include("not connected yet") expect(helper.runner_status_icon(runner)).to include("not connected yet")
end end
it "returns offline text" do it "returns offline text" do
runner = create(:ci_runner, contacted_at: 1.day.ago, active: true) runner = create(:ci_runner, contacted_at: 1.day.ago, active: true)
expect(runner_status_icon(runner)).to include("Runner is offline") expect(helper.runner_status_icon(runner)).to include("Runner is offline")
end end
it "returns online text" do it "returns online text" do
runner = create(:ci_runner, contacted_at: 1.second.ago, active: true) runner = create(:ci_runner, contacted_at: 1.second.ago, active: true)
expect(runner_status_icon(runner)).to include("Runner is online") expect(helper.runner_status_icon(runner)).to include("Runner is online")
end end
it "returns paused text" do it "returns paused text" do
runner = create(:ci_runner, contacted_at: 1.second.ago, active: false) runner = create(:ci_runner, contacted_at: 1.second.ago, active: false)
expect(runner_status_icon(runner)).to include("Runner is paused") expect(helper.runner_status_icon(runner)).to include("Runner is paused")
end end
end end
...@@ -42,7 +42,7 @@ RSpec.describe Ci::RunnersHelper do ...@@ -42,7 +42,7 @@ RSpec.describe Ci::RunnersHelper do
context 'without sorting' do context 'without sorting' do
it 'returns cached value' do it 'returns cached value' do
expect(runner_contacted_at(runner)).to eq(contacted_at_cached) expect(helper.runner_contacted_at(runner)).to eq(contacted_at_cached)
end end
end end
...@@ -52,7 +52,7 @@ RSpec.describe Ci::RunnersHelper do ...@@ -52,7 +52,7 @@ RSpec.describe Ci::RunnersHelper do
end end
it 'returns cached value' do it 'returns cached value' do
expect(runner_contacted_at(runner)).to eq(contacted_at_cached) expect(helper.runner_contacted_at(runner)).to eq(contacted_at_cached)
end end
end end
...@@ -62,11 +62,33 @@ RSpec.describe Ci::RunnersHelper do ...@@ -62,11 +62,33 @@ RSpec.describe Ci::RunnersHelper do
end end
it 'returns stored value' do it 'returns stored value' do
expect(runner_contacted_at(runner)).to eq(contacted_at_stored) expect(helper.runner_contacted_at(runner)).to eq(contacted_at_stored)
end end
end end
end end
describe '#admin_runners_data_attributes' do
let_it_be(:admin) { create(:user, :admin) }
let_it_be(:instance_runner) { create(:ci_runner, :instance) }
let_it_be(:project_runner) { create(:ci_runner, :project ) }
before do
allow(helper).to receive(:current_user).and_return(admin)
end
it 'returns the data in format' do
expect(helper.admin_runners_data_attributes).to eq({
runner_install_help_page: 'https://docs.gitlab.com/runner/install/',
registration_token: Gitlab::CurrentSettings.runners_registration_token,
active_runners_count: '0',
all_runners_count: '2',
instance_runners_count: '1',
group_runners_count: '0',
project_runners_count: '1'
})
end
end
describe '#group_shared_runners_settings_data' do describe '#group_shared_runners_settings_data' do
let_it_be(:parent) { create(:group) } let_it_be(:parent) { create(:group) }
let_it_be(:group) { create(:group, parent: parent, shared_runners_enabled: false) } let_it_be(:group) { create(:group, parent: parent, shared_runners_enabled: false) }
...@@ -86,7 +108,7 @@ RSpec.describe Ci::RunnersHelper do ...@@ -86,7 +108,7 @@ RSpec.describe Ci::RunnersHelper do
parent_shared_runners_availability: nil parent_shared_runners_availability: nil
}.merge(runner_constants) }.merge(runner_constants)
expect(group_shared_runners_settings_data(parent)).to eq result expect(helper.group_shared_runners_settings_data(parent)).to eq result
end end
it 'returns group data for child group' do it 'returns group data for child group' do
...@@ -96,7 +118,7 @@ RSpec.describe Ci::RunnersHelper do ...@@ -96,7 +118,7 @@ RSpec.describe Ci::RunnersHelper do
parent_shared_runners_availability: Namespace::SR_ENABLED parent_shared_runners_availability: Namespace::SR_ENABLED
}.merge(runner_constants) }.merge(runner_constants)
expect(group_shared_runners_settings_data(group)).to eq result expect(helper.group_shared_runners_settings_data(group)).to eq result
end end
end end
...@@ -104,7 +126,7 @@ RSpec.describe Ci::RunnersHelper do ...@@ -104,7 +126,7 @@ RSpec.describe Ci::RunnersHelper do
let(:group) { create(:group) } let(:group) { create(:group) }
it 'returns group data to render a runner list' do it 'returns group data to render a runner list' do
data = group_runners_data_attributes(group) data = helper.group_runners_data_attributes(group)
expect(data[:registration_token]).to eq(group.runners_token) expect(data[:registration_token]).to eq(group.runners_token)
expect(data[:group_id]).to eq(group.id) expect(data[:group_id]).to eq(group.id)
......
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