Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-03-17 21:08:54 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-03-17 21:08:54 +0300
commit1038f06b8654472558735796de54647888dabec4 (patch)
tree598742afff03a355d27236bc6b8966d47c66e737 /spec
parent6c41e447edac3453ae0df99fb9232ec71b679b75 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/groups/releases_controller_spec.rb34
-rw-r--r--spec/features/admin/admin_settings_spec.rb14
-rw-r--r--spec/finders/releases/group_releases_finder_spec.rb204
-rw-r--r--spec/frontend/content_editor/extensions/code_block_highlight_spec.js74
-rw-r--r--spec/frontend/content_editor/services/code_block_language_loader_spec.js70
-rw-r--r--spec/frontend/content_editor/services/content_editor_spec.js24
-rw-r--r--spec/frontend/fixtures/merge_requests.rb2
-rw-r--r--spec/frontend/security_configuration/components/training_provider_list_spec.js80
-rw-r--r--spec/frontend/security_configuration/mock_data.js2
-rw-r--r--spec/graphql/resolvers/board_list_issues_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/design_management/version_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/design_management/versions_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/group_issues_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/issue_status_counts_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb31
-rw-r--r--spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/labels_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/package_pipelines_resolver_spec.rb24
-rw-r--r--spec/graphql/resolvers/paginated_tree_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/project_milestones_resolver_spec.rb24
-rw-r--r--spec/graphql/resolvers/project_pipeline_resolver_spec.rb10
-rw-r--r--spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb13
-rw-r--r--spec/graphql/resolvers/timelog_resolver_spec.rb28
-rw-r--r--spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb37
-rw-r--r--spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb37
-rw-r--r--spec/models/users/credit_card_validation_spec.rb2
-rw-r--r--spec/requests/api/repositories_spec.rb7
-rw-r--r--spec/support/shared_examples/graphql/members_shared_examples.rb6
29 files changed, 635 insertions, 140 deletions
diff --git a/spec/controllers/groups/releases_controller_spec.rb b/spec/controllers/groups/releases_controller_spec.rb
index 582a77b1c50..8b08f913e10 100644
--- a/spec/controllers/groups/releases_controller_spec.rb
+++ b/spec/controllers/groups/releases_controller_spec.rb
@@ -20,11 +20,11 @@ RSpec.describe Groups::ReleasesController do
context 'as json' do
let(:format) { :json }
- subject { get :index, params: { group_id: group }, format: format }
+ subject(:index) { get :index, params: { group_id: group }, format: format }
context 'json_response' do
before do
- subject
+ index
end
it 'returns an application/json content_type' do
@@ -38,7 +38,7 @@ RSpec.describe Groups::ReleasesController do
context 'the user is not authorized' do
before do
- subject
+ index
end
it 'does not return any releases' do
@@ -54,12 +54,38 @@ RSpec.describe Groups::ReleasesController do
it "returns all group's public and private project's releases as JSON, ordered by released_at" do
sign_in(guest)
- subject
+ index
expect(json_response.map {|r| r['tag'] } ).to match_array(%w(p2 p1 v2 v1))
end
end
+ context 'group_releases_finder_inoperator feature flag' do
+ before do
+ sign_in(guest)
+ end
+
+ it 'calls old code when disabled' do
+ stub_feature_flags(group_releases_finder_inoperator: false)
+
+ allow(ReleasesFinder).to receive(:new).and_call_original
+
+ index
+
+ expect(ReleasesFinder).to have_received(:new)
+ end
+
+ it 'calls new code when enabled' do
+ stub_feature_flags(group_releases_finder_inoperator: true)
+
+ allow(Releases::GroupReleasesFinder).to receive(:new).and_call_original
+
+ index
+
+ expect(Releases::GroupReleasesFinder).to have_received(:new)
+ end
+ end
+
context 'N+1 queries' do
it 'avoids N+1 database queries' do
control_count = ActiveRecord::QueryRecorder.new { subject }.count
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 33e22c377a3..df93bd773a6 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -707,6 +707,20 @@ RSpec.describe 'Admin updates settings' do
include_examples 'regular throttle rate limit settings'
end
+
+ it 'changes search rate limits' do
+ visit network_admin_application_settings_path
+
+ page.within('.as-search-limits') do
+ fill_in 'Maximum number of requests per minute for an authenticated user', with: 98
+ fill_in 'Maximum number of requests per minute for an unauthenticated IP address', with: 76
+ click_button 'Save changes'
+ end
+
+ expect(page).to have_content "Application settings saved successfully"
+ expect(current_settings.search_rate_limit).to eq(98)
+ expect(current_settings.search_rate_limit_unauthenticated).to eq(76)
+ end
end
context 'Preferences page' do
diff --git a/spec/finders/releases/group_releases_finder_spec.rb b/spec/finders/releases/group_releases_finder_spec.rb
new file mode 100644
index 00000000000..b8899a8ee40
--- /dev/null
+++ b/spec/finders/releases/group_releases_finder_spec.rb
@@ -0,0 +1,204 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Releases::GroupReleasesFinder do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :repository, group: group) }
+ let(:params) { {} }
+ let(:args) { {} }
+ let(:repository) { project.repository }
+ let(:v1_0_0) { create(:release, project: project, tag: 'v1.0.0') }
+ let(:v1_1_0) { create(:release, project: project, tag: 'v1.1.0') }
+ let(:v1_1_1) { create(:release, project: project, tag: 'v1.1.1') }
+
+ before do
+ v1_0_0.update_attribute(:released_at, 2.days.ago)
+ v1_1_0.update_attribute(:released_at, 1.day.ago)
+ v1_1_1.update_attribute(:released_at, 0.5.days.ago)
+ end
+
+ shared_examples_for 'when the user is not part of the project' do
+ it 'returns no releases' do
+ is_expected.to be_empty
+ end
+ end
+
+ shared_examples_for 'when the user is not part of the group' do
+ before do
+ allow(Ability).to receive(:allowed?).with(user, :read_release, group).and_return(false)
+ end
+
+ it 'returns no releases' do
+ is_expected.to be_empty
+ end
+ end
+
+ shared_examples_for 'preload' do
+ before do
+ allow(Ability).to receive(:allowed?).with(user, :read_release, group).and_return(true)
+ end
+
+ it 'preloads associations' do
+ expect(Release).to receive(:preloaded).once.and_call_original
+
+ releases
+ end
+
+ context 'when preload is false' do
+ let(:args) { { preload: false } }
+
+ it 'does not preload associations' do
+ expect(Release).not_to receive(:preloaded)
+
+ releases
+ end
+ end
+ end
+
+ describe 'when parent is a group' do
+ context 'without subgroups' do
+ let(:project2) { create(:project, :repository, namespace: group) }
+ let!(:v6) { create(:release, project: project2, tag: 'v6') }
+
+ subject(:releases) { described_class.new(group, user, params).execute(**args) }
+
+ it_behaves_like 'preload'
+ it_behaves_like 'when the user is not part of the group'
+
+ context 'when the user is a project guest on one sibling project' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'does not return any releases' do
+ expect(releases.size).to eq(0)
+ expect(releases).to eq([])
+ end
+ end
+
+ context 'when the user is a guest on the group' do
+ before do
+ group.add_guest(user)
+ v1_0_0.update_attribute(:released_at, 3.days.ago)
+ v6.update_attribute(:released_at, 2.days.ago)
+ v1_1_0.update_attribute(:released_at, 1.day.ago)
+ v1_1_1.update_attribute(:released_at, v1_1_0.released_at)
+ end
+
+ it 'sorts by release date and id' do
+ expect(releases.size).to eq(4)
+ expect(releases).to eq([v1_1_1, v1_1_0, v6, v1_0_0])
+ end
+ end
+ end
+
+ describe 'with subgroups' do
+ let(:params) { { include_subgroups: true } }
+
+ subject(:releases) { described_class.new(group, user, params).execute(**args) }
+
+ context 'with a single-level subgroup' do
+ let(:subgroup) { create(:group, parent: group) }
+ let(:project2) { create(:project, :repository, namespace: subgroup) }
+ let!(:v6) { create(:release, project: project2, tag: 'v6') }
+
+ it_behaves_like 'when the user is not part of the group'
+
+ context 'when the user a project guest in the subgroup project' do
+ before do
+ project2.add_guest(user)
+ end
+
+ it 'does not return any releases' do
+ expect(releases).to match_array([])
+ end
+ end
+
+ context 'when the user is a guest on the group' do
+ before do
+ group.add_guest(user)
+ v6.update_attribute(:released_at, 2.days.ago)
+ end
+
+ it 'returns all releases' do
+ expect(releases).to match_array([v1_1_1, v1_1_0, v1_0_0, v6])
+ end
+ end
+ end
+
+ context 'with a multi-level subgroup' do
+ let(:subgroup) { create(:group, parent: group) }
+ let(:subsubgroup) { create(:group, parent: subgroup) }
+ let(:project2) { create(:project, :repository, namespace: subgroup) }
+ let(:project3) { create(:project, :repository, namespace: subsubgroup) }
+ let!(:v6) { create(:release, project: project2, tag: 'v6') }
+ let!(:p3) { create(:release, project: project3, tag: 'p3') }
+
+ before do
+ v6.update_attribute(:released_at, 2.days.ago)
+ p3.update_attribute(:released_at, 3.days.ago)
+ end
+
+ it_behaves_like 'when the user is not part of the group'
+
+ context 'when the user a project guest in the subgroup and subsubgroup project' do
+ before do
+ project2.add_guest(user)
+ project3.add_guest(user)
+ end
+
+ it 'does not return any releases' do
+ expect(releases).to match_array([])
+ end
+ end
+
+ context 'when the user a project guest in the subsubgroup project' do
+ before do
+ project3.add_guest(user)
+ end
+
+ it 'does not return any releases' do
+ expect(releases).to match_array([])
+ end
+ end
+
+ context 'when the user a guest on the group' do
+ before do
+ group.add_guest(user)
+ end
+
+ it 'returns all releases' do
+ expect(releases).to match_array([v1_1_1, v1_1_0, v6, v1_0_0, p3])
+ end
+ end
+
+ context 'performance testing' do
+ shared_examples 'avoids N+1 queries' do |query_params = {}|
+ context 'with subgroups' do
+ let(:params) { query_params }
+
+ it 'include_subgroups avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ releases
+ end.count
+
+ subgroups = create_list(:group, 10, parent: group)
+ projects = create_list(:project, 10, namespace: subgroups[0])
+ create_list(:release, 10, project: projects[0], author: user)
+
+ expect do
+ releases
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
+ end
+
+ it_behaves_like 'avoids N+1 queries'
+ it_behaves_like 'avoids N+1 queries', { simple: true }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/frontend/content_editor/extensions/code_block_highlight_spec.js b/spec/frontend/content_editor/extensions/code_block_highlight_spec.js
index 05fa0f79ef0..02e5b1dc271 100644
--- a/spec/frontend/content_editor/extensions/code_block_highlight_spec.js
+++ b/spec/frontend/content_editor/extensions/code_block_highlight_spec.js
@@ -1,5 +1,5 @@
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
-import { createTestEditor } from '../test_utils';
+import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
const CODE_BLOCK_HTML = `<pre class="code highlight js-syntax-highlight language-javascript" lang="javascript" v-pre="true">
<code>
@@ -12,34 +12,78 @@ const CODE_BLOCK_HTML = `<pre class="code highlight js-syntax-highlight language
describe('content_editor/extensions/code_block_highlight', () => {
let parsedCodeBlockHtmlFixture;
let tiptapEditor;
+ let doc;
+ let codeBlock;
+ let languageLoader;
const parseHTML = (html) => new DOMParser().parseFromString(html, 'text/html');
const preElement = () => parsedCodeBlockHtmlFixture.querySelector('pre');
beforeEach(() => {
- tiptapEditor = createTestEditor({ extensions: [CodeBlockHighlight] });
- parsedCodeBlockHtmlFixture = parseHTML(CODE_BLOCK_HTML);
+ languageLoader = { loadLanguages: jest.fn() };
+ tiptapEditor = createTestEditor({
+ extensions: [CodeBlockHighlight.configure({ languageLoader })],
+ });
- tiptapEditor.commands.setContent(CODE_BLOCK_HTML);
+ ({
+ builders: { doc, codeBlock },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ codeBlock: { nodeType: CodeBlockHighlight.name },
+ },
+ }));
});
- it('extracts language and params attributes from Markdown API output', () => {
- const language = preElement().getAttribute('lang');
+ describe('when parsing HTML', () => {
+ beforeEach(() => {
+ parsedCodeBlockHtmlFixture = parseHTML(CODE_BLOCK_HTML);
- expect(tiptapEditor.getJSON().content[0].attrs).toMatchObject({
- language,
+ tiptapEditor.commands.setContent(CODE_BLOCK_HTML);
+ });
+ it('extracts language and params attributes from Markdown API output', () => {
+ const language = preElement().getAttribute('lang');
+
+ expect(tiptapEditor.getJSON().content[0].attrs).toMatchObject({
+ language,
+ });
+ });
+
+ it('adds code, highlight, and js-syntax-highlight to code block element', () => {
+ const editorHtmlOutput = parseHTML(tiptapEditor.getHTML()).querySelector('pre');
+
+ expect(editorHtmlOutput.classList.toString()).toContain('code highlight js-syntax-highlight');
});
- });
- it('adds code, highlight, and js-syntax-highlight to code block element', () => {
- const editorHtmlOutput = parseHTML(tiptapEditor.getHTML()).querySelector('pre');
+ it('adds content-editor-code-block class to the pre element', () => {
+ const editorHtmlOutput = parseHTML(tiptapEditor.getHTML()).querySelector('pre');
- expect(editorHtmlOutput.classList.toString()).toContain('code highlight js-syntax-highlight');
+ expect(editorHtmlOutput.classList.toString()).toContain('content-editor-code-block');
+ });
});
- it('adds content-editor-code-block class to the pre element', () => {
- const editorHtmlOutput = parseHTML(tiptapEditor.getHTML()).querySelector('pre');
+ describe.each`
+ inputRule
+ ${'```'}
+ ${'~~~'}
+ `('when typing $inputRule input rule', ({ inputRule }) => {
+ const language = 'javascript';
+
+ beforeEach(() => {
+ triggerNodeInputRule({
+ tiptapEditor,
+ inputRuleText: `${inputRule}${language} `,
+ });
+ });
+
+ it('creates a new code block and loads related language', () => {
+ const expectedDoc = doc(codeBlock({ language }));
- expect(editorHtmlOutput.classList.toString()).toContain('content-editor-code-block');
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
+ });
+
+ it('loads language when language loader is available', () => {
+ expect(languageLoader.loadLanguages).toHaveBeenCalledWith([language]);
+ });
});
});
diff --git a/spec/frontend/content_editor/services/code_block_language_loader_spec.js b/spec/frontend/content_editor/services/code_block_language_loader_spec.js
new file mode 100644
index 00000000000..bb97c9afa41
--- /dev/null
+++ b/spec/frontend/content_editor/services/code_block_language_loader_spec.js
@@ -0,0 +1,70 @@
+import CodeBlockLanguageBlocker from '~/content_editor/services/code_block_language_loader';
+
+describe('content_editor/services/code_block_language_loader', () => {
+ let languageLoader;
+ let lowlight;
+
+ beforeEach(() => {
+ lowlight = {
+ languages: [],
+ registerLanguage: jest
+ .fn()
+ .mockImplementation((language) => lowlight.languages.push(language)),
+ registered: jest.fn().mockImplementation((language) => lowlight.languages.includes(language)),
+ };
+ languageLoader = new CodeBlockLanguageBlocker(lowlight);
+ });
+
+ describe('loadLanguages', () => {
+ it('loads highlight.js language packages identified by a list of languages', async () => {
+ const languages = ['javascript', 'ruby'];
+
+ await languageLoader.loadLanguages(languages);
+
+ languages.forEach((language) => {
+ expect(lowlight.registerLanguage).toHaveBeenCalledWith(language, expect.any(Function));
+ });
+ });
+
+ describe('when language is already registered', () => {
+ it('does not load the language again', async () => {
+ const languages = ['javascript'];
+
+ await languageLoader.loadLanguages(languages);
+ await languageLoader.loadLanguages(languages);
+
+ expect(lowlight.registerLanguage).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+
+ describe('loadLanguagesFromDOM', () => {
+ it('loads highlight.js language packages identified by pre tags in a DOM fragment', async () => {
+ const parser = new DOMParser();
+ const { body } = parser.parseFromString(
+ `
+ <pre lang="javascript"></pre>
+ <pre lang="ruby"></pre>
+ `,
+ 'text/html',
+ );
+
+ await languageLoader.loadLanguagesFromDOM(body);
+
+ expect(lowlight.registerLanguage).toHaveBeenCalledWith('javascript', expect.any(Function));
+ expect(lowlight.registerLanguage).toHaveBeenCalledWith('ruby', expect.any(Function));
+ });
+ });
+
+ describe('isLanguageLoaded', () => {
+ it('returns true when a language is registered', async () => {
+ const language = 'javascript';
+
+ expect(languageLoader.isLanguageLoaded(language)).toBe(false);
+
+ await languageLoader.loadLanguages([language]);
+
+ expect(languageLoader.isLanguageLoaded(language)).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/content_editor/services/content_editor_spec.js b/spec/frontend/content_editor/services/content_editor_spec.js
index 3bc72b13302..5b7a27b501d 100644
--- a/spec/frontend/content_editor/services/content_editor_spec.js
+++ b/spec/frontend/content_editor/services/content_editor_spec.js
@@ -11,6 +11,7 @@ describe('content_editor/services/content_editor', () => {
let contentEditor;
let serializer;
let deserializer;
+ let languageLoader;
let eventHub;
let doc;
let p;
@@ -27,8 +28,15 @@ describe('content_editor/services/content_editor', () => {
serializer = { deserialize: jest.fn() };
deserializer = { deserialize: jest.fn() };
+ languageLoader = { loadLanguagesFromDOM: jest.fn() };
eventHub = eventHubFactory();
- contentEditor = new ContentEditor({ tiptapEditor, serializer, deserializer, eventHub });
+ contentEditor = new ContentEditor({
+ tiptapEditor,
+ serializer,
+ deserializer,
+ eventHub,
+ languageLoader,
+ });
});
describe('.dispose', () => {
@@ -43,10 +51,12 @@ describe('content_editor/services/content_editor', () => {
describe('when setSerializedContent succeeds', () => {
let document;
+ const dom = {};
+ const testMarkdown = '**bold text**';
beforeEach(() => {
document = doc(p('document'));
- deserializer.deserialize.mockResolvedValueOnce({ document });
+ deserializer.deserialize.mockResolvedValueOnce({ document, dom });
});
it('emits loadingContent and loadingSuccess event in the eventHub', () => {
@@ -59,14 +69,20 @@ describe('content_editor/services/content_editor', () => {
expect(loadingContentEmitted).toBe(true);
});
- contentEditor.setSerializedContent('**bold text**');
+ contentEditor.setSerializedContent(testMarkdown);
});
it('sets the deserialized document in the tiptap editor object', async () => {
- await contentEditor.setSerializedContent('**bold text**');
+ await contentEditor.setSerializedContent(testMarkdown);
expect(contentEditor.tiptapEditor.state.doc.toJSON()).toEqual(document.toJSON());
});
+
+ it('passes deserialized DOM document to language loader', async () => {
+ await contentEditor.setSerializedContent(testMarkdown);
+
+ expect(languageLoader.loadLanguagesFromDOM).toHaveBeenCalledWith(dom);
+ });
});
describe('when setSerializedContent fails', () => {
diff --git a/spec/frontend/fixtures/merge_requests.rb b/spec/frontend/fixtures/merge_requests.rb
index 1eae854eca3..cb4eb43b88d 100644
--- a/spec/frontend/fixtures/merge_requests.rb
+++ b/spec/frontend/fixtures/merge_requests.rb
@@ -140,7 +140,7 @@ RSpec.describe Projects::MergeRequestsController, '(JavaScript fixtures)', type:
query_name = 'ready_to_merge.query.graphql'
it "#{base_output_path}#{query_name}.json" do
- query = get_graphql_query_as_string("#{base_input_path}#{query_name}", ee: true)
+ query = get_graphql_query_as_string("#{base_input_path}#{query_name}", ee: Gitlab.ee?)
post_graphql(query, current_user: user, variables: { projectPath: project.full_path, iid: merge_request.iid.to_s })
diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js
index db56f77b60e..b8c1bef0ddd 100644
--- a/spec/frontend/security_configuration/components/training_provider_list_spec.js
+++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js
@@ -12,6 +12,7 @@ import {
TRACK_PROVIDER_LEARN_MORE_CLICK_ACTION,
TRACK_PROVIDER_LEARN_MORE_CLICK_LABEL,
} from '~/security_configuration/constants';
+import { TEMP_PROVIDER_URLS } from '~/security_configuration/components/constants';
import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
import { updateSecurityTrainingOptimisticResponse } from '~/security_configuration/graphql/cache_utils';
import securityTrainingProvidersQuery from '~/security_configuration/graphql/security_training_providers.query.graphql';
@@ -145,55 +146,60 @@ describe('TrainingProviderList component', () => {
expect(findCards()).toHaveLength(TEST_TRAINING_PROVIDERS_DEFAULT.data.length);
});
- TEST_TRAINING_PROVIDERS_DEFAULT.data.forEach(
- ({ name, description, url, isEnabled }, index) => {
- it(`shows the name for card ${index}`, () => {
- expect(findCards().at(index).text()).toContain(name);
- });
+ TEST_TRAINING_PROVIDERS_DEFAULT.data.forEach(({ name, description, isEnabled }, index) => {
+ it(`shows the name for card ${index}`, () => {
+ expect(findCards().at(index).text()).toContain(name);
+ });
- it(`shows the description for card ${index}`, () => {
- expect(findCards().at(index).text()).toContain(description);
- });
+ it(`shows the description for card ${index}`, () => {
+ expect(findCards().at(index).text()).toContain(description);
+ });
+
+ it(`shows the learn more link for enabled card ${index}`, () => {
+ const learnMoreLink = findCards().at(index).find(GlLink);
+ const tempLogo = TEMP_PROVIDER_URLS[name];
- it(`shows the learn more link for card ${index}`, () => {
- expect(findLinks().at(index).attributes()).toEqual({
+ if (tempLogo) {
+ expect(learnMoreLink.attributes()).toEqual({
target: '_blank',
- href: url,
+ href: TEMP_PROVIDER_URLS[name],
});
- });
+ } else {
+ expect(learnMoreLink.exists()).toBe(false);
+ }
+ });
- it(`shows the toggle with the correct value for card ${index}`, () => {
- expect(findToggles().at(index).props('value')).toEqual(isEnabled);
- });
+ it(`shows the toggle with the correct value for card ${index}`, () => {
+ expect(findToggles().at(index).props('value')).toEqual(isEnabled);
+ });
- it(`shows a radio button to select the provider as primary within card ${index}`, () => {
- const primaryProviderRadioForCurrentCard = findPrimaryProviderRadios().at(index);
+ it(`shows a radio button to select the provider as primary within card ${index}`, () => {
+ const primaryProviderRadioForCurrentCard = findPrimaryProviderRadios().at(index);
- // if the given provider is not enabled it should not be possible select it as primary
- expect(primaryProviderRadioForCurrentCard.find('input').attributes('disabled')).toBe(
- isEnabled ? undefined : 'disabled',
- );
+ // if the given provider is not enabled it should not be possible select it as primary
+ expect(primaryProviderRadioForCurrentCard.find('input').attributes('disabled')).toBe(
+ isEnabled ? undefined : 'disabled',
+ );
- expect(primaryProviderRadioForCurrentCard.text()).toBe(
- TrainingProviderList.i18n.primaryTraining,
- );
- });
+ expect(primaryProviderRadioForCurrentCard.text()).toBe(
+ TrainingProviderList.i18n.primaryTraining,
+ );
+ });
- it('shows a info-tooltip that describes the purpose of a primary provider', () => {
- const infoIcon = findPrimaryProviderRadios().at(index).find(GlIcon);
- const tooltip = getBinding(infoIcon.element, 'gl-tooltip');
+ it('shows a info-tooltip that describes the purpose of a primary provider', () => {
+ const infoIcon = findPrimaryProviderRadios().at(index).find(GlIcon);
+ const tooltip = getBinding(infoIcon.element, 'gl-tooltip');
- expect(infoIcon.props()).toMatchObject({
- name: 'information-o',
- });
- expect(tooltip.value).toBe(TrainingProviderList.i18n.primaryTrainingDescription);
+ expect(infoIcon.props()).toMatchObject({
+ name: 'information-o',
});
+ expect(tooltip.value).toBe(TrainingProviderList.i18n.primaryTrainingDescription);
+ });
- it('does not show loader when query is populated', () => {
- expect(findLoader().exists()).toBe(false);
- });
- },
- );
+ it('does not show loader when query is populated', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+ });
});
describe('provider logo', () => {
diff --git a/spec/frontend/security_configuration/mock_data.js b/spec/frontend/security_configuration/mock_data.js
index 55f5c20e45d..18a480bf082 100644
--- a/spec/frontend/security_configuration/mock_data.js
+++ b/spec/frontend/security_configuration/mock_data.js
@@ -1,6 +1,6 @@
export const testProjectPath = 'foo/bar';
export const testProviderIds = [101, 102, 103];
-export const testProviderName = ['Vendor Name 1', 'Vendor Name 2', 'Vendor Name 3'];
+export const testProviderName = ['Kontra', 'Secure Code Warrior', 'Other Vendor'];
export const testTrainingUrls = [
'https://www.vendornameone.com/url',
'https://www.vendornametwo.com/url',
diff --git a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
index a6b536e1158..392385d2a30 100644
--- a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
@@ -25,10 +25,10 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
let(:wildcard_started) { 'STARTED' }
let(:filters) { { milestone_title: ["started"], milestone_wildcard_id: wildcard_started } }
- it 'raises a mutually exclusive filter error when milestone wildcard and title are provided' do
- expect do
+ it 'generates a mutually exclusive filter error when milestone wildcard and title are provided' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do
resolve_board_list_issues(args: { filters: filters })
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
end
it 'returns the issues in the correct order' do
diff --git a/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb b/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb
index b0fc78af2af..8b9874c3580 100644
--- a/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb
+++ b/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb
@@ -26,8 +26,10 @@ RSpec.describe Resolvers::DesignManagement::VersionInCollectionResolver do
subject(:result) { resolve_version(issue.design_collection) }
context 'Neither id nor sha is passed as parameters' do
- it 'raises an appropriate error' do
- expect { result }.to raise_error(appropriate_error)
+ it 'generates an appropriate error' do
+ expect_graphql_error_to_be_created(appropriate_error) do
+ result
+ end
end
end
diff --git a/spec/graphql/resolvers/design_management/version_resolver_spec.rb b/spec/graphql/resolvers/design_management/version_resolver_spec.rb
index af1e6a73d09..ab1d7d4d9c5 100644
--- a/spec/graphql/resolvers/design_management/version_resolver_spec.rb
+++ b/spec/graphql/resolvers/design_management/version_resolver_spec.rb
@@ -22,8 +22,10 @@ RSpec.describe Resolvers::DesignManagement::VersionResolver do
context 'the current user is not authorized' do
let(:current_user) { create(:user) }
- it 'raises an error on resolution' do
- expect { resolve_version }.to raise_error(::Gitlab::Graphql::Errors::ResourceNotAvailable)
+ it 'generates an error on resolution' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ resolve_version
+ end
end
end
diff --git a/spec/graphql/resolvers/design_management/versions_resolver_spec.rb b/spec/graphql/resolvers/design_management/versions_resolver_spec.rb
index 2c9c3a47650..d98138f6385 100644
--- a/spec/graphql/resolvers/design_management/versions_resolver_spec.rb
+++ b/spec/graphql/resolvers/design_management/versions_resolver_spec.rb
@@ -98,8 +98,10 @@ RSpec.describe Resolvers::DesignManagement::VersionsResolver do
}
end
- it 'raises a suitable error' do
- expect { result }.to raise_error(GraphQL::ExecutionError)
+ it 'generates a suitable error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ result
+ end
end
end
end
diff --git a/spec/graphql/resolvers/group_issues_resolver_spec.rb b/spec/graphql/resolvers/group_issues_resolver_spec.rb
index e17429560ac..f5f6086cc09 100644
--- a/spec/graphql/resolvers/group_issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_issues_resolver_spec.rb
@@ -86,10 +86,10 @@ RSpec.describe Resolvers::GroupIssuesResolver do
end
context 'release_tag filter' do
- it 'returns an error when trying to filter by negated release_tag' do
- expect do
+ it 'generates an error when trying to filter by negated release_tag' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'releaseTag filter is not allowed when parent is a group.') do
resolve_issues(not: { release_tag: ['v1.0'] })
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'releaseTag filter is not allowed when parent is a group.')
+ end
end
end
end
diff --git a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
index 3fbd9bd2368..77f4ce4cac5 100644
--- a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
+++ b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
@@ -70,10 +70,10 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do
end
context 'when both assignee_username and assignee_usernames are provided' do
- it 'raises a mutually exclusive filter error' do
- expect do
+ it 'generates a mutually exclusive filter error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.') do
resolve_issue_status_counts(assignee_usernames: [current_user.username], assignee_username: current_user.username)
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.')
+ end
end
end
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index 326c105a358..5e9a3d0a68b 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -78,10 +78,10 @@ RSpec.describe Resolvers::IssuesResolver do
expect(resolve_issues(milestone_wildcard_id: wildcard_none)).to contain_exactly(issue2)
end
- it 'raises a mutually exclusive filter error when wildcard and title are provided' do
- expect do
+ it 'generates a mutually exclusive filter error when wildcard and title are provided' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [milestoneTitle, milestoneWildcardId] arguments is allowed at the same time.') do
resolve_issues(milestone_title: ["started milestone"], milestone_wildcard_id: wildcard_started)
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [milestoneTitle, milestoneWildcardId] arguments is allowed at the same time.')
+ end
end
context 'negated filtering' do
@@ -97,10 +97,10 @@ RSpec.describe Resolvers::IssuesResolver do
expect(resolve_issues(not: { milestone_wildcard_id: wildcard_upcoming })).to contain_exactly(issue6)
end
- it 'raises a mutually exclusive filter error when wildcard and title are provided as negated filters' do
- expect do
+ it 'generates a mutually exclusive filter error when wildcard and title are provided as negated filters' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [milestoneTitle, milestoneWildcardId] arguments is allowed at the same time.') do
resolve_issues(not: { milestone_title: ["started milestone"], milestone_wildcard_id: wildcard_started })
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [milestoneTitle, milestoneWildcardId] arguments is allowed at the same time.')
+ end
end
end
end
@@ -122,10 +122,10 @@ RSpec.describe Resolvers::IssuesResolver do
end
context 'when release_tag_wildcard_id is also provided' do
- it 'raises a mutually eclusive argument error' do
- expect do
+ it 'generates a mutually eclusive argument error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [releaseTag, releaseTagWildcardId] arguments is allowed at the same time.') do
resolve_issues(release_tag: [release1.tag], release_tag_wildcard_id: 'ANY')
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [releaseTag, releaseTagWildcardId] arguments is allowed at the same time.')
+ end
end
end
end
@@ -191,10 +191,10 @@ RSpec.describe Resolvers::IssuesResolver do
end
context 'when both assignee_username and assignee_usernames are provided' do
- it 'raises a mutually exclusive filter error' do
- expect do
+ it 'generates a mutually exclusive filter error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.') do
resolve_issues(assignee_usernames: [assignee.username], assignee_username: assignee.username)
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.')
+ end
end
end
end
@@ -331,11 +331,12 @@ RSpec.describe Resolvers::IssuesResolver do
stub_feature_flags(disable_anonymous_search: true)
end
- it 'returns an error' do
+ it 'generates an error' do
error_message = "User must be authenticated to include the `search` argument."
- expect { resolve(described_class, obj: public_project, args: { search: 'test' }, ctx: { current_user: nil }) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, error_message)
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, error_message) do
+ resolve(described_class, obj: public_project, args: { search: 'test' }, ctx: { current_user: nil })
+ end
end
end
diff --git a/spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb b/spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb
index bdb1ced46ae..e4cf62b0361 100644
--- a/spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb
+++ b/spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb
@@ -34,8 +34,10 @@ RSpec.describe Resolvers::Kas::AgentConfigurationsResolver do
allow(kas_client).to receive(:list_agent_config_files).and_raise(GRPC::DeadlineExceeded)
end
- it 'raises a graphql error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, 'GRPC::DeadlineExceeded')
+ it 'generates a graphql error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable, 'GRPC::DeadlineExceeded') do
+ subject
+ end
end
end
diff --git a/spec/graphql/resolvers/labels_resolver_spec.rb b/spec/graphql/resolvers/labels_resolver_spec.rb
index be6229553d7..efd2596b9eb 100644
--- a/spec/graphql/resolvers/labels_resolver_spec.rb
+++ b/spec/graphql/resolvers/labels_resolver_spec.rb
@@ -28,7 +28,9 @@ RSpec.describe Resolvers::LabelsResolver do
describe '#resolve' do
context 'with unauthorized user' do
it 'returns no labels' do
- expect { resolve_labels(project) }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ resolve_labels(project)
+ end
end
end
diff --git a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb
index 892dc641201..c757c876616 100644
--- a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb
+++ b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb
@@ -25,32 +25,40 @@ RSpec.describe Resolvers::PackagePipelinesResolver do
context 'with invalid after' do
let(:args) { { first: 1, after: 'not_json_string' } }
- it 'raises argument error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ it 'generates an argument error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do
+ subject
+ end
end
end
context 'with invalid after key' do
let(:args) { { first: 1, after: encode_cursor(foo: 3) } }
- it 'raises argument error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ it 'generates an argument error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do
+ subject
+ end
end
end
context 'with invalid before' do
let(:args) { { last: 1, before: 'not_json_string' } }
- it 'raises argument error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ it 'generates an argument error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do
+ subject
+ end
end
end
context 'with invalid before key' do
let(:args) { { last: 1, before: encode_cursor(foo: 3) } }
- it 'raises argument error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ it 'generates an argument error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do
+ subject
+ end
end
end
diff --git a/spec/graphql/resolvers/paginated_tree_resolver_spec.rb b/spec/graphql/resolvers/paginated_tree_resolver_spec.rb
index 82b05937aa3..4b05e9076d7 100644
--- a/spec/graphql/resolvers/paginated_tree_resolver_spec.rb
+++ b/spec/graphql/resolvers/paginated_tree_resolver_spec.rb
@@ -65,7 +65,11 @@ RSpec.describe Resolvers::PaginatedTreeResolver do
context 'when cursor is invalid' do
let(:args) { super().merge(after: 'invalid') }
- it { expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError) }
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do
+ subject
+ end
+ end
end
it 'returns all tree entries during cursor pagination' do
diff --git a/spec/graphql/resolvers/project_milestones_resolver_spec.rb b/spec/graphql/resolvers/project_milestones_resolver_spec.rb
index e168291c804..2cf490c2b6a 100644
--- a/spec/graphql/resolvers/project_milestones_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_milestones_resolver_spec.rb
@@ -103,27 +103,27 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
end
context 'when start date is after end_date' do
- it 'raises error' do
- expect do
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'startDate is after endDate') do
resolve_project_milestones(start_date: Time.now, end_date: Time.now - 2.days)
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, "startDate is after endDate")
+ end
end
end
end
context 'when only start_date is present' do
- it 'raises error' do
- expect do
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
resolve_project_milestones(start_date: Time.now)
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/)
+ end
end
end
context 'when only end_date is present' do
- it 'raises error' do
- expect do
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
resolve_project_milestones(end_date: Time.now)
- end.to raise_error(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/)
+ end
end
end
@@ -174,12 +174,12 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
end
context 'when user cannot read milestones' do
- it 'raises error' do
+ it 'generates an error' do
unauthorized_user = create(:user)
- expect do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
resolve_project_milestones({}, { current_user: unauthorized_user })
- end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
end
end
end
diff --git a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
index 6a8aa39f3b2..398f8f52269 100644
--- a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
@@ -85,13 +85,15 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
end
it 'errors when no iid or sha is passed' do
- expect { resolve_pipeline(project, {}) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do
+ resolve_pipeline(project, {})
+ end
end
it 'errors when both iid and sha are passed' do
- expect { resolve_pipeline(project, { iid: '1234', sha: 'sha' }) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do
+ resolve_pipeline(project, { iid: '1234', sha: 'sha' })
+ end
end
context 'when the pipeline is a dangling pipeline' do
diff --git a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
index c6d8c518fb7..b95bab41e3e 100644
--- a/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb
@@ -14,10 +14,10 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
let_it_be(:project) { create(:project) }
shared_examples 'no project service access' do
- it 'raises error' do
- expect do
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
resolve_jira_projects
- end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
end
end
@@ -89,11 +89,14 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
.to_raise(JIRA::HTTPError.new(double(message: '{"errorMessages":["Some failure"]}')))
end
- it 'raises failure error' do
+ it 'generates a failure error' do
config_docs_link_url = Rails.application.routes.url_helpers.help_page_path('integration/jira/configure')
docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: config_docs_link_url }
error_message = 'An error occurred while requesting data from Jira: Some failure. Check your %{docs_link_start}Jira integration configuration</a> and try again.' % { docs_link_start: docs_link_start }
- expect { resolve_jira_projects }.to raise_error(error_message)
+
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::BaseError, error_message) do
+ resolve_jira_projects
+ end
end
end
end
diff --git a/spec/graphql/resolvers/timelog_resolver_spec.rb b/spec/graphql/resolvers/timelog_resolver_spec.rb
index 82ed572c3ee..84fa2932829 100644
--- a/spec/graphql/resolvers/timelog_resolver_spec.rb
+++ b/spec/graphql/resolvers/timelog_resolver_spec.rb
@@ -85,27 +85,30 @@ RSpec.describe Resolvers::TimelogResolver do
context 'when start_time and start_date are present' do
let(:args) { { start_time: 6.days.ago, start_date: 6.days.ago } }
- it 'returns correct error' do
- expect { timelogs }
- .to raise_error(error_class, /Provide either a start date or time, but not both/)
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(error_class, /Provide either a start date or time, but not both/) do
+ timelogs
+ end
end
end
context 'when end_time and end_date are present' do
let(:args) { { end_time: 2.days.ago, end_date: 2.days.ago } }
- it 'returns correct error' do
- expect { timelogs }
- .to raise_error(error_class, /Provide either an end date or time, but not both/)
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(error_class, /Provide either an end date or time, but not both/) do
+ timelogs
+ end
end
end
context 'when start argument is after end argument' do
let(:args) { { start_time: 2.days.ago, end_time: 6.days.ago } }
- it 'returns correct error' do
- expect { timelogs }
- .to raise_error(error_class, /Start argument must be before End argument/)
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(error_class, /Start argument must be before End argument/) do
+ timelogs
+ end
end
end
end
@@ -276,9 +279,10 @@ RSpec.describe Resolvers::TimelogResolver do
let(:args) { {} }
let(:extra_args) { {} }
- it 'returns correct error' do
- expect { timelogs }
- .to raise_error(error_class, /Provide at least one argument/)
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(error_class, /Provide at least one argument/) do
+ timelogs
+ end
end
end
diff --git a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb
new file mode 100644
index 00000000000..6aea549b136
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_encrypted_values_on_projects_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenEncryptedValuesOnProjects do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+
+ let(:perform) { described_class.new.perform(1, 4) }
+
+ before do
+ namespaces.create!(id: 123, name: 'sample', path: 'sample')
+
+ projects.create!(id: 1, namespace_id: 123, runners_token_encrypted: 'duplicate')
+ projects.create!(id: 2, namespace_id: 123, runners_token_encrypted: 'a-runners-token')
+ projects.create!(id: 3, namespace_id: 123, runners_token_encrypted: 'duplicate')
+ projects.create!(id: 4, namespace_id: 123, runners_token_encrypted: nil)
+ projects.create!(id: 5, namespace_id: 123, runners_token_encrypted: 'duplicate-2')
+ projects.create!(id: 6, namespace_id: 123, runners_token_encrypted: 'duplicate-2')
+ end
+
+ describe '#up' do
+ before do
+ stub_const("#{described_class}::SUB_BATCH_SIZE", 2)
+ end
+
+ it 'nullifies duplicate tokens', :aggregate_failures do
+ perform
+
+ expect(projects.count).to eq(6)
+ expect(projects.all.pluck(:id, :runners_token_encrypted).to_h).to eq(
+ { 1 => nil, 2 => 'a-runners-token', 3 => nil, 4 => nil, 5 => 'duplicate-2', 6 => 'duplicate-2' }
+ )
+ expect(projects.pluck(:runners_token_encrypted).uniq).to match_array [nil, 'a-runners-token', 'duplicate-2']
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb
new file mode 100644
index 00000000000..cbe762c2680
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/reset_duplicate_ci_runners_token_values_on_projects_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenValuesOnProjects do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+
+ let(:perform) { described_class.new.perform(1, 4) }
+
+ before do
+ namespaces.create!(id: 123, name: 'sample', path: 'sample')
+
+ projects.create!(id: 1, namespace_id: 123, runners_token: 'duplicate')
+ projects.create!(id: 2, namespace_id: 123, runners_token: 'a-runners-token')
+ projects.create!(id: 3, namespace_id: 123, runners_token: 'duplicate')
+ projects.create!(id: 4, namespace_id: 123, runners_token: nil)
+ projects.create!(id: 5, namespace_id: 123, runners_token: 'duplicate-2')
+ projects.create!(id: 6, namespace_id: 123, runners_token: 'duplicate-2')
+ end
+
+ describe '#up' do
+ before do
+ stub_const("#{described_class}::SUB_BATCH_SIZE", 2)
+ end
+
+ it 'nullifies duplicate tokens', :aggregate_failures do
+ perform
+
+ expect(projects.count).to eq(6)
+ expect(projects.all.pluck(:id, :runners_token).to_h).to eq(
+ { 1 => nil, 2 => 'a-runners-token', 3 => nil, 4 => nil, 5 => 'duplicate-2', 6 => 'duplicate-2' }
+ )
+ expect(projects.pluck(:runners_token).uniq).to match_array [nil, 'a-runners-token', 'duplicate-2']
+ end
+ end
+end
diff --git a/spec/models/users/credit_card_validation_spec.rb b/spec/models/users/credit_card_validation_spec.rb
index 43edf7ed093..34cfd500c26 100644
--- a/spec/models/users/credit_card_validation_spec.rb
+++ b/spec/models/users/credit_card_validation_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Users::CreditCardValidation do
it { is_expected.to belong_to(:user) }
- it { is_expected.to validate_length_of(:holder_name).is_at_most(26) }
+ it { is_expected.to validate_length_of(:holder_name).is_at_most(50) }
it { is_expected.to validate_length_of(:network).is_at_most(32) }
it { is_expected.to validate_numericality_of(:last_digits).is_less_than_or_equal_to(9999) }
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index f42fc7aabc2..1d199a72d1d 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -783,6 +783,13 @@ RSpec.describe API::Repositories do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['notes']).to be_present
end
+
+ context 'when previous tag version does not exist' do
+ it_behaves_like '422 response' do
+ let(:request) { get api("/projects/#{project.id}/repository/changelog", user), params: { version: 'v0.0.0' } }
+ let(:message) { 'Failed to generate the changelog: The commit start range is unspecified, and no previous tag could be found to use instead' }
+ end
+ end
end
describe 'POST /projects/:id/repository/changelog' do
diff --git a/spec/support/shared_examples/graphql/members_shared_examples.rb b/spec/support/shared_examples/graphql/members_shared_examples.rb
index b0bdd27a95f..8e9e22f4359 100644
--- a/spec/support/shared_examples/graphql/members_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/members_shared_examples.rb
@@ -76,8 +76,10 @@ RSpec.shared_examples 'querying members with a group' do
resolve(described_class, obj: resource, args: base_args.merge(args), ctx: { current_user: other_user })
end
- it 'raises an error' do
- expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ subject
+ end
end
end
end