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
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-11-17 00:08:11 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-11-17 00:08:11 +0300
commit19db7fd1fefc4e4249d4e55f409f321fdb85aed1 (patch)
tree0093c7fa3eb11954b49c828b78caae28f5fb97c2 /spec
parent8fa0c53e26c947ac647b8067fde3e9673b77b1a6 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/users/active_sessions_spec.rb26
-rw-r--r--spec/frontend/boards/mock_data.js12
-rw-r--r--spec/frontend/ci/runner/components/search_tokens/tag_token_spec.js4
-rw-r--r--spec/frontend/fixtures/freeze_period.rb9
-rw-r--r--spec/frontend/issues/list/mock_data.js34
-rw-r--r--spec/frontend/jobs/components/filtered_search/jobs_filtered_search_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js4
-rw-r--r--spec/frontend/pipelines/components/pipelines_filtered_search_spec.js12
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_closed_spec.js141
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js18
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js6
-rw-r--r--spec/lib/banzai/filter/syntax_highlight_filter_spec.rb4
-rw-r--r--spec/lib/banzai/filter/timeout_html_pipeline_filter_spec.rb34
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb5
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb8
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb2
-rw-r--r--spec/lib/gitlab/auth/unique_ips_limiter_spec.rb10
-rw-r--r--spec/lib/gitlab/checks/timed_logger_spec.rb44
-rw-r--r--spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb22
-rw-r--r--spec/lib/gitlab/git/cross_repo_comparer_spec.rb117
-rw-r--r--spec/lib/gitlab/git/cross_repo_spec.rb83
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb46
-rw-r--r--spec/lib/gitlab/puma_logging/json_formatter_spec.rb4
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb17
-rw-r--r--spec/lib/json_web_token/hmac_token_spec.rb20
-rw-r--r--spec/lib/peek/views/active_record_spec.rb2
-rw-r--r--spec/models/project_spec.rb47
-rw-r--r--spec/requests/api/settings_spec.rb8
-rw-r--r--spec/requests/api/usage_data_queries_spec.rb2
-rw-r--r--spec/serializers/entity_date_helper_spec.rb6
-rw-r--r--spec/services/ci/create_pipeline_service/rules_spec.rb8
-rw-r--r--spec/support/banzai/filter_timeout_shared_examples.rb37
-rw-r--r--spec/support/cycle_analytics_helpers/test_generation.rb28
-rw-r--r--spec/support/helpers/features/runners_helpers.rb2
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb4
-rw-r--r--spec/support/shared_contexts/rack_attack_shared_context.rb2
-rw-r--r--spec/support/shared_examples/requests/rack_attack_shared_examples.rb3
-rw-r--r--spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb13
39 files changed, 518 insertions, 338 deletions
diff --git a/spec/features/users/active_sessions_spec.rb b/spec/features/users/active_sessions_spec.rb
index e2ee78a7cc5..1605073acda 100644
--- a/spec/features/users/active_sessions_spec.rb
+++ b/spec/features/users/active_sessions_spec.rb
@@ -4,25 +4,29 @@ require 'spec_helper'
RSpec.describe 'Active user sessions', :clean_gitlab_redis_sessions do
it 'successful login adds a new active user login' do
+ user = create(:user)
+
now = Time.zone.parse('2018-03-12 09:06')
- Timecop.freeze(now) do
- user = create(:user)
+ travel_to(now) do
gitlab_sign_in(user)
expect(page).to have_current_path root_path, ignore_query: true
sessions = ActiveSession.list(user)
expect(sessions.count).to eq 1
+ gitlab_sign_out
+ end
- # refresh the current page updates the updated_at
- Timecop.freeze(now + 1.minute) do
- visit current_path
+ # refresh the current page updates the updated_at
+ travel_to(now + 1.minute) do
+ gitlab_sign_in(user)
+
+ visit current_path
- sessions = ActiveSession.list(user)
- expect(sessions.first).to have_attributes(
- created_at: Time.zone.parse('2018-03-12 09:06'),
- updated_at: Time.zone.parse('2018-03-12 09:07')
- )
- end
+ sessions = ActiveSession.list(user)
+ expect(sessions.first).to have_attributes(
+ created_at: Time.zone.parse('2018-03-12 09:06'),
+ updated_at: Time.zone.parse('2018-03-12 09:07')
+ )
end
end
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index 3c26fa97338..0cdab747a8d 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -2,8 +2,8 @@ import { GlFilteredSearchToken } from '@gitlab/ui';
import { keyBy } from 'lodash';
import { ListType } from '~/boards/constants';
import {
- OPERATOR_IS_AND_IS_NOT,
- OPERATOR_IS_ONLY,
+ OPERATORS_IS_NOT,
+ OPERATORS_IS,
TOKEN_TITLE_ASSIGNEE,
TOKEN_TITLE_AUTHOR,
TOKEN_TITLE_LABEL,
@@ -747,7 +747,7 @@ export const mockConfidentialToken = {
title: 'Confidential',
unique: true,
token: GlFilteredSearchToken,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
options: [
{ icon: 'eye-slash', value: 'yes', title: 'Yes' },
{ icon: 'eye', value: 'no', title: 'No' },
@@ -759,7 +759,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI
icon: 'user',
title: TOKEN_TITLE_ASSIGNEE,
type: TOKEN_TYPE_ASSIGNEE,
- operators: OPERATOR_IS_AND_IS_NOT,
+ operators: OPERATORS_IS_NOT,
token: AuthorToken,
unique: true,
fetchAuthors,
@@ -769,7 +769,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI
icon: 'pencil',
title: TOKEN_TITLE_AUTHOR,
type: TOKEN_TYPE_AUTHOR,
- operators: OPERATOR_IS_AND_IS_NOT,
+ operators: OPERATORS_IS_NOT,
symbol: '@',
token: AuthorToken,
unique: true,
@@ -780,7 +780,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedI
icon: 'labels',
title: TOKEN_TITLE_LABEL,
type: TOKEN_TYPE_LABEL,
- operators: OPERATOR_IS_AND_IS_NOT,
+ operators: OPERATORS_IS_NOT,
token: LabelToken,
unique: false,
symbol: '~',
diff --git a/spec/frontend/ci/runner/components/search_tokens/tag_token_spec.js b/spec/frontend/ci/runner/components/search_tokens/tag_token_spec.js
index d3c7ea50f9d..3dce5a509ca 100644
--- a/spec/frontend/ci/runner/components/search_tokens/tag_token_spec.js
+++ b/spec/frontend/ci/runner/components/search_tokens/tag_token_spec.js
@@ -7,7 +7,7 @@ import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import TagToken, { TAG_SUGGESTIONS_PATH } from '~/ci/runner/components/search_tokens/tag_token.vue';
-import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
+import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
import { getRecentlyUsedSuggestions } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
jest.mock('~/flash');
@@ -42,7 +42,7 @@ const mockTagTokenConfig = {
type: 'tag',
token: TagToken,
recentSuggestionsStorageKey: mockStorageKey,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
};
describe('TagToken', () => {
diff --git a/spec/frontend/fixtures/freeze_period.rb b/spec/frontend/fixtures/freeze_period.rb
index 5aa466ef015..a1c7564d36e 100644
--- a/spec/frontend/fixtures/freeze_period.rb
+++ b/spec/frontend/fixtures/freeze_period.rb
@@ -13,15 +13,6 @@ RSpec.describe 'Freeze Periods (JavaScript fixtures)' do
remove_repository(project)
end
- around do |example|
- freeze_time do
- # Mock time to sept 19 (intl. talk like a pirate day)
- travel_to(Time.utc(2020, 9, 19))
-
- example.run
- end
- end
-
describe API::FreezePeriods, '(JavaScript fixtures)', type: :request do
include ApiHelpers
diff --git a/spec/frontend/issues/list/mock_data.js b/spec/frontend/issues/list/mock_data.js
index 62fcbf7aad0..72d3fe93745 100644
--- a/spec/frontend/issues/list/mock_data.js
+++ b/spec/frontend/issues/list/mock_data.js
@@ -1,7 +1,7 @@
import {
FILTERED_SEARCH_TERM,
OPERATOR_IS,
- OPERATOR_IS_NOT,
+ OPERATOR_NOT,
OPERATOR_OR,
TOKEN_TYPE_ASSIGNEE,
TOKEN_TYPE_AUTHOR,
@@ -184,41 +184,41 @@ export const locationSearchWithSpecialValues = [
export const filteredTokens = [
{ type: TOKEN_TYPE_AUTHOR, value: { data: 'homer', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_AUTHOR, value: { data: 'marge', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_AUTHOR, value: { data: 'marge', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_ASSIGNEE, value: { data: 'bart', operator: OPERATOR_IS } },
{ type: TOKEN_TYPE_ASSIGNEE, value: { data: 'lisa', operator: OPERATOR_IS } },
{ type: TOKEN_TYPE_ASSIGNEE, value: { data: '5', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_ASSIGNEE, value: { data: 'patty', operator: OPERATOR_IS_NOT } },
- { type: TOKEN_TYPE_ASSIGNEE, value: { data: 'selma', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_ASSIGNEE, value: { data: 'patty', operator: OPERATOR_NOT } },
+ { type: TOKEN_TYPE_ASSIGNEE, value: { data: 'selma', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_ASSIGNEE, value: { data: 'carl', operator: OPERATOR_OR } },
{ type: TOKEN_TYPE_ASSIGNEE, value: { data: 'lenny', operator: OPERATOR_OR } },
{ type: TOKEN_TYPE_MILESTONE, value: { data: 'season 3', operator: OPERATOR_IS } },
{ type: TOKEN_TYPE_MILESTONE, value: { data: 'season 4', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_MILESTONE, value: { data: 'season 20', operator: OPERATOR_IS_NOT } },
- { type: TOKEN_TYPE_MILESTONE, value: { data: 'season 30', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_MILESTONE, value: { data: 'season 20', operator: OPERATOR_NOT } },
+ { type: TOKEN_TYPE_MILESTONE, value: { data: 'season 30', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_LABEL, value: { data: 'cartoon', operator: OPERATOR_IS } },
{ type: TOKEN_TYPE_LABEL, value: { data: 'tv', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_LABEL, value: { data: 'live action', operator: OPERATOR_IS_NOT } },
- { type: TOKEN_TYPE_LABEL, value: { data: 'drama', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_LABEL, value: { data: 'live action', operator: OPERATOR_NOT } },
+ { type: TOKEN_TYPE_LABEL, value: { data: 'drama', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_RELEASE, value: { data: 'v3', operator: OPERATOR_IS } },
{ type: TOKEN_TYPE_RELEASE, value: { data: 'v4', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_RELEASE, value: { data: 'v20', operator: OPERATOR_IS_NOT } },
- { type: TOKEN_TYPE_RELEASE, value: { data: 'v30', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_RELEASE, value: { data: 'v20', operator: OPERATOR_NOT } },
+ { type: TOKEN_TYPE_RELEASE, value: { data: 'v30', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_TYPE, value: { data: 'issue', operator: OPERATOR_IS } },
{ type: TOKEN_TYPE_TYPE, value: { data: 'feature', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_TYPE, value: { data: 'bug', operator: OPERATOR_IS_NOT } },
- { type: TOKEN_TYPE_TYPE, value: { data: 'incident', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_TYPE, value: { data: 'bug', operator: OPERATOR_NOT } },
+ { type: TOKEN_TYPE_TYPE, value: { data: 'incident', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_MY_REACTION, value: { data: 'thumbsup', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_MY_REACTION, value: { data: 'thumbsdown', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_MY_REACTION, value: { data: 'thumbsdown', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_CONFIDENTIAL, value: { data: 'yes', operator: OPERATOR_IS } },
{ type: TOKEN_TYPE_ITERATION, value: { data: '4', operator: OPERATOR_IS } },
{ type: TOKEN_TYPE_ITERATION, value: { data: '12', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_ITERATION, value: { data: '20', operator: OPERATOR_IS_NOT } },
- { type: TOKEN_TYPE_ITERATION, value: { data: '42', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_ITERATION, value: { data: '20', operator: OPERATOR_NOT } },
+ { type: TOKEN_TYPE_ITERATION, value: { data: '42', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_EPIC, value: { data: '12', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_EPIC, value: { data: '34', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_EPIC, value: { data: '34', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_WEIGHT, value: { data: '1', operator: OPERATOR_IS } },
- { type: TOKEN_TYPE_WEIGHT, value: { data: '3', operator: OPERATOR_IS_NOT } },
+ { type: TOKEN_TYPE_WEIGHT, value: { data: '3', operator: OPERATOR_NOT } },
{ type: TOKEN_TYPE_CONTACT, value: { data: '123', operator: OPERATOR_IS } },
{ type: TOKEN_TYPE_ORGANIZATION, value: { data: '456', operator: OPERATOR_IS } },
{ type: FILTERED_SEARCH_TERM, value: { data: 'find' } },
diff --git a/spec/frontend/jobs/components/filtered_search/jobs_filtered_search_spec.js b/spec/frontend/jobs/components/filtered_search/jobs_filtered_search_spec.js
index 98bdfc3fcbc..fcdb162dfed 100644
--- a/spec/frontend/jobs/components/filtered_search/jobs_filtered_search_spec.js
+++ b/spec/frontend/jobs/components/filtered_search/jobs_filtered_search_spec.js
@@ -1,6 +1,6 @@
import { GlFilteredSearch } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
+import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
import JobsFilteredSearch from '~/jobs/components/filtered_search/jobs_filtered_search.vue';
import { mockFailedSearchToken } from '../../mock_data';
@@ -41,7 +41,7 @@ describe('Jobs filtered search', () => {
icon: 'status',
title: 'Status',
unique: true,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
});
});
diff --git a/spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js b/spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js
index 8fd50bea280..69765d31674 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js
@@ -8,7 +8,7 @@ import ArtifactsList from '~/packages_and_registries/harbor_registry/components/
import waitForPromises from 'helpers/wait_for_promises';
import DetailsHeader from '~/packages_and_registries/harbor_registry/components/details/details_header.vue';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
-import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
+import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
import {
NAME_SORT_FIELD,
TOKEN_TYPE_TAG_NAME,
@@ -137,7 +137,7 @@ describe('Harbor Details Page', () => {
title: s__('HarborRegistry|Tag'),
unique: true,
token: GlFilteredSearchToken,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
},
],
});
diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
index ee3eaaf5ef3..e5ad735bf66 100644
--- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
@@ -6,7 +6,7 @@ import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import PipelinesFilteredSearch from '~/pipelines/components/pipelines_list/pipelines_filtered_search.vue';
-import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
+import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
import { TRACKING_CATEGORIES } from '~/pipelines/constants';
import { users, mockSearch, branches, tags } from '../mock_data';
@@ -63,7 +63,7 @@ describe('Pipelines filtered search', () => {
title: 'Trigger author',
unique: true,
projectId: '21',
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
});
expect(findBranchToken()).toMatchObject({
@@ -73,7 +73,7 @@ describe('Pipelines filtered search', () => {
unique: true,
projectId: '21',
defaultBranchName: 'main',
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
});
expect(findSourceToken()).toMatchObject({
@@ -81,7 +81,7 @@ describe('Pipelines filtered search', () => {
icon: 'trigger-source',
title: 'Source',
unique: true,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
});
expect(findStatusToken()).toMatchObject({
@@ -89,7 +89,7 @@ describe('Pipelines filtered search', () => {
icon: 'status',
title: 'Status',
unique: true,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
});
expect(findTagToken()).toMatchObject({
@@ -97,7 +97,7 @@ describe('Pipelines filtered search', () => {
icon: 'tag',
title: 'Tag name',
unique: true,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_closed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_closed_spec.js
index 06ee017dee7..270a37f87e7 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_closed_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_closed_spec.js
@@ -1,9 +1,28 @@
-import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { shallowMount, mount } from '@vue/test-utils';
+import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+
+import api from '~/api';
+
+import showGlobalToast from '~/vue_shared/plugins/global_toast';
+
import closedComponent from '~/vue_merge_request_widget/components/states/mr_widget_closed.vue';
import MrWidgetAuthorTime from '~/vue_merge_request_widget/components/mr_widget_author_time.vue';
import StateContainer from '~/vue_merge_request_widget/components/state_container.vue';
+import Actions from '~/vue_merge_request_widget/components/action_buttons.vue';
+
+import { MR_WIDGET_CLOSED_REOPEN_FAILURE } from '~/vue_merge_request_widget/i18n';
+
+jest.mock('~/api', () => ({
+ updateMergeRequest: jest.fn(),
+}));
+jest.mock('~/vue_shared/plugins/global_toast');
+
+useMockLocationHelper();
const MOCK_DATA = {
+ iid: 1,
metrics: {
mergedBy: {},
closedBy: {
@@ -19,22 +38,39 @@ const MOCK_DATA = {
},
targetBranchPath: '/twitter/flight/commits/so_long_jquery',
targetBranch: 'so_long_jquery',
+ targetProjectId: 'twitter/flight',
};
+function createComponent({ shallow = true, props = {} } = {}) {
+ const mounter = shallow ? shallowMount : mount;
+
+ return mounter(closedComponent, {
+ propsData: {
+ mr: MOCK_DATA,
+ ...props,
+ },
+ });
+}
+
+function findActions(wrapper) {
+ return wrapper.findComponent(StateContainer).findComponent(Actions);
+}
+
+function findReopenActionButton(wrapper) {
+ return findActions(wrapper).find('button[data-testid="extension-actions-reopen-button"]');
+}
+
describe('MRWidgetClosed', () => {
let wrapper;
beforeEach(() => {
- wrapper = shallowMount(closedComponent, {
- propsData: {
- mr: MOCK_DATA,
- },
- });
+ wrapper = createComponent();
});
afterEach(() => {
- wrapper.destroy();
- wrapper = null;
+ if (wrapper) {
+ wrapper.destroy();
+ }
});
it('renders closed icon', () => {
@@ -51,4 +87,93 @@ describe('MRWidgetClosed', () => {
dateReadable: MOCK_DATA.metrics.readableClosedAt,
});
});
+
+ describe('actions', () => {
+ describe('reopen', () => {
+ beforeEach(() => {
+ window.gon = { current_user_id: 1 };
+ api.updateMergeRequest.mockResolvedValue(true);
+ wrapper = createComponent({ shallow: false });
+ });
+
+ it('shows the "reopen" button', () => {
+ expect(wrapper.findComponent(StateContainer).props().actions.length).toBe(1);
+ expect(findReopenActionButton(wrapper).text()).toBe('Reopen');
+ });
+
+ it('does not show widget actions when the user is not logged in', () => {
+ window.gon = {};
+
+ wrapper = createComponent();
+
+ expect(findActions(wrapper).exists()).toBe(false);
+ });
+
+ it('makes the reopen request with the correct MR information', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ reopenButton.trigger('click');
+ await nextTick();
+
+ expect(api.updateMergeRequest).toHaveBeenCalledWith(
+ MOCK_DATA.targetProjectId,
+ MOCK_DATA.iid,
+ { state_event: 'reopen' },
+ );
+ });
+
+ it('shows "Reopening..." while the reopen network request is pending', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ api.updateMergeRequest.mockReturnValue(new Promise(() => {}));
+
+ reopenButton.trigger('click');
+ await nextTick();
+
+ expect(reopenButton.text()).toBe('Reopening...');
+ });
+
+ it('shows "Refreshing..." when the reopen has succeeded', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ reopenButton.trigger('click');
+ await waitForPromises();
+
+ expect(reopenButton.text()).toBe('Refreshing...');
+ });
+
+ it('reloads the page when a reopen has succeeded', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ reopenButton.trigger('click');
+ await waitForPromises();
+
+ expect(window.location.reload).toHaveBeenCalledTimes(1);
+ });
+
+ it('shows "Reopen" when a reopen request has failed', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ api.updateMergeRequest.mockRejectedValue(false);
+
+ reopenButton.trigger('click');
+ await waitForPromises();
+
+ expect(window.location.reload).not.toHaveBeenCalled();
+ expect(reopenButton.text()).toBe('Reopen');
+ });
+
+ it('requests a toast popup when a reopen request has failed', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ api.updateMergeRequest.mockRejectedValue(false);
+
+ reopenButton.trigger('click');
+ await waitForPromises();
+
+ expect(showGlobalToast).toHaveBeenCalledTimes(1);
+ expect(showGlobalToast).toHaveBeenCalledWith(MR_WIDGET_CLOSED_REOPEN_FAILURE);
+ });
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
index a6713b7e7e4..f9cc884f221 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
@@ -1,7 +1,7 @@
import { GlFilteredSearchToken } from '@gitlab/ui';
import { mockLabels } from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
import Api from '~/api';
-import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
+import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import BranchToken from '~/vue_shared/components/filtered_search_bar/tokens/branch_token.vue';
import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
@@ -202,7 +202,7 @@ export const mockBranchToken = {
title: 'Source Branch',
unique: true,
token: BranchToken,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
fetchBranches: Api.branches.bind(Api),
};
@@ -213,7 +213,7 @@ export const mockAuthorToken = {
unique: false,
symbol: '@',
token: AuthorToken,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
fetchPath: 'gitlab-org/gitlab-test',
fetchAuthors: Api.projectUsers.bind(Api),
};
@@ -225,7 +225,7 @@ export const mockLabelToken = {
unique: false,
symbol: '~',
token: LabelToken,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
fetchLabels: () => Promise.resolve(mockLabels),
};
@@ -236,7 +236,7 @@ export const mockMilestoneToken = {
unique: true,
symbol: '%',
token: MilestoneToken,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
fetchMilestones: () => Promise.resolve({ data: mockMilestones }),
};
@@ -254,7 +254,7 @@ export const mockReactionEmojiToken = {
title: 'My-Reaction',
unique: true,
token: EmojiToken,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
fetchEmojis: () => Promise.resolve(mockEmojis),
};
@@ -265,7 +265,7 @@ export const mockCrmContactToken = {
token: CrmContactToken,
isProject: false,
fullPath: 'group',
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
unique: true,
};
@@ -276,7 +276,7 @@ export const mockCrmOrganizationToken = {
token: CrmOrganizationToken,
isProject: false,
fullPath: 'group',
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
unique: true,
};
@@ -286,7 +286,7 @@ export const mockMembershipToken = {
title: 'Membership',
token: GlFilteredSearchToken,
unique: true,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
options: [
{ value: 'exclude', title: 'Direct' },
{ value: 'only', title: 'Inherited' },
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
index a0126c2bd63..5546b0c7032 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
@@ -17,7 +17,7 @@ import {
import {
DEFAULT_NONE_ANY,
OPERATOR_IS,
- OPERATOR_IS_NOT,
+ OPERATOR_NOT,
} from '~/vue_shared/components/filtered_search_bar/constants';
import {
getRecentlyUsedSuggestions,
@@ -301,9 +301,9 @@ describe('BaseToken', () => {
describe('with default suggestions', () => {
describe.each`
- operator | shouldRenderFilteredSearchSuggestion
- ${OPERATOR_IS} | ${true}
- ${OPERATOR_IS_NOT} | ${false}
+ operator | shouldRenderFilteredSearchSuggestion
+ ${OPERATOR_IS} | ${true}
+ ${OPERATOR_NOT} | ${false}
`('when operator is $operator', ({ shouldRenderFilteredSearchSuggestion, operator }) => {
beforeEach(() => {
const props = {
diff --git a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
index c0c3c4a9729..2e2d04efb55 100644
--- a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
@@ -2,7 +2,7 @@ import { GlAlert, GlBadge, GlPagination, GlTabs, GlTab } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Tracking from '~/tracking';
-import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
+import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import PageWrapper from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
@@ -293,7 +293,7 @@ describe('AlertManagementEmptyState', () => {
unique: true,
symbol: '@',
token: AuthorToken,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
fetchPath: '/link',
fetchAuthors: expect.any(Function),
},
@@ -304,7 +304,7 @@ describe('AlertManagementEmptyState', () => {
unique: true,
symbol: '@',
token: AuthorToken,
- operators: OPERATOR_IS_ONLY,
+ operators: OPERATORS_IS,
fetchPath: '/link',
fetchAuthors: expect.any(Function),
},
diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
index a409c15533b..cbd931c514f 100644
--- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
+++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
@@ -192,4 +192,8 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
include_examples "XSS prevention", "ruby"
end
+
+ it_behaves_like "filter timeout" do
+ let(:text) { '<pre lang="ruby"><code>def fun end</code></pre>' }
+ end
end
diff --git a/spec/lib/banzai/filter/timeout_html_pipeline_filter_spec.rb b/spec/lib/banzai/filter/timeout_html_pipeline_filter_spec.rb
new file mode 100644
index 00000000000..cdb40ef5b04
--- /dev/null
+++ b/spec/lib/banzai/filter/timeout_html_pipeline_filter_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::TimeoutHtmlPipelineFilter do
+ include FilterSpecHelper
+
+ it_behaves_like 'filter timeout' do
+ let(:text) { '<p>some text</p>' }
+ end
+
+ it 'raises NotImplementedError' do
+ expect { filter('test') }.to raise_error NotImplementedError
+ end
+
+ context 'when markup_rendering_timeout is disabled' do
+ it 'waits until the execution completes' do
+ text = '<p>some text</p>'
+
+ stub_feature_flags(markup_rendering_timeout: false)
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:call_with_timeout) do
+ text
+ end
+ end
+
+ expect(Gitlab::RenderTimeout).not_to receive(:timeout)
+
+ result = filter(text)
+
+ expect(result).to eq text
+ end
+ end
+end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
index 24f8fb40445..271022e7c55 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
@@ -22,10 +22,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::BaseQueryBuilder do
project.add_maintainer(user)
mr1.metrics.update!(merged_at: 1.month.ago)
mr2.metrics.update!(merged_at: Time.now)
- end
-
- around do |example|
- Timecop.freeze { example.run }
+ freeze_time
end
describe 'date range parameters' do
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
index 258f4a0d019..4db5d64164e 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
@@ -18,10 +18,6 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Median do
subject { described_class.new(stage: stage, query: query).seconds }
- around do |example|
- Timecop.freeze { example.run }
- end
-
it 'retruns nil when no results' do
expect(subject).to eq(nil)
end
@@ -30,11 +26,11 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Median do
merge_request1 = create(:merge_request, source_branch: '1', target_project: project, source_project: project)
merge_request2 = create(:merge_request, source_branch: '2', target_project: project, source_project: project)
- travel_to(5.minutes.from_now) do
+ travel(5.minutes) do
merge_request1.metrics.update!(merged_at: Time.zone.now)
end
- travel_to(10.minutes.from_now) do
+ travel(10.minutes) do
merge_request2.metrics.update!(merged_at: Time.zone.now)
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
index 34d5158a5ab..ab5a360d908 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
let(:params) { { from: 1.year.ago, current_user: user } }
diff --git a/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb b/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
index b239de841b6..84f6411eae6 100644
--- a/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
+++ b/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
@@ -22,14 +22,14 @@ RSpec.describe Gitlab::Auth::UniqueIpsLimiter, :clean_gitlab_redis_shared_state
end
it 'resets count after specified time window' do
- Timecop.freeze do
+ freeze_time do
expect(described_class.update_and_return_ips_count(user.id, 'ip2')).to eq(1)
expect(described_class.update_and_return_ips_count(user.id, 'ip3')).to eq(2)
+ end
- travel_to(Time.now.utc + described_class.config.unique_ips_limit_time_window) do
- expect(described_class.update_and_return_ips_count(user.id, 'ip4')).to eq(1)
- expect(described_class.update_and_return_ips_count(user.id, 'ip5')).to eq(2)
- end
+ travel_to(Time.now.utc + described_class.config.unique_ips_limit_time_window) do
+ expect(described_class.update_and_return_ips_count(user.id, 'ip4')).to eq(1)
+ expect(described_class.update_and_return_ips_count(user.id, 'ip5')).to eq(2)
end
end
end
diff --git a/spec/lib/gitlab/checks/timed_logger_spec.rb b/spec/lib/gitlab/checks/timed_logger_spec.rb
index 6c488212eca..261fdd6c002 100644
--- a/spec/lib/gitlab/checks/timed_logger_spec.rb
+++ b/spec/lib/gitlab/checks/timed_logger_spec.rb
@@ -17,38 +17,44 @@ RSpec.describe Gitlab::Checks::TimedLogger do
logger.append_message("Checking ref: #{ref}")
end
+ around do |example|
+ freeze_time do
+ example.run
+ end
+ end
+
describe '#log_timed' do
it 'logs message' do
- Timecop.freeze(start + 30.seconds) do
- logger.log_timed(log_messages[:foo], start) { bar_check }
- end
+ travel_to(start + 30.seconds)
+
+ logger.log_timed(log_messages[:foo], start) { bar_check }
expect(logger.full_message).to eq("Checking ref: bar\nFoo message... (30000.0ms)")
end
context 'when time limit was reached' do
it 'cancels action' do
- Timecop.freeze(start + 50.seconds) do
- expect do
- logger.log_timed(log_messages[:foo], start) do
- bar_check
- end
- end.to raise_error(described_class::TimeoutError)
- end
+ travel_to(start + 50.seconds)
+
+ expect do
+ logger.log_timed(log_messages[:foo], start) do
+ bar_check
+ end
+ end.to raise_error(described_class::TimeoutError)
expect(logger.full_message).to eq("Checking ref: bar\nFoo message... (cancelled)")
end
it 'cancels action with time elapsed if work was performed' do
- Timecop.freeze(start + 30.seconds) do
- expect do
- logger.log_timed(log_messages[:foo], start) do
- grpc_check
- end
- end.to raise_error(described_class::TimeoutError)
-
- expect(logger.full_message).to eq("Checking ref: bar\nFoo message... (cancelled after 30000.0ms)")
- end
+ travel_to(start + 30.seconds)
+
+ expect do
+ logger.log_timed(log_messages[:foo], start) do
+ grpc_check
+ end
+ end.to raise_error(described_class::TimeoutError)
+
+ expect(logger.full_message).to eq("Checking ref: bar\nFoo message... (cancelled after 30000.0ms)")
end
end
end
diff --git a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
index 0e7d7f1efda..92ffeee8509 100644
--- a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
@@ -29,8 +29,8 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
context 'when from date is given' do
before do
- Timecop.freeze(5.days.ago) { create(:issue, project: project) }
- Timecop.freeze(5.days.from_now) { create(:issue, project: project) }
+ travel_to(5.days.ago) { create(:issue, project: project) }
+ travel_to(5.days.from_now) { create(:issue, project: project) }
end
it "finds the number of issues created after the 'from date'" do
@@ -45,15 +45,15 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
end
it "doesn't find issues from other projects" do
- Timecop.freeze(5.days.from_now) { create(:issue, project: create(:project)) }
+ travel_to(5.days.from_now) { create(:issue, project: create(:project)) }
expect(subject[:value]).to eq('-')
end
context 'when `to` parameter is given' do
before do
- Timecop.freeze(5.days.ago) { create(:issue, project: project) }
- Timecop.freeze(5.days.from_now) { create(:issue, project: project) }
+ travel_to(5.days.ago) { create(:issue, project: project) }
+ travel_to(5.days.from_now) { create(:issue, project: project) }
end
it "doesn't find any record" do
@@ -78,8 +78,8 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
context 'when from date is given' do
before do
- Timecop.freeze(5.days.ago) { create_commit("Test message", project, user, 'master') }
- Timecop.freeze(5.days.from_now) { create_commit("Test message", project, user, 'master') }
+ travel_to(5.days.ago) { create_commit("Test message", project, user, 'master') }
+ travel_to(5.days.from_now) { create_commit("Test message", project, user, 'master') }
end
it "finds the number of commits created after the 'from date'" do
@@ -94,21 +94,21 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
end
it "doesn't find commits from other projects" do
- Timecop.freeze(5.days.from_now) { create_commit("Test message", create(:project, :repository), user, 'master') }
+ travel_to(5.days.from_now) { create_commit("Test message", create(:project, :repository), user, 'master') }
expect(subject[:value]).to eq('-')
end
it "finds a large (> 100) number of commits if present" do
- Timecop.freeze(5.days.from_now) { create_commit("Test message", project, user, 'master', count: 100) }
+ travel_to(5.days.from_now) { create_commit("Test message", project, user, 'master', count: 100) }
expect(subject[:value]).to eq('100')
end
context 'when `to` parameter is given' do
before do
- Timecop.freeze(5.days.ago) { create_commit("Test message", project, user, 'master') }
- Timecop.freeze(5.days.from_now) { create_commit("Test message", project, user, 'master') }
+ travel_to(5.days.ago) { create_commit("Test message", project, user, 'master') }
+ travel_to(5.days.from_now) { create_commit("Test message", project, user, 'master') }
end
it "doesn't find any record" do
diff --git a/spec/lib/gitlab/git/cross_repo_comparer_spec.rb b/spec/lib/gitlab/git/cross_repo_comparer_spec.rb
deleted file mode 100644
index 7888e224d59..00000000000
--- a/spec/lib/gitlab/git/cross_repo_comparer_spec.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Git::CrossRepoComparer do
- let(:source_project) { create(:project, :repository) }
- let(:target_project) { create(:project, :repository) }
-
- let(:source_repo) { source_project.repository.raw_repository }
- let(:target_repo) { target_project.repository.raw_repository }
-
- let(:source_branch) { 'feature' }
- let(:target_branch) { 'master' }
- let(:straight) { false }
-
- let(:source_commit) { source_repo.commit(source_branch) }
- let(:target_commit) { source_repo.commit(target_branch) }
-
- subject(:result) { described_class.new(source_repo, target_repo).compare(source_branch, target_branch, straight: straight) }
-
- describe '#compare' do
- context 'within a single repository' do
- let(:target_project) { source_project }
-
- context 'a non-straight comparison' do
- it 'compares without fetching from another repo' do
- expect(source_repo).not_to receive(:fetch_source_branch!)
-
- expect_compare(result, from: source_commit, to: target_commit)
- expect(result.straight).to eq(false)
- end
- end
-
- context 'a straight comparison' do
- let(:straight) { true }
-
- it 'compares without fetching from another repo' do
- expect(source_repo).not_to receive(:fetch_source_branch!)
-
- expect_compare(result, from: source_commit, to: target_commit)
- expect(result.straight).to eq(true)
- end
- end
- end
-
- context 'across two repositories' do
- context 'target ref exists in source repo' do
- it 'compares without fetching from another repo' do
- expect(source_repo).not_to receive(:fetch_source_branch!)
- expect(source_repo).not_to receive(:delete_refs)
-
- expect_compare(result, from: source_commit, to: target_commit)
- end
- end
-
- context 'target ref does not exist in source repo' do
- it 'compares in the source repo by fetching from the target to a temporary ref' do
- new_commit_id = create_commit(target_project.owner, target_repo, target_branch)
- new_commit = target_repo.commit(new_commit_id)
-
- # This is how the temporary ref is generated
- expect(SecureRandom).to receive(:hex).at_least(:once).and_return('foo')
-
- expect(source_repo)
- .to receive(:fetch_source_branch!)
- .with(target_repo, new_commit_id, 'refs/tmp/foo')
- .and_call_original
-
- expect(source_repo).to receive(:delete_refs).with('refs/tmp/foo').and_call_original
-
- expect_compare(result, from: source_commit, to: new_commit)
- end
- end
-
- context 'source ref does not exist in source repo' do
- let(:source_branch) { 'does-not-exist' }
-
- it 'returns an empty comparison' do
- expect(source_repo).not_to receive(:fetch_source_branch!)
- expect(source_repo).not_to receive(:delete_refs)
-
- expect(result).to be_a(::Gitlab::Git::Compare)
- expect(result.commits.size).to eq(0)
- end
- end
-
- context 'target ref does not exist in target repo' do
- let(:target_branch) { 'does-not-exist' }
-
- it 'returns nil' do
- expect(source_repo).not_to receive(:fetch_source_branch!)
- expect(source_repo).not_to receive(:delete_refs)
-
- is_expected.to be_nil
- end
- end
- end
- end
-
- def expect_compare(of, from:, to:)
- expect(of).to be_a(::Gitlab::Git::Compare)
- expect(from).to be_a(::Gitlab::Git::Commit)
- expect(to).to be_a(::Gitlab::Git::Commit)
-
- expect(of.commits).not_to be_empty
- expect(of.head).to eq(from)
- expect(of.base).to eq(to)
- end
-
- def create_commit(user, repo, branch)
- action = { action: :create, file_path: '/FILE', content: 'content' }
-
- result = repo.commit_files(user, branch_name: branch, message: 'Commit', actions: [action])
-
- result.newrev
- end
-end
diff --git a/spec/lib/gitlab/git/cross_repo_spec.rb b/spec/lib/gitlab/git/cross_repo_spec.rb
new file mode 100644
index 00000000000..09a28c144a4
--- /dev/null
+++ b/spec/lib/gitlab/git/cross_repo_spec.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Git::CrossRepo do
+ let_it_be(:source_project) { create(:project, :repository) }
+ let_it_be(:target_project) { create(:project, :repository) }
+
+ let(:source_repo) { source_project.repository.raw_repository }
+ let(:target_repo) { target_project.repository.raw_repository }
+
+ let(:source_branch) { 'feature' }
+ let(:target_branch) { target_repo.root_ref }
+
+ let(:source_commit) { source_repo.commit(source_branch) }
+ let(:target_commit) { source_repo.commit(target_branch) }
+
+ def execute(&block)
+ described_class.new(source_repo, target_repo).execute(target_branch, &block)
+ end
+
+ describe '#execute' do
+ context 'when executed within a single repository' do
+ let(:target_project) { source_project }
+
+ it 'does not fetch from another repo' do
+ expect(source_repo).not_to receive(:fetch_source_branch!)
+
+ expect { |block| execute(&block) }.to yield_with_args(target_branch)
+ end
+ end
+
+ context 'when executed across two repositories' do
+ context 'and target ref exists in source repo' do
+ it 'does not fetch from another repo' do
+ expect(source_repo).not_to receive(:fetch_source_branch!)
+ expect(source_repo).not_to receive(:delete_refs)
+
+ expect { |block| execute(&block) }.to yield_with_args(target_commit.id)
+ end
+ end
+
+ context 'and target ref does not exist in source repo' do
+ let_it_be(:target_project) { create(:project, :repository) }
+
+ it 'fetches from the target to a temporary ref' do
+ new_commit_id = create_commit(target_project.owner, target_repo, target_branch)
+
+ # This is how the temporary ref is generated
+ expect(SecureRandom).to receive(:hex).at_least(:once).and_return('foo')
+
+ expect(source_repo)
+ .to receive(:fetch_source_branch!)
+ .with(target_repo, new_commit_id, 'refs/tmp/foo')
+ .and_call_original
+
+ expect(source_repo).to receive(:delete_refs).with('refs/tmp/foo').and_call_original
+
+ expect { |block| execute(&block) }.to yield_with_args(new_commit_id)
+ end
+ end
+
+ context 'and target ref does not exist in target repo' do
+ let(:target_branch) { 'does-not-exist' }
+
+ it 'returns nil' do
+ expect(source_repo).not_to receive(:fetch_source_branch!)
+ expect(source_repo).not_to receive(:delete_refs)
+
+ expect { |block| execute(&block) }.not_to yield_control
+ end
+ end
+ end
+ end
+
+ def create_commit(user, repo, branch)
+ action = { action: :create, file_path: '/FILE', content: 'content' }
+
+ result = repo.commit_files(user, branch_name: branch, message: 'Commit', actions: [action])
+
+ result.newrev
+ end
+end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 5e27979cbf3..1984c1157fe 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -2211,15 +2211,49 @@ RSpec.describe Gitlab::Git::Repository do
end
describe '#compare_source_branch' do
- it 'delegates to Gitlab::Git::CrossRepoComparer' do
- expect_next_instance_of(::Gitlab::Git::CrossRepoComparer) do |instance|
- expect(instance.source_repo).to eq(:source_repository)
- expect(instance.target_repo).to eq(repository)
+ it 'compares two branches cross repo' do
+ mutable_repository.commit_files(
+ user,
+ branch_name: mutable_repository.root_ref, message: 'Committing something',
+ actions: [{ action: :create, file_path: 'encoding/CHANGELOG', content: 'New file' }]
+ )
+
+ repository.commit_files(
+ user,
+ branch_name: repository.root_ref, message: 'Commit to root ref',
+ actions: [{ action: :create, file_path: 'encoding/CHANGELOG', content: 'One more' }]
+ )
+
+ [
+ [repository, mutable_repository, true],
+ [repository, mutable_repository, false],
+ [mutable_repository, repository, true],
+ [mutable_repository, repository, false]
+ ].each do |source_repo, target_repo, straight|
+ raw_compare = target_repo.compare_source_branch(
+ target_repo.root_ref, source_repo, source_repo.root_ref, straight: straight)
+
+ expect(raw_compare).to be_a(::Gitlab::Git::Compare)
- expect(instance).to receive(:compare).with('feature', 'master', straight: :straight)
+ expect(raw_compare.commits).to eq([source_repo.commit])
+ expect(raw_compare.head).to eq(source_repo.commit)
+ expect(raw_compare.base).to eq(target_repo.commit)
+ expect(raw_compare.straight).to eq(straight)
end
+ end
- repository.compare_source_branch('master', :source_repository, 'feature', straight: :straight)
+ context 'source ref does not exist in source repo' do
+ it 'returns an empty comparison' do
+ expect_next_instance_of(::Gitlab::Git::CrossRepo) do |instance|
+ expect(instance).not_to receive(:fetch_source_branch!)
+ end
+
+ raw_compare = repository.compare_source_branch(
+ repository.root_ref, mutable_repository, 'does-not-exist', straight: true)
+
+ expect(raw_compare).to be_a(::Gitlab::Git::Compare)
+ expect(raw_compare.commits.size).to eq(0)
+ end
end
end
diff --git a/spec/lib/gitlab/puma_logging/json_formatter_spec.rb b/spec/lib/gitlab/puma_logging/json_formatter_spec.rb
index 64ace09e01b..d38f54bccf1 100644
--- a/spec/lib/gitlab/puma_logging/json_formatter_spec.rb
+++ b/spec/lib/gitlab/puma_logging/json_formatter_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe Gitlab::PumaLogging::JSONFormatter do
it "generate json format with timestamp and pid" do
- Timecop.freeze( Time.utc(2019, 12, 04, 9, 10, 11, 123456)) do
- expect(subject.call('log message')).to eq "{\"timestamp\":\"2019-12-04T09:10:11.123Z\",\"pid\":#{Process.pid},\"message\":\"log message\"}"
+ travel_to(Time.utc(2019, 12, 04, 9, 10, 11)) do
+ expect(subject.call('log message')).to eq "{\"timestamp\":\"2019-12-04T09:10:11.000Z\",\"pid\":#{Process.pid},\"message\":\"log message\"}"
end
end
end
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index 5c9a3cc0a24..f2488229a55 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -349,6 +349,23 @@ RSpec.describe Gitlab::Workhorse do
expect(subject[:GitConfigOptions]).to be_empty
end
end
+
+ context 'when remote_ip is available in the application context' do
+ it 'includes a RemoteIP params' do
+ result = {}
+ Gitlab::ApplicationContext.with_context(remote_ip: "1.2.3.4") do
+ result = described_class.git_http_ok(repository, Gitlab::GlRepository::PROJECT, user, action)
+ end
+ expect(result[:RemoteIP]).to eql("1.2.3.4")
+ end
+ end
+
+ context 'when remote_ip is not available in the application context' do
+ it 'does not include RemoteIP params' do
+ result = described_class.git_http_ok(repository, Gitlab::GlRepository::PROJECT, user, action)
+ expect(result).not_to have_key(:RemoteIP)
+ end
+ end
end
describe '.set_key_and_notify' do
diff --git a/spec/lib/json_web_token/hmac_token_spec.rb b/spec/lib/json_web_token/hmac_token_spec.rb
index cf7e5c54f45..016084eaf69 100644
--- a/spec/lib/json_web_token/hmac_token_spec.rb
+++ b/spec/lib/json_web_token/hmac_token_spec.rb
@@ -1,9 +1,11 @@
# frozen_string_literal: true
require 'json'
-require 'timecop'
+require 'active_support/testing/time_helpers'
RSpec.describe JSONWebToken::HMACToken do
+ include ActiveSupport::Testing::TimeHelpers
+
let(:secret) { 'shh secret squirrel' }
shared_examples 'a valid, non-expired token' do
@@ -54,13 +56,13 @@ RSpec.describe JSONWebToken::HMACToken do
end
context 'that is expired' do
- # Needs the ! so Timecop.freeze() is effective
+ # Needs the ! so freeze_time() is effective
let!(:encoded_token) { described_class.new(secret).encoded }
it "raises exception saying 'Signature has expired'" do
# Needs to be 120 seconds, because the default expiry is 60 seconds
# with an additional 60 second leeway.
- Timecop.freeze(Time.now + 120) do
+ travel_to(Time.now + 120) do
expect { decoded_token }.to raise_error(JWT::ExpiredSignature, 'Signature has expired')
end
end
@@ -77,19 +79,19 @@ RSpec.describe JSONWebToken::HMACToken do
context 'that has expired' do
let(:expire_time) { 0 }
+ around do |example|
+ travel_to(Time.now + 1) { example.run }
+ end
+
context 'with the default leeway' do
- Timecop.freeze(Time.now + 1) do
- it_behaves_like 'a valid, non-expired token'
- end
+ it_behaves_like 'a valid, non-expired token'
end
context 'with a leeway of 0 seconds' do
let(:leeway) { 0 }
it "raises exception saying 'Signature has expired'" do
- Timecop.freeze(Time.now + 1) do
- expect { decoded_token }.to raise_error(JWT::ExpiredSignature, 'Signature has expired')
- end
+ expect { decoded_token }.to raise_error(JWT::ExpiredSignature, 'Signature has expired')
end
end
end
diff --git a/spec/lib/peek/views/active_record_spec.rb b/spec/lib/peek/views/active_record_spec.rb
index 7bc15f40065..fc768bdcb82 100644
--- a/spec/lib/peek/views/active_record_spec.rb
+++ b/spec/lib/peek/views/active_record_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
end
it 'includes db role data and db_config_name name' do
- Timecop.freeze(2021, 2, 23, 10, 0) do
+ travel_to(Time.utc(2021, 2, 23, 10, 0)) do
ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1)
ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 2.seconds, '2', event_2)
ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 3.seconds, '3', event_3)
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index e76cd22d342..8cccc9ad83e 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -3010,44 +3010,6 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#uses_external_project_ci_config?' do
- subject(:uses_external_project_ci_config) { project.uses_external_project_ci_config? }
-
- let(:project) { build(:project) }
-
- context 'when ci_config_path is configured with external project' do
- before do
- project.ci_config_path = '.gitlab-ci.yml@hello/world'
- end
-
- it { is_expected.to eq(true) }
- end
-
- context 'when ci_config_path is nil' do
- before do
- project.ci_config_path = nil
- end
-
- it { is_expected.to eq(false) }
- end
-
- context 'when ci_config_path is configured with a file in the project' do
- before do
- project.ci_config_path = 'hello/world/gitlab-ci.yml'
- end
-
- it { is_expected.to eq(false) }
- end
-
- context 'when ci_config_path is configured with remote file' do
- before do
- project.ci_config_path = 'https://example.org/file.yml'
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
describe '#latest_successful_build_for_ref' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:pipeline) { create_pipeline(project) }
@@ -7518,15 +7480,6 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#ci_config_external_project' do
- subject(:ci_config_external_project) { project.ci_config_external_project }
-
- let(:other_project) { create(:project) }
- let(:project) { build(:project, ci_config_path: ".gitlab-ci.yml@#{other_project.full_path}") }
-
- it { is_expected.to eq(other_project) }
- end
-
describe '#enabled_group_deploy_keys' do
let_it_be(:project) { create(:project) }
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 3a9b2d02af5..4eb03204de3 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -61,6 +61,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['inactive_projects_min_size_mb']).to eq(0)
expect(json_response['inactive_projects_send_warning_email_after_months']).to eq(1)
expect(json_response['can_create_group']).to eq(true)
+ expect(json_response['jira_connect_application_key']).to eq(nil)
+ expect(json_response['jira_connect_proxy_url']).to eq(nil)
end
end
@@ -158,7 +160,9 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
inactive_projects_delete_after_months: 24,
inactive_projects_min_size_mb: 10,
inactive_projects_send_warning_email_after_months: 12,
- can_create_group: false
+ can_create_group: false,
+ jira_connect_application_key: '123',
+ jira_connect_proxy_url: 'http://example.com'
}
expect(response).to have_gitlab_http_status(:ok)
@@ -220,6 +224,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['inactive_projects_min_size_mb']).to eq(10)
expect(json_response['inactive_projects_send_warning_email_after_months']).to eq(12)
expect(json_response['can_create_group']).to eq(false)
+ expect(json_response['jira_connect_application_key']).to eq('123')
+ expect(json_response['jira_connect_proxy_url']).to eq('http://example.com')
end
end
diff --git a/spec/requests/api/usage_data_queries_spec.rb b/spec/requests/api/usage_data_queries_spec.rb
index 6ce03954246..c2fb7d0c72a 100644
--- a/spec/requests/api/usage_data_queries_spec.rb
+++ b/spec/requests/api/usage_data_queries_spec.rb
@@ -80,7 +80,7 @@ RSpec.describe API::UsageDataQueries do
end
it 'matches the generated query' do
- Timecop.freeze(2021, 1, 1) do
+ travel_to(Time.utc(2021, 1, 1)) do
get api(endpoint, admin)
end
diff --git a/spec/serializers/entity_date_helper_spec.rb b/spec/serializers/entity_date_helper_spec.rb
index a8c338675e2..5a4571339b3 100644
--- a/spec/serializers/entity_date_helper_spec.rb
+++ b/spec/serializers/entity_date_helper_spec.rb
@@ -48,7 +48,7 @@ RSpec.describe EntityDateHelper do
describe '#remaining_days_in_words' do
around do |example|
- Timecop.freeze(Time.utc(2017, 3, 17)) { example.run }
+ travel_to(Time.utc(2017, 3, 17)) { example.run }
end
context 'when less than 31 days remaining' do
@@ -75,7 +75,9 @@ RSpec.describe EntityDateHelper do
end
it 'returns 1 day remaining when queried mid-day' do
- Timecop.freeze(Time.utc(2017, 3, 17, 13, 10)) do
+ travel_back
+
+ travel_to(Time.utc(2017, 3, 17, 13, 10)) do
expect(milestone_remaining).to eq("<strong>1</strong> day remaining")
end
end
diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb
index 5fdefb2b306..b866293393b 100644
--- a/spec/services/ci/create_pipeline_service/rules_spec.rb
+++ b/spec/services/ci/create_pipeline_service/rules_spec.rb
@@ -912,7 +912,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
context 'when outside freeze period' do
it 'creates two jobs' do
- Timecop.freeze(2020, 4, 10, 22, 59) do
+ travel_to(Time.utc(2020, 4, 10, 22, 59)) do
expect(pipeline).to be_persisted
expect(build_names).to contain_exactly('test-job', 'deploy-job')
end
@@ -921,7 +921,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
context 'when inside freeze period' do
it 'creates one job' do
- Timecop.freeze(2020, 4, 10, 23, 1) do
+ travel_to(Time.utc(2020, 4, 10, 23, 1)) do
expect(pipeline).to be_persisted
expect(build_names).to contain_exactly('test-job')
end
@@ -946,7 +946,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
context 'when outside freeze period' do
it 'creates two jobs' do
- Timecop.freeze(2020, 4, 10, 22, 59) do
+ travel_to(Time.utc(2020, 4, 10, 22, 59)) do
expect(pipeline).to be_persisted
expect(build_names).to contain_exactly('deploy-job')
end
@@ -955,7 +955,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
context 'when inside freeze period' do
it 'does not create the pipeline', :aggregate_failures do
- Timecop.freeze(2020, 4, 10, 23, 1) do
+ travel_to(Time.utc(2020, 4, 10, 23, 1)) do
expect(response).to be_error
expect(pipeline).not_to be_persisted
end
diff --git a/spec/support/banzai/filter_timeout_shared_examples.rb b/spec/support/banzai/filter_timeout_shared_examples.rb
new file mode 100644
index 00000000000..1f2ebe6fef6
--- /dev/null
+++ b/spec/support/banzai/filter_timeout_shared_examples.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+# This shared_example requires the following variables:
+# - text: The text to be run through the filter
+#
+# Usage:
+#
+# it_behaves_like 'filter timeout' do
+# let(:text) { 'some text' }
+# end
+RSpec.shared_examples 'filter timeout' do
+ context 'when rendering takes too long' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:context) { { project: project } }
+
+ it 'times out' do
+ stub_const("Banzai::Filter::TimeoutHtmlPipelineFilter::RENDER_TIMEOUT", 0.1)
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:call_with_timeout) do
+ sleep(0.2)
+ text
+ end
+ end
+
+ expect(Gitlab::RenderTimeout).to receive(:timeout).and_call_original
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
+ instance_of(Timeout::Error),
+ project_id: context[:project].id,
+ class_name: described_class.name.demodulize
+ )
+
+ result = filter(text)
+
+ expect(result.to_html).to eq text
+ end
+ end
+end
diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb
index f866220b919..816caf5f775 100644
--- a/spec/support/cycle_analytics_helpers/test_generation.rb
+++ b/spec/support/cycle_analytics_helpers/test_generation.rb
@@ -42,17 +42,17 @@ module CycleAnalyticsHelpers
end_time = start_time + rand(1..5).days
start_time_conditions.each do |condition_name, condition_fn|
- Timecop.freeze(start_time) { condition_fn[self, data] }
+ travel_to(start_time) { condition_fn[self, data] }
end
# Run `before_end_fn` at the midpoint between `start_time` and `end_time`
- Timecop.freeze(start_time + (end_time - start_time) / 2) { before_end_fn[self, data] } if before_end_fn
+ travel_to(start_time + (end_time - start_time) / 2) { before_end_fn[self, data] } if before_end_fn
end_time_conditions.each do |condition_name, condition_fn|
- Timecop.freeze(end_time) { condition_fn[self, data] }
+ travel_to(end_time) { condition_fn[self, data] }
end
- Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn
+ travel_to(end_time + 1.day) { post_fn[self, data] } if post_fn
end_time - start_time
end
@@ -74,14 +74,14 @@ module CycleAnalyticsHelpers
end_time = rand(1..10).days.from_now
start_time_conditions.each do |condition_name, condition_fn|
- Timecop.freeze(start_time) { condition_fn[self, data] }
+ travel_to(start_time) { condition_fn[self, data] }
end
end_time_conditions.each do |condition_name, condition_fn|
- Timecop.freeze(end_time) { condition_fn[self, data] }
+ travel_to(end_time) { condition_fn[self, data] }
end
- Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn
+ travel_to(end_time + 1.day) { post_fn[self, data] } if post_fn
# Turn off the stub before checking assertions
allow(self).to receive(:project).and_call_original
@@ -97,17 +97,17 @@ module CycleAnalyticsHelpers
end_time = start_time + rand(1..5).days
# Run `before_end_fn` at the midpoint between `start_time` and `end_time`
- Timecop.freeze(start_time + (end_time - start_time) / 2) { before_end_fn[self, data] } if before_end_fn
+ travel_to(start_time + (end_time - start_time) / 2) { before_end_fn[self, data] } if before_end_fn
end_time_conditions.each do |condition_name, condition_fn|
- Timecop.freeze(start_time) { condition_fn[self, data] }
+ travel_to(start_time) { condition_fn[self, data] }
end
start_time_conditions.each do |condition_name, condition_fn|
- Timecop.freeze(end_time) { condition_fn[self, data] }
+ travel_to(end_time) { condition_fn[self, data] }
end
- Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn
+ travel_to(end_time + 1.day) { post_fn[self, data] } if post_fn
expect(subject[phase].project_median).to be_nil
end
@@ -122,10 +122,10 @@ module CycleAnalyticsHelpers
end_time = rand(1..10).days.from_now
end_time_conditions.each_with_index do |(_condition_name, condition_fn), index|
- Timecop.freeze(end_time + index.days) { condition_fn[self, data] }
+ travel_to(end_time + index.days) { condition_fn[self, data] }
end
- Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn
+ travel_to(end_time + 1.day) { post_fn[self, data] } if post_fn
expect(subject[phase].project_median).to be_nil
end
@@ -139,7 +139,7 @@ module CycleAnalyticsHelpers
start_time = Time.now
start_time_conditions.each do |condition_name, condition_fn|
- Timecop.freeze(start_time) { condition_fn[self, data] }
+ travel_to(start_time) { condition_fn[self, data] }
end
post_fn[self, data] if post_fn
diff --git a/spec/support/helpers/features/runners_helpers.rb b/spec/support/helpers/features/runners_helpers.rb
index 63fc628358c..c5d26108953 100644
--- a/spec/support/helpers/features/runners_helpers.rb
+++ b/spec/support/helpers/features/runners_helpers.rb
@@ -50,7 +50,7 @@ module Spec
page.within(search_bar_selector) do
click_on filter
- # For OPERATOR_IS_ONLY, clicking the filter
+ # For OPERATORS_IS, clicking the filter
# immediately preselects "=" operator
page.find('input').send_keys(value)
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index 32e6e8d50bd..40eb46878ad 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -3,12 +3,14 @@
require 'action_dispatch/testing/test_request'
require 'fileutils'
require 'graphlyte'
+require 'active_support/testing/time_helpers'
require_relative '../../../lib/gitlab/popen'
module JavaScriptFixturesHelpers
extend ActiveSupport::Concern
include Gitlab::Popen
+ include ActiveSupport::Testing::TimeHelpers
extend self
@@ -22,7 +24,7 @@ module JavaScriptFixturesHelpers
# pick an arbitrary date from the past, so tests are not time dependent
# Also see spec/frontend/__helpers__/fake_date/jest.js
- Timecop.freeze(Time.utc(2015, 7, 3, 10)) { example.run }
+ travel_to(Time.utc(2015, 7, 3, 10)) { example.run }
raise NoMethodError.new('You need to set `response` for the fixture generator! This will automatically happen with `type: :controller` or `type: :request`.', 'response') unless respond_to?(:response)
diff --git a/spec/support/shared_contexts/rack_attack_shared_context.rb b/spec/support/shared_contexts/rack_attack_shared_context.rb
index e7b2ee76c3c..12625ead72b 100644
--- a/spec/support/shared_contexts/rack_attack_shared_context.rb
+++ b/spec/support/shared_contexts/rack_attack_shared_context.rb
@@ -6,7 +6,7 @@ RSpec.shared_context 'rack attack cache store' do
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
# Make time-dependent tests deterministic
- Timecop.freeze { example.run }
+ freeze_time { example.run }
Rack::Attack.cache.store = Rails.cache
end
diff --git a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
index 11759b6671f..82ed6eb4c95 100644
--- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
+++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
@@ -68,6 +68,7 @@ RSpec.shared_examples 'rate-limited token requests' do
# Set low limits
settings_to_set[:"#{throttle_setting_prefix}_requests_per_period"] = requests_per_period
settings_to_set[:"#{throttle_setting_prefix}_period_in_seconds"] = period_in_seconds
+ travel_back
end
after do
@@ -220,6 +221,7 @@ RSpec.shared_examples 'rate-limited web authenticated requests' do
# Set low limits
settings_to_set[:"#{throttle_setting_prefix}_requests_per_period"] = requests_per_period
settings_to_set[:"#{throttle_setting_prefix}_period_in_seconds"] = period_in_seconds
+ travel_back
end
after do
@@ -436,6 +438,7 @@ RSpec.shared_examples 'rate-limited unauthenticated requests' do
# Set low limits
settings_to_set[:"#{throttle_setting_prefix}_requests_per_period"] = requests_per_period
settings_to_set[:"#{throttle_setting_prefix}_period_in_seconds"] = period_in_seconds
+ travel_back
end
context 'when the throttle is enabled' do
diff --git a/spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb b/spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb
index 11343f69d6f..491ea64cff1 100644
--- a/spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb
+++ b/spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb
@@ -10,23 +10,24 @@ RSpec.describe Metrics::Dashboard::PruneOldAnnotationsWorker do
describe '#perform' do
it 'removes all annotations older than cut off', :aggregate_failures do
- Timecop.freeze(now) do
+ travel_to(now) do
described_class.new.perform
expect(Metrics::Dashboard::Annotation.all).to match_array([one_day_old_annotation, two_weeks_old_annotation])
# is idempotent in the scope of 24h
expect { described_class.new.perform }.not_to change { Metrics::Dashboard::Annotation.all.to_a }
- travel_to(24.hours.from_now) do
- described_class.new.perform
- expect(Metrics::Dashboard::Annotation.all).to match_array([one_day_old_annotation])
- end
+ end
+
+ travel_to(now + 24.hours) do
+ described_class.new.perform
+ expect(Metrics::Dashboard::Annotation.all).to match_array([one_day_old_annotation])
end
end
context 'batch to be deleted is bigger than upper limit' do
it 'schedules second job to clear remaining records' do
- Timecop.freeze(now) do
+ travel_to(now) do
create(:metrics_dashboard_annotation, starting_at: 1.month.ago)
stub_const("#{described_class}::DELETE_LIMIT", 1)