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>2021-03-04 18:11:19 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-03-04 18:11:19 +0300
commit770adf92515e4311dfb42d89750d32a1e0628913 (patch)
tree574db6e5e92af5c1a0ffe87be345fffa24bb95f7 /spec
parentd5d47b45ddddcef0f8fc80a35ca7a8a2a0765fd1 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/finders/merge_requests/oldest_per_commit_finder_spec.rb61
-rw-r--r--spec/frontend/.eslintrc.yml1
-rw-r--r--spec/frontend/__helpers__/fake_date/fixtures.js4
-rw-r--r--spec/frontend/__helpers__/fake_date/index.js1
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js82
-rw-r--r--spec/frontend/authentication/u2f/authenticate_spec.js2
-rw-r--r--spec/frontend/authentication/u2f/register_spec.js2
-rw-r--r--spec/frontend/authentication/webauthn/authenticate_spec.js1
-rw-r--r--spec/frontend/authentication/webauthn/register_spec.js1
-rw-r--r--spec/frontend/awards_handler_spec.js1
-rw-r--r--spec/frontend/behaviors/quick_submit_spec.js2
-rw-r--r--spec/frontend/behaviors/requires_input_spec.js1
-rw-r--r--spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js2
-rw-r--r--spec/frontend/blob/blob_file_dropzone_spec.js1
-rw-r--r--spec/frontend/blob/sketch/index_spec.js2
-rw-r--r--spec/frontend/blob/viewer/index_spec.js2
-rw-r--r--spec/frontend/bootstrap_linked_tabs_spec.js2
-rw-r--r--spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js3
-rw-r--r--spec/frontend/ci_variable_list/ci_variable_list/native_form_variable_list_spec.js2
-rw-r--r--spec/frontend/collapsed_sidebar_todo_spec.js3
-rw-r--r--spec/frontend/commit/pipelines/pipelines_spec.js2
-rw-r--r--spec/frontend/create_item_dropdown_spec.js2
-rw-r--r--spec/frontend/deprecated_jquery_dropdown_spec.js2
-rw-r--r--spec/frontend/diffs/mock_data/diff_with_commit.js2
-rw-r--r--spec/frontend/filtered_search/dropdown_user_spec.js1
-rw-r--r--spec/frontend/filtered_search/dropdown_utils_spec.js1
-rw-r--r--spec/frontend/filtered_search/visual_token_value_spec.js2
-rw-r--r--spec/frontend/gl_field_errors_spec.js2
-rw-r--r--spec/frontend/header_spec.js1
-rw-r--r--spec/frontend/integrations/integration_settings_form_spec.js1
-rw-r--r--spec/frontend/issue_spec.js5
-rw-r--r--spec/frontend/line_highlighter_spec.js1
-rw-r--r--spec/frontend/merge_request_spec.js1
-rw-r--r--spec/frontend/merge_request_tabs_spec.js5
-rw-r--r--spec/frontend/mini_pipeline_graph_dropdown_spec.js2
-rw-r--r--spec/frontend/new_branch_spec.js2
-rw-r--r--spec/frontend/notes/components/diff_discussion_header_spec.js4
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js2
-rw-r--r--spec/frontend/notes/stores/getters_spec.js2
-rw-r--r--spec/frontend/oauth_remember_me_spec.js2
-rw-r--r--spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js2
-rw-r--r--spec/frontend/pages/admin/application_settings/account_and_limits_spec.js1
-rw-r--r--spec/frontend/pages/admin/users/new/index_spec.js2
-rw-r--r--spec/frontend/pages/dashboard/todos/index/todos_spec.js1
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js2
-rw-r--r--spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js2
-rw-r--r--spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js2
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js5
-rw-r--r--spec/frontend/pipeline_editor/components/header/validation_segment_spec.js21
-rw-r--r--spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js69
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js46
-rw-r--r--spec/frontend/pipelines/pipelines_table_row_spec.js2
-rw-r--r--spec/frontend/pipelines/pipelines_table_spec.js2
-rw-r--r--spec/frontend/pipelines_spec.js2
-rw-r--r--spec/frontend/project_select_combo_button_spec.js2
-rw-r--r--spec/frontend/prometheus_metrics/custom_metrics_spec.js1
-rw-r--r--spec/frontend/prometheus_metrics/prometheus_metrics_spec.js1
-rw-r--r--spec/frontend/read_more_spec.js2
-rw-r--r--spec/frontend/right_sidebar_spec.js1
-rw-r--r--spec/frontend/search/highlight_blob_search_result_spec.js2
-rw-r--r--spec/frontend/search_autocomplete_spec.js1
-rw-r--r--spec/frontend/settings_panels_spec.js2
-rw-r--r--spec/frontend/shortcuts_spec.js2
-rw-r--r--spec/frontend/test_setup.js5
-rw-r--r--spec/frontend/user_popovers_spec.js1
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_details_spec.js14
-rw-r--r--spec/frontend/vue_shared/alert_details/mocks/alerts.json2
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js1
-rw-r--r--spec/frontend/zen_mode_spec.js2
-rw-r--r--spec/graphql/types/alert_management/alert_type_spec.rb3
-rw-r--r--spec/lib/error_tracking/sentry_client/api_urls_spec.rb (renamed from spec/lib/sentry/api_urls_spec.rb)4
-rw-r--r--spec/lib/error_tracking/sentry_client/event_spec.rb (renamed from spec/lib/sentry/client/event_spec.rb)2
-rw-r--r--spec/lib/error_tracking/sentry_client/issue_link_spec.rb (renamed from spec/lib/sentry/client/issue_link_spec.rb)2
-rw-r--r--spec/lib/error_tracking/sentry_client/issue_spec.rb (renamed from spec/lib/sentry/client/issue_spec.rb)10
-rw-r--r--spec/lib/error_tracking/sentry_client/pagination_parser_spec.rb (renamed from spec/lib/sentry/pagination_parser_spec.rb)2
-rw-r--r--spec/lib/error_tracking/sentry_client/projects_spec.rb (renamed from spec/lib/sentry/client/projects_spec.rb)6
-rw-r--r--spec/lib/error_tracking/sentry_client/repo_spec.rb (renamed from spec/lib/sentry/client/repo_spec.rb)4
-rw-r--r--spec/lib/error_tracking/sentry_client_spec.rb (renamed from spec/lib/sentry/client_spec.rb)4
-rw-r--r--spec/mailers/emails/merge_requests_spec.rb39
-rw-r--r--spec/mailers/notify_spec.rb31
-rw-r--r--spec/models/bulk_imports/entity_spec.rb16
-rw-r--r--spec/models/error_tracking/project_error_tracking_setting_spec.rb14
-rw-r--r--spec/models/merge_request_spec.rb13
-rw-r--r--spec/requests/api/graphql/mutations/alert_management/alerts/create_alert_issue_spec.rb6
-rw-r--r--spec/requests/api/graphql/project/alert_management/alert/issue_spec.rb71
-rw-r--r--spec/requests/api/graphql/project/alert_management/alerts_spec.rb4
-rw-r--r--spec/requests/api/invitations_spec.rb12
-rw-r--r--spec/services/members/invite_service_spec.rb173
-rw-r--r--spec/services/merge_requests/after_create_service_spec.rb22
-rw-r--r--spec/services/merge_requests/create_service_spec.rb4
-rw-r--r--spec/services/repositories/changelog_service_spec.rb2
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb1
-rw-r--r--spec/support/shared_contexts/features/error_tracking_shared_context.rb2
-rw-r--r--spec/support/shared_examples/lib/sentry/client_shared_examples.rb4
-rw-r--r--spec/workers/error_tracking_issue_link_worker_spec.rb12
95 files changed, 513 insertions, 366 deletions
diff --git a/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
index 4e9d021fa5d..4724a8eb5c7 100644
--- a/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
+++ b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
@@ -6,12 +6,20 @@ RSpec.describe MergeRequests::OldestPerCommitFinder do
describe '#execute' do
it 'returns a Hash mapping commit SHAs to their oldest merge requests' do
project = create(:project)
+ sha1 = Digest::SHA1.hexdigest('foo')
+ sha2 = Digest::SHA1.hexdigest('bar')
+ sha3 = Digest::SHA1.hexdigest('baz')
mr1 = create(:merge_request, :merged, target_project: project)
mr2 = create(:merge_request, :merged, target_project: project)
+ mr3 = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ merge_commit_sha: sha3
+ )
+
mr1_diff = create(:merge_request_diff, merge_request: mr1)
mr2_diff = create(:merge_request_diff, merge_request: mr2)
- sha1 = Digest::SHA1.hexdigest('foo')
- sha2 = Digest::SHA1.hexdigest('bar')
create(:merge_request_diff_commit, merge_request_diff: mr1_diff, sha: sha1)
create(:merge_request_diff_commit, merge_request_diff: mr2_diff, sha: sha1)
@@ -22,11 +30,16 @@ RSpec.describe MergeRequests::OldestPerCommitFinder do
relative_order: 1
)
- commits = [double(:commit, id: sha1), double(:commit, id: sha2)]
+ commits = [
+ double(:commit, id: sha1),
+ double(:commit, id: sha2),
+ double(:commit, id: sha3)
+ ]
expect(described_class.new(project).execute(commits)).to eq(
sha1 => mr1,
- sha2 => mr2
+ sha2 => mr2,
+ sha3 => mr3
)
end
@@ -42,5 +55,45 @@ RSpec.describe MergeRequests::OldestPerCommitFinder do
expect(described_class.new(mr.target_project).execute(commits))
.to be_empty
end
+
+ it 'includes the merge request for a merge commit' do
+ project = create(:project)
+ sha = Digest::SHA1.hexdigest('foo')
+ mr = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ merge_commit_sha: sha
+ )
+
+ commits = [double(:commit, id: sha)]
+
+ # This expectation is set so we're certain that the merge commit SHAs (if
+ # a matching merge request is found) aren't also used for finding MRs
+ # according to diffs.
+ expect(MergeRequestDiffCommit)
+ .not_to receive(:oldest_merge_request_id_per_commit)
+
+ expect(described_class.new(project).execute(commits)).to eq(sha => mr)
+ end
+
+ it 'includes the oldest merge request when a merge commit is present in a newer merge request' do
+ project = create(:project)
+ sha = Digest::SHA1.hexdigest('foo')
+ mr1 = create(
+ :merge_request,
+ :merged,
+ target_project: project, merge_commit_sha: sha
+ )
+
+ mr2 = create(:merge_request, :merged, target_project: project)
+ mr_diff = create(:merge_request_diff, merge_request: mr2)
+
+ create(:merge_request_diff_commit, merge_request_diff: mr_diff, sha: sha)
+
+ commits = [double(:commit, id: sha)]
+
+ expect(described_class.new(project).execute(commits)).to eq(sha => mr1)
+ end
end
end
diff --git a/spec/frontend/.eslintrc.yml b/spec/frontend/.eslintrc.yml
index d0e585e844a..145e6c8961a 100644
--- a/spec/frontend/.eslintrc.yml
+++ b/spec/frontend/.eslintrc.yml
@@ -14,7 +14,6 @@ settings:
globals:
getJSONFixture: false
loadFixtures: false
- preloadFixtures: false
setFixtures: false
rules:
jest/expect-expect:
diff --git a/spec/frontend/__helpers__/fake_date/fixtures.js b/spec/frontend/__helpers__/fake_date/fixtures.js
new file mode 100644
index 00000000000..fcf9d4a9c64
--- /dev/null
+++ b/spec/frontend/__helpers__/fake_date/fixtures.js
@@ -0,0 +1,4 @@
+import { useFakeDate } from './jest';
+
+// Also see spec/support/helpers/javascript_fixtures_helpers.rb
+export const useFixturesFakeDate = () => useFakeDate(2015, 6, 3, 10);
diff --git a/spec/frontend/__helpers__/fake_date/index.js b/spec/frontend/__helpers__/fake_date/index.js
index 3d1b124ce79..9d00349bd26 100644
--- a/spec/frontend/__helpers__/fake_date/index.js
+++ b/spec/frontend/__helpers__/fake_date/index.js
@@ -1,2 +1,3 @@
export * from './fake_date';
export * from './jest';
+export * from './fixtures';
diff --git a/spec/frontend/alert_management/components/alert_management_table_spec.js b/spec/frontend/alert_management/components/alert_management_table_spec.js
index cea665aa50d..233585735b6 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -2,6 +2,8 @@ import { GlTable, GlAlert, GlLoadingIcon, GlDropdown, GlIcon, GlAvatar } from '@
import { mount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import mockAlerts from 'jest/vue_shared/alert_details/mocks/alerts.json';
import AlertManagementTable from '~/alert_management/components/alert_management_table.vue';
import { visitUrl } from '~/lib/utils/url_utility';
@@ -18,19 +20,18 @@ describe('AlertManagementTable', () => {
let wrapper;
let mock;
- const findAlertsTable = () => wrapper.find(GlTable);
+ const findAlertsTable = () => wrapper.findComponent(GlTable);
const findAlerts = () => wrapper.findAll('table tbody tr');
- const findAlert = () => wrapper.find(GlAlert);
- const findLoader = () => wrapper.find(GlLoadingIcon);
- const findStatusDropdown = () => wrapper.find(GlDropdown);
- const findDateFields = () => wrapper.findAll(TimeAgo);
- const findSearch = () => wrapper.find(FilteredSearchBar);
- const findSeverityColumnHeader = () =>
- wrapper.find('[data-testid="alert-management-severity-sort"]');
- const findFirstIDField = () => wrapper.findAll('[data-testid="idField"]').at(0);
- const findAssignees = () => wrapper.findAll('[data-testid="assigneesField"]');
- const findSeverityFields = () => wrapper.findAll('[data-testid="severityField"]');
- const findIssueFields = () => wrapper.findAll('[data-testid="issueField"]');
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findLoader = () => wrapper.findComponent(GlLoadingIcon);
+ const findStatusDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDateFields = () => wrapper.findAllComponents(TimeAgo);
+ const findSearch = () => wrapper.findComponent(FilteredSearchBar);
+ const findSeverityColumnHeader = () => wrapper.findByTestId('alert-management-severity-sort');
+ const findFirstIDField = () => wrapper.findAllByTestId('idField').at(0);
+ const findAssignees = () => wrapper.findAllByTestId('assigneesField');
+ const findSeverityFields = () => wrapper.findAllByTestId('severityField');
+ const findIssueFields = () => wrapper.findAllByTestId('issueField');
const alertsCount = {
open: 24,
triggered: 20,
@@ -40,29 +41,34 @@ describe('AlertManagementTable', () => {
};
function mountComponent({ provide = {}, data = {}, loading = false, stubs = {} } = {}) {
- wrapper = mount(AlertManagementTable, {
- provide: {
- ...defaultProvideValues,
- alertManagementEnabled: true,
- userCanEnableAlertManagement: true,
- ...provide,
- },
- data() {
- return data;
- },
- mocks: {
- $apollo: {
- mutate: jest.fn(),
- query: jest.fn(),
- queries: {
- alerts: {
- loading,
+ wrapper = extendedWrapper(
+ mount(AlertManagementTable, {
+ provide: {
+ ...defaultProvideValues,
+ alertManagementEnabled: true,
+ userCanEnableAlertManagement: true,
+ ...provide,
+ },
+ data() {
+ return data;
+ },
+ mocks: {
+ $apollo: {
+ mutate: jest.fn(),
+ query: jest.fn(),
+ queries: {
+ alerts: {
+ loading,
+ },
},
},
},
- },
- stubs,
- });
+ stubs,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ }),
+ );
}
beforeEach(() => {
@@ -72,7 +78,6 @@ describe('AlertManagementTable', () => {
afterEach(() => {
if (wrapper) {
wrapper.destroy();
- wrapper = null;
}
mock.restore();
});
@@ -241,9 +246,14 @@ describe('AlertManagementTable', () => {
expect(findIssueFields().at(0).text()).toBe('None');
});
- it('renders a link when one exists', () => {
- expect(findIssueFields().at(1).text()).toBe('#1');
- expect(findIssueFields().at(1).attributes('href')).toBe('/gitlab-org/gitlab/-/issues/1');
+ it('renders a link when one exists with the issue state and title tooltip', () => {
+ const issueField = findIssueFields().at(1);
+ const tooltip = getBinding(issueField.element, 'gl-tooltip');
+
+ expect(issueField.text()).toBe(`#1 (closed)`);
+ expect(issueField.attributes('href')).toBe('/gitlab-org/gitlab/-/issues/1');
+ expect(issueField.attributes('title')).toBe('My test issue');
+ expect(tooltip).not.toBe(undefined);
});
});
diff --git a/spec/frontend/authentication/u2f/authenticate_spec.js b/spec/frontend/authentication/u2f/authenticate_spec.js
index bf50ee88035..153d4be56af 100644
--- a/spec/frontend/authentication/u2f/authenticate_spec.js
+++ b/spec/frontend/authentication/u2f/authenticate_spec.js
@@ -8,8 +8,6 @@ describe('U2FAuthenticate', () => {
let container;
let component;
- preloadFixtures('u2f/authenticate.html');
-
beforeEach(() => {
loadFixtures('u2f/authenticate.html');
u2fDevice = new MockU2FDevice();
diff --git a/spec/frontend/authentication/u2f/register_spec.js b/spec/frontend/authentication/u2f/register_spec.js
index 9cbadbc2fef..a814144ac7a 100644
--- a/spec/frontend/authentication/u2f/register_spec.js
+++ b/spec/frontend/authentication/u2f/register_spec.js
@@ -8,8 +8,6 @@ describe('U2FRegister', () => {
let container;
let component;
- preloadFixtures('u2f/register.html');
-
beforeEach((done) => {
loadFixtures('u2f/register.html');
u2fDevice = new MockU2FDevice();
diff --git a/spec/frontend/authentication/webauthn/authenticate_spec.js b/spec/frontend/authentication/webauthn/authenticate_spec.js
index 0a82adfd0ee..8b27560bbbe 100644
--- a/spec/frontend/authentication/webauthn/authenticate_spec.js
+++ b/spec/frontend/authentication/webauthn/authenticate_spec.js
@@ -13,7 +13,6 @@ const mockResponse = {
};
describe('WebAuthnAuthenticate', () => {
- preloadFixtures('webauthn/authenticate.html');
useMockNavigatorCredentials();
let fallbackElement;
diff --git a/spec/frontend/authentication/webauthn/register_spec.js b/spec/frontend/authentication/webauthn/register_spec.js
index 1de952d176d..43cd3d7ca34 100644
--- a/spec/frontend/authentication/webauthn/register_spec.js
+++ b/spec/frontend/authentication/webauthn/register_spec.js
@@ -5,7 +5,6 @@ import MockWebAuthnDevice from './mock_webauthn_device';
import { useMockNavigatorCredentials } from './util';
describe('WebAuthnRegister', () => {
- preloadFixtures('webauthn/register.html');
useMockNavigatorCredentials();
const mockResponse = {
diff --git a/spec/frontend/awards_handler_spec.js b/spec/frontend/awards_handler_spec.js
index edd17cfd810..988f5c98e2b 100644
--- a/spec/frontend/awards_handler_spec.js
+++ b/spec/frontend/awards_handler_spec.js
@@ -60,7 +60,6 @@ describe('AwardsHandler', () => {
u: '6.0',
},
};
- preloadFixtures('snippets/show.html');
const openAndWaitForEmojiMenu = (sel = '.js-add-award') => {
$(sel).eq(0).click();
diff --git a/spec/frontend/behaviors/quick_submit_spec.js b/spec/frontend/behaviors/quick_submit_spec.js
index d3d65892aff..86a85831c6b 100644
--- a/spec/frontend/behaviors/quick_submit_spec.js
+++ b/spec/frontend/behaviors/quick_submit_spec.js
@@ -6,8 +6,6 @@ describe('Quick Submit behavior', () => {
const keydownEvent = (options = { keyCode: 13, metaKey: true }) => $.Event('keydown', options);
- preloadFixtures('snippets/show.html');
-
beforeEach(() => {
loadFixtures('snippets/show.html');
diff --git a/spec/frontend/behaviors/requires_input_spec.js b/spec/frontend/behaviors/requires_input_spec.js
index 0f27f89d6dc..bb22133ae44 100644
--- a/spec/frontend/behaviors/requires_input_spec.js
+++ b/spec/frontend/behaviors/requires_input_spec.js
@@ -3,7 +3,6 @@ import '~/behaviors/requires_input';
describe('requiresInput', () => {
let submitButton;
- preloadFixtures('branches/new_branch.html');
beforeEach(() => {
loadFixtures('branches/new_branch.html');
diff --git a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
index 94ba1615c89..26d38b115b6 100644
--- a/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
+++ b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
@@ -13,8 +13,6 @@ describe('ShortcutsIssuable', () => {
const snippetShowFixtureName = 'snippets/show.html';
const mrShowFixtureName = 'merge_requests/merge_request_of_current_user.html';
- preloadFixtures(snippetShowFixtureName, mrShowFixtureName);
-
beforeAll((done) => {
initCopyAsGFM();
diff --git a/spec/frontend/blob/blob_file_dropzone_spec.js b/spec/frontend/blob/blob_file_dropzone_spec.js
index 95520577e9a..e387ab7c18a 100644
--- a/spec/frontend/blob/blob_file_dropzone_spec.js
+++ b/spec/frontend/blob/blob_file_dropzone_spec.js
@@ -7,7 +7,6 @@ jest.mock('~/projects/upload_file_experiment', () => ({
}));
describe('BlobFileDropzone', () => {
- preloadFixtures('blob/show.html');
let dropzone;
let replaceFileButton;
diff --git a/spec/frontend/blob/sketch/index_spec.js b/spec/frontend/blob/sketch/index_spec.js
index a24e7de9037..7424897b22c 100644
--- a/spec/frontend/blob/sketch/index_spec.js
+++ b/spec/frontend/blob/sketch/index_spec.js
@@ -4,8 +4,6 @@ import SketchLoader from '~/blob/sketch';
jest.mock('jszip');
describe('Sketch viewer', () => {
- preloadFixtures('static/sketch_viewer.html');
-
beforeEach(() => {
loadFixtures('static/sketch_viewer.html');
});
diff --git a/spec/frontend/blob/viewer/index_spec.js b/spec/frontend/blob/viewer/index_spec.js
index d793b5eb190..e4f145ae81b 100644
--- a/spec/frontend/blob/viewer/index_spec.js
+++ b/spec/frontend/blob/viewer/index_spec.js
@@ -16,8 +16,6 @@ describe('Blob viewer', () => {
setTestTimeout(2000);
- preloadFixtures('blob/show_readme.html');
-
beforeEach(() => {
$.fn.extend(jQueryMock);
mock = new MockAdapter(axios);
diff --git a/spec/frontend/bootstrap_linked_tabs_spec.js b/spec/frontend/bootstrap_linked_tabs_spec.js
index 2d8939e6480..30fb140bc69 100644
--- a/spec/frontend/bootstrap_linked_tabs_spec.js
+++ b/spec/frontend/bootstrap_linked_tabs_spec.js
@@ -1,8 +1,6 @@
import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs';
describe('Linked Tabs', () => {
- preloadFixtures('static/linked_tabs.html');
-
beforeEach(() => {
loadFixtures('static/linked_tabs.html');
});
diff --git a/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js b/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js
index ad1bdec1735..1bca21b1d57 100644
--- a/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js
+++ b/spec/frontend/ci_variable_list/ci_variable_list/ci_variable_list_spec.js
@@ -4,9 +4,6 @@ import VariableList from '~/ci_variable_list/ci_variable_list';
const HIDE_CLASS = 'hide';
describe('VariableList', () => {
- preloadFixtures('pipeline_schedules/edit.html');
- preloadFixtures('pipeline_schedules/edit_with_variables.html');
-
let $wrapper;
let variableList;
diff --git a/spec/frontend/ci_variable_list/ci_variable_list/native_form_variable_list_spec.js b/spec/frontend/ci_variable_list/ci_variable_list/native_form_variable_list_spec.js
index 4982b68fa81..eee1362440d 100644
--- a/spec/frontend/ci_variable_list/ci_variable_list/native_form_variable_list_spec.js
+++ b/spec/frontend/ci_variable_list/ci_variable_list/native_form_variable_list_spec.js
@@ -2,8 +2,6 @@ import $ from 'jquery';
import setupNativeFormVariableList from '~/ci_variable_list/native_form_variable_list';
describe('NativeFormVariableList', () => {
- preloadFixtures('pipeline_schedules/edit.html');
-
let $wrapper;
beforeEach(() => {
diff --git a/spec/frontend/collapsed_sidebar_todo_spec.js b/spec/frontend/collapsed_sidebar_todo_spec.js
index ef53cc9e103..7c659822672 100644
--- a/spec/frontend/collapsed_sidebar_todo_spec.js
+++ b/spec/frontend/collapsed_sidebar_todo_spec.js
@@ -14,9 +14,6 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
const jsonFixtureName = 'todos/todos.json';
let mock;
- preloadFixtures(fixtureName);
- preloadFixtures(jsonFixtureName);
-
beforeEach(() => {
const todoData = getJSONFixture(jsonFixtureName);
new Sidebar();
diff --git a/spec/frontend/commit/pipelines/pipelines_spec.js b/spec/frontend/commit/pipelines/pipelines_spec.js
index 3d6debda520..c8c8f6408b7 100644
--- a/spec/frontend/commit/pipelines/pipelines_spec.js
+++ b/spec/frontend/commit/pipelines/pipelines_spec.js
@@ -17,8 +17,6 @@ describe('Pipelines table in Commits and Merge requests', () => {
errorStateSvgPath: 'foo',
};
- preloadFixtures(jsonFixtureName);
-
const findRunPipelineBtn = () => vm.$el.querySelector('[data-testid="run_pipeline_button"]');
const findRunPipelineBtnMobile = () =>
vm.$el.querySelector('[data-testid="run_pipeline_button_mobile"]');
diff --git a/spec/frontend/create_item_dropdown_spec.js b/spec/frontend/create_item_dropdown_spec.js
index 7314eb5eee8..56c09cd731e 100644
--- a/spec/frontend/create_item_dropdown_spec.js
+++ b/spec/frontend/create_item_dropdown_spec.js
@@ -20,8 +20,6 @@ const DROPDOWN_ITEM_DATA = [
];
describe('CreateItemDropdown', () => {
- preloadFixtures('static/create_item_dropdown.html');
-
let $wrapperEl;
let createItemDropdown;
diff --git a/spec/frontend/deprecated_jquery_dropdown_spec.js b/spec/frontend/deprecated_jquery_dropdown_spec.js
index 6070532a1bf..7858f88f8c3 100644
--- a/spec/frontend/deprecated_jquery_dropdown_spec.js
+++ b/spec/frontend/deprecated_jquery_dropdown_spec.js
@@ -10,8 +10,6 @@ jest.mock('~/lib/utils/url_utility', () => ({
}));
describe('deprecatedJQueryDropdown', () => {
- preloadFixtures('static/deprecated_jquery_dropdown.html');
-
const NON_SELECTABLE_CLASSES =
'.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
const SEARCH_INPUT_SELECTOR = '.dropdown-input-field';
diff --git a/spec/frontend/diffs/mock_data/diff_with_commit.js b/spec/frontend/diffs/mock_data/diff_with_commit.js
index d646294ee84..f3b39bd3577 100644
--- a/spec/frontend/diffs/mock_data/diff_with_commit.js
+++ b/spec/frontend/diffs/mock_data/diff_with_commit.js
@@ -1,7 +1,5 @@
const FIXTURE = 'merge_request_diffs/with_commit.json';
-preloadFixtures(FIXTURE);
-
export default function getDiffWithCommit() {
return getJSONFixture(FIXTURE);
}
diff --git a/spec/frontend/filtered_search/dropdown_user_spec.js b/spec/frontend/filtered_search/dropdown_user_spec.js
index 0e2d2ee6c09..961587f7146 100644
--- a/spec/frontend/filtered_search/dropdown_user_spec.js
+++ b/spec/frontend/filtered_search/dropdown_user_spec.js
@@ -78,7 +78,6 @@ describe('Dropdown User', () => {
describe('hideCurrentUser', () => {
const fixtureTemplate = 'issues/issue_list.html';
- preloadFixtures(fixtureTemplate);
let dropdown;
let authorFilterDropdownElement;
diff --git a/spec/frontend/filtered_search/dropdown_utils_spec.js b/spec/frontend/filtered_search/dropdown_utils_spec.js
index 32d1f909d0b..49e14f58630 100644
--- a/spec/frontend/filtered_search/dropdown_utils_spec.js
+++ b/spec/frontend/filtered_search/dropdown_utils_spec.js
@@ -5,7 +5,6 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
describe('Dropdown Utils', () => {
const issueListFixture = 'issues/issue_list.html';
- preloadFixtures(issueListFixture);
describe('getEscapedText', () => {
it('should return same word when it has no space', () => {
diff --git a/spec/frontend/filtered_search/visual_token_value_spec.js b/spec/frontend/filtered_search/visual_token_value_spec.js
index a2082271efe..772fa7d07ed 100644
--- a/spec/frontend/filtered_search/visual_token_value_spec.js
+++ b/spec/frontend/filtered_search/visual_token_value_spec.js
@@ -133,8 +133,6 @@ describe('Filtered Search Visual Tokens', () => {
const jsonFixtureName = 'labels/project_labels.json';
const dummyEndpoint = '/dummy/endpoint';
- preloadFixtures(jsonFixtureName);
-
let labelData;
beforeAll(() => {
diff --git a/spec/frontend/gl_field_errors_spec.js b/spec/frontend/gl_field_errors_spec.js
index a1737211252..ada3b34e6b1 100644
--- a/spec/frontend/gl_field_errors_spec.js
+++ b/spec/frontend/gl_field_errors_spec.js
@@ -8,8 +8,6 @@ describe('GL Style Field Errors', () => {
testContext = {};
});
- preloadFixtures('static/gl_field_errors.html');
-
beforeEach(() => {
loadFixtures('static/gl_field_errors.html');
const $form = $('form.gl-show-field-errors');
diff --git a/spec/frontend/header_spec.js b/spec/frontend/header_spec.js
index 27305abfafa..4ca6d7259bd 100644
--- a/spec/frontend/header_spec.js
+++ b/spec/frontend/header_spec.js
@@ -15,7 +15,6 @@ describe('Header', () => {
$(document).trigger('todo:toggle', newCount);
}
- preloadFixtures(fixtureTemplate);
beforeEach(() => {
initTodoToggle();
loadFixtures(fixtureTemplate);
diff --git a/spec/frontend/integrations/integration_settings_form_spec.js b/spec/frontend/integrations/integration_settings_form_spec.js
index 348b942703f..cbb2ef380ba 100644
--- a/spec/frontend/integrations/integration_settings_form_spec.js
+++ b/spec/frontend/integrations/integration_settings_form_spec.js
@@ -7,7 +7,6 @@ jest.mock('~/vue_shared/plugins/global_toast');
describe('IntegrationSettingsForm', () => {
const FIXTURE = 'services/edit_service.html';
- preloadFixtures(FIXTURE);
beforeEach(() => {
loadFixtures(FIXTURE);
diff --git a/spec/frontend/issue_spec.js b/spec/frontend/issue_spec.js
index 970fdacd492..952ef54d286 100644
--- a/spec/frontend/issue_spec.js
+++ b/spec/frontend/issue_spec.js
@@ -8,11 +8,6 @@ describe('Issue', () => {
let testContext;
let mock;
- beforeAll(() => {
- preloadFixtures('issues/closed-issue.html');
- preloadFixtures('issues/open-issue.html');
- });
-
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet(/(.*)\/related_branches$/).reply(200, {});
diff --git a/spec/frontend/line_highlighter_spec.js b/spec/frontend/line_highlighter_spec.js
index 8318f63ab3e..b5a0adc9d49 100644
--- a/spec/frontend/line_highlighter_spec.js
+++ b/spec/frontend/line_highlighter_spec.js
@@ -7,7 +7,6 @@ import LineHighlighter from '~/line_highlighter';
describe('LineHighlighter', () => {
const testContext = {};
- preloadFixtures('static/line_highlighter.html');
const clickLine = (number, eventData = {}) => {
if ($.isEmptyObject(eventData)) {
return $(`#L${number}`).click();
diff --git a/spec/frontend/merge_request_spec.js b/spec/frontend/merge_request_spec.js
index 84647a108b2..0b7ed349507 100644
--- a/spec/frontend/merge_request_spec.js
+++ b/spec/frontend/merge_request_spec.js
@@ -9,7 +9,6 @@ describe('MergeRequest', () => {
describe('task lists', () => {
let mock;
- preloadFixtures('merge_requests/merge_request_with_task_list.html');
beforeEach(() => {
loadFixtures('merge_requests/merge_request_with_task_list.html');
diff --git a/spec/frontend/merge_request_tabs_spec.js b/spec/frontend/merge_request_tabs_spec.js
index fd2c240aff3..23e9bf8b447 100644
--- a/spec/frontend/merge_request_tabs_spec.js
+++ b/spec/frontend/merge_request_tabs_spec.js
@@ -21,11 +21,6 @@ describe('MergeRequestTabs', () => {
$.extend(stubLocation, defaults, stubs || {});
};
- preloadFixtures(
- 'merge_requests/merge_request_with_task_list.html',
- 'merge_requests/diff_comment.html',
- );
-
beforeEach(() => {
initMrPage();
diff --git a/spec/frontend/mini_pipeline_graph_dropdown_spec.js b/spec/frontend/mini_pipeline_graph_dropdown_spec.js
index 3ff34c967e4..ccd5a4ea142 100644
--- a/spec/frontend/mini_pipeline_graph_dropdown_spec.js
+++ b/spec/frontend/mini_pipeline_graph_dropdown_spec.js
@@ -5,8 +5,6 @@ import axios from '~/lib/utils/axios_utils';
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
describe('Mini Pipeline Graph Dropdown', () => {
- preloadFixtures('static/mini_dropdown_graph.html');
-
beforeEach(() => {
loadFixtures('static/mini_dropdown_graph.html');
});
diff --git a/spec/frontend/new_branch_spec.js b/spec/frontend/new_branch_spec.js
index 7e6b8a78d4f..66b28a8c0dc 100644
--- a/spec/frontend/new_branch_spec.js
+++ b/spec/frontend/new_branch_spec.js
@@ -9,8 +9,6 @@ describe('Branch', () => {
});
describe('create a new branch', () => {
- preloadFixtures('branches/new_branch.html');
-
function fillNameWith(value) {
$('.js-branch-name').val(value).trigger('blur');
}
diff --git a/spec/frontend/notes/components/diff_discussion_header_spec.js b/spec/frontend/notes/components/diff_discussion_header_spec.js
index fdc89522901..fa34a5e8d39 100644
--- a/spec/frontend/notes/components/diff_discussion_header_spec.js
+++ b/spec/frontend/notes/components/diff_discussion_header_spec.js
@@ -6,14 +6,10 @@ import createStore from '~/notes/stores';
import mockDiffFile from '../../diffs/mock_data/diff_discussions';
import { discussionMock } from '../mock_data';
-const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
-
describe('diff_discussion_header component', () => {
let store;
let wrapper;
- preloadFixtures(discussionWithTwoUnresolvedNotes);
-
beforeEach(() => {
window.mrTabs = {};
store = createStore();
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index 34df39bf1c7..dd65351ef88 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -24,8 +24,6 @@ describe('noteable_discussion component', () => {
let wrapper;
let originalGon;
- preloadFixtures(discussionWithTwoUnresolvedNotes);
-
beforeEach(() => {
window.mrTabs = {};
store = createStore();
diff --git a/spec/frontend/notes/stores/getters_spec.js b/spec/frontend/notes/stores/getters_spec.js
index 4ebfc679310..4d2f86a1ecf 100644
--- a/spec/frontend/notes/stores/getters_spec.js
+++ b/spec/frontend/notes/stores/getters_spec.js
@@ -26,8 +26,6 @@ const createDiscussionNeighborParams = (discussionId, diffOrder, step) => ({
describe('Getters Notes Store', () => {
let state;
- preloadFixtures(discussionWithTwoUnresolvedNotes);
-
beforeEach(() => {
state = {
discussions: [individualNote],
diff --git a/spec/frontend/oauth_remember_me_spec.js b/spec/frontend/oauth_remember_me_spec.js
index 910676a97ed..70bda1d9f9e 100644
--- a/spec/frontend/oauth_remember_me_spec.js
+++ b/spec/frontend/oauth_remember_me_spec.js
@@ -6,8 +6,6 @@ describe('OAuthRememberMe', () => {
return $(`#oauth-container .oauth-login${selector}`).parent('form').attr('action');
};
- preloadFixtures('static/oauth_remember_me.html');
-
beforeEach(() => {
loadFixtures('static/oauth_remember_me.html');
diff --git a/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js
index 2c76adf761f..71c9da238b4 100644
--- a/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js
+++ b/spec/frontend/pages/admin/abuse_reports/abuse_reports_spec.js
@@ -14,8 +14,6 @@ describe('Abuse Reports', () => {
const findMessage = (searchText) =>
$messages.filter((index, element) => element.innerText.indexOf(searchText) > -1).first();
- preloadFixtures(FIXTURE);
-
beforeEach(() => {
loadFixtures(FIXTURE);
new AbuseReports(); // eslint-disable-line no-new
diff --git a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js
index 8816609d1d2..9f326dc33c0 100644
--- a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js
+++ b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js
@@ -8,7 +8,6 @@ describe('AccountAndLimits', () => {
const FIXTURE = 'application_settings/accounts_and_limit.html';
let $userDefaultExternal;
let $userInternalRegex;
- preloadFixtures(FIXTURE);
beforeEach(() => {
loadFixtures(FIXTURE);
diff --git a/spec/frontend/pages/admin/users/new/index_spec.js b/spec/frontend/pages/admin/users/new/index_spec.js
index 60482860e84..ec9fe487030 100644
--- a/spec/frontend/pages/admin/users/new/index_spec.js
+++ b/spec/frontend/pages/admin/users/new/index_spec.js
@@ -7,8 +7,6 @@ describe('UserInternalRegexHandler', () => {
let $userEmail;
let $warningMessage;
- preloadFixtures(FIXTURE);
-
beforeEach(() => {
loadFixtures(FIXTURE);
// eslint-disable-next-line no-new
diff --git a/spec/frontend/pages/dashboard/todos/index/todos_spec.js b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
index fb612f17669..de8b29d54fc 100644
--- a/spec/frontend/pages/dashboard/todos/index/todos_spec.js
+++ b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
@@ -14,7 +14,6 @@ const TEST_COUNT_BIG = 2000;
const TEST_DONE_COUNT_BIG = 7300;
describe('Todos', () => {
- preloadFixtures('todos/todos.html');
let todoItem;
let mock;
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
index de63409b181..2a3b07f95f2 100644
--- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
+++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
@@ -6,8 +6,6 @@ import TimezoneDropdown, {
} from '~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown';
describe('Timezone Dropdown', () => {
- preloadFixtures('pipeline_schedules/edit.html');
-
let $inputEl = null;
let $dropdownEl = null;
let $wrapper = null;
diff --git a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
index 8632c852720..e39a3904613 100644
--- a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
+++ b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js
@@ -6,8 +6,6 @@ describe('preserve_url_fragment', () => {
return $(`.omniauth-container ${selector}`).parent('form').attr('action');
};
- preloadFixtures('sessions/new.html');
-
beforeEach(() => {
loadFixtures('sessions/new.html');
});
diff --git a/spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js b/spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js
index f04c16d2ddb..6aa725fbd7d 100644
--- a/spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js
+++ b/spec/frontend/pages/sessions/new/signin_tabs_memoizer_spec.js
@@ -18,8 +18,6 @@ describe('SigninTabsMemoizer', () => {
return memo;
}
- preloadFixtures(fixtureTemplate);
-
beforeEach(() => {
loadFixtures(fixtureTemplate);
diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
index 5eeccd78265..ef8ca574e59 100644
--- a/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_editor_header_spec.js
@@ -3,7 +3,7 @@ import PipelineEditorHeader from '~/pipeline_editor/components/header/pipeline_e
import PipelineStatus from '~/pipeline_editor/components/header/pipeline_status.vue';
import ValidationSegment from '~/pipeline_editor/components/header/validation_segment.vue';
-import { mockLintResponse } from '../../mock_data';
+import { mockCiYml, mockLintResponse } from '../../mock_data';
describe('Pipeline editor header', () => {
let wrapper;
@@ -19,8 +19,9 @@ describe('Pipeline editor header', () => {
...mockProvide,
...provide,
},
- props: {
+ propsData: {
ciConfigData: mockLintResponse,
+ ciFileContent: mockCiYml,
isCiConfigDataLoading: false,
},
});
diff --git a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
index cf1d89e1d7c..274c2d1b8da 100644
--- a/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/validation_segment_spec.js
@@ -7,9 +7,9 @@ import ValidationSegment, {
i18n,
} from '~/pipeline_editor/components/header/validation_segment.vue';
import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
-import { mockYmlHelpPagePath, mergeUnwrappedCiConfig } from '../../mock_data';
+import { mockYmlHelpPagePath, mergeUnwrappedCiConfig, mockCiYml } from '../../mock_data';
-describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
+describe('Validation segment component', () => {
let wrapper;
const createComponent = (props = {}) => {
@@ -20,6 +20,7 @@ describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
},
propsData: {
ciConfig: mergeUnwrappedCiConfig(),
+ ciFileContent: mockCiYml,
loading: false,
...props,
},
@@ -42,6 +43,20 @@ describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
expect(wrapper.text()).toBe(i18n.loading);
});
+ describe('when config is empty', () => {
+ beforeEach(() => {
+ createComponent({ ciFileContent: '' });
+ });
+
+ it('has check icon', () => {
+ expect(findIcon().props('name')).toBe('check');
+ });
+
+ it('shows a message for empty state', () => {
+ expect(findValidationMsg().text()).toBe(i18n.empty);
+ });
+ });
+
describe('when config is valid', () => {
beforeEach(() => {
createComponent({});
@@ -61,7 +76,7 @@ describe('~/pipeline_editor/components/info/validation_segment.vue', () => {
});
});
- describe('when config is not valid', () => {
+ describe('when config is invalid', () => {
beforeEach(() => {
createComponent({
ciConfig: mergeUnwrappedCiConfig({
diff --git a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js
index 2210fc87f68..b444d9dcfea 100644
--- a/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js
+++ b/spec/frontend/pipeline_editor/components/ui/pipeline_editor_empty_state_spec.js
@@ -1,42 +1,79 @@
-import { GlSprintf } from '@gitlab/ui';
+import { GlButton, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue';
describe('Pipeline editor empty state', () => {
let wrapper;
const defaultProvide = {
+ glFeatures: {
+ pipelineEditorEmptyStateAction: false,
+ },
emptyStateIllustrationPath: 'my/svg/path',
};
- const createComponent = () => {
+ const createComponent = ({ provide } = {}) => {
wrapper = shallowMount(PipelineEditorEmptyState, {
- provide: defaultProvide,
+ provide: { ...defaultProvide, ...provide },
});
};
const findSvgImage = () => wrapper.find('img');
const findTitle = () => wrapper.find('h1');
+ const findConfirmButton = () => wrapper.findComponent(GlButton);
const findDescription = () => wrapper.findComponent(GlSprintf);
- beforeEach(() => {
- createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
});
- it('renders an svg image', () => {
- expect(findSvgImage().exists()).toBe(true);
- });
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
- it('renders a title', () => {
- expect(findTitle().exists()).toBe(true);
- expect(findTitle().text()).toBe(wrapper.vm.$options.i18n.title);
+ it('renders an svg image', () => {
+ expect(findSvgImage().exists()).toBe(true);
+ });
+
+ it('renders a title', () => {
+ expect(findTitle().exists()).toBe(true);
+ expect(findTitle().text()).toBe(wrapper.vm.$options.i18n.title);
+ });
+
+ it('renders a description', () => {
+ expect(findDescription().exists()).toBe(true);
+ expect(findDescription().html()).toContain(wrapper.vm.$options.i18n.body);
+ });
+
+ describe('with feature flag off', () => {
+ it('does not renders a CTA button', () => {
+ expect(findConfirmButton().exists()).toBe(false);
+ });
+ });
});
- it('renders a description', () => {
- expect(findDescription().exists()).toBe(true);
- expect(findDescription().html()).toContain(wrapper.vm.$options.i18n.body);
+ describe('with feature flag on', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ glFeatures: {
+ pipelineEditorEmptyStateAction: true,
+ },
+ },
+ });
+ });
+
+ it('renders a CTA button', () => {
+ expect(findConfirmButton().exists()).toBe(true);
+ expect(findConfirmButton().text()).toBe(wrapper.vm.$options.i18n.btnText);
+ });
+
+ it('emits an event when clicking on the CTA', async () => {
+ const expectedEvent = 'createEmptyConfigFile';
+ expect(wrapper.emitted(expectedEvent)).toBeUndefined();
+
+ await findConfirmButton().vm.$emit('click');
+ expect(wrapper.emitted(expectedEvent)).toHaveLength(1);
+ });
});
});
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
index 0dfd123db75..887d296222f 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -7,6 +7,7 @@ import httpStatusCodes from '~/lib/utils/http_status';
import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue';
+import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue';
import { COMMIT_SUCCESS, COMMIT_FAILURE, LOAD_FAILURE_UNKNOWN } from '~/pipeline_editor/constants';
import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.graphql';
@@ -30,6 +31,9 @@ const MockEditorLite = {
const mockProvide = {
ciConfigPath: mockCiConfigPath,
defaultBranch: mockDefaultBranch,
+ glFeatures: {
+ pipelineEditorEmptyStateAction: false,
+ },
projectFullPath: mockProjectFullPath,
};
@@ -40,14 +44,17 @@ describe('Pipeline editor app component', () => {
let mockBlobContentData;
let mockCiConfigData;
- const createComponent = ({ blobLoading = false, options = {} } = {}) => {
+ const createComponent = ({ blobLoading = false, options = {}, provide = {} } = {}) => {
wrapper = shallowMount(PipelineEditorApp, {
- provide: mockProvide,
+ provide: { ...mockProvide, ...provide },
stubs: {
GlTabs,
GlButton,
CommitForm,
+ PipelineEditorHome,
+ PipelineEditorTabs,
EditorLite: MockEditorLite,
+ PipelineEditorEmptyState,
},
mocks: {
$apollo: {
@@ -65,7 +72,7 @@ describe('Pipeline editor app component', () => {
});
};
- const createComponentWithApollo = ({ props = {} } = {}) => {
+ const createComponentWithApollo = ({ props = {}, provide = {} } = {}) => {
const handlers = [[getCiConfigData, mockCiConfigData]];
const resolvers = {
Query: {
@@ -86,7 +93,7 @@ describe('Pipeline editor app component', () => {
apolloProvider: mockApollo,
};
- createComponent({ props, options });
+ createComponent({ props, provide, options });
};
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
@@ -94,6 +101,8 @@ describe('Pipeline editor app component', () => {
const findEditorHome = () => wrapper.findComponent(PipelineEditorHome);
const findTextEditor = () => wrapper.findComponent(TextEditor);
const findEmptyState = () => wrapper.findComponent(PipelineEditorEmptyState);
+ const findEmptyStateButton = () =>
+ wrapper.findComponent(PipelineEditorEmptyState).findComponent(GlButton);
beforeEach(() => {
mockBlobContentData = jest.fn();
@@ -105,7 +114,6 @@ describe('Pipeline editor app component', () => {
mockCiConfigData.mockReset();
wrapper.destroy();
- wrapper = null;
});
it('displays a loading icon if the blob query is loading', () => {
@@ -196,6 +204,34 @@ describe('Pipeline editor app component', () => {
});
});
+ describe('when landing on the empty state with feature flag on', () => {
+ it('user can click on CTA button and see an empty editor', async () => {
+ mockBlobContentData.mockRejectedValueOnce({
+ response: {
+ status: httpStatusCodes.NOT_FOUND,
+ },
+ });
+
+ createComponentWithApollo({
+ provide: {
+ glFeatures: {
+ pipelineEditorEmptyStateAction: true,
+ },
+ },
+ });
+
+ await waitForPromises();
+
+ expect(findEmptyState().exists()).toBe(true);
+ expect(findTextEditor().exists()).toBe(false);
+
+ await findEmptyStateButton().vm.$emit('click');
+
+ expect(findEmptyState().exists()).toBe(false);
+ expect(findTextEditor().exists()).toBe(true);
+ });
+ });
+
describe('when the user commits', () => {
const updateFailureMessage = 'The GitLab CI configuration could not be updated.';
diff --git a/spec/frontend/pipelines/pipelines_table_row_spec.js b/spec/frontend/pipelines/pipelines_table_row_spec.js
index 56da636bb3d..26767cd3805 100644
--- a/spec/frontend/pipelines/pipelines_table_row_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_row_spec.js
@@ -19,8 +19,6 @@ describe('Pipelines Table Row', () => {
let pipelineWithoutAuthor;
let pipelineWithoutCommit;
- preloadFixtures(jsonFixtureName);
-
beforeEach(() => {
const { pipelines } = getJSONFixture(jsonFixtureName);
diff --git a/spec/frontend/pipelines/pipelines_table_spec.js b/spec/frontend/pipelines/pipelines_table_spec.js
index 4f4d71e5dab..d72ea7b42a6 100644
--- a/spec/frontend/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/pipelines/pipelines_table_spec.js
@@ -52,8 +52,6 @@ describe('Pipelines Table', () => {
const findTimeAgoTh = () => wrapper.findByTestId('timeago-th');
const findActionsTh = () => wrapper.findByTestId('actions-th');
- preloadFixtures(jsonFixtureName);
-
beforeEach(() => {
const { pipelines } = getJSONFixture(jsonFixtureName);
pipeline = pipelines.find((p) => p.user !== null && p.commit !== null);
diff --git a/spec/frontend/pipelines_spec.js b/spec/frontend/pipelines_spec.js
index 6d4d634c575..add91fbcc23 100644
--- a/spec/frontend/pipelines_spec.js
+++ b/spec/frontend/pipelines_spec.js
@@ -1,8 +1,6 @@
import Pipelines from '~/pipelines';
describe('Pipelines', () => {
- preloadFixtures('static/pipeline_graph.html');
-
beforeEach(() => {
loadFixtures('static/pipeline_graph.html');
});
diff --git a/spec/frontend/project_select_combo_button_spec.js b/spec/frontend/project_select_combo_button_spec.js
index c47db71b4ac..5cdc3d174a1 100644
--- a/spec/frontend/project_select_combo_button_spec.js
+++ b/spec/frontend/project_select_combo_button_spec.js
@@ -10,8 +10,6 @@ describe('Project Select Combo Button', () => {
testContext = {};
});
- preloadFixtures(fixturePath);
-
beforeEach(() => {
testContext.defaults = {
label: 'Select project to create issue',
diff --git a/spec/frontend/prometheus_metrics/custom_metrics_spec.js b/spec/frontend/prometheus_metrics/custom_metrics_spec.js
index 3e3d4ee361a..20593351ee5 100644
--- a/spec/frontend/prometheus_metrics/custom_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/custom_metrics_spec.js
@@ -9,7 +9,6 @@ describe('PrometheusMetrics', () => {
const customMetricsEndpoint =
'http://test.host/frontend-fixtures/services-project/prometheus/metrics';
let mock;
- preloadFixtures(FIXTURE);
beforeEach(() => {
mock = new MockAdapter(axios);
diff --git a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
index 722a5274ad4..a703dc0a66f 100644
--- a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
@@ -6,7 +6,6 @@ import { metrics2 as metrics, missingVarMetrics } from './mock_data';
describe('PrometheusMetrics', () => {
const FIXTURE = 'services/prometheus/prometheus_service.html';
- preloadFixtures(FIXTURE);
beforeEach(() => {
loadFixtures(FIXTURE);
diff --git a/spec/frontend/read_more_spec.js b/spec/frontend/read_more_spec.js
index d1d01272403..16f0d7fb075 100644
--- a/spec/frontend/read_more_spec.js
+++ b/spec/frontend/read_more_spec.js
@@ -3,8 +3,6 @@ import initReadMore from '~/read_more';
describe('Read more click-to-expand functionality', () => {
const fixtureName = 'projects/overview.html';
- preloadFixtures(fixtureName);
-
beforeEach(() => {
loadFixtures(fixtureName);
});
diff --git a/spec/frontend/right_sidebar_spec.js b/spec/frontend/right_sidebar_spec.js
index f3719b28baa..8699e1cf420 100644
--- a/spec/frontend/right_sidebar_spec.js
+++ b/spec/frontend/right_sidebar_spec.js
@@ -27,7 +27,6 @@ const assertSidebarState = (state) => {
describe('RightSidebar', () => {
describe('fixture tests', () => {
const fixtureName = 'issues/open-issue.html';
- preloadFixtures(fixtureName);
let mock;
beforeEach(() => {
diff --git a/spec/frontend/search/highlight_blob_search_result_spec.js b/spec/frontend/search/highlight_blob_search_result_spec.js
index c1b0c7d794b..6908bcbd283 100644
--- a/spec/frontend/search/highlight_blob_search_result_spec.js
+++ b/spec/frontend/search/highlight_blob_search_result_spec.js
@@ -4,8 +4,6 @@ const fixture = 'search/blob_search_result.html';
const searchKeyword = 'Send'; // spec/frontend/fixtures/search.rb#79
describe('search/highlight_blob_search_result', () => {
- preloadFixtures(fixture);
-
beforeEach(() => loadFixtures(fixture));
it('highlights lines with search term occurrence', () => {
diff --git a/spec/frontend/search_autocomplete_spec.js b/spec/frontend/search_autocomplete_spec.js
index a9fbe0fe552..5aca07d59e4 100644
--- a/spec/frontend/search_autocomplete_spec.js
+++ b/spec/frontend/search_autocomplete_spec.js
@@ -105,7 +105,6 @@ describe('Search autocomplete dropdown', () => {
expect(list.find(mrsIHaveCreatedLink).text()).toBe("Merge requests I've created");
};
- preloadFixtures('static/search_autocomplete.html');
beforeEach(() => {
loadFixtures('static/search_autocomplete.html');
diff --git a/spec/frontend/settings_panels_spec.js b/spec/frontend/settings_panels_spec.js
index 8666106d3c6..6b739617b97 100644
--- a/spec/frontend/settings_panels_spec.js
+++ b/spec/frontend/settings_panels_spec.js
@@ -2,8 +2,6 @@ import $ from 'jquery';
import initSettingsPanels, { isExpanded } from '~/settings_panels';
describe('Settings Panels', () => {
- preloadFixtures('groups/edit.html');
-
beforeEach(() => {
loadFixtures('groups/edit.html');
});
diff --git a/spec/frontend/shortcuts_spec.js b/spec/frontend/shortcuts_spec.js
index 1650dd2c1ca..fc5eeee9687 100644
--- a/spec/frontend/shortcuts_spec.js
+++ b/spec/frontend/shortcuts_spec.js
@@ -20,8 +20,6 @@ describe('Shortcuts', () => {
target,
});
- preloadFixtures(fixtureName);
-
beforeEach(() => {
loadFixtures(fixtureName);
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index b6b29faef79..9b95ed6b816 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -44,11 +44,6 @@ Object.assign(global, {
getJSONFixture,
loadFixtures: loadHTMLFixture,
setFixtures: setHTMLFixture,
-
- // The following functions fill the fixtures cache in Karma.
- // This is not necessary in Jest because we make no Ajax request.
- loadJSONFixtures() {},
- preloadFixtures() {},
});
// custom-jquery-matchers was written for an old Jest version, we need to make it compatible
diff --git a/spec/frontend/user_popovers_spec.js b/spec/frontend/user_popovers_spec.js
index 5c6053f413f..745b66fd700 100644
--- a/spec/frontend/user_popovers_spec.js
+++ b/spec/frontend/user_popovers_spec.js
@@ -3,7 +3,6 @@ import initUserPopovers from '~/user_popovers';
describe('User Popovers', () => {
const fixtureTemplate = 'merge_requests/merge_request_with_mentions.html';
- preloadFixtures(fixtureTemplate);
const selector = '.js-user-link, .gfm-project_member';
const findFixtureLinks = () => {
diff --git a/spec/frontend/vue_shared/alert_details/alert_details_spec.js b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
index ce410a8b3e7..20301e1bc88 100644
--- a/spec/frontend/vue_shared/alert_details/alert_details_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
@@ -89,7 +89,7 @@ describe('AlertDetails', () => {
const findIncidentCreationAlert = () => wrapper.findByTestId('incidentCreationError');
const findEnvironmentName = () => wrapper.findByTestId('environmentName');
const findEnvironmentPath = () => wrapper.findByTestId('environmentPath');
- const findDetailsTable = () => wrapper.find(AlertDetailsTable);
+ const findDetailsTable = () => wrapper.findComponent(AlertDetailsTable);
const findMetricsTab = () => wrapper.findByTestId('metrics');
describe('Alert details', () => {
@@ -192,23 +192,21 @@ describe('AlertDetails', () => {
describe('Create incident from alert', () => {
it('should display "View incident" button that links the incident page when incident exists', () => {
- const issueIid = '3';
+ const iid = '3';
mountComponent({
- data: { alert: { ...mockAlert, issueIid }, sidebarStatus: false },
+ data: { alert: { ...mockAlert, issue: { iid } }, sidebarStatus: false },
});
expect(findViewIncidentBtn().exists()).toBe(true);
- expect(findViewIncidentBtn().attributes('href')).toBe(
- joinPaths(projectIssuesPath, issueIid),
- );
+ expect(findViewIncidentBtn().attributes('href')).toBe(joinPaths(projectIssuesPath, iid));
expect(findCreateIncidentBtn().exists()).toBe(false);
});
it('should display "Create incident" button when incident doesn\'t exist yet', () => {
- const issueIid = null;
+ const issue = null;
mountComponent({
mountMethod: mount,
- data: { alert: { ...mockAlert, issueIid } },
+ data: { alert: { ...mockAlert, issue } },
});
return wrapper.vm.$nextTick().then(() => {
diff --git a/spec/frontend/vue_shared/alert_details/mocks/alerts.json b/spec/frontend/vue_shared/alert_details/mocks/alerts.json
index 5267a4fe50d..007557e234a 100644
--- a/spec/frontend/vue_shared/alert_details/mocks/alerts.json
+++ b/spec/frontend/vue_shared/alert_details/mocks/alerts.json
@@ -21,7 +21,7 @@
"endedAt": "2020-04-17T23:18:14.996Z",
"status": "ACKNOWLEDGED",
"assignees": { "nodes": [{ "username": "root", "avatarUrl": "/url", "name": "root" }] },
- "issueIid": "1",
+ "issue": { "state" : "closed", "iid": "1", "title": "My test issue" },
"notes": {
"nodes": [
{
diff --git a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
index a6c5e23ae14..650d204201e 100644
--- a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
@@ -18,7 +18,6 @@ const DEFAULT_PROPS = {
describe('User Popover Component', () => {
const fixtureTemplate = 'merge_requests/diff_comment.html';
- preloadFixtures(fixtureTemplate);
let wrapper;
diff --git a/spec/frontend/zen_mode_spec.js b/spec/frontend/zen_mode_spec.js
index 5cc1d2200d3..bf4b57d8afb 100644
--- a/spec/frontend/zen_mode_spec.js
+++ b/spec/frontend/zen_mode_spec.js
@@ -13,8 +13,6 @@ describe('ZenMode', () => {
let dropzoneForElementSpy;
const fixtureName = 'snippets/show.html';
- preloadFixtures(fixtureName);
-
function enterZen() {
$('.notes-form .js-zen-enter').click();
}
diff --git a/spec/graphql/types/alert_management/alert_type_spec.rb b/spec/graphql/types/alert_management/alert_type_spec.rb
index 82b48a20708..9ff01418c9a 100644
--- a/spec/graphql/types/alert_management/alert_type_spec.rb
+++ b/spec/graphql/types/alert_management/alert_type_spec.rb
@@ -10,7 +10,8 @@ RSpec.describe GitlabSchema.types['AlertManagementAlert'] do
it 'exposes the expected fields' do
expected_fields = %i[
iid
- issue_iid
+ issueIid
+ issue
title
description
severity
diff --git a/spec/lib/sentry/api_urls_spec.rb b/spec/lib/error_tracking/sentry_client/api_urls_spec.rb
index d56b4397e1c..bd701748dc2 100644
--- a/spec/lib/sentry/api_urls_spec.rb
+++ b/spec/lib/error_tracking/sentry_client/api_urls_spec.rb
@@ -2,13 +2,13 @@
require 'spec_helper'
-RSpec.describe Sentry::ApiUrls do
+RSpec.describe ErrorTracking::SentryClient::ApiUrls do
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project/' }
let(:token) { 'test-token' }
let(:issue_id) { '123456' }
let(:issue_id_with_reserved_chars) { '123$%' }
let(:escaped_issue_id) { '123%24%25' }
- let(:api_urls) { Sentry::ApiUrls.new(sentry_url) }
+ let(:api_urls) { described_class.new(sentry_url) }
# Sentry API returns 404 if there are extra slashes in the URL!
shared_examples 'correct url with extra slashes' do
diff --git a/spec/lib/sentry/client/event_spec.rb b/spec/lib/error_tracking/sentry_client/event_spec.rb
index 07ed331c44c..64e674f1e9b 100644
--- a/spec/lib/sentry/client/event_spec.rb
+++ b/spec/lib/error_tracking/sentry_client/event_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Sentry::Client do
+RSpec.describe ErrorTracking::SentryClient do
include SentryClientHelpers
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
diff --git a/spec/lib/sentry/client/issue_link_spec.rb b/spec/lib/error_tracking/sentry_client/issue_link_spec.rb
index fe3abe7cb23..f86d328ef89 100644
--- a/spec/lib/sentry/client/issue_link_spec.rb
+++ b/spec/lib/error_tracking/sentry_client/issue_link_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Sentry::Client::IssueLink do
+RSpec.describe ErrorTracking::SentryClient::IssueLink do
include SentryClientHelpers
let_it_be(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
diff --git a/spec/lib/sentry/client/issue_spec.rb b/spec/lib/error_tracking/sentry_client/issue_spec.rb
index dedef905c95..e54296c58e0 100644
--- a/spec/lib/sentry/client/issue_spec.rb
+++ b/spec/lib/error_tracking/sentry_client/issue_spec.rb
@@ -2,12 +2,12 @@
require 'spec_helper'
-RSpec.describe Sentry::Client::Issue do
+RSpec.describe ErrorTracking::SentryClient::Issue do
include SentryClientHelpers
let(:token) { 'test-token' }
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0' }
- let(:client) { Sentry::Client.new(sentry_url, token) }
+ let(:client) { ErrorTracking::SentryClient.new(sentry_url, token) }
let(:issue_id) { 11 }
describe '#list_issues' do
@@ -136,7 +136,7 @@ RSpec.describe Sentry::Client::Issue do
subject { client.list_issues(issue_status: issue_status, limit: limit, sort: 'fish') }
it 'throws an error' do
- expect { subject }.to raise_error(Sentry::Client::BadRequestError, 'Invalid value for sort param')
+ expect { subject }.to raise_error(ErrorTracking::SentryClient::BadRequestError, 'Invalid value for sort param')
end
end
@@ -164,7 +164,7 @@ RSpec.describe Sentry::Client::Issue do
end
it 'raises exception' do
- expect { subject }.to raise_error(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "id"')
+ expect { subject }.to raise_error(ErrorTracking::SentryClient::MissingKeysError, 'Sentry API response is missing keys. key not found: "id"')
end
end
@@ -173,7 +173,7 @@ RSpec.describe Sentry::Client::Issue do
deep_size = double('Gitlab::Utils::DeepSize', valid?: false)
allow(Gitlab::Utils::DeepSize).to receive(:new).with(sentry_api_response).and_return(deep_size)
- expect { subject }.to raise_error(Sentry::Client::ResponseInvalidSizeError, 'Sentry API response is too big. Limit is 1 MB.')
+ expect { subject }.to raise_error(ErrorTracking::SentryClient::ResponseInvalidSizeError, 'Sentry API response is too big. Limit is 1 MB.')
end
end
diff --git a/spec/lib/sentry/pagination_parser_spec.rb b/spec/lib/error_tracking/sentry_client/pagination_parser_spec.rb
index c4ed24827bb..c4b771d5b93 100644
--- a/spec/lib/sentry/pagination_parser_spec.rb
+++ b/spec/lib/error_tracking/sentry_client/pagination_parser_spec.rb
@@ -2,7 +2,7 @@
require 'fast_spec_helper'
-RSpec.describe Sentry::PaginationParser do
+RSpec.describe ErrorTracking::SentryClient::PaginationParser do
describe '.parse' do
subject { described_class.parse(headers) }
diff --git a/spec/lib/sentry/client/projects_spec.rb b/spec/lib/error_tracking/sentry_client/projects_spec.rb
index ea2c5ccb81e..247f9c1c085 100644
--- a/spec/lib/sentry/client/projects_spec.rb
+++ b/spec/lib/error_tracking/sentry_client/projects_spec.rb
@@ -2,12 +2,12 @@
require 'spec_helper'
-RSpec.describe Sentry::Client::Projects do
+RSpec.describe ErrorTracking::SentryClient::Projects do
include SentryClientHelpers
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
let(:token) { 'test-token' }
- let(:client) { Sentry::Client.new(sentry_url, token) }
+ let(:client) { ErrorTracking::SentryClient.new(sentry_url, token) }
let(:projects_sample_response) do
Gitlab::Utils.deep_indifferent_access(
Gitlab::Json.parse(fixture_file('sentry/list_projects_sample_response.json'))
@@ -44,7 +44,7 @@ RSpec.describe Sentry::Client::Projects do
end
it 'raises exception' do
- expect { subject }.to raise_error(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "slug"')
+ expect { subject }.to raise_error(ErrorTracking::SentryClient::MissingKeysError, 'Sentry API response is missing keys. key not found: "slug"')
end
end
diff --git a/spec/lib/sentry/client/repo_spec.rb b/spec/lib/error_tracking/sentry_client/repo_spec.rb
index 956c0b6eee1..9a1c7a69c3d 100644
--- a/spec/lib/sentry/client/repo_spec.rb
+++ b/spec/lib/error_tracking/sentry_client/repo_spec.rb
@@ -2,12 +2,12 @@
require 'spec_helper'
-RSpec.describe Sentry::Client::Repo do
+RSpec.describe ErrorTracking::SentryClient::Repo do
include SentryClientHelpers
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
let(:token) { 'test-token' }
- let(:client) { Sentry::Client.new(sentry_url, token) }
+ let(:client) { ErrorTracking::SentryClient.new(sentry_url, token) }
let(:repos_sample_response) { Gitlab::Json.parse(fixture_file('sentry/repos_sample_response.json')) }
describe '#repos' do
diff --git a/spec/lib/sentry/client_spec.rb b/spec/lib/error_tracking/sentry_client_spec.rb
index cddcb6e98fa..9ffd756f057 100644
--- a/spec/lib/sentry/client_spec.rb
+++ b/spec/lib/error_tracking/sentry_client_spec.rb
@@ -2,11 +2,11 @@
require 'spec_helper'
-RSpec.describe Sentry::Client do
+RSpec.describe ErrorTracking::SentryClient do
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
let(:token) { 'test-token' }
- subject { Sentry::Client.new(sentry_url, token) }
+ subject { described_class.new(sentry_url, token) }
it { is_expected.to respond_to :projects }
it { is_expected.to respond_to :list_issues }
diff --git a/spec/mailers/emails/merge_requests_spec.rb b/spec/mailers/emails/merge_requests_spec.rb
index 5ab0265203e..1a61d3c4362 100644
--- a/spec/mailers/emails/merge_requests_spec.rb
+++ b/spec/mailers/emails/merge_requests_spec.rb
@@ -6,7 +6,8 @@ require 'email_spec'
RSpec.describe Emails::MergeRequests do
include EmailSpec::Matchers
- let_it_be(:recipient) { create(:user) }
+ include_context 'gitlab email notification'
+
let_it_be(:current_user) { create(:user) }
let_it_be(:assignee, reload: true) { create(:user, email: 'assignee@example.com', name: 'John Doe') }
let_it_be(:reviewer, reload: true) { create(:user, email: 'reviewer@example.com', name: 'Jane Doe') }
@@ -20,6 +21,42 @@ RSpec.describe Emails::MergeRequests do
description: 'Awesome description')
end
+ let(:recipient) { assignee }
+
+ describe '#merged_merge_request_email' do
+ let(:merge_author) { assignee }
+
+ subject { Notify.merged_merge_request_email(recipient.id, merge_request.id, merge_author.id) }
+
+ it_behaves_like 'a multiple recipients email'
+ it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
+ let(:model) { merge_request }
+ end
+
+ it_behaves_like 'it should show Gmail Actions View Merge request link'
+ it_behaves_like 'an unsubscribeable thread'
+ it_behaves_like 'appearance header and footer enabled'
+ it_behaves_like 'appearance header and footer not enabled'
+
+ it 'is sent as the merge author' do
+ sender = subject.header[:from].addrs[0]
+ expect(sender.display_name).to eq(merge_author.name)
+ expect(sender.address).to eq(gitlab_sender)
+ end
+
+ it 'has the correct subject and body' do
+ aggregate_failures do
+ is_expected.to have_referable_subject(merge_request, reply: true)
+ is_expected.to have_body_text('merged')
+ is_expected.to have_body_text(project_merge_request_path(project, merge_request))
+ is_expected.to have_link(merge_request.to_reference, href: project_merge_request_url(merge_request.target_project, merge_request))
+
+ expect(subject.text_part).to have_content(assignee.name)
+ expect(subject.text_part).to have_content(reviewer.name)
+ end
+ end
+ end
+
describe "#merge_when_pipeline_succeeds_email" do
let(:title) { "Merge request #{merge_request.to_reference} was scheduled to merge after pipeline succeeds by #{current_user.name}" }
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index a965980271b..762c57615b8 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -495,37 +495,6 @@ RSpec.describe Notify do
end
end
- describe 'that are merged' do
- let(:merge_author) { create(:user) }
-
- subject { described_class.merged_merge_request_email(recipient.id, merge_request.id, merge_author.id) }
-
- it_behaves_like 'a multiple recipients email'
- it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
- let(:model) { merge_request }
- end
-
- it_behaves_like 'it should show Gmail Actions View Merge request link'
- it_behaves_like 'an unsubscribeable thread'
- it_behaves_like 'appearance header and footer enabled'
- it_behaves_like 'appearance header and footer not enabled'
-
- it 'is sent as the merge author' do
- sender = subject.header[:from].addrs[0]
- expect(sender.display_name).to eq(merge_author.name)
- expect(sender.address).to eq(gitlab_sender)
- end
-
- it 'has the correct subject and body' do
- aggregate_failures do
- is_expected.to have_referable_subject(merge_request, reply: true)
- is_expected.to have_body_text('merged')
- is_expected.to have_body_text(project_merge_request_path(project, merge_request))
- is_expected.to have_link(merge_request.to_reference, href: project_merge_request_url(merge_request.target_project, merge_request))
- end
- end
- end
-
describe 'that are unmergeable' do
let_it_be(:merge_request) do
create(:merge_request, :conflict,
diff --git a/spec/models/bulk_imports/entity_spec.rb b/spec/models/bulk_imports/entity_spec.rb
index 6c9dc061430..17ab4d5954c 100644
--- a/spec/models/bulk_imports/entity_spec.rb
+++ b/spec/models/bulk_imports/entity_spec.rb
@@ -189,20 +189,4 @@ RSpec.describe BulkImports::Entity, type: :model do
expect(entity.next_page_for(:relation)).to eq('nextPage')
end
end
-
- describe 'caching', :clean_gitlab_redis_cache do
- let(:entity) { create(:bulk_import_entity, :started) }
-
- it 'removes entity cache keys' do
- cache_key = "bulk_import:#{entity.bulk_import.id}:entity:#{entity.id}:relation:1"
-
- Gitlab::Redis::Cache.with do |redis|
- redis.set(cache_key, 1)
-
- expect(redis).to receive(:del).with(cache_key)
- end
-
- entity.finish!
- end
- end
end
diff --git a/spec/models/error_tracking/project_error_tracking_setting_spec.rb b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
index 72ed11f6c74..3ae0666f7d0 100644
--- a/spec/models/error_tracking/project_error_tracking_setting_spec.rb
+++ b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
@@ -111,7 +111,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
describe '#sentry_client' do
it 'returns sentry client' do
- expect(subject.sentry_client).to be_a(Sentry::Client)
+ expect(subject.sentry_client).to be_a(ErrorTracking::SentryClient)
end
end
@@ -152,7 +152,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
end
end
- context 'when sentry client raises Sentry::Client::Error' do
+ context 'when sentry client raises ErrorTracking::SentryClient::Error' do
let(:sentry_client) { spy(:sentry_client) }
before do
@@ -160,7 +160,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
allow(subject).to receive(:sentry_client).and_return(sentry_client)
allow(sentry_client).to receive(:list_issues).with(opts)
- .and_raise(Sentry::Client::Error, 'error message')
+ .and_raise(ErrorTracking::SentryClient::Error, 'error message')
end
it 'returns error' do
@@ -171,7 +171,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
end
end
- context 'when sentry client raises Sentry::Client::MissingKeysError' do
+ context 'when sentry client raises ErrorTracking::SentryClient::MissingKeysError' do
let(:sentry_client) { spy(:sentry_client) }
before do
@@ -179,7 +179,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
allow(subject).to receive(:sentry_client).and_return(sentry_client)
allow(sentry_client).to receive(:list_issues).with(opts)
- .and_raise(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "id"')
+ .and_raise(ErrorTracking::SentryClient::MissingKeysError, 'Sentry API response is missing keys. key not found: "id"')
end
it 'returns error' do
@@ -190,7 +190,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
end
end
- context 'when sentry client raises Sentry::Client::ResponseInvalidSizeError' do
+ context 'when sentry client raises ErrorTracking::SentryClient::ResponseInvalidSizeError' do
let(:sentry_client) { spy(:sentry_client) }
let(:error_msg) {"Sentry API response is too big. Limit is #{Gitlab::Utils::DeepSize.human_default_max_size}."}
@@ -199,7 +199,7 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
allow(subject).to receive(:sentry_client).and_return(sentry_client)
allow(sentry_client).to receive(:list_issues).with(opts)
- .and_raise(Sentry::Client::ResponseInvalidSizeError, error_msg)
+ .and_raise(ErrorTracking::SentryClient::ResponseInvalidSizeError, error_msg)
end
it 'returns error' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index f22ee7b1686..551da6d0471 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -2885,11 +2885,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
describe '#mergeable?' do
subject { build_stubbed(:merge_request) }
- it 'returns false if still preparing' do
- expect(subject).to receive(:preparing?) { true }
- expect(subject.mergeable?).to be_falsey
- end
-
it 'returns false if #mergeable_state? is false' do
expect(subject).to receive(:mergeable_state?) { false }
@@ -3080,7 +3075,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
subject { build(:merge_request, merge_status: status) }
where(:status, :public_status) do
- 'preparing' | 'checking'
'cannot_be_merged_rechecking' | 'checking'
'checking' | 'checking'
'cannot_be_merged' | 'cannot_be_merged'
@@ -4136,13 +4130,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
include_examples 'for an valid state transition'
end
- context 'when the status is preparing' do
- let(:merge_status) { :preparing }
- let(:expected_merge_status) { 'unchecked' }
-
- include_examples 'for an valid state transition'
- end
-
context 'when the status is can_be_merged' do
let(:merge_status) { :can_be_merged }
let(:expected_merge_status) { 'unchecked' }
diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/create_alert_issue_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/create_alert_issue_spec.rb
index 6141a172253..f637ca98353 100644
--- a/spec/requests/api/graphql/mutations/alert_management/alerts/create_alert_issue_spec.rb
+++ b/spec/requests/api/graphql/mutations/alert_management/alerts/create_alert_issue_spec.rb
@@ -20,7 +20,9 @@ RSpec.describe 'Create an alert issue from an alert' do
errors
alert {
iid
- issueIid
+ issue {
+ iid
+ }
}
issue {
iid
@@ -46,7 +48,7 @@ RSpec.describe 'Create an alert issue from an alert' do
expect(mutation_response.slice('alert', 'issue')).to eq(
'alert' => {
'iid' => alert.iid.to_s,
- 'issueIid' => new_issue.iid.to_s
+ 'issue' => { 'iid' => new_issue.iid.to_s }
},
'issue' => {
'iid' => new_issue.iid.to_s,
diff --git a/spec/requests/api/graphql/project/alert_management/alert/issue_spec.rb b/spec/requests/api/graphql/project/alert_management/alert/issue_spec.rb
new file mode 100644
index 00000000000..9724de4fedb
--- /dev/null
+++ b/spec/requests/api/graphql/project/alert_management/alert/issue_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'getting Alert Management Alert Issue' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:current_user) { create(:user) }
+ let(:payload) { {} }
+ let(:query) { 'avg(metric) > 1.0' }
+
+ let(:fields) do
+ <<~QUERY
+ nodes {
+ iid
+ issue {
+ iid
+ state
+ }
+ }
+ QUERY
+ end
+
+ let(:graphql_query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field('alertManagementAlerts', {}, fields)
+ )
+ end
+
+ let(:alerts) { graphql_data.dig('project', 'alertManagementAlerts', 'nodes') }
+ let(:first_alert) { alerts.first }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ context 'with gitlab alert' do
+ before do
+ create(:alert_management_alert, :with_issue, project: project, payload: payload)
+ end
+
+ it 'includes the correct alert issue payload data' do
+ post_graphql(graphql_query, current_user: current_user)
+
+ expect(first_alert).to include('issue' => { "iid" => "1", "state" => "opened" })
+ end
+ end
+
+ describe 'performance' do
+ let(:first_n) { var('Int') }
+ let(:params) { { first: first_n } }
+ let(:limited_query) { with_signature([first_n], query) }
+
+ context 'with gitlab alert' do
+ before do
+ create(:alert_management_alert, :with_issue, project: project, payload: payload)
+ end
+
+ it 'avoids N+1 queries' do
+ base_count = ActiveRecord::QueryRecorder.new do
+ post_graphql(limited_query, current_user: current_user, variables: first_n.with(1))
+ end
+
+ expect { post_graphql(limited_query, current_user: current_user) }.not_to exceed_query_limit(base_count)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/alert_management/alerts_spec.rb b/spec/requests/api/graphql/project/alert_management/alerts_spec.rb
index 8deed75a466..fe77d9dc86d 100644
--- a/spec/requests/api/graphql/project/alert_management/alerts_spec.rb
+++ b/spec/requests/api/graphql/project/alert_management/alerts_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'getting Alert Management Alerts' do
let_it_be(:payload) { { 'custom' => { 'alert' => 'payload' }, 'runbook' => 'runbook' } }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:current_user) { create(:user) }
- let_it_be(:resolved_alert) { create(:alert_management_alert, :all_fields, :resolved, project: project, issue: nil, severity: :low).present }
+ let_it_be(:resolved_alert) { create(:alert_management_alert, :all_fields, :resolved, project: project, severity: :low).present }
let_it_be(:triggered_alert) { create(:alert_management_alert, :all_fields, project: project, severity: :critical, payload: payload).present }
let_it_be(:other_project_alert) { create(:alert_management_alert, :all_fields).present }
@@ -60,7 +60,6 @@ RSpec.describe 'getting Alert Management Alerts' do
it 'returns the correct properties of the alerts' do
expect(first_alert).to include(
'iid' => triggered_alert.iid.to_s,
- 'issueIid' => triggered_alert.issue_iid.to_s,
'title' => triggered_alert.title,
'description' => triggered_alert.description,
'severity' => triggered_alert.severity.upcase,
@@ -82,7 +81,6 @@ RSpec.describe 'getting Alert Management Alerts' do
expect(second_alert).to include(
'iid' => resolved_alert.iid.to_s,
- 'issueIid' => resolved_alert.issue_iid.to_s,
'status' => 'RESOLVED',
'endedAt' => resolved_alert.ended_at.strftime('%Y-%m-%dT%H:%M:%SZ')
)
diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb
index 2ea237469b1..a40eae8fdaf 100644
--- a/spec/requests/api/invitations_spec.rb
+++ b/spec/requests/api/invitations_spec.rb
@@ -3,14 +3,14 @@
require 'spec_helper'
RSpec.describe API::Invitations do
- let(:maintainer) { create(:user, username: 'maintainer_user') }
- let(:developer) { create(:user) }
- let(:access_requester) { create(:user) }
- let(:stranger) { create(:user) }
+ let_it_be(:maintainer) { create(:user, username: 'maintainer_user') }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:access_requester) { create(:user) }
+ let_it_be(:stranger) { create(:user) }
let(:email) { 'email1@example.com' }
let(:email2) { 'email2@example.com' }
- let(:project) do
+ let_it_be(:project) do
create(:project, :public, creator_id: maintainer.id, namespace: maintainer.namespace) do |project|
project.add_developer(developer)
project.add_maintainer(maintainer)
@@ -18,7 +18,7 @@ RSpec.describe API::Invitations do
end
end
- let!(:group) do
+ let_it_be(:group, reload: true) do
create(:group, :public) do |group|
group.add_developer(developer)
group.add_owner(maintainer)
diff --git a/spec/services/members/invite_service_spec.rb b/spec/services/members/invite_service_spec.rb
index 08cdf0d3ae1..cced93896a5 100644
--- a/spec/services/members/invite_service_spec.rb
+++ b/spec/services/members/invite_service_spec.rb
@@ -2,76 +2,155 @@
require 'spec_helper'
-RSpec.describe Members::InviteService do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
- let(:project_user) { create(:user) }
-
- before do
- project.add_maintainer(user)
+RSpec.describe Members::InviteService, :aggregate_failures do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.owner }
+ let_it_be(:project_user) { create(:user) }
+ let(:params) { {} }
+ let(:base_params) { { access_level: Gitlab::Access::GUEST } }
+
+ subject(:result) { described_class.new(user, base_params.merge(params)).execute(project) }
+
+ context 'when email is previously unused by current members' do
+ let(:params) { { email: 'email@example.org' } }
+
+ it 'successfully creates a member' do
+ expect { result }.to change(ProjectMember, :count).by(1)
+ expect(result[:status]).to eq(:success)
+ end
end
- it 'adds an existing user to members' do
- params = { email: project_user.email.to_s, access_level: Gitlab::Access::GUEST }
- result = described_class.new(user, params).execute(project)
+ context 'when emails are passed as an array' do
+ let(:params) { { email: %w[email@example.org email2@example.org] } }
- expect(result[:status]).to eq(:success)
- expect(project.users).to include project_user
+ it 'successfully creates members' do
+ expect { result }.to change(ProjectMember, :count).by(2)
+ expect(result[:status]).to eq(:success)
+ end
end
- it 'creates a new user for an unknown email address' do
- params = { email: 'email@example.org', access_level: Gitlab::Access::GUEST }
- result = described_class.new(user, params).execute(project)
+ context 'when emails are passed as an empty string' do
+ let(:params) { { email: '' } }
- expect(result[:status]).to eq(:success)
+ it 'returns an error' do
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Email cannot be blank')
+ end
end
- it 'limits the number of emails to 100' do
- emails = Array.new(101).map { |n| "email#{n}@example.com" }
- params = { email: emails, access_level: Gitlab::Access::GUEST }
+ context 'when email param is not included' do
+ it 'returns an error' do
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Email cannot be blank')
+ end
+ end
- result = described_class.new(user, params).execute(project)
+ context 'when email is not a valid email' do
+ let(:params) { { email: '_bogus_' } }
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('Too many users specified (limit is 100)')
+ it 'returns an error' do
+ expect { result }.not_to change(ProjectMember, :count)
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]['_bogus_']).to eq("Invite email is invalid")
+ end
end
- it 'does not invite an invalid email' do
- params = { email: project_user.id.to_s, access_level: Gitlab::Access::GUEST }
- result = described_class.new(user, params).execute(project)
+ context 'when duplicate email addresses are passed' do
+ let(:params) { { email: 'email@example.org,email@example.org' } }
+
+ it 'only creates one member per unique address' do
+ expect { result }.to change(ProjectMember, :count).by(1)
+ expect(result[:status]).to eq(:success)
+ end
+ end
- expect(result[:status]).to eq(:error)
- expect(result[:message][project_user.id.to_s]).to eq("Invite email is invalid")
- expect(project.users).not_to include project_user
+ context 'when observing email limits' do
+ let_it_be(:emails) { Array(1..101).map { |n| "email#{n}@example.com" } }
+
+ context 'when over the allowed default limit of emails' do
+ let(:params) { { email: emails } }
+
+ it 'limits the number of emails to 100' do
+ expect { result }.not_to change(ProjectMember, :count)
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Too many users specified (limit is 100)')
+ end
+ end
+
+ context 'when over the allowed custom limit of emails' do
+ let(:params) { { email: 'email@example.org,email2@example.org', limit: 1 } }
+
+ it 'limits the number of emails to the limit supplied' do
+ expect { result }.not_to change(ProjectMember, :count)
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Too many users specified (limit is 1)')
+ end
+ end
+
+ context 'when limit allowed is disabled via limit param' do
+ let(:params) { { email: emails, limit: -1 } }
+
+ it 'does not limit number of emails' do
+ expect { result }.to change(ProjectMember, :count).by(101)
+ expect(result[:status]).to eq(:success)
+ end
+ end
end
- it 'does not invite to an invalid access level' do
- params = { email: project_user.email, access_level: -1 }
- result = described_class.new(user, params).execute(project)
+ context 'when email belongs to an existing user' do
+ let(:params) { { email: project_user.email } }
- expect(result[:status]).to eq(:error)
- expect(result[:message][project_user.email]).to eq("Access level is not included in the list")
+ it 'adds an existing user to members' do
+ expect { result }.to change(ProjectMember, :count).by(1)
+ expect(result[:status]).to eq(:success)
+ expect(project.users).to include project_user
+ end
end
- it 'does not add a member with an existing invite' do
- invited_member = create(:project_member, :invited, project: project)
+ context 'when access level is not valid' do
+ let(:params) { { email: project_user.email, access_level: -1 } }
- params = { email: invited_member.invite_email,
- access_level: Gitlab::Access::GUEST }
- result = described_class.new(user, params).execute(project)
+ it 'returns an error' do
+ expect { result }.not_to change(ProjectMember, :count)
+ expect(result[:status]).to eq(:error)
+ expect(result[:message][project_user.email]).to eq("Access level is not included in the list")
+ end
+ end
+
+ context 'when invite already exists for an included email' do
+ let!(:invited_member) { create(:project_member, :invited, project: project) }
+ let(:params) { { email: "#{invited_member.invite_email},#{project_user.email}" } }
- expect(result[:status]).to eq(:error)
- expect(result[:message][invited_member.invite_email]).to eq("Member already invited to #{project.name}")
+ it 'adds new email and returns an error for the already invited email' do
+ expect { result }.to change(ProjectMember, :count).by(1)
+ expect(result[:status]).to eq(:error)
+ expect(result[:message][invited_member.invite_email]).to eq("Member already invited to #{project.name}")
+ expect(project.users).to include project_user
+ end
end
- it 'does not add a member with an access_request' do
- requested_member = create(:project_member, :access_request, project: project)
+ context 'when access request already exists for an included email' do
+ let!(:requested_member) { create(:project_member, :access_request, project: project) }
+ let(:params) { { email: "#{requested_member.user.email},#{project_user.email}" } }
+
+ it 'adds new email and returns an error for the already invited email' do
+ expect { result }.to change(ProjectMember, :count).by(1)
+ expect(result[:status]).to eq(:error)
+ expect(result[:message][requested_member.user.email])
+ .to eq("Member cannot be invited because they already requested to join #{project.name}")
+ expect(project.users).to include project_user
+ end
+ end
- params = { email: requested_member.user.email,
- access_level: Gitlab::Access::GUEST }
- result = described_class.new(user, params).execute(project)
+ context 'when email is already a member on the project' do
+ let!(:existing_member) { create(:project_member, :guest, project: project) }
+ let(:params) { { email: "#{existing_member.user.email},#{project_user.email}" } }
- expect(result[:status]).to eq(:error)
- expect(result[:message][requested_member.user.email]).to eq("Member cannot be invited because they already requested to join #{project.name}")
+ it 'adds new email and returns an error for the already invited email' do
+ expect { result }.to change(ProjectMember, :count).by(1)
+ expect(result[:status]).to eq(:error)
+ expect(result[:message][existing_member.user.email]).to eq("Already a member of #{project.name}")
+ expect(project.users).to include project_user
+ end
end
end
diff --git a/spec/services/merge_requests/after_create_service_spec.rb b/spec/services/merge_requests/after_create_service_spec.rb
index 22af346634f..f21feb70bc5 100644
--- a/spec/services/merge_requests/after_create_service_spec.rb
+++ b/spec/services/merge_requests/after_create_service_spec.rb
@@ -67,27 +67,5 @@ RSpec.describe MergeRequests::AfterCreateService do
it_behaves_like 'records an onboarding progress action', :merge_request_created do
let(:namespace) { merge_request.target_project.namespace }
end
-
- context 'when merge request is in unchecked state' do
- before do
- merge_request.mark_as_unchecked!
- execute_service
- end
-
- it 'does not change its state' do
- expect(merge_request.reload).to be_unchecked
- end
- end
-
- context 'when merge request is in preparing state' do
- before do
- merge_request.mark_as_preparing!
- execute_service
- end
-
- it 'marks the merge request as unchecked' do
- expect(merge_request.reload).to be_unchecked
- end
- end
end
end
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index e63e678bdd8..4f47a22b07c 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -67,10 +67,6 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
expect(Event.where(attributes).count).to eq(1)
end
- it 'sets the merge_status to preparing' do
- expect(merge_request.reload).to be_preparing
- end
-
describe 'when marked with /wip' do
context 'in title and in description' do
let(:opts) do
diff --git a/spec/services/repositories/changelog_service_spec.rb b/spec/services/repositories/changelog_service_spec.rb
index 4ec692d678a..91bc248b20a 100644
--- a/spec/services/repositories/changelog_service_spec.rb
+++ b/spec/services/repositories/changelog_service_spec.rb
@@ -76,7 +76,7 @@ RSpec.describe Repositories::ChangelogService do
recorder = ActiveRecord::QueryRecorder.new { service.execute }
changelog = project.repository.blob_at('master', 'CHANGELOG.md')&.data
- expect(recorder.count).to eq(10)
+ expect(recorder.count).to eq(11)
expect(changelog).to include('Title 1', 'Title 2')
end
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index 2224af88ab9..09425c3742a 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -12,6 +12,7 @@ module JavaScriptFixturesHelpers
included do |base|
base.around do |example|
# 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 }
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/features/error_tracking_shared_context.rb b/spec/support/shared_contexts/features/error_tracking_shared_context.rb
index 1f4eb3a6df9..f04111e0ce0 100644
--- a/spec/support/shared_contexts/features/error_tracking_shared_context.rb
+++ b/spec/support/shared_contexts/features/error_tracking_shared_context.rb
@@ -9,7 +9,7 @@ RSpec.shared_context 'sentry error tracking context feature' do
let_it_be(:issue_response) { Gitlab::Json.parse(issue_response_body) }
let_it_be(:event_response_body) { fixture_file('sentry/issue_latest_event_sample_response.json') }
let_it_be(:event_response) { Gitlab::Json.parse(event_response_body) }
- let(:sentry_api_urls) { Sentry::ApiUrls.new(project_error_tracking_settings.api_url) }
+ let(:sentry_api_urls) { ErrorTracking::SentryClient::ApiUrls.new(project_error_tracking_settings.api_url) }
let(:issue_id) { issue_response['id'] }
let(:issue_seen) { 1.year.ago.utc }
let(:formatted_issue_seen) { issue_seen.strftime("%Y-%m-%d %-l:%M:%S%p %Z") }
diff --git a/spec/support/shared_examples/lib/sentry/client_shared_examples.rb b/spec/support/shared_examples/lib/sentry/client_shared_examples.rb
index 4221708b55c..d73c7b6848d 100644
--- a/spec/support/shared_examples/lib/sentry/client_shared_examples.rb
+++ b/spec/support/shared_examples/lib/sentry/client_shared_examples.rb
@@ -26,7 +26,7 @@ RSpec.shared_examples 'no Sentry redirects' do |http_method|
end
it 'does not follow redirects' do
- expect { subject }.to raise_exception(Sentry::Client::Error, 'Sentry response status code: 302')
+ expect { subject }.to raise_exception(ErrorTracking::SentryClient::Error, 'Sentry response status code: 302')
expect(redirect_req_stub).to have_been_requested
expect(redirected_req_stub).not_to have_been_requested
end
@@ -53,7 +53,7 @@ RSpec.shared_examples 'maps Sentry exceptions' do |http_method|
it do
expect { subject }
- .to raise_exception(Sentry::Client::Error, message)
+ .to raise_exception(ErrorTracking::SentryClient::Error, message)
end
end
end
diff --git a/spec/workers/error_tracking_issue_link_worker_spec.rb b/spec/workers/error_tracking_issue_link_worker_spec.rb
index 5be568c2dad..90e747c8788 100644
--- a/spec/workers/error_tracking_issue_link_worker_spec.rb
+++ b/spec/workers/error_tracking_issue_link_worker_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe ErrorTrackingIssueLinkWorker do
describe '#perform' do
it 'creates a link between an issue and a Sentry issue in Sentry' do
- expect_next_instance_of(Sentry::Client) do |client|
+ expect_next_instance_of(ErrorTracking::SentryClient) do |client|
expect(client).to receive(:repos).with('sentry-org').and_return([repo])
expect(client)
.to receive(:create_issue_link)
@@ -33,8 +33,8 @@ RSpec.describe ErrorTrackingIssueLinkWorker do
shared_examples_for 'makes no external API requests' do
it 'takes no action' do
- expect_any_instance_of(Sentry::Client).not_to receive(:repos)
- expect_any_instance_of(Sentry::Client).not_to receive(:create_issue_link)
+ expect_any_instance_of(ErrorTracking::SentryClient).not_to receive(:repos)
+ expect_any_instance_of(ErrorTracking::SentryClient).not_to receive(:create_issue_link)
expect(subject).to be nil
end
@@ -42,7 +42,7 @@ RSpec.describe ErrorTrackingIssueLinkWorker do
shared_examples_for 'attempts to create a link via plugin' do
it 'takes no action' do
- expect_next_instance_of(Sentry::Client) do |client|
+ expect_next_instance_of(ErrorTracking::SentryClient) do |client|
expect(client).to receive(:repos).with('sentry-org').and_return([repo])
expect(client)
.to receive(:create_issue_link)
@@ -98,8 +98,8 @@ RSpec.describe ErrorTrackingIssueLinkWorker do
context 'when Sentry repos request errors' do
it 'falls back to creating a link via plugin' do
- expect_next_instance_of(Sentry::Client) do |client|
- expect(client).to receive(:repos).with('sentry-org').and_raise(Sentry::Client::Error)
+ expect_next_instance_of(ErrorTracking::SentryClient) do |client|
+ expect(client).to receive(:repos).with('sentry-org').and_raise(ErrorTracking::SentryClient::Error)
expect(client)
.to receive(:create_issue_link)
.with(nil, sentry_issue.sentry_issue_identifier, issue)