summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-03-31 15:08:32 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-03-31 15:08:32 +0000
commit85ea3dd4f4855e99d9a69c8e609095199597195a (patch)
tree46e74d30d0ef5cced04005b4a76c66ec18f6a749 /spec
parent5820d448c17f93606afb52d878c00d84681764e0 (diff)
downloadgitlab-ce-85ea3dd4f4855e99d9a69c8e609095199597195a.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/components/diffs/stats_component_spec.rb67
-rw-r--r--spec/components/pajamas/alert_component_spec.rb104
-rw-r--r--spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb12
-rw-r--r--spec/features/merge_requests/user_mass_updates_spec.rb2
-rw-r--r--spec/frontend/issues/show/components/description_spec.js104
-rw-r--r--spec/frontend/jira_connect/subscriptions/pages/sign_in_spec.js2
-rw-r--r--spec/frontend/runner/admin_runners/admin_runners_app_spec.js10
-rw-r--r--spec/frontend/runner/components/__snapshots__/runner_status_popover_spec.js.snap3
-rw-r--r--spec/frontend/runner/components/runner_list_spec.js30
-rw-r--r--spec/frontend/runner/components/runner_status_popover_spec.js36
-rw-r--r--spec/frontend/runner/group_runners/group_runners_app_spec.js12
-rw-r--r--spec/frontend/runner/mock_data.js4
-rw-r--r--spec/helpers/ci/runners_helper_spec.rb18
-rw-r--r--spec/helpers/diff_helper_spec.rb10
-rw-r--r--spec/lib/gitlab/data_builder/note_spec.rb79
-rw-r--r--spec/lib/gitlab/hook_data/issuable_builder_spec.rb8
-rw-r--r--spec/lib/gitlab/hook_data/merge_request_builder_spec.rb1
-rw-r--r--spec/models/concerns/issuable_spec.rb10
-rw-r--r--spec/models/issue_spec.rb21
-rw-r--r--spec/models/merge_request_spec.rb12
-rw-r--r--spec/models/project_import_state_spec.rb13
-rw-r--r--spec/support/shared_examples/models/issuable_hook_data_shared_examples.rb61
-rw-r--r--spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb54
23 files changed, 436 insertions, 237 deletions
diff --git a/spec/components/diffs/stats_component_spec.rb b/spec/components/diffs/stats_component_spec.rb
new file mode 100644
index 00000000000..2e5a5f2ca26
--- /dev/null
+++ b/spec/components/diffs/stats_component_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Diffs::StatsComponent, type: :component do
+ include RepoHelpers
+
+ subject(:component) do
+ described_class.new(diff_files: diff_files)
+ end
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:repository) { project.repository }
+ let_it_be(:commit) { project.commit(sample_commit.id) }
+ let_it_be(:diffs) { commit.raw_diffs }
+ let_it_be(:diff) { diffs.first }
+ let_it_be(:diff_refs) { commit.diff_refs }
+ let_it_be(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
+ let_it_be(:diff_files) { [diff_file] }
+
+ describe "rendered component" do
+ subject { rendered_component }
+
+ let(:element) { page.find(".js-diff-stats-dropdown") }
+
+ before do
+ render_inline component
+ end
+
+ it { is_expected.to have_selector(".js-diff-stats-dropdown") }
+
+ it "renders the data attributes" do
+ expect(element["data-changed"]).to eq("1")
+ expect(element["data-added"]).to eq("10")
+ expect(element["data-deleted"]).to eq("3")
+
+ expect(Gitlab::Json.parse(element["data-files"])).to eq([{
+ "href" => "##{Digest::SHA1.hexdigest(diff_file.file_path)}",
+ "title" => diff_file.new_path,
+ "name" => diff_file.file_path,
+ "path" => diff_file.file_path,
+ "icon" => "file-modified",
+ "iconColor" => "",
+ "added" => diff_file.added_lines,
+ "removed" => diff_file.removed_lines
+ }])
+ end
+ end
+
+ describe "#diff_file_path_text" do
+ it "returns full path by default" do
+ expect(subject.diff_file_path_text(diff_file)).to eq(diff_file.new_path)
+ end
+
+ it "returns truncated path" do
+ expect(subject.diff_file_path_text(diff_file, max: 10)).to eq("...open.rb")
+ end
+
+ it "returns the path if max is oddly small" do
+ expect(subject.diff_file_path_text(diff_file, max: 3)).to eq(diff_file.new_path)
+ end
+
+ it "returns the path if max is oddly large" do
+ expect(subject.diff_file_path_text(diff_file, max: 100)).to eq(diff_file.new_path)
+ end
+ end
+end
diff --git a/spec/components/pajamas/alert_component_spec.rb b/spec/components/pajamas/alert_component_spec.rb
new file mode 100644
index 00000000000..628d715ff64
--- /dev/null
+++ b/spec/components/pajamas/alert_component_spec.rb
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+RSpec.describe Pajamas::AlertComponent, :aggregate_failures, type: :component do
+ context 'with content' do
+ before do
+ render_inline(described_class.new) { '_content_' }
+ end
+
+ it 'has content' do
+ expect(rendered_component).to have_text('_content_')
+ end
+ end
+
+ context 'with defaults' do
+ before do
+ render_inline described_class.new
+ end
+
+ it 'does not set a title' do
+ expect(rendered_component).not_to have_selector('.gl-alert-title')
+ expect(rendered_component).to have_selector('.gl-alert-icon-no-title')
+ end
+
+ it 'renders the default variant' do
+ expect(rendered_component).to have_selector('.gl-alert-info')
+ expect(rendered_component).to have_selector("[data-testid='information-o-icon']")
+ end
+
+ it 'renders a dismiss button' do
+ expect(rendered_component).to have_selector('.gl-dismiss-btn.js-close')
+ expect(rendered_component).to have_selector("[data-testid='close-icon']")
+ end
+ end
+
+ context 'with custom options' do
+ context 'with simple options' do
+ context 'without dismissible content' do
+ before do
+ render_inline described_class.new(
+ title: '_title_',
+ dismissible: false,
+ alert_class: '_alert_class_',
+ alert_data: {
+ feature_id: '_feature_id_',
+ dismiss_endpoint: '_dismiss_endpoint_'
+ }
+ )
+ end
+
+ it 'sets the title' do
+ expect(rendered_component).to have_selector('.gl-alert-title')
+ expect(rendered_component).to have_content('_title_')
+ expect(rendered_component).not_to have_selector('.gl-alert-icon-no-title')
+ end
+
+ it 'sets to not be dismissible' do
+ expect(rendered_component).not_to have_selector('.gl-dismiss-btn.js-close')
+ expect(rendered_component).not_to have_selector("[data-testid='close-icon']")
+ end
+
+ it 'sets the alert_class' do
+ expect(rendered_component).to have_selector('._alert_class_')
+ end
+
+ it 'sets the alert_data' do
+ expect(rendered_component).to have_selector('[data-feature-id="_feature_id_"][data-dismiss-endpoint="_dismiss_endpoint_"]')
+ end
+ end
+ end
+
+ context 'with dismissible content' do
+ before do
+ render_inline described_class.new(
+ close_button_class: '_close_button_class_',
+ close_button_data: {
+ testid: '_close_button_testid_'
+ }
+ )
+ end
+
+ it 'renders a dismiss button and data' do
+ expect(rendered_component).to have_selector('.gl-dismiss-btn.js-close._close_button_class_')
+ expect(rendered_component).to have_selector("[data-testid='close-icon']")
+ expect(rendered_component).to have_selector('[data-testid="_close_button_testid_"]')
+ end
+ end
+
+ context 'with setting variant type' do
+ where(:variant) { [:warning, :success, :danger, :tip] }
+
+ before do
+ render_inline described_class.new(variant: variant)
+ end
+
+ with_them do
+ it 'renders the variant' do
+ expect(rendered_component).to have_selector(".gl-alert-#{variant}")
+ expect(rendered_component).to have_selector("[data-testid='#{described_class::ICONS[variant]}-icon']")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb b/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb
index a655c742973..fc741d0f3f6 100644
--- a/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb
+++ b/spec/controllers/projects/packages/infrastructure_registry_controller_spec.rb
@@ -41,17 +41,5 @@ RSpec.describe Projects::Packages::InfrastructureRegistryController do
it_behaves_like 'returning response status', :not_found
end
-
- context 'with package file pending destruction' do
- let_it_be(:package_file_pending_destruction) { create(:package_file, :pending_destruction, package: terraform_module) }
-
- let(:terraform_module_package_file) { terraform_module.package_files.first }
-
- it 'does not return them' do
- subject
-
- expect(assigns(:package_files)).to contain_exactly(terraform_module_package_file)
- end
- end
end
end
diff --git a/spec/features/merge_requests/user_mass_updates_spec.rb b/spec/features/merge_requests/user_mass_updates_spec.rb
index f781ba0827c..a15b6072e70 100644
--- a/spec/features/merge_requests/user_mass_updates_spec.rb
+++ b/spec/features/merge_requests/user_mass_updates_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe 'Merge requests > User mass updates', :js do
it 'updates merge request with assignee' do
change_assignee(user.name)
- expect(find('.issuable-meta a.author-link')[:title]).to eq "Attention requested from assignee #{user.name}, go to their profile."
+ expect(find('.issuable-meta a.author-link')[:title]).to eq "Attention requested from assignee #{user.name}"
end
end
end
diff --git a/spec/frontend/issues/show/components/description_spec.js b/spec/frontend/issues/show/components/description_spec.js
index 6f6f50b89bc..b96dfc00c11 100644
--- a/spec/frontend/issues/show/components/description_spec.js
+++ b/spec/frontend/issues/show/components/description_spec.js
@@ -2,11 +2,13 @@ import $ from 'jquery';
import { nextTick } from 'vue';
import '~/behaviors/markdown/render_gfm';
import { GlTooltip, GlModal } from '@gitlab/ui';
+import setWindowLocation from 'helpers/set_window_location_helper';
import { stubComponent } from 'helpers/stub_component';
import { TEST_HOST } from 'helpers/test_constants';
import { mockTracking } from 'helpers/tracking_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import Description from '~/issues/show/components/description.vue';
+import { updateHistory } from '~/lib/utils/url_utility';
import TaskList from '~/task_list';
import WorkItemDetailModal from '~/work_items/components/work_item_detail_modal.vue';
import CreateWorkItem from '~/work_items/pages/create_work_item.vue';
@@ -17,6 +19,10 @@ import {
} from '../mock_data/mock_data';
jest.mock('~/flash');
+jest.mock('~/lib/utils/url_utility', () => ({
+ ...jest.requireActual('~/lib/utils/url_utility'),
+ updateHistory: jest.fn(),
+}));
jest.mock('~/task_list');
const showModal = jest.fn();
@@ -55,6 +61,8 @@ describe('Description component', () => {
}
beforeEach(() => {
+ setWindowLocation(TEST_HOST);
+
if (!document.querySelector('.issuable-meta')) {
const metaData = document.createElement('div');
metaData.classList.add('issuable-meta');
@@ -285,48 +293,86 @@ describe('Description component', () => {
describe('work items detail', () => {
const findTaskLink = () => wrapper.find('a.gfm-issue');
- beforeEach(() => {
- createComponent({
- props: {
- descriptionHtml: descriptionHtmlWithTask,
- },
- provide: {
- glFeatures: { workItems: true },
- },
+ describe('when opening and closing', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ descriptionHtml: descriptionHtmlWithTask,
+ },
+ provide: {
+ glFeatures: { workItems: true },
+ },
+ });
+ return nextTick();
});
- return nextTick();
- });
- it('opens when task button is clicked', async () => {
- expect(findWorkItemDetailModal().props('visible')).toBe(false);
+ it('opens when task button is clicked', async () => {
+ expect(findWorkItemDetailModal().props('visible')).toBe(false);
- await findTaskLink().trigger('click');
+ await findTaskLink().trigger('click');
- expect(findWorkItemDetailModal().props('visible')).toBe(true);
- });
+ expect(findWorkItemDetailModal().props('visible')).toBe(true);
+ expect(updateHistory).toHaveBeenCalledWith({
+ url: `${TEST_HOST}/?work_item_id=2`,
+ replace: true,
+ });
+ });
- it('closes from an open state', async () => {
- await findTaskLink().trigger('click');
+ it('closes from an open state', async () => {
+ await findTaskLink().trigger('click');
- expect(findWorkItemDetailModal().props('visible')).toBe(true);
+ expect(findWorkItemDetailModal().props('visible')).toBe(true);
- findWorkItemDetailModal().vm.$emit('close');
- await nextTick();
+ findWorkItemDetailModal().vm.$emit('close');
+ await nextTick();
- expect(findWorkItemDetailModal().props('visible')).toBe(false);
- });
+ expect(findWorkItemDetailModal().props('visible')).toBe(false);
+ expect(updateHistory).toHaveBeenLastCalledWith({
+ url: `${TEST_HOST}/`,
+ replace: true,
+ });
+ });
- it('tracks when opened', async () => {
- const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ it('tracks when opened', async () => {
+ const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
- await findTaskLink().trigger('click');
+ await findTaskLink().trigger('click');
- expect(trackingSpy).toHaveBeenCalledWith('workItems:show', 'viewed_work_item_from_modal', {
- category: 'workItems:show',
- label: 'work_item_view',
- property: 'type_task',
+ expect(trackingSpy).toHaveBeenCalledWith(
+ 'workItems:show',
+ 'viewed_work_item_from_modal',
+ {
+ category: 'workItems:show',
+ label: 'work_item_view',
+ property: 'type_task',
+ },
+ );
});
});
+
+ describe('when url query `work_item_id` exists', () => {
+ it.each`
+ behavior | workItemId | visible
+ ${'opens'} | ${'123'} | ${true}
+ ${'does not open'} | ${'123e'} | ${false}
+ ${'does not open'} | ${'12e3'} | ${false}
+ ${'does not open'} | ${'1e23'} | ${false}
+ ${'does not open'} | ${'x'} | ${false}
+ ${'does not open'} | ${'undefined'} | ${false}
+ `(
+ '$behavior when url contains `work_item_id=$workItemId`',
+ async ({ workItemId, visible }) => {
+ setWindowLocation(`?work_item_id=${workItemId}`);
+
+ createComponent({
+ props: { descriptionHtml: descriptionHtmlWithTask },
+ provide: { glFeatures: { workItems: true } },
+ });
+
+ expect(findWorkItemDetailModal().props('visible')).toBe(visible);
+ },
+ );
+ });
});
});
});
diff --git a/spec/frontend/jira_connect/subscriptions/pages/sign_in_spec.js b/spec/frontend/jira_connect/subscriptions/pages/sign_in_spec.js
index 175896c4ab0..97d1b077164 100644
--- a/spec/frontend/jira_connect/subscriptions/pages/sign_in_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/pages/sign_in_spec.js
@@ -5,7 +5,7 @@ import SignInLegacyButton from '~/jira_connect/subscriptions/components/sign_in_
import SignInOauthButton from '~/jira_connect/subscriptions/components/sign_in_oauth_button.vue';
import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
import createStore from '~/jira_connect/subscriptions/store';
-import { I18N_DEFAULT_SIGN_IN_BUTTON_TEXT } from '../../../../../app/assets/javascripts/jira_connect/subscriptions/constants';
+import { I18N_DEFAULT_SIGN_IN_BUTTON_TEXT } from '~/jira_connect/subscriptions/constants';
jest.mock('~/jira_connect/subscriptions/utils');
diff --git a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
index edc25eb7e02..f8011860a49 100644
--- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
+++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
@@ -41,7 +41,13 @@ import adminRunnersCountQuery from '~/runner/graphql/list/admin_runners_count.qu
import { captureException } from '~/runner/sentry_utils';
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-import { runnersData, runnersCountData, runnersDataPaginated } from '../mock_data';
+import {
+ runnersData,
+ runnersCountData,
+ runnersDataPaginated,
+ onlineContactTimeoutSecs,
+ staleTimeoutSecs,
+} from '../mock_data';
const mockRegistrationToken = 'MOCK_REGISTRATION_TOKEN';
const mockRunners = runnersData.data.runners.nodes;
@@ -94,6 +100,8 @@ describe('AdminRunnersApp', () => {
},
provide: {
localMutations,
+ onlineContactTimeoutSecs,
+ staleTimeoutSecs,
...provide,
},
...options,
diff --git a/spec/frontend/runner/components/__snapshots__/runner_status_popover_spec.js.snap b/spec/frontend/runner/components/__snapshots__/runner_status_popover_spec.js.snap
new file mode 100644
index 00000000000..80a04401760
--- /dev/null
+++ b/spec/frontend/runner/components/__snapshots__/runner_status_popover_spec.js.snap
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RunnerStatusPopover renders complete text 1`] = `"Never contacted: Runner has never contacted GitLab (when you register a runner, use gitlab-runner run to bring it online) Online: Runner has contacted GitLab within the last 2 hours Offline: Runner has not contacted GitLab in more than 2 hours Stale: Runner has not contacted GitLab in more than 2 months"`;
diff --git a/spec/frontend/runner/components/runner_list_spec.js b/spec/frontend/runner/components/runner_list_spec.js
index fab94771990..872394430ae 100644
--- a/spec/frontend/runner/components/runner_list_spec.js
+++ b/spec/frontend/runner/components/runner_list_spec.js
@@ -6,7 +6,8 @@ import {
} from 'helpers/vue_test_utils_helper';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import RunnerList from '~/runner/components/runner_list.vue';
-import { runnersData } from '../mock_data';
+import RunnerStatusPopover from '~/runner/components/runner_status_popover.vue';
+import { runnersData, onlineContactTimeoutSecs, staleTimeoutSecs } from '../mock_data';
const mockRunners = runnersData.data.runners.nodes;
const mockActiveRunnersCount = mockRunners.length;
@@ -28,21 +29,34 @@ describe('RunnerList', () => {
activeRunnersCount: mockActiveRunnersCount,
...props,
},
+ provide: {
+ onlineContactTimeoutSecs,
+ staleTimeoutSecs,
+ },
...options,
});
};
- beforeEach(() => {
- createComponent({}, mountExtended);
- });
-
afterEach(() => {
wrapper.destroy();
});
it('Displays headers', () => {
+ createComponent(
+ {
+ stubs: {
+ RunnerStatusPopover: {
+ template: '<div/>',
+ },
+ },
+ },
+ mountExtended,
+ );
+
const headerLabels = findHeaders().wrappers.map((w) => w.text());
+ expect(findHeaders().at(0).findComponent(RunnerStatusPopover).exists()).toBe(true);
+
expect(headerLabels).toEqual([
'Status',
'Runner',
@@ -61,6 +75,8 @@ describe('RunnerList', () => {
});
it('Displays a list of runners', () => {
+ createComponent({}, mountExtended);
+
expect(findRows()).toHaveLength(4);
expect(findSkeletonLoader().exists()).toBe(false);
@@ -69,6 +85,8 @@ describe('RunnerList', () => {
it('Displays details of a runner', () => {
const { id, description, version, shortSha } = mockRunners[0];
+ createComponent({}, mountExtended);
+
// Badges
expect(findCell({ fieldKey: 'status' }).text()).toMatchInterpolatedText(
'never contacted paused',
@@ -183,6 +201,8 @@ describe('RunnerList', () => {
const { id, shortSha } = mockRunners[0];
const numericId = getIdFromGraphQLId(id);
+ createComponent({}, mountExtended);
+
expect(findCell({ fieldKey: 'summary' }).text()).toContain(`#${numericId} (${shortSha})`);
});
diff --git a/spec/frontend/runner/components/runner_status_popover_spec.js b/spec/frontend/runner/components/runner_status_popover_spec.js
new file mode 100644
index 00000000000..789283d1245
--- /dev/null
+++ b/spec/frontend/runner/components/runner_status_popover_spec.js
@@ -0,0 +1,36 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import RunnerStatusPopover from '~/runner/components/runner_status_popover.vue';
+import HelpPopover from '~/vue_shared/components/help_popover.vue';
+import { onlineContactTimeoutSecs, staleTimeoutSecs } from '../mock_data';
+
+describe('RunnerStatusPopover', () => {
+ let wrapper;
+
+ const createComponent = ({ provide = {} } = {}) => {
+ wrapper = shallowMountExtended(RunnerStatusPopover, {
+ provide: {
+ onlineContactTimeoutSecs,
+ staleTimeoutSecs,
+ ...provide,
+ },
+ stubs: {
+ GlSprintf,
+ },
+ });
+ };
+
+ const findHelpPopover = () => wrapper.findComponent(HelpPopover);
+
+ it('renders popoover', () => {
+ createComponent();
+
+ expect(findHelpPopover().exists()).toBe(true);
+ });
+
+ it('renders complete text', () => {
+ createComponent();
+
+ expect(findHelpPopover().text()).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/runner/group_runners/group_runners_app_spec.js b/spec/frontend/runner/group_runners/group_runners_app_spec.js
index 6d7ecc4506a..706f46a7c56 100644
--- a/spec/frontend/runner/group_runners/group_runners_app_spec.js
+++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js
@@ -38,7 +38,13 @@ import getGroupRunnersCountQuery from '~/runner/graphql/list/group_runners_count
import GroupRunnersApp from '~/runner/group_runners/group_runners_app.vue';
import { captureException } from '~/runner/sentry_utils';
import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-import { groupRunnersData, groupRunnersDataPaginated, groupRunnersCountData } from '../mock_data';
+import {
+ groupRunnersData,
+ groupRunnersDataPaginated,
+ groupRunnersCountData,
+ onlineContactTimeoutSecs,
+ staleTimeoutSecs,
+} from '../mock_data';
Vue.use(VueApollo);
Vue.use(GlToast);
@@ -90,6 +96,10 @@ describe('GroupRunnersApp', () => {
groupRunnersLimitedCount: mockGroupRunnersLimitedCount,
...props,
},
+ provide: {
+ onlineContactTimeoutSecs,
+ staleTimeoutSecs,
+ },
});
};
diff --git a/spec/frontend/runner/mock_data.js b/spec/frontend/runner/mock_data.js
index 49c25039719..fbe8926124c 100644
--- a/spec/frontend/runner/mock_data.js
+++ b/spec/frontend/runner/mock_data.js
@@ -14,6 +14,10 @@ import runnerWithGroupData from 'test_fixtures/graphql/runner/details/runner.que
import runnerProjectsData from 'test_fixtures/graphql/runner/details/runner_projects.query.graphql.json';
import runnerJobsData from 'test_fixtures/graphql/runner/details/runner_jobs.query.graphql.json';
+// Other mock data
+export const onlineContactTimeoutSecs = 2 * 60 * 60;
+export const staleTimeoutSecs = 5259492; // Ruby's `2.months`
+
export {
runnersData,
runnersCountData,
diff --git a/spec/helpers/ci/runners_helper_spec.rb b/spec/helpers/ci/runners_helper_spec.rb
index dd1804e2078..0046d481282 100644
--- a/spec/helpers/ci/runners_helper_spec.rb
+++ b/spec/helpers/ci/runners_helper_spec.rb
@@ -86,7 +86,9 @@ RSpec.describe Ci::RunnersHelper do
it 'returns the data in format' do
expect(helper.admin_runners_data_attributes).to eq({
runner_install_help_page: 'https://docs.gitlab.com/runner/install/',
- registration_token: Gitlab::CurrentSettings.runners_registration_token
+ registration_token: Gitlab::CurrentSettings.runners_registration_token,
+ online_contact_timeout_secs: 7200,
+ stale_timeout_secs: 7889238
})
end
end
@@ -128,12 +130,14 @@ RSpec.describe Ci::RunnersHelper do
let(:group) { create(:group) }
it 'returns group data to render a runner list' do
- data = helper.group_runners_data_attributes(group)
-
- expect(data[:registration_token]).to eq(group.runners_token)
- expect(data[:group_id]).to eq(group.id)
- expect(data[:group_full_path]).to eq(group.full_path)
- expect(data[:runner_install_help_page]).to eq('https://docs.gitlab.com/runner/install/')
+ expect(helper.group_runners_data_attributes(group)).to eq({
+ registration_token: group.runners_token,
+ group_id: group.id,
+ group_full_path: group.full_path,
+ runner_install_help_page: 'https://docs.gitlab.com/runner/install/',
+ online_contact_timeout_secs: 7200,
+ stale_timeout_secs: 7889238
+ })
end
end
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index ccc2db00236..84e702cd6a9 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -425,16 +425,6 @@ RSpec.describe DiffHelper do
end
end
- describe '#diff_file_path_text' do
- it 'returns full path by default' do
- expect(diff_file_path_text(diff_file)).to eq(diff_file.new_path)
- end
-
- it 'returns truncated path' do
- expect(diff_file_path_text(diff_file, max: 10)).to eq("...open.rb")
- end
- end
-
describe "#collapsed_diff_url" do
let(:params) do
{
diff --git a/spec/lib/gitlab/data_builder/note_spec.rb b/spec/lib/gitlab/data_builder/note_spec.rb
index 90ca5430526..3fa535dd800 100644
--- a/spec/lib/gitlab/data_builder/note_spec.rb
+++ b/spec/lib/gitlab/data_builder/note_spec.rb
@@ -8,18 +8,22 @@ RSpec.describe Gitlab::DataBuilder::Note do
let(:data) { described_class.build(note, user) }
let(:fixed_time) { Time.at(1425600000) } # Avoid time precision errors
- before do
- expect(data).to have_key(:object_attributes)
- expect(data[:object_attributes]).to have_key(:url)
- expect(data[:object_attributes][:url])
- .to eq(Gitlab::UrlBuilder.build(note))
- expect(data[:object_kind]).to eq('note')
- expect(data[:user]).to eq(user.hook_attrs)
+ shared_examples 'includes general data' do
+ specify do
+ expect(data).to have_key(:object_attributes)
+ expect(data[:object_attributes]).to have_key(:url)
+ expect(data[:object_attributes][:url])
+ .to eq(Gitlab::UrlBuilder.build(note))
+ expect(data[:object_kind]).to eq('note')
+ expect(data[:user]).to eq(user.hook_attrs)
+ end
end
describe 'When asking for a note on commit' do
let(:note) { create(:note_on_commit, project: project) }
+ it_behaves_like 'includes general data'
+
it 'returns the note and commit-specific data' do
expect(data).to have_key(:commit)
end
@@ -31,6 +35,8 @@ RSpec.describe Gitlab::DataBuilder::Note do
describe 'When asking for a note on commit diff' do
let(:note) { create(:diff_note_on_commit, project: project) }
+ it_behaves_like 'includes general data'
+
it 'returns the note and commit-specific data' do
expect(data).to have_key(:commit)
end
@@ -51,22 +57,21 @@ RSpec.describe Gitlab::DataBuilder::Note do
create(:note_on_issue, noteable: issue, project: project)
end
+ it_behaves_like 'includes general data'
+
it 'returns the note and issue-specific data' do
- without_timestamps = lambda { |label| label.except('created_at', 'updated_at') }
- hook_attrs = issue.reload.hook_attrs
+ expect_next_instance_of(Gitlab::HookData::IssueBuilder) do |issue_data_builder|
+ expect(issue_data_builder).to receive(:build).and_return('Issue data')
+ end
- expect(data).to have_key(:issue)
- expect(data[:issue].except('updated_at', 'labels'))
- .to eq(hook_attrs.except('updated_at', 'labels'))
- expect(data[:issue]['updated_at'])
- .to be >= hook_attrs['updated_at']
- expect(data[:issue]['labels'].map(&without_timestamps))
- .to eq(hook_attrs['labels'].map(&without_timestamps))
+ expect(data[:issue]).to eq('Issue data')
end
context 'with confidential issue' do
let(:issue) { create(:issue, project: project, confidential: true) }
+ it_behaves_like 'includes general data'
+
it 'sets event_type to confidential_note' do
expect(data[:event_type]).to eq('confidential_note')
end
@@ -77,10 +82,12 @@ RSpec.describe Gitlab::DataBuilder::Note do
end
describe 'When asking for a note on merge request' do
+ let(:label) { create(:label, project: project) }
let(:merge_request) do
- create(:merge_request, created_at: fixed_time,
+ create(:labeled_merge_request, created_at: fixed_time,
updated_at: fixed_time,
- source_project: project)
+ source_project: project,
+ labels: [label])
end
let(:note) do
@@ -88,12 +95,14 @@ RSpec.describe Gitlab::DataBuilder::Note do
project: project)
end
- it 'returns the note and merge request data' do
- expect(data).to have_key(:merge_request)
- expect(data[:merge_request].except('updated_at'))
- .to eq(merge_request.reload.hook_attrs.except('updated_at'))
- expect(data[:merge_request]['updated_at'])
- .to be >= merge_request.hook_attrs['updated_at']
+ it_behaves_like 'includes general data'
+
+ it 'returns the merge request data' do
+ expect_next_instance_of(Gitlab::HookData::MergeRequestBuilder) do |mr_data_builder|
+ expect(mr_data_builder).to receive(:build).and_return('MR data')
+ end
+
+ expect(data[:merge_request]).to eq('MR data')
end
include_examples 'project hook data'
@@ -101,9 +110,11 @@ RSpec.describe Gitlab::DataBuilder::Note do
end
describe 'When asking for a note on merge request diff' do
+ let(:label) { create(:label, project: project) }
let(:merge_request) do
- create(:merge_request, created_at: fixed_time, updated_at: fixed_time,
- source_project: project)
+ create(:labeled_merge_request, created_at: fixed_time, updated_at: fixed_time,
+ source_project: project,
+ labels: [label])
end
let(:note) do
@@ -111,12 +122,14 @@ RSpec.describe Gitlab::DataBuilder::Note do
project: project)
end
- it 'returns the note and merge request diff data' do
- expect(data).to have_key(:merge_request)
- expect(data[:merge_request].except('updated_at'))
- .to eq(merge_request.reload.hook_attrs.except('updated_at'))
- expect(data[:merge_request]['updated_at'])
- .to be >= merge_request.hook_attrs['updated_at']
+ it_behaves_like 'includes general data'
+
+ it 'returns the merge request data' do
+ expect_next_instance_of(Gitlab::HookData::MergeRequestBuilder) do |mr_data_builder|
+ expect(mr_data_builder).to receive(:build).and_return('MR data')
+ end
+
+ expect(data[:merge_request]).to eq('MR data')
end
include_examples 'project hook data'
@@ -134,6 +147,8 @@ RSpec.describe Gitlab::DataBuilder::Note do
project: project)
end
+ it_behaves_like 'includes general data'
+
it 'returns the note and project snippet data' do
expect(data).to have_key(:snippet)
expect(data[:snippet].except('updated_at'))
diff --git a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb
index f5ee8eba8bc..676396697fb 100644
--- a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::HookData::IssuableBuilder do
let_it_be(:user) { create(:user) }
# This shared example requires a `builder` and `user` variable
- shared_examples 'issuable hook data' do |kind|
+ shared_examples 'issuable hook data' do |kind, hook_data_issuable_builder_class|
let(:data) { builder.build(user: user) }
include_examples 'project hook data' do
@@ -20,7 +20,7 @@ RSpec.describe Gitlab::HookData::IssuableBuilder do
expect(data[:object_kind]).to eq(kind)
expect(data[:user]).to eq(user.hook_attrs)
expect(data[:project]).to eq(builder.issuable.project.hook_attrs)
- expect(data[:object_attributes]).to eq(builder.issuable.hook_attrs)
+ expect(data[:object_attributes]).to eq(hook_data_issuable_builder_class.new(issuable).build)
expect(data[:changes]).to eq({})
expect(data[:repository]).to eq(builder.issuable.project.hook_attrs.slice(:name, :url, :description, :homepage))
end
@@ -95,12 +95,12 @@ RSpec.describe Gitlab::HookData::IssuableBuilder do
end
describe '#build' do
- it_behaves_like 'issuable hook data', 'issue' do
+ it_behaves_like 'issuable hook data', 'issue', Gitlab::HookData::IssueBuilder do
let(:issuable) { create(:issue, description: 'A description') }
let(:builder) { described_class.new(issuable) }
end
- it_behaves_like 'issuable hook data', 'merge_request' do
+ it_behaves_like 'issuable hook data', 'merge_request', Gitlab::HookData::MergeRequestBuilder do
let(:issuable) { create(:merge_request, description: 'A description') }
let(:builder) { described_class.new(issuable) }
end
diff --git a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
index ddd681f75f0..771fc0218e2 100644
--- a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
@@ -62,6 +62,7 @@ RSpec.describe Gitlab::HookData::MergeRequestBuilder do
expect(data).to include(:human_time_estimate)
expect(data).to include(:human_total_time_spent)
expect(data).to include(:human_time_change)
+ expect(data).to include(:labels)
end
context 'when the MR has an image in the description' do
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index e3c0e3a7a2b..b38135fc0b2 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -625,6 +625,16 @@ RSpec.describe Issuable do
end
end
+ describe "#labels_hook_attrs" do
+ let(:project) { create(:project) }
+ let(:label) { create(:label) }
+ let(:issue) { create(:labeled_issue, project: project, labels: [label]) }
+
+ it "returns a list of label hook attributes" do
+ expect(issue.labels_hook_attrs).to match_array([label.hook_attrs])
+ end
+ end
+
describe '.labels_hash' do
let(:feature_label) { create(:label, title: 'Feature') }
let(:second_label) { create(:label, title: 'Second Label') }
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 61ad9dc26be..fe09dadd0db 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -1172,18 +1172,6 @@ RSpec.describe Issue do
end
end
- describe '#hook_attrs' do
- it 'delegates to Gitlab::HookData::IssueBuilder#build' do
- builder = double
-
- expect(Gitlab::HookData::IssueBuilder)
- .to receive(:new).with(subject).and_return(builder)
- expect(builder).to receive(:build)
-
- subject.hook_attrs
- end
- end
-
describe '#check_for_spam?' do
let_it_be(:support_bot) { ::User.support_bot }
@@ -1332,15 +1320,6 @@ RSpec.describe Issue do
subject { create(:issue, updated_at: 1.hour.ago) }
end
- describe "#labels_hook_attrs" do
- let(:label) { create(:label) }
- let(:issue) { create(:labeled_issue, project: reusable_project, labels: [label]) }
-
- it "returns a list of label hook attributes" do
- expect(issue.labels_hook_attrs).to eq([label.hook_attrs])
- end
- end
-
context "relative positioning" do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 0d15851e583..9d734e85668 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1757,18 +1757,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
- describe '#hook_attrs' do
- it 'delegates to Gitlab::HookData::MergeRequestBuilder#build' do
- builder = double
-
- expect(Gitlab::HookData::MergeRequestBuilder)
- .to receive(:new).with(subject).and_return(builder)
- expect(builder).to receive(:build)
-
- subject.hook_attrs
- end
- end
-
describe '#diverged_commits_count' do
let(:project) { create(:project, :repository) }
let(:forked_project) { fork_project(project, nil, repository: true) }
diff --git a/spec/models/project_import_state_spec.rb b/spec/models/project_import_state_spec.rb
index 4ad2446f8d0..6d84b2c6931 100644
--- a/spec/models/project_import_state_spec.rb
+++ b/spec/models/project_import_state_spec.rb
@@ -89,19 +89,6 @@ RSpec.describe ProjectImportState, type: :model do
import_state.mark_as_failed(error_message)
end.to change { project.reload.import_data }.from(import_data).to(nil)
end
-
- context 'when remove_import_data_on_failure feature flag is disabled' do
- it 'removes project import data' do
- stub_feature_flags(remove_import_data_on_failure: false)
-
- project = create(:project, import_data: ProjectImportData.new(data: { 'test' => 'some data' }))
- import_state = create(:import_state, :started, project: project)
-
- expect do
- import_state.mark_as_failed(error_message)
- end.not_to change { project.reload.import_data }
- end
- end
end
describe '#human_status_name' do
diff --git a/spec/support/shared_examples/models/issuable_hook_data_shared_examples.rb b/spec/support/shared_examples/models/issuable_hook_data_shared_examples.rb
deleted file mode 100644
index 13ffc1b7f87..00000000000
--- a/spec/support/shared_examples/models/issuable_hook_data_shared_examples.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-# This shared example requires a `builder` and `user` variable
-RSpec.shared_examples 'issuable hook data' do |kind|
- let(:data) { builder.build(user: user) }
-
- include_examples 'project hook data' do
- let(:project) { builder.issuable.project }
- end
-
- include_examples 'deprecated repository hook data'
-
- context "with a #{kind}" do
- it 'contains issuable data' do
- expect(data[:object_kind]).to eq(kind)
- expect(data[:user]).to eq(user.hook_attrs)
- expect(data[:project]).to eq(builder.issuable.project.hook_attrs)
- expect(data[:object_attributes]).to eq(builder.issuable.hook_attrs)
- expect(data[:changes]).to eq({})
- expect(data[:repository]).to eq(builder.issuable.project.hook_attrs.slice(:name, :url, :description, :homepage))
- end
-
- it 'does not contain certain keys' do
- expect(data).not_to have_key(:assignees)
- expect(data).not_to have_key(:assignee)
- end
-
- describe 'changes are given' do
- let(:changes) do
- {
- cached_markdown_version: %w[foo bar],
- description: ['A description', 'A cool description'],
- description_html: %w[foo bar],
- in_progress_merge_commit_sha: %w[foo bar],
- lock_version: %w[foo bar],
- merge_jid: %w[foo bar],
- title: ['A title', 'Hello World'],
- title_html: %w[foo bar]
- }
- end
-
- let(:data) { builder.build(user: user, changes: changes) }
-
- it 'populates the :changes hash' do
- expect(data[:changes]).to match(hash_including({
- title: { previous: 'A title', current: 'Hello World' },
- description: { previous: 'A description', current: 'A cool description' }
- }))
- end
-
- it 'does not contain certain keys' do
- expect(data[:changes]).not_to have_key('cached_markdown_version')
- expect(data[:changes]).not_to have_key('description_html')
- expect(data[:changes]).not_to have_key('lock_version')
- expect(data[:changes]).not_to have_key('title_html')
- expect(data[:changes]).not_to have_key('in_progress_merge_commit_sha')
- expect(data[:changes]).not_to have_key('merge_jid')
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
index 95471203983..7677e5d8cb2 100644
--- a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
@@ -154,6 +154,30 @@ RSpec.shared_examples 'logs an auth warning' do |requested_actions|
end
end
+RSpec.shared_examples 'allowed to delete container repository images' do
+ let(:authentication_abilities) do
+ [:admin_container_image]
+ end
+
+ it_behaves_like 'a valid token'
+
+ context 'allow to delete images' do
+ let(:current_params) do
+ { scopes: ["repository:#{project.full_path}:*"] }
+ end
+
+ it_behaves_like 'a deletable'
+ end
+
+ context 'allow to delete images since registry 2.7' do
+ let(:current_params) do
+ { scopes: ["repository:#{project.full_path}:delete"] }
+ end
+
+ it_behaves_like 'a deletable since registry 2.7'
+ end
+end
+
RSpec.shared_examples 'a container registry auth service' do
include_context 'container registry auth service context'
@@ -544,38 +568,14 @@ RSpec.shared_examples 'a container registry auth service' do
end
context 'delete authorized as maintainer' do
- let_it_be(:current_project) { create(:project) }
+ let_it_be(:project) { create(:project) }
let_it_be(:current_user) { create(:user) }
- let(:authentication_abilities) do
- [:admin_container_image]
- end
-
before_all do
- current_project.add_maintainer(current_user)
- end
-
- it_behaves_like 'a valid token'
-
- context 'allow to delete images' do
- let(:current_params) do
- { scopes: ["repository:#{current_project.full_path}:*"] }
- end
-
- it_behaves_like 'a deletable' do
- let(:project) { current_project }
- end
+ project.add_maintainer(current_user)
end
- context 'allow to delete images since registry 2.7' do
- let(:current_params) do
- { scopes: ["repository:#{current_project.full_path}:delete"] }
- end
-
- it_behaves_like 'a deletable since registry 2.7' do
- let(:project) { current_project }
- end
- end
+ it_behaves_like 'allowed to delete container repository images'
end
context 'build authorized as user' do