Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js')
-rw-r--r--spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js334
1 files changed, 334 insertions, 0 deletions
diff --git a/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js
new file mode 100644
index 00000000000..61cbef0c557
--- /dev/null
+++ b/spec/frontend/custom_metrics/components/custom_metrics_form_fields_spec.js
@@ -0,0 +1,334 @@
+import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import { TEST_HOST } from 'helpers/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
+import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
+import axios from '~/lib/utils/axios_utils';
+
+const { CancelToken } = axios;
+
+describe('custom metrics form fields component', () => {
+ let component;
+ let mockAxios;
+
+ const getNamedInput = name => component.element.querySelector(`input[name="${name}"]`);
+ const validateQueryPath = `${TEST_HOST}/mock/path`;
+ const validQueryResponse = { data: { success: true, query: { valid: true, error: '' } } };
+ const csrfToken = 'mockToken';
+ const formOperation = 'post';
+ const debouncedValidateQueryMock = jest.fn();
+ const makeFormData = (data = {}) => ({
+ formData: {
+ title: '',
+ yLabel: '',
+ query: '',
+ unit: '',
+ group: '',
+ legend: '',
+ ...data,
+ },
+ });
+ const mountComponent = (props, methods = {}) => {
+ component = mount(CustomMetricsFormFields, {
+ propsData: {
+ formOperation,
+ validateQueryPath,
+ ...props,
+ },
+ csrfToken,
+ methods,
+ });
+ };
+
+ beforeEach(() => {
+ mockAxios = new MockAdapter(axios);
+ mockAxios.onPost(validateQueryPath).reply(validQueryResponse);
+ });
+
+ afterEach(() => {
+ component.destroy();
+ mockAxios.restore();
+ });
+
+ it('checks form validity', done => {
+ mountComponent({
+ metricPersisted: true,
+ ...makeFormData({
+ title: 'title',
+ yLabel: 'yLabel',
+ unit: 'unit',
+ group: 'group',
+ }),
+ });
+
+ component.vm.$nextTick(() => {
+ expect(component.vm.formIsValid).toBe(false);
+ done();
+ });
+ });
+
+ describe('hidden inputs', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('specifies form operation _method', () => {
+ expect(getNamedInput('_method', 'input').value).toBe('post');
+ });
+
+ it('specifies authenticity token', () => {
+ expect(getNamedInput('authenticity_token', 'input').value).toBe(csrfToken);
+ });
+ });
+
+ describe('name input', () => {
+ const name = 'prometheus_metric[title]';
+
+ it('is empty by default', () => {
+ mountComponent();
+
+ expect(getNamedInput(name).value).toBe('');
+ });
+
+ it('receives a persisted value', () => {
+ const title = 'mockTitle';
+ mountComponent(makeFormData({ title }));
+
+ expect(getNamedInput(name).value).toBe(title);
+ });
+ });
+
+ describe('group input', () => {
+ it('has a default value', () => {
+ mountComponent();
+
+ expect(getNamedInput('prometheus_metric[group]', 'glformradiogroup-stub').value).toBe(
+ 'business',
+ );
+ });
+ });
+
+ describe('query input', () => {
+ const queryInputName = 'prometheus_metric[query]';
+ beforeEach(() => {
+ mockAxios.onPost(validateQueryPath).reply(validQueryResponse);
+ });
+
+ it('is empty by default', () => {
+ mountComponent();
+
+ expect(getNamedInput(queryInputName).value).toBe('');
+ });
+
+ it('receives and validates a persisted value', () => {
+ const query = 'persistedQuery';
+ const axiosPost = jest.spyOn(axios, 'post');
+ const source = CancelToken.source();
+ mountComponent({ metricPersisted: true, ...makeFormData({ query }) });
+
+ expect(axiosPost).toHaveBeenCalledWith(
+ validateQueryPath,
+ { query },
+ { cancelToken: source.token },
+ );
+ expect(getNamedInput(queryInputName).value).toBe(query);
+ jest.runAllTimers();
+ });
+
+ it('checks validity on user input', () => {
+ const query = 'changedQuery';
+ mountComponent(
+ {},
+ {
+ debouncedValidateQuery: debouncedValidateQueryMock,
+ },
+ );
+ const queryInput = component.find(`input[name="${queryInputName}"]`);
+ queryInput.setValue(query);
+ queryInput.trigger('input');
+
+ expect(debouncedValidateQueryMock).toHaveBeenCalledWith(query);
+ });
+
+ describe('when query validation is in flight', () => {
+ beforeEach(() => {
+ jest.useFakeTimers();
+ mountComponent(
+ { metricPersisted: true, ...makeFormData({ query: 'validQuery' }) },
+ {
+ requestValidation: jest.fn().mockImplementation(
+ () =>
+ new Promise(resolve =>
+ setTimeout(() => {
+ resolve(validQueryResponse);
+ }, 4000),
+ ),
+ ),
+ },
+ );
+ });
+
+ afterEach(() => {
+ jest.clearAllTimers();
+ });
+
+ it('expect queryValidateInFlight is in flight', done => {
+ const queryInput = component.find(`input[name="${queryInputName}"]`);
+ queryInput.setValue('query');
+ queryInput.trigger('input');
+
+ component.vm.$nextTick(() => {
+ expect(component.vm.queryValidateInFlight).toBe(true);
+ jest.runOnlyPendingTimers();
+ waitForPromises()
+ .then(() => {
+ component.vm.$nextTick(() => {
+ expect(component.vm.queryValidateInFlight).toBe(false);
+ expect(component.vm.queryIsValid).toBe(true);
+ done();
+ });
+ })
+ .catch(done.fail);
+ });
+ });
+
+ it('expect loading message to display', done => {
+ const queryInput = component.find(`input[name="${queryInputName}"]`);
+ queryInput.setValue('query');
+ queryInput.trigger('input');
+ component.vm.$nextTick(() => {
+ expect(component.text()).toContain('Validating query');
+ jest.runOnlyPendingTimers();
+ done();
+ });
+ });
+
+ it('expect loading message to disappear', done => {
+ const queryInput = component.find(`input[name="${queryInputName}"]`);
+ queryInput.setValue('query');
+ queryInput.trigger('input');
+ component.vm.$nextTick(() => {
+ jest.runOnlyPendingTimers();
+ waitForPromises()
+ .then(() => {
+ component.vm.$nextTick(() => {
+ expect(component.vm.queryValidateInFlight).toBe(false);
+ expect(component.vm.queryIsValid).toBe(true);
+ expect(component.vm.errorMessage).toBe('');
+ done();
+ });
+ })
+ .catch(done.fail);
+ });
+ });
+ });
+
+ describe('when query is invalid', () => {
+ const errorMessage = 'mockErrorMessage';
+ const invalidQueryResponse = {
+ data: { success: true, query: { valid: false, error: errorMessage } },
+ };
+
+ beforeEach(() => {
+ mountComponent(
+ { metricPersisted: true, ...makeFormData({ query: 'invalidQuery' }) },
+ {
+ requestValidation: jest
+ .fn()
+ .mockImplementation(() => Promise.resolve(invalidQueryResponse)),
+ },
+ );
+ });
+
+ it('sets queryIsValid to false', done => {
+ component.vm.$nextTick(() => {
+ expect(component.vm.queryValidateInFlight).toBe(false);
+ expect(component.vm.queryIsValid).toBe(false);
+ done();
+ });
+ });
+
+ it('shows invalid query message', done => {
+ component.vm.$nextTick(() => {
+ expect(component.text()).toContain(errorMessage);
+ done();
+ });
+ });
+ });
+
+ describe('when query is valid', () => {
+ beforeEach(() => {
+ mountComponent(
+ { metricPersisted: true, ...makeFormData({ query: 'validQuery' }) },
+ {
+ requestValidation: jest
+ .fn()
+ .mockImplementation(() => Promise.resolve(validQueryResponse)),
+ },
+ );
+ });
+
+ it('sets queryIsValid to true when query is valid', done => {
+ component.vm.$nextTick(() => {
+ expect(component.vm.queryIsValid).toBe(true);
+ done();
+ });
+ });
+
+ it('shows valid query message', () => {
+ expect(component.text()).toContain('PromQL query is valid');
+ });
+ });
+ });
+
+ describe('yLabel input', () => {
+ const name = 'prometheus_metric[y_label]';
+
+ it('is empty by default', () => {
+ mountComponent();
+
+ expect(getNamedInput(name).value).toBe('');
+ });
+
+ it('receives a persisted value', () => {
+ const yLabel = 'mockYLabel';
+ mountComponent(makeFormData({ yLabel }));
+
+ expect(getNamedInput(name).value).toBe(yLabel);
+ });
+ });
+
+ describe('unit input', () => {
+ const name = 'prometheus_metric[unit]';
+
+ it('is empty by default', () => {
+ mountComponent();
+
+ expect(getNamedInput(name).value).toBe('');
+ });
+
+ it('receives a persisted value', () => {
+ const unit = 'mockUnit';
+ mountComponent(makeFormData({ unit }));
+
+ expect(getNamedInput(name).value).toBe(unit);
+ });
+ });
+
+ describe('legend input', () => {
+ const name = 'prometheus_metric[legend]';
+
+ it('is empty by default', () => {
+ mountComponent();
+
+ expect(getNamedInput(name).value).toBe('');
+ });
+
+ it('receives a persisted value', () => {
+ const legend = 'mockLegend';
+ mountComponent(makeFormData({ legend }));
+
+ expect(getNamedInput(name).value).toBe(legend);
+ });
+ });
+});