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>2020-04-14 18:09:44 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-14 18:09:44 +0300
commit874ead9c3a50de4c4ca4551eaf5b7eb976d26b50 (patch)
tree637ee9f2da5e251bc08ebf3e972209d51966bf7c /spec/frontend
parent2e4c4055181eec9186458dd5dd3219c937032ec7 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js1
-rw-r--r--spec/frontend/monitoring/store/actions_spec.js111
-rw-r--r--spec/frontend/smart_interval_spec.js197
-rw-r--r--spec/frontend/static_site_editor/components/static_site_editor_spec.js9
-rw-r--r--spec/frontend/static_site_editor/store/getters_spec.js12
-rw-r--r--spec/frontend/static_site_editor/store/mutations_spec.js1
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js19
7 files changed, 297 insertions, 53 deletions
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index 3aad4c87237..870e47edde0 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -50,6 +50,7 @@ describe('Time series component', () => {
propsData: {
graphData: { ...graphData, type },
deploymentData: store.state.monitoringDashboard.deploymentData,
+ annotations: store.state.monitoringDashboard.annotations,
projectPath: `${mockHost}${mockProjectDir}`,
},
store,
diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js
index d6faec29b65..c34a5afceb0 100644
--- a/spec/frontend/monitoring/store/actions_spec.js
+++ b/spec/frontend/monitoring/store/actions_spec.js
@@ -16,6 +16,7 @@ import {
fetchDeploymentsData,
fetchEnvironmentsData,
fetchDashboardData,
+ fetchAnnotations,
fetchPrometheusMetric,
setInitialState,
filterEnvironments,
@@ -24,10 +25,12 @@ import {
} from '~/monitoring/stores/actions';
import { gqClient, parseEnvironmentsResponse } from '~/monitoring/stores/utils';
import getEnvironments from '~/monitoring/queries/getEnvironments.query.graphql';
+import getAnnotations from '~/monitoring/queries/getAnnotations.query.graphql';
import storeState from '~/monitoring/stores/state';
import {
deploymentData,
environmentData,
+ annotationsData,
metricsDashboardResponse,
metricsDashboardViewModel,
dashboardGitResponse,
@@ -120,17 +123,15 @@ describe('Monitoring store actions', () => {
});
it('setting SET_ENVIRONMENTS_FILTER should dispatch fetchEnvironmentsData', () => {
- jest.spyOn(gqClient, 'mutate').mockReturnValue(
- Promise.resolve({
- data: {
- project: {
- data: {
- environments: [],
- },
+ jest.spyOn(gqClient, 'mutate').mockReturnValue({
+ data: {
+ project: {
+ data: {
+ environments: [],
},
},
- }),
- );
+ },
+ });
return testAction(
filterEnvironments,
@@ -180,17 +181,15 @@ describe('Monitoring store actions', () => {
});
it('dispatches receiveEnvironmentsDataSuccess on success', () => {
- jest.spyOn(gqClient, 'mutate').mockReturnValue(
- Promise.resolve({
- data: {
- project: {
- data: {
- environments: environmentData,
- },
+ jest.spyOn(gqClient, 'mutate').mockResolvedValue({
+ data: {
+ project: {
+ data: {
+ environments: environmentData,
},
},
- }),
- );
+ },
+ });
return testAction(
fetchEnvironmentsData,
@@ -208,7 +207,7 @@ describe('Monitoring store actions', () => {
});
it('dispatches receiveEnvironmentsDataFailure on error', () => {
- jest.spyOn(gqClient, 'mutate').mockReturnValue(Promise.reject());
+ jest.spyOn(gqClient, 'mutate').mockRejectedValue({});
return testAction(
fetchEnvironmentsData,
@@ -220,6 +219,80 @@ describe('Monitoring store actions', () => {
});
});
+ describe('fetchAnnotations', () => {
+ const { state } = store;
+ state.projectPath = 'gitlab-org/gitlab-test';
+ state.currentEnvironmentName = 'production';
+ state.currentDashboard = '.gitlab/dashboards/custom_dashboard.yml';
+
+ afterEach(() => {
+ resetStore(store);
+ });
+
+ it('fetches annotations data and dispatches receiveAnnotationsSuccess', () => {
+ const mockMutate = jest.spyOn(gqClient, 'mutate');
+ const mutationVariables = {
+ mutation: getAnnotations,
+ variables: {
+ projectPath: state.projectPath,
+ environmentName: state.currentEnvironmentName,
+ dashboardId: state.currentDashboard,
+ },
+ };
+
+ mockMutate.mockResolvedValue({
+ data: {
+ project: {
+ environment: {
+ metricDashboard: {
+ annotations: annotationsData,
+ },
+ },
+ },
+ },
+ });
+
+ return testAction(
+ fetchAnnotations,
+ null,
+ state,
+ [],
+ [
+ { type: 'requestAnnotations' },
+ { type: 'receiveAnnotationsSuccess', payload: annotationsData },
+ ],
+ () => {
+ expect(mockMutate).toHaveBeenCalledWith(mutationVariables);
+ },
+ );
+ });
+
+ it('dispatches receiveAnnotationsFailure if the annotations API call fails', () => {
+ const mockMutate = jest.spyOn(gqClient, 'mutate');
+ const mutationVariables = {
+ mutation: getAnnotations,
+ variables: {
+ projectPath: state.projectPath,
+ environmentName: state.currentEnvironmentName,
+ dashboardId: state.currentDashboard,
+ },
+ };
+
+ mockMutate.mockRejectedValue({});
+
+ return testAction(
+ fetchAnnotations,
+ null,
+ state,
+ [],
+ [{ type: 'requestAnnotations' }, { type: 'receiveAnnotationsFailure' }],
+ () => {
+ expect(mockMutate).toHaveBeenCalledWith(mutationVariables);
+ },
+ );
+ });
+ });
+
describe('Set initial state', () => {
let mockedState;
beforeEach(() => {
diff --git a/spec/frontend/smart_interval_spec.js b/spec/frontend/smart_interval_spec.js
new file mode 100644
index 00000000000..b32ac99e4e4
--- /dev/null
+++ b/spec/frontend/smart_interval_spec.js
@@ -0,0 +1,197 @@
+import $ from 'jquery';
+import { assignIn } from 'lodash';
+import waitForPromises from 'helpers/wait_for_promises';
+import SmartInterval from '~/smart_interval';
+
+jest.useFakeTimers();
+
+let interval;
+
+describe('SmartInterval', () => {
+ const DEFAULT_MAX_INTERVAL = 100;
+ const DEFAULT_STARTING_INTERVAL = 5;
+ const DEFAULT_INCREMENT_FACTOR = 2;
+
+ function createDefaultSmartInterval(config) {
+ const defaultParams = {
+ callback: () => Promise.resolve(),
+ startingInterval: DEFAULT_STARTING_INTERVAL,
+ maxInterval: DEFAULT_MAX_INTERVAL,
+ incrementByFactorOf: DEFAULT_INCREMENT_FACTOR,
+ lazyStart: false,
+ immediateExecution: false,
+ hiddenInterval: null,
+ };
+
+ if (config) {
+ assignIn(defaultParams, config);
+ }
+
+ return new SmartInterval(defaultParams);
+ }
+
+ afterEach(() => {
+ interval.destroy();
+ });
+
+ describe('Increment Interval', () => {
+ it('should increment the interval delay', () => {
+ interval = createDefaultSmartInterval();
+
+ jest.runOnlyPendingTimers();
+
+ return waitForPromises().then(() => {
+ const intervalConfig = interval.cfg;
+ const iterationCount = 4;
+ const maxIntervalAfterIterations =
+ intervalConfig.startingInterval * intervalConfig.incrementByFactorOf ** iterationCount;
+ const currentInterval = interval.getCurrentInterval();
+
+ // Provide some flexibility for performance of testing environment
+ expect(currentInterval).toBeGreaterThan(intervalConfig.startingInterval);
+ expect(currentInterval).toBeLessThanOrEqual(maxIntervalAfterIterations);
+ });
+ });
+
+ it('should not increment past maxInterval', () => {
+ interval = createDefaultSmartInterval({ maxInterval: DEFAULT_STARTING_INTERVAL });
+
+ jest.runOnlyPendingTimers();
+
+ return waitForPromises().then(() => {
+ const currentInterval = interval.getCurrentInterval();
+
+ expect(currentInterval).toBe(interval.cfg.maxInterval);
+ });
+ });
+
+ it('does not increment while waiting for callback', () => {
+ interval = createDefaultSmartInterval({
+ callback: () => new Promise($.noop),
+ });
+
+ jest.runOnlyPendingTimers();
+
+ return waitForPromises().then(() => {
+ const oneInterval = interval.cfg.startingInterval * DEFAULT_INCREMENT_FACTOR;
+
+ expect(interval.getCurrentInterval()).toEqual(oneInterval);
+ });
+ });
+ });
+
+ describe('Public methods', () => {
+ beforeEach(() => {
+ interval = createDefaultSmartInterval();
+ });
+
+ it('should cancel an interval', () => {
+ jest.runOnlyPendingTimers();
+
+ interval.cancel();
+
+ return waitForPromises().then(() => {
+ const { intervalId } = interval.state;
+ const currentInterval = interval.getCurrentInterval();
+ const intervalLowerLimit = interval.cfg.startingInterval;
+
+ expect(intervalId).toBeUndefined();
+ expect(currentInterval).toBe(intervalLowerLimit);
+ });
+ });
+
+ it('should resume an interval', () => {
+ jest.runOnlyPendingTimers();
+
+ interval.cancel();
+
+ interval.resume();
+
+ return waitForPromises().then(() => {
+ const { intervalId } = interval.state;
+
+ expect(intervalId).toBeTruthy();
+ });
+ });
+ });
+
+ describe('DOM Events', () => {
+ beforeEach(() => {
+ // This ensures DOM and DOM events are initialized for these specs.
+ setFixtures('<div></div>');
+
+ interval = createDefaultSmartInterval();
+ });
+
+ it('should pause when page is not visible', () => {
+ jest.runOnlyPendingTimers();
+
+ return waitForPromises().then(() => {
+ expect(interval.state.intervalId).toBeTruthy();
+
+ // simulates triggering of visibilitychange event
+ interval.onVisibilityChange({ target: { visibilityState: 'hidden' } });
+
+ expect(interval.state.intervalId).toBeUndefined();
+ });
+ });
+
+ it('should change to the hidden interval when page is not visible', () => {
+ interval.destroy();
+
+ const HIDDEN_INTERVAL = 1500;
+ interval = createDefaultSmartInterval({ hiddenInterval: HIDDEN_INTERVAL });
+
+ jest.runOnlyPendingTimers();
+
+ return waitForPromises().then(() => {
+ expect(interval.state.intervalId).toBeTruthy();
+ expect(
+ interval.getCurrentInterval() >= DEFAULT_STARTING_INTERVAL &&
+ interval.getCurrentInterval() <= DEFAULT_MAX_INTERVAL,
+ ).toBeTruthy();
+
+ // simulates triggering of visibilitychange event
+ interval.onVisibilityChange({ target: { visibilityState: 'hidden' } });
+
+ expect(interval.state.intervalId).toBeTruthy();
+ expect(interval.getCurrentInterval()).toBe(HIDDEN_INTERVAL);
+ });
+ });
+
+ it('should resume when page is becomes visible at the previous interval', () => {
+ jest.runOnlyPendingTimers();
+
+ return waitForPromises().then(() => {
+ expect(interval.state.intervalId).toBeTruthy();
+
+ // simulates triggering of visibilitychange event
+ interval.onVisibilityChange({ target: { visibilityState: 'hidden' } });
+
+ expect(interval.state.intervalId).toBeUndefined();
+
+ // simulates triggering of visibilitychange event
+ interval.onVisibilityChange({ target: { visibilityState: 'visible' } });
+
+ expect(interval.state.intervalId).toBeTruthy();
+ });
+ });
+
+ it('should cancel on page unload', () => {
+ jest.runOnlyPendingTimers();
+
+ return waitForPromises().then(() => {
+ $(document).triggerHandler('beforeunload');
+
+ expect(interval.state.intervalId).toBeUndefined();
+ expect(interval.getCurrentInterval()).toBe(interval.cfg.startingInterval);
+ });
+ });
+
+ it('should execute callback before first interval', () => {
+ interval = createDefaultSmartInterval({ immediateExecution: true });
+
+ expect(interval.cfg.immediateExecution).toBeFalsy();
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/components/static_site_editor_spec.js b/spec/frontend/static_site_editor/components/static_site_editor_spec.js
index a40f8edbeb2..2c4fa0e061a 100644
--- a/spec/frontend/static_site_editor/components/static_site_editor_spec.js
+++ b/spec/frontend/static_site_editor/components/static_site_editor_spec.js
@@ -30,7 +30,6 @@ describe('StaticSiteEditor', () => {
store = new Vuex.Store({
state: createState(initialState),
getters: {
- isContentLoaded: () => false,
contentChanged: () => false,
...getters,
},
@@ -43,9 +42,11 @@ describe('StaticSiteEditor', () => {
};
const buildContentLoadedStore = ({ initialState, getters } = {}) => {
buildStore({
- initialState,
+ initialState: {
+ isContentLoaded: true,
+ ...initialState,
+ },
getters: {
- isContentLoaded: () => true,
...getters,
},
});
@@ -85,7 +86,7 @@ describe('StaticSiteEditor', () => {
const content = 'edit area content';
beforeEach(() => {
- buildStore({ initialState: { content }, getters: { isContentLoaded: () => true } });
+ buildContentLoadedStore({ initialState: { content } });
buildWrapper();
});
diff --git a/spec/frontend/static_site_editor/store/getters_spec.js b/spec/frontend/static_site_editor/store/getters_spec.js
index 1b482db9366..5793e344784 100644
--- a/spec/frontend/static_site_editor/store/getters_spec.js
+++ b/spec/frontend/static_site_editor/store/getters_spec.js
@@ -1,18 +1,8 @@
import createState from '~/static_site_editor/store/state';
-import { isContentLoaded, contentChanged } from '~/static_site_editor/store/getters';
+import { contentChanged } from '~/static_site_editor/store/getters';
import { sourceContent as content } from '../mock_data';
describe('Static Site Editor Store getters', () => {
- describe('isContentLoaded', () => {
- it('returns true when originalContent is not empty', () => {
- expect(isContentLoaded(createState({ originalContent: content }))).toBe(true);
- });
-
- it('returns false when originalContent is empty', () => {
- expect(isContentLoaded(createState({ originalContent: '' }))).toBe(false);
- });
- });
-
describe('contentChanged', () => {
it('returns true when content and originalContent are different', () => {
const state = createState({ content, originalContent: 'something else' });
diff --git a/spec/frontend/static_site_editor/store/mutations_spec.js b/spec/frontend/static_site_editor/store/mutations_spec.js
index 1fd687eed4a..0b213c11a04 100644
--- a/spec/frontend/static_site_editor/store/mutations_spec.js
+++ b/spec/frontend/static_site_editor/store/mutations_spec.js
@@ -19,6 +19,7 @@ describe('Static Site Editor Store mutations', () => {
mutation | stateProperty | payload | expectedValue
${types.LOAD_CONTENT} | ${'isLoadingContent'} | ${undefined} | ${true}
${types.RECEIVE_CONTENT_SUCCESS} | ${'isLoadingContent'} | ${contentLoadedPayload} | ${false}
+ ${types.RECEIVE_CONTENT_SUCCESS} | ${'isContentLoaded'} | ${contentLoadedPayload} | ${true}
${types.RECEIVE_CONTENT_SUCCESS} | ${'title'} | ${contentLoadedPayload} | ${title}
${types.RECEIVE_CONTENT_SUCCESS} | ${'content'} | ${contentLoadedPayload} | ${content}
${types.RECEIVE_CONTENT_SUCCESS} | ${'originalContent'} | ${contentLoadedPayload} | ${content}
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 ef95cb1b8f2..e022f68fdec 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -273,25 +273,6 @@ describe('mrWidgetOptions', () => {
};
});
- it('should not tell service to check status if document is not visible', () => {
- Object.defineProperty(document, 'visibilityState', {
- value: 'hidden',
- configurable: true,
- });
- vm.checkStatus(cb);
-
- return vm.$nextTick().then(() => {
- expect(vm.service.checkStatus).not.toHaveBeenCalled();
- expect(vm.mr.setData).not.toHaveBeenCalled();
- expect(vm.handleNotification).not.toHaveBeenCalled();
- expect(isCbExecuted).toBeFalsy();
- Object.defineProperty(document, 'visibilityState', {
- value: 'visible',
- configurable: true,
- });
- });
- });
-
it('should tell service to check status if document is visible', () => {
vm.checkStatus(cb);