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:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-08-31 21:09:40 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-08-31 21:09:40 +0300
commite33402e375d7c05441d1ba6ac5030efb8a9c9537 (patch)
tree7367bd7ddcedea4d2f08294b6e6a80261fe75062 /spec/frontend
parent532c924885ebec865e0c87f484eadaf2828910e2 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/blob/line_highlighter_spec.js9
-rw-r--r--spec/frontend/tracking/internal_events_spec.js85
-rw-r--r--spec/frontend/tracking/tracking_initialization_spec.js29
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js72
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_mock_data.js7
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js31
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/components/chunk_new_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js16
9 files changed, 185 insertions, 68 deletions
diff --git a/spec/frontend/blob/line_highlighter_spec.js b/spec/frontend/blob/line_highlighter_spec.js
index de39a8f688a..c7a86d6230a 100644
--- a/spec/frontend/blob/line_highlighter_spec.js
+++ b/spec/frontend/blob/line_highlighter_spec.js
@@ -72,6 +72,15 @@ describe('LineHighlighter', () => {
expect(utils.scrollToElement).toHaveBeenCalledWith('#L5', expect.anything());
});
+ it('does not scroll to the first highlighted line when disableScroll is `true`', () => {
+ jest.spyOn(utils, 'scrollToElement');
+ const highlighter = new LineHighlighter();
+ const scrollEnabled = false;
+ highlighter.highlightHash('#L5-25', scrollEnabled);
+
+ expect(utils.scrollToElement).not.toHaveBeenCalled();
+ });
+
it('discards click events', () => {
const clickSpy = jest.fn();
diff --git a/spec/frontend/tracking/internal_events_spec.js b/spec/frontend/tracking/internal_events_spec.js
index ca244c25b06..264dee37e43 100644
--- a/spec/frontend/tracking/internal_events_spec.js
+++ b/spec/frontend/tracking/internal_events_spec.js
@@ -6,6 +6,7 @@ import {
GITLAB_INTERNAL_EVENT_CATEGORY,
SERVICE_PING_SCHEMA,
LOAD_INTERNAL_EVENTS_SELECTOR,
+ USER_CONTEXT_SCHEMA,
} from '~/tracking/constants';
import * as utils from '~/tracking/utils';
import { Tracker } from '~/tracking/tracker';
@@ -145,4 +146,88 @@ describe('InternalEvents', () => {
});
});
});
+
+ describe('initBrowserSDK', () => {
+ beforeEach(() => {
+ window.glClient = {
+ setDocumentTitle: jest.fn(),
+ page: jest.fn(),
+ };
+ window.gl = {
+ environment: 'testing',
+ key: 'value',
+ };
+ window.gl.snowplowStandardContext = {
+ schema: 'iglu:com.gitlab/gitlab_standard',
+ data: {
+ environment: 'testing',
+ key: 'value',
+ google_analytics_id: '',
+ source: 'gitlab-javascript',
+ extra: {},
+ },
+ };
+ });
+
+ it('should not call setDocumentTitle or page methods when window.glClient is undefined', () => {
+ window.glClient = undefined;
+
+ InternalEvents.initBrowserSDK();
+
+ expect(window.glClient?.setDocumentTitle).toBeUndefined();
+ expect(window.glClient?.page).toBeUndefined();
+ });
+
+ it('should call setDocumentTitle and page methods on window.glClient when it is defined', () => {
+ const mockStandardContext = window.gl.snowplowStandardContext;
+ const userContext = {
+ schema: USER_CONTEXT_SCHEMA,
+ data: mockStandardContext?.data,
+ };
+
+ InternalEvents.initBrowserSDK();
+
+ expect(window.glClient.setDocumentTitle).toHaveBeenCalledWith('GitLab');
+ expect(window.glClient.page).toHaveBeenCalledWith({
+ title: 'GitLab',
+ context: [userContext],
+ });
+ });
+
+ it('should call page method with combined standard and experiment contexts', () => {
+ const mockStandardContext = window.gl.snowplowStandardContext;
+ const userContext = {
+ schema: USER_CONTEXT_SCHEMA,
+ data: mockStandardContext?.data,
+ };
+
+ InternalEvents.initBrowserSDK();
+
+ expect(window.glClient.page).toHaveBeenCalledWith({
+ title: 'GitLab',
+ context: [userContext],
+ });
+ });
+
+ it('should call setDocumentTitle and page methods with default data when window.gl is undefined', () => {
+ window.gl = undefined;
+
+ InternalEvents.initBrowserSDK();
+
+ expect(window.glClient.setDocumentTitle).toHaveBeenCalledWith('GitLab');
+ expect(window.glClient.page).toHaveBeenCalledWith({
+ title: 'GitLab',
+ context: [
+ {
+ schema: USER_CONTEXT_SCHEMA,
+ data: {
+ google_analytics_id: '',
+ source: 'gitlab-javascript',
+ extra: {},
+ },
+ },
+ ],
+ });
+ });
+ });
});
diff --git a/spec/frontend/tracking/tracking_initialization_spec.js b/spec/frontend/tracking/tracking_initialization_spec.js
index 3c512cf73a7..2dc3c6ab41c 100644
--- a/spec/frontend/tracking/tracking_initialization_spec.js
+++ b/spec/frontend/tracking/tracking_initialization_spec.js
@@ -1,6 +1,6 @@
import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
import { getExperimentData, getAllExperimentContexts } from '~/experimentation/utils';
-import Tracking, { initUserTracking, initDefaultTrackers } from '~/tracking';
+import Tracking, { initUserTracking, initDefaultTrackers, InternalEvents } from '~/tracking';
import getStandardContext from '~/tracking/get_standard_context';
jest.mock('~/experimentation/utils', () => ({
@@ -15,6 +15,9 @@ describe('Tracking', () => {
let trackLoadEventsSpy;
let enableFormTracking;
let setAnonymousUrlsSpy;
+ let bindInternalEventDocumentSpy;
+ let trackInternalLoadEventsSpy;
+ let initBrowserSDKSpy;
beforeAll(() => {
window.gl = window.gl || {};
@@ -74,6 +77,15 @@ describe('Tracking', () => {
.spyOn(Tracking, 'enableFormTracking')
.mockImplementation(() => null);
setAnonymousUrlsSpy = jest.spyOn(Tracking, 'setAnonymousUrls').mockImplementation(() => null);
+ bindInternalEventDocumentSpy = jest
+ .spyOn(InternalEvents, 'bindInternalEventDocument')
+ .mockImplementation(() => null);
+ trackInternalLoadEventsSpy = jest
+ .spyOn(InternalEvents, 'trackInternalLoadEvents')
+ .mockImplementation(() => null);
+ initBrowserSDKSpy = jest
+ .spyOn(InternalEvents, 'initBrowserSDK')
+ .mockImplementation(() => null);
});
it('should activate features based on what has been enabled', () => {
@@ -117,6 +129,21 @@ describe('Tracking', () => {
expect(setAnonymousUrlsSpy).toHaveBeenCalled();
});
+ it('binds the document event handling for intenral events', () => {
+ initDefaultTrackers();
+ expect(bindInternalEventDocumentSpy).toHaveBeenCalled();
+ });
+
+ it('tracks page loaded events for internal events', () => {
+ initDefaultTrackers();
+ expect(trackInternalLoadEventsSpy).toHaveBeenCalled();
+ });
+
+ it('calls initBrowserSDKSpy', () => {
+ initDefaultTrackers();
+ expect(initBrowserSDKSpy).toHaveBeenCalled();
+ });
+
describe('when there are experiment contexts', () => {
const experimentContexts = [
{
diff --git a/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js
index b901b80e8bf..6f5e08a0829 100644
--- a/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js
@@ -2,7 +2,6 @@ import { mount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/alert';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
-import { visitUrl } from '~/lib/utils/url_utility';
import {
CREATED,
MANUAL_DEPLOY,
@@ -20,6 +19,7 @@ import {
deploymentMockData,
playDetails,
retryDetails,
+ mockRedeployProps,
} from './deployment_mock_data';
jest.mock('~/alert');
@@ -36,7 +36,6 @@ describe('DeploymentAction component', () => {
const findStopButton = () => wrapper.find('.js-stop-env');
const findDeployButton = () => wrapper.find('.js-manual-deploy-action');
- const findManualRedeployButton = () => wrapper.find('.js-manual-redeploy-action');
const findRedeployButton = () => wrapper.find('.js-redeploy-action');
beforeEach(() => {
@@ -78,23 +77,25 @@ describe('DeploymentAction component', () => {
expect(findDeployButton().exists()).toBe(false);
});
});
-
- describe('when there is no retry_path in details', () => {
- it('the manual redeploy button does not appear', () => {
- expect(findManualRedeployButton().exists()).toBe(false);
- });
- });
});
describe('when conditions are met', () => {
describe.each`
- configConst | computedDeploymentStatus | displayConditionChanges | finderFn | endpoint
- ${STOPPING} | ${CREATED} | ${{}} | ${findStopButton} | ${deploymentMockData.stop_url}
- ${DEPLOYING} | ${MANUAL_DEPLOY} | ${playDetails} | ${findDeployButton} | ${playDetails.playable_build.play_path}
- ${REDEPLOYING} | ${FAILED} | ${retryDetails} | ${findManualRedeployButton} | ${retryDetails.playable_build.retry_path}
+ configConst | computedDeploymentStatus | displayConditionChanges | finderFn | endpoint | props
+ ${STOPPING} | ${CREATED} | ${{}} | ${findStopButton} | ${deploymentMockData.stop_url} | ${{}}
+ ${DEPLOYING} | ${MANUAL_DEPLOY} | ${playDetails} | ${findDeployButton} | ${playDetails.playable_build.play_path} | ${{}}
+ ${REDEPLOYING} | ${FAILED} | ${{}} | ${findRedeployButton} | ${retryDetails.playable_build.retry_path} | ${mockRedeployProps}
+ ${REDEPLOYING} | ${SUCCESS} | ${{}} | ${findRedeployButton} | ${retryDetails.playable_build.retry_path} | ${mockRedeployProps}
`(
'$configConst action',
- ({ configConst, computedDeploymentStatus, displayConditionChanges, finderFn, endpoint }) => {
+ ({
+ configConst,
+ computedDeploymentStatus,
+ displayConditionChanges,
+ finderFn,
+ endpoint,
+ props,
+ }) => {
describe(`${configConst} action`, () => {
beforeEach(() => {
factory({
@@ -103,6 +104,7 @@ describe('DeploymentAction component', () => {
deployment: {
...deploymentMockData,
details: displayConditionChanges,
+ ...props,
},
},
});
@@ -163,25 +165,6 @@ describe('DeploymentAction component', () => {
expect(createAlert).not.toHaveBeenCalled();
});
- describe('response includes redirect_url', () => {
- const url = '/root/example';
- beforeEach(async () => {
- executeActionSpy.mockResolvedValueOnce({
- data: { redirect_url: url },
- });
-
- await waitForPromises();
-
- confirmAction.mockResolvedValueOnce(true);
- finderFn().trigger('click');
- });
-
- it('calls visit url with the redirect_url', () => {
- expect(visitUrl).toHaveBeenCalled();
- expect(visitUrl).toHaveBeenCalledWith(url);
- });
- });
-
describe('it should call the executeAction method', () => {
beforeEach(async () => {
jest.spyOn(wrapper.vm, 'executeAction').mockImplementation();
@@ -234,7 +217,7 @@ describe('DeploymentAction component', () => {
);
});
- describe('with the reviewAppsRedeployMrWidget feature flag turned on', () => {
+ describe('redeploy action', () => {
beforeEach(() => {
factory({
propsData: {
@@ -246,11 +229,6 @@ describe('DeploymentAction component', () => {
environment_available: false,
},
},
- provide: {
- glFeatures: {
- reviewAppsRedeployMrWidget: true,
- },
- },
});
});
@@ -304,24 +282,6 @@ describe('DeploymentAction component', () => {
expect(createAlert).not.toHaveBeenCalled();
});
- describe('response includes redirect_url', () => {
- const url = '/root/example';
- beforeEach(async () => {
- executeActionSpy.mockResolvedValueOnce({
- data: { redirect_url: url },
- });
-
- await waitForPromises();
-
- confirmAction.mockResolvedValueOnce(true);
- findRedeployButton().trigger('click');
- });
-
- it('does not call visit url', () => {
- expect(visitUrl).not.toHaveBeenCalled();
- });
- });
-
describe('it should call the executeAction method', () => {
beforeEach(async () => {
jest.spyOn(wrapper.vm, 'executeAction').mockImplementation();
diff --git a/spec/frontend/vue_merge_request_widget/deployment/deployment_mock_data.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_mock_data.js
index 374fe4e1b95..2c6a40c6e16 100644
--- a/spec/frontend/vue_merge_request_widget/deployment/deployment_mock_data.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_mock_data.js
@@ -74,4 +74,9 @@ const retryDetails = {
},
};
-export { actionButtonMocks, deploymentMockData, playDetails, retryDetails };
+const mockRedeployProps = {
+ retry_url: retryDetails.playable_build.retry_path,
+ environment_available: false,
+};
+
+export { actionButtonMocks, deploymentMockData, playDetails, retryDetails, mockRedeployProps };
diff --git a/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js
index 234491c531a..0a96feb184f 100644
--- a/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js
@@ -10,7 +10,12 @@ import {
import DeploymentComponent from '~/vue_merge_request_widget/components/deployment/deployment.vue';
import DeploymentInfo from '~/vue_merge_request_widget/components/deployment/deployment_info.vue';
import DeploymentViewButton from '~/vue_merge_request_widget/components/deployment/deployment_view_button.vue';
-import { deploymentMockData, playDetails, retryDetails } from './deployment_mock_data';
+import {
+ deploymentMockData,
+ playDetails,
+ retryDetails,
+ mockRedeployProps,
+} from './deployment_mock_data';
describe('Deployment component', () => {
let wrapper;
@@ -46,7 +51,6 @@ describe('Deployment component', () => {
};
const defaultGroup = ['.js-deploy-url', '.js-stop-env'];
const manualDeployGroup = ['.js-manual-deploy-action', ...defaultGroup];
- const manualRedeployGroup = ['.js-manual-redeploy-action', ...defaultGroup];
describe.each`
status | previous | deploymentDetails | text | actionButtons
@@ -62,7 +66,7 @@ describe('Deployment component', () => {
${SUCCESS} | ${true} | ${noDetails} | ${'Deployed to'} | ${defaultGroup}
${SUCCESS} | ${false} | ${deployDetail} | ${'Deployed to'} | ${defaultGroup}
${SUCCESS} | ${false} | ${noDetails} | ${'Deployed to'} | ${defaultGroup}
- ${FAILED} | ${true} | ${retryDetail} | ${'Failed to deploy to'} | ${manualRedeployGroup}
+ ${FAILED} | ${true} | ${retryDetail} | ${'Failed to deploy to'} | ${defaultGroup}
${FAILED} | ${true} | ${noDetails} | ${'Failed to deploy to'} | ${defaultGroup}
${FAILED} | ${false} | ${retryDetail} | ${'Failed to deploy to'} | ${noActions}
${FAILED} | ${false} | ${noDetails} | ${'Failed to deploy to'} | ${noActions}
@@ -139,6 +143,27 @@ describe('Deployment component', () => {
}
},
);
+
+ describe('redeploy action', () => {
+ beforeEach(() => {
+ factory({
+ propsData: {
+ showMetrics: false,
+ deployment: {
+ ...deploymentMockData,
+ ...mockRedeployProps,
+ },
+ },
+ });
+ });
+
+ it('shows only the redeploy button', () => {
+ expect(wrapper.find('.js-redeploy-action').exists()).toBe(true);
+ expect(wrapper.find('.js-deploy-url').exists()).toBe(false);
+ expect(wrapper.find('.js-stop-env').exists()).toBe(false);
+ expect(wrapper.find('.js-manual-deploy-action').exists()).toBe(false);
+ });
+ });
});
describe('hasExternalUrls', () => {
diff --git a/spec/frontend/vue_shared/components/source_viewer/components/chunk_new_spec.js b/spec/frontend/vue_shared/components/source_viewer/components/chunk_new_spec.js
index 1154c930e5d..852598b13dc 100644
--- a/spec/frontend/vue_shared/components/source_viewer/components/chunk_new_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/components/chunk_new_spec.js
@@ -35,6 +35,7 @@ describe('Chunk component', () => {
await nextTick();
expect(findContent().exists()).toBe(true);
+ expect(wrapper.emitted('appear')).toHaveLength(1);
});
});
diff --git a/spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js b/spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js
index 431ede17954..1a498d0c5b1 100644
--- a/spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js
@@ -58,7 +58,8 @@ describe('Source Viewer component', () => {
describe('hash highlighting', () => {
it('calls highlightHash with expected parameter', () => {
- expect(lineHighlighter.highlightHash).toHaveBeenCalledWith(hash);
+ const scrollEnabled = false;
+ expect(lineHighlighter.highlightHash).toHaveBeenCalledWith(hash, scrollEnabled);
});
});
});
diff --git a/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js
index 7998b4c17a1..2043f36443d 100644
--- a/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js
@@ -1,6 +1,4 @@
import hljs from 'highlight.js/lib/core';
-import Vue from 'vue';
-import VueRouter from 'vue-router';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
@@ -25,11 +23,10 @@ import LineHighlighter from '~/blob/line_highlighter';
import eventHub from '~/notes/event_hub';
import Tracking from '~/tracking';
-jest.mock('~/blob/line_highlighter');
+const lineHighlighter = new LineHighlighter();
+jest.mock('~/blob/line_highlighter', () => jest.fn().mockReturnValue({ highlightHash: jest.fn() }));
jest.mock('highlight.js/lib/core');
jest.mock('~/vue_shared/components/source_viewer/plugins/index');
-Vue.use(VueRouter);
-const router = new VueRouter();
const mockAxios = new MockAdapter(axios);
const generateContent = (content, totalLines = 1, delimiter = '\n') => {
@@ -45,6 +42,7 @@ const execImmediately = (callback) => callback();
describe('Source Viewer component', () => {
let wrapper;
const language = 'docker';
+ const selectedRangeHash = '#L1-2';
const mappedLanguage = ROUGE_TO_HLJS_LANGUAGE_MAP[language];
const chunk1 = generateContent('// Some source code 1', 70);
const chunk2 = generateContent('// Some source code 2', 70);
@@ -61,8 +59,8 @@ describe('Source Viewer component', () => {
const createComponent = async (blob = {}) => {
wrapper = shallowMountExtended(SourceViewer, {
- router,
propsData: { blob: { ...DEFAULT_BLOB_DATA, ...blob }, currentRef, projectPath },
+ mocks: { $route: { hash: selectedRangeHash } },
});
await waitForPromises();
};
@@ -271,6 +269,12 @@ describe('Source Viewer component', () => {
it('instantiates the lineHighlighter class', () => {
expect(LineHighlighter).toHaveBeenCalledWith({ scrollBehavior: 'auto' });
});
+
+ it('highlights the range when chunk appears', () => {
+ findChunks().at(0).vm.$emit('appear');
+ const scrollEnabled = false;
+ expect(lineHighlighter.highlightHash).toHaveBeenCalledWith(selectedRangeHash, scrollEnabled);
+ });
});
describe('Codeowners validation', () => {