Commit 8448931b authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'mrincon/runner-badge-vue' into 'master'

Fetch runner type in runner details using graphql

See merge request gitlab-org/gitlab!60019
parents add45945 4b03eeb5
<script>
import { GlBadge } from '@gitlab/ui';
import { s__ } from '~/locale';
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '../constants';
const badge = {
[INSTANCE_TYPE]: {
variant: 'success',
text: s__('Runners|shared'),
},
[GROUP_TYPE]: {
variant: 'success',
text: s__('Runners|group'),
},
[PROJECT_TYPE]: {
variant: 'info',
text: s__('Runners|specific'),
},
};
export default {
components: {
GlBadge,
},
props: {
type: {
type: String,
required: true,
},
},
computed: {
variant() {
return badge[this.type]?.variant;
},
text() {
return badge[this.type]?.text;
},
},
};
</script>
<template>
<gl-badge v-if="text" :variant="variant" v-bind="$attrs">
{{ text }}
</gl-badge>
</template>
import { s__ } from '~/locale';
export const I18N_DETAILS_TITLE = s__('Runners|Runner #%{runner_id}');
export const RUNNER_ENTITY_TYPE = 'Ci::Runner';
// CiRunnerType
export const INSTANCE_TYPE = 'INSTANCE_TYPE';
export const GROUP_TYPE = 'GROUP_TYPE';
export const PROJECT_TYPE = 'PROJECT_TYPE';
query getRunner($id: CiRunnerID!) {
runner(id: $id) {
id
runnerType
}
}
import { s__ } from '~/locale';
export const I18N_TITLE = s__('Runners|Runner #%{runner_id}');
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import RunnerDetailsApp from './runner_details_app.vue';
export const initRunnerDetail = (selector = '#js-runner-detail') => {
Vue.use(VueApollo);
export const initRunnerDetail = (selector = '#js-runner-details') => {
const el = document.querySelector(selector);
if (!el) {
......@@ -10,8 +14,18 @@ export const initRunnerDetail = (selector = '#js-runner-detail') => {
const { runnerId } = el.dataset;
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(
{},
{
assumeImmutableResults: true,
},
),
});
return new Vue({
el,
apolloProvider,
render(h) {
return h(RunnerDetailsApp, {
props: {
......
<script>
import { I18N_TITLE } from './constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import RunnerTypeBadge from '../components/runner_type_badge.vue';
import { I18N_DETAILS_TITLE, RUNNER_ENTITY_TYPE } from '../constants';
import getRunnerQuery from '../graphql/get_runner.query.graphql';
export default {
components: {
RunnerTypeBadge,
},
i18n: {
I18N_TITLE,
I18N_DETAILS_TITLE,
},
props: {
runnerId: {
......@@ -11,10 +17,27 @@ export default {
required: true,
},
},
data() {
return {
runner: {},
};
},
apollo: {
runner: {
query: getRunnerQuery,
variables() {
return {
id: convertToGraphQLId(RUNNER_ENTITY_TYPE, this.runnerId),
};
},
},
},
};
</script>
<template>
<h2 class="page-title">
{{ sprintf($options.i18n.I18N_TITLE, { runner_id: runnerId }) }}
{{ sprintf($options.i18n.I18N_DETAILS_TITLE, { runner_id: runnerId }) }}
<runner-type-badge v-if="runner.runnerType" :type="runner.runnerType" />
</h2>
</template>
......@@ -5,7 +5,7 @@
- add_to_breadcrumbs _('Runners'), admin_runners_path
- if Feature.enabled?(:runner_detailed_view_vue_ui, current_user, default_enabled: :yaml)
#js-runner-detail{ data: {runner_id: @runner.id} }
#js-runner-details{ data: {runner_id: @runner.id} }
- else
%h2.page-title
= s_('Runners|Runner #%{runner_id}' % { runner_id: @runner.id })
......
import { GlBadge } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import RunnerTypeBadge from '~/runner/components/runner_type_badge.vue';
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
describe('RunnerTypeBadge', () => {
let wrapper;
const findBadge = () => wrapper.findComponent(GlBadge);
const createComponent = ({ props = {} } = {}) => {
wrapper = shallowMount(RunnerTypeBadge, {
propsData: {
...props,
},
});
};
afterEach(() => {
wrapper.destroy();
});
it.each`
type | text | variant
${INSTANCE_TYPE} | ${'shared'} | ${'success'}
${GROUP_TYPE} | ${'group'} | ${'success'}
${PROJECT_TYPE} | ${'specific'} | ${'info'}
`('displays $type runner with as "$text" with a $variant variant ', ({ type, text, variant }) => {
createComponent({ props: { type } });
expect(findBadge().text()).toBe(text);
expect(findBadge().props('variant')).toBe(variant);
});
it('does not display a badge when type is unknown', () => {
createComponent({ props: { type: 'AN_UNKNOWN_VALUE' } });
expect(findBadge().exists()).toBe(false);
});
});
import { shallowMount } from '@vue/test-utils';
import RunnerDetailsApp from '~/runner/runner_details/runner_details_app.vue';
const mockRunnerId = '55';
describe('RunnerDetailsApp', () => {
let wrapper;
const createComponent = (props) => {
wrapper = shallowMount(RunnerDetailsApp, {
propsData: {
runnerId: mockRunnerId,
...props,
},
});
};
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('displays the runner id', () => {
expect(wrapper.text()).toContain('Runner #55');
});
});
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import RunnerTypeBadge from '~/runner/components/runner_type_badge.vue';
import { INSTANCE_TYPE } from '~/runner/constants';
import getRunnerQuery from '~/runner/graphql/get_runner.query.graphql';
import RunnerDetailsApp from '~/runner/runner_details/runner_details_app.vue';
const mockRunnerId = '55';
const localVue = createLocalVue();
localVue.use(VueApollo);
describe('RunnerDetailsApp', () => {
let wrapper;
let mockRunnerQuery;
const findRunnerTypeBadge = () => wrapper.findComponent(RunnerTypeBadge);
const createComponentWithApollo = ({ props = {}, mountFn = shallowMount } = {}) => {
const handlers = [[getRunnerQuery, mockRunnerQuery]];
wrapper = mountFn(RunnerDetailsApp, {
localVue,
apolloProvider: createMockApollo(handlers),
propsData: {
runnerId: mockRunnerId,
...props,
},
});
return waitForPromises();
};
beforeEach(async () => {
mockRunnerQuery = jest.fn().mockResolvedValue({
data: {
runner: {
id: `gid://gitlab/Ci::Runner/${mockRunnerId}`,
runnerType: INSTANCE_TYPE,
__typename: 'CiRunner',
},
},
});
});
afterEach(() => {
mockRunnerQuery.mockReset();
wrapper.destroy();
});
it('expect GraphQL ID to be requested', async () => {
await createComponentWithApollo();
expect(mockRunnerQuery).toHaveBeenCalledWith({ id: `gid://gitlab/Ci::Runner/${mockRunnerId}` });
});
it('displays the runner id', async () => {
await createComponentWithApollo();
expect(wrapper.text()).toContain('Runner #55');
});
it('displays the runner type', async () => {
await createComponentWithApollo({ mountFn: mount });
expect(findRunnerTypeBadge().text()).toBe('shared');
});
});
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