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/vue_mr_widget/mr_widget_options_spec.js')
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js236
1 files changed, 211 insertions, 25 deletions
diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
index 9719e81fe12..6abbb052aef 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -29,8 +29,11 @@ import {
workingExtension,
collapsedDataErrorExtension,
fullDataErrorExtension,
+ fullReportExtension,
+ noTelemetryExtension,
pollingExtension,
pollingErrorExtension,
+ multiPollingExtension,
} from './test_extensions';
jest.mock('~/api.js');
@@ -48,6 +51,8 @@ describe('MrWidgetOptions', () => {
const COLLABORATION_MESSAGE = 'Members who can merge are allowed to add commits';
const findExtensionToggleButton = () =>
wrapper.find('[data-testid="widget-extension"] [data-testid="toggle-button"]');
+ const findExtensionLink = (linkHref) =>
+ wrapper.find(`[data-testid="widget-extension"] [href="${linkHref}"]`);
beforeEach(() => {
gl.mrWidgetData = { ...mockData };
@@ -67,7 +72,7 @@ describe('MrWidgetOptions', () => {
gon.features = {};
});
- const createComponent = (mrData = mockData, options = {}) => {
+ const createComponent = (mrData = mockData, options = {}, glFeatures = {}) => {
if (wrapper) {
wrapper.destroy();
}
@@ -76,6 +81,9 @@ describe('MrWidgetOptions', () => {
propsData: {
mrData: { ...mrData },
},
+ provide: {
+ glFeatures,
+ },
...options,
});
@@ -423,7 +431,7 @@ describe('MrWidgetOptions', () => {
beforeEach(() => {
const favicon = document.createElement('link');
favicon.setAttribute('id', 'favicon');
- favicon.setAttribute('data-original-href', faviconDataUrl);
+ favicon.dataset.originalHref = faviconDataUrl;
document.body.appendChild(favicon);
faviconElement = document.getElementById('favicon');
@@ -621,7 +629,16 @@ describe('MrWidgetOptions', () => {
});
describe('code quality widget', () => {
- it('renders the component', () => {
+ beforeEach(() => {
+ jest.spyOn(document, 'dispatchEvent');
+ });
+ it('renders the component when refactorCodeQualityExtension is false', () => {
+ createComponent(mockData, {}, { refactorCodeQualityExtension: false });
+ expect(wrapper.find('.js-codequality-widget').exists()).toBe(true);
+ });
+
+ it('does not render the component when refactorCodeQualityExtension is true', () => {
+ createComponent(mockData, {}, { refactorCodeQualityExtension: true });
expect(wrapper.find('.js-codequality-widget').exists()).toBe(true);
});
});
@@ -911,18 +928,6 @@ describe('MrWidgetOptions', () => {
expect(wrapper.text()).toContain('Test extension summary count: 1');
});
- it('triggers trackRedisHllUserEvent API call', async () => {
- await waitForPromises();
-
- wrapper
- .find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
- .trigger('click');
-
- await nextTick();
-
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith('test_expand_event');
- });
-
it('renders full data', async () => {
await waitForPromises();
@@ -982,31 +987,98 @@ describe('MrWidgetOptions', () => {
describe('mock polling extension', () => {
let pollRequest;
- let pollStop;
+
+ const findWidgetTestExtension = () => wrapper.find('[data-testid="widget-extension"]');
beforeEach(() => {
pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
- pollStop = jest.spyOn(Poll.prototype, 'stop');
+
+ registeredExtensions.extensions = [];
});
afterEach(() => {
pollRequest.mockRestore();
- pollStop.mockRestore();
registeredExtensions.extensions = [];
+
+ // Clear all left-over timeouts that may be registered in the poll class
+ let id = window.setTimeout(() => {}, 0);
+
+ while (id > 0) {
+ window.clearTimeout(id);
+ id -= 1;
+ }
});
- describe('success', () => {
- beforeEach(() => {
- registerExtension(pollingExtension);
+ describe('success - multi polling', () => {
+ it('sets data when polling is complete', async () => {
+ registerExtension(
+ multiPollingExtension([
+ () =>
+ Promise.resolve({
+ headers: { 'poll-interval': 0 },
+ status: 200,
+ data: { reports: 'parsed' },
+ }),
+ () =>
+ Promise.resolve({
+ status: 200,
+ data: { reports: 'parsed' },
+ }),
+ ]),
+ );
- createComponent();
+ await createComponent();
+ expect(findWidgetTestExtension().html()).toContain(
+ 'Multi polling test extension reports: parsed, count: 2',
+ );
});
- it('does not make additional requests after poll is successful', () => {
+ it('shows loading state until polling is complete', async () => {
+ registerExtension(
+ multiPollingExtension([
+ () =>
+ Promise.resolve({
+ headers: { 'poll-interval': 1 },
+ status: 204,
+ }),
+ () =>
+ Promise.resolve({
+ status: 200,
+ data: { reports: 'parsed' },
+ }),
+ ]),
+ );
+
+ await createComponent();
+ expect(findWidgetTestExtension().html()).toContain('Test extension loading...');
+ });
+ });
+
+ describe('success', () => {
+ it('does not make additional requests after poll is successful', async () => {
+ registerExtension(pollingExtension);
+ await createComponent();
// called two times due to parent component polling (mount) and extension polling
expect(pollRequest).toHaveBeenCalledTimes(2);
- expect(pollStop).toHaveBeenCalledTimes(1);
+ });
+
+ it('keeps polling when poll-interval header is provided', async () => {
+ registerExtension({
+ ...pollingExtension,
+ methods: {
+ ...pollingExtension.methods,
+ fetchCollapsedData() {
+ return Promise.resolve({
+ data: {},
+ headers: { 'poll-interval': 1 },
+ status: 204,
+ });
+ },
+ },
+ });
+ await createComponent();
+ expect(findWidgetTestExtension().html()).toContain('Test extension loading...');
});
});
@@ -1024,7 +1096,6 @@ describe('MrWidgetOptions', () => {
it('does not make additional requests after poll has failed', () => {
// called two times due to parent component polling (mount) and extension polling
expect(pollRequest).toHaveBeenCalledTimes(2);
- expect(pollStop).toHaveBeenCalledTimes(1);
});
it('captures sentry error and displays error when poll has failed', () => {
@@ -1080,4 +1151,119 @@ describe('MrWidgetOptions', () => {
itHandlesTheException();
});
});
+
+ describe('telemetry', () => {
+ afterEach(() => {
+ registeredExtensions.extensions = [];
+ });
+
+ it('triggers view events when mounted', () => {
+ registerExtension(workingExtension());
+ createComponent();
+
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(1);
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_merge_request_widget_test_extension_view',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(1);
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_merge_request_widget_test_extension_count_view',
+ );
+ });
+
+ describe('expand button', () => {
+ it('triggers expand events when clicked', async () => {
+ registerExtension(workingExtension());
+ createComponent();
+
+ await waitForPromises();
+
+ api.trackRedisHllUserEvent.mockClear();
+ api.trackRedisCounterEvent.mockClear();
+
+ findExtensionToggleButton().trigger('click');
+
+ // The default working extension is a "warning" type, which generates a second - more specific - telemetry event for expansions
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(2);
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_merge_request_widget_test_extension_expand',
+ );
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_merge_request_widget_test_extension_expand_warning',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(2);
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_merge_request_widget_test_extension_count_expand',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_merge_request_widget_test_extension_count_expand_warning',
+ );
+ });
+
+ it.each`
+ widgetName | nonStandardEvent
+ ${'WidgetCodeQuality'} | ${'i_testing_code_quality_widget_total'}
+ ${'WidgetTerraform'} | ${'i_testing_terraform_widget_total'}
+ ${'WidgetIssues'} | ${'i_testing_load_performance_widget_total'}
+ ${'WidgetTestReport'} | ${'i_testing_summary_widget_total'}
+ `(
+ "sends non-standard events for the '$widgetName' widget",
+ async ({ widgetName, nonStandardEvent }) => {
+ const definition = {
+ ...workingExtension(),
+ name: widgetName,
+ };
+
+ registerExtension(definition);
+ createComponent();
+
+ await waitForPromises();
+
+ api.trackRedisHllUserEvent.mockClear();
+
+ findExtensionToggleButton().trigger('click');
+
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(nonStandardEvent);
+ },
+ );
+ });
+
+ it('triggers the "full report clicked" events when the appropriate button is clicked', () => {
+ registerExtension(fullReportExtension);
+ createComponent();
+
+ api.trackRedisHllUserEvent.mockClear();
+ api.trackRedisCounterEvent.mockClear();
+
+ findExtensionLink('testref').trigger('click');
+
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(1);
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_merge_request_widget_test_extension_click_full_report',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(1);
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_merge_request_widget_test_extension_count_click_full_report',
+ );
+ });
+
+ describe('when disabled', () => {
+ afterEach(() => {
+ registeredExtensions.extensions = [];
+ });
+
+ it("doesn't emit any telemetry events", async () => {
+ registerExtension(noTelemetryExtension);
+ createComponent();
+
+ await waitForPromises();
+
+ findExtensionToggleButton().trigger('click');
+ findExtensionLink('testref').trigger('click'); // The "full report" link
+
+ expect(api.trackRedisHllUserEvent).not.toHaveBeenCalled();
+ expect(api.trackRedisCounterEvent).not.toHaveBeenCalled();
+ });
+ });
+ });
});