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>2023-05-22 21:10:38 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-22 21:10:38 +0300
commit7e2f555a6dc37839727dee130d8ed4421b680d42 (patch)
treef2bcca7814bbaa6ee50e14830bc3a74307b1148e /spec
parent4ec96676406da695de083b4f394290902da2a964 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/runners_spec.rb5
-rw-r--r--spec/frontend/analytics/cycle_analytics/components/filter_bar_spec.js4
-rw-r--r--spec/frontend/ci/runner/components/runner_create_form_spec.js3
-rw-r--r--spec/frontend/ci/runner/components/runner_form_fields_spec.js30
-rw-r--r--spec/frontend/content_editor/extensions/code_spec.js58
-rw-r--r--spec/frontend/environments/edit_environment_spec.js125
-rw-r--r--spec/models/import_failure_spec.rb28
-rw-r--r--spec/support/shared_examples/features/runners_shared_examples.rb2
-rw-r--r--spec/workers/gitlab/github_gists_import/import_gist_worker_spec.rb80
9 files changed, 268 insertions, 67 deletions
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index 452a5700e08..4df9109875e 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -49,6 +49,11 @@ RSpec.describe 'Runners', feature_category: :runner_fleet do
it_behaves_like 'creates runner and shows register page' do
let(:register_path_pattern) { register_project_runner_path(project, '.*') }
end
+
+ it 'shows the locked field' do
+ expect(page).to have_selector('input[type="checkbox"][name="locked"]')
+ expect(page).to have_content(_('Lock to current projects'))
+ end
end
end
diff --git a/spec/frontend/analytics/cycle_analytics/components/filter_bar_spec.js b/spec/frontend/analytics/cycle_analytics/components/filter_bar_spec.js
index f1b3af39199..f57d8559ddf 100644
--- a/spec/frontend/analytics/cycle_analytics/components/filter_bar_spec.js
+++ b/spec/frontend/analytics/cycle_analytics/components/filter_bar_spec.js
@@ -119,6 +119,10 @@ describe('Filter bar', () => {
it('renders FilteredSearchBar component', () => {
expect(findFilteredSearch().exists()).toBe(true);
});
+
+ it('passes the `terms-as-tokens` prop', () => {
+ expect(findFilteredSearch().props('termsAsTokens')).toBe(true);
+ });
});
describe('when the state has data', () => {
diff --git a/spec/frontend/ci/runner/components/runner_create_form_spec.js b/spec/frontend/ci/runner/components/runner_create_form_spec.js
index 329dd2f73ee..243d23aeb38 100644
--- a/spec/frontend/ci/runner/components/runner_create_form_spec.js
+++ b/spec/frontend/ci/runner/components/runner_create_form_spec.js
@@ -21,12 +21,14 @@ jest.mock('~/ci/runner/sentry_utils');
const mockCreatedRunner = runnerCreateResult.data.runnerCreate.runner;
const defaultRunnerModel = {
+ runnerType: INSTANCE_TYPE,
description: '',
accessLevel: DEFAULT_ACCESS_LEVEL,
paused: false,
maintenanceNote: '',
maximumTimeout: '',
runUntagged: false,
+ locked: false,
tagList: '',
};
@@ -81,6 +83,7 @@ describe('RunnerCreateForm', () => {
findRunnerFormFields().vm.$emit('input', {
...defaultRunnerModel,
+ runnerType: props.runnerType,
description: 'My runner',
maximumTimeout: 0,
tagList: 'tag1, tag2',
diff --git a/spec/frontend/ci/runner/components/runner_form_fields_spec.js b/spec/frontend/ci/runner/components/runner_form_fields_spec.js
index 5b429645d17..0e2f2aa2e91 100644
--- a/spec/frontend/ci/runner/components/runner_form_fields_spec.js
+++ b/spec/frontend/ci/runner/components/runner_form_fields_spec.js
@@ -1,7 +1,11 @@
import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import RunnerFormFields from '~/ci/runner/components/runner_form_fields.vue';
-import { ACCESS_LEVEL_NOT_PROTECTED, ACCESS_LEVEL_REF_PROTECTED } from '~/ci/runner/constants';
+import {
+ ACCESS_LEVEL_NOT_PROTECTED,
+ ACCESS_LEVEL_REF_PROTECTED,
+ PROJECT_TYPE,
+} from '~/ci/runner/constants';
const mockDescription = 'My description';
const mockMaxTimeout = 60;
@@ -63,6 +67,30 @@ describe('RunnerFormFields', () => {
});
});
+ it('locked checkbox is not shown', () => {
+ createComponent();
+
+ expect(findInput('locked').exists()).toBe(false);
+ });
+
+ it('when runner is of project type, locked checkbox can be checked', async () => {
+ createComponent({
+ runner: {
+ runnerType: PROJECT_TYPE,
+ locked: false,
+ },
+ });
+
+ findInput('locked').setChecked(true);
+
+ await nextTick();
+
+ expect(wrapper.emitted('input')[0][0]).toEqual({
+ runnerType: PROJECT_TYPE,
+ locked: true,
+ });
+ });
+
it('unchecks checkbox fields', async () => {
createComponent({
runner: {
diff --git a/spec/frontend/content_editor/extensions/code_spec.js b/spec/frontend/content_editor/extensions/code_spec.js
index 0a54ac6a96b..4d8629a35c0 100644
--- a/spec/frontend/content_editor/extensions/code_spec.js
+++ b/spec/frontend/content_editor/extensions/code_spec.js
@@ -1,8 +1,60 @@
+import Bold from '~/content_editor/extensions/bold';
import Code from '~/content_editor/extensions/code';
-import { EXTENSION_PRIORITY_LOWER } from '~/content_editor/constants';
+import { createTestEditor, createDocBuilder } from '../test_utils';
describe('content_editor/extensions/code', () => {
- it('has a lower loading priority', () => {
- expect(Code.config.priority).toBe(EXTENSION_PRIORITY_LOWER);
+ let tiptapEditor;
+ let doc;
+ let p;
+ let bold;
+ let code;
+
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({ extensions: [Bold, Code] });
+
+ ({
+ builders: { doc, p, bold, code },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ bold: { markType: Bold.name },
+ code: { markType: Code.name },
+ },
+ }));
+ });
+
+ it.each`
+ markOrder | description
+ ${['bold', 'code']} | ${'bold is toggled before code'}
+ ${['code', 'bold']} | ${'code is toggled before bold'}
+ `('has a lower loading priority, when $description', ({ markOrder }) => {
+ const initialDoc = doc(p('code block'));
+ const expectedDoc = doc(p(bold(code('code block'))));
+
+ tiptapEditor.commands.setContent(initialDoc.toJSON());
+ tiptapEditor.commands.selectAll();
+ markOrder.forEach((mark) => tiptapEditor.commands.toggleMark(mark));
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
+ });
+
+ describe('shortcut: RightArrow', () => {
+ it('exits the code block', () => {
+ const initialDoc = doc(p('You can write ', code('java')));
+ const expectedDoc = doc(p('You can write ', code('javascript'), ' here'));
+ const pos = 25;
+
+ tiptapEditor.commands.setContent(initialDoc.toJSON());
+ tiptapEditor.commands.setTextSelection(pos);
+
+ // insert 'script' after 'java' within the code block
+ tiptapEditor.commands.insertContent({ type: 'text', text: 'script' });
+
+ // insert ' here' after the code block
+ tiptapEditor.commands.keyboardShortcut('ArrowRight');
+ tiptapEditor.commands.insertContent({ type: 'text', text: 'here' });
+
+ expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
+ });
});
});
diff --git a/spec/frontend/environments/edit_environment_spec.js b/spec/frontend/environments/edit_environment_spec.js
index 34f338fabe6..cc28e12788b 100644
--- a/spec/frontend/environments/edit_environment_spec.js
+++ b/spec/frontend/environments/edit_environment_spec.js
@@ -1,5 +1,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import EditEnvironment from '~/environments/components/edit_environment.vue';
@@ -7,49 +9,56 @@ import { createAlert } from '~/alert';
import axios from '~/lib/utils/axios_utils';
import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { visitUrl } from '~/lib/utils/url_utility';
+import getEnvironment from '~/environments/graphql/queries/environment.query.graphql';
+import { __ } from '~/locale';
+import createMockApollo from '../__helpers__/mock_apollo_helper';
jest.mock('~/lib/utils/url_utility');
jest.mock('~/alert');
-const DEFAULT_OPTS = {
- provide: {
- projectEnvironmentsPath: '/projects/environments',
- updateEnvironmentPath: '/proejcts/environments/1',
- protectedEnvironmentSettingsPath: '/projects/1/settings/ci_cd',
- },
- propsData: { environment: { id: '0', name: 'foo', external_url: 'https://foo.example.com' } },
+const environment = { id: '1', name: 'foo', externalUrl: 'https://foo.example.com' };
+const resolvedEnvironment = { project: { id: '1', environment } };
+
+const provide = {
+ projectEnvironmentsPath: '/projects/environments',
+ updateEnvironmentPath: '/projects/environments/1',
+ protectedEnvironmentSettingsPath: '/projects/1/settings/ci_cd',
+ projectPath: '/path/to/project',
+ environmentName: environment.name,
};
describe('~/environments/components/edit.vue', () => {
+ Vue.use(VueApollo);
+
let wrapper;
let mock;
- const createWrapper = (opts = {}) =>
- mountExtended(EditEnvironment, {
- ...DEFAULT_OPTS,
- ...opts,
- });
+ const createWrapper = () => {
+ const mockApollo = createMockApollo([
+ [getEnvironment, jest.fn().mockResolvedValue({ data: resolvedEnvironment })],
+ ]);
- beforeEach(() => {
- mock = new MockAdapter(axios);
- wrapper = createWrapper();
- });
+ return mountExtended(EditEnvironment, {
+ provide,
+ apolloProvider: mockApollo,
+ });
+ };
afterEach(() => {
mock.restore();
});
- const findNameInput = () => wrapper.findByLabelText('Name');
- const findExternalUrlInput = () => wrapper.findByLabelText('External URL');
- const findForm = () => wrapper.findByRole('form', { name: 'Edit environment' });
+ const findNameInput = () => wrapper.findByLabelText(__('Name'));
+ const findExternalUrlInput = () => wrapper.findByLabelText(__('External URL'));
+ const findForm = () => wrapper.findByRole('form', { name: __('Edit environment') });
const showsLoading = () => wrapper.findComponent(GlLoadingIcon).exists();
const submitForm = async (expected, response) => {
mock
- .onPut(DEFAULT_OPTS.provide.updateEnvironmentPath, {
+ .onPut(provide.updateEnvironmentPath, {
external_url: expected.url,
- id: '0',
+ id: '1',
})
.reply(...response);
await findExternalUrlInput().setValue(expected.url);
@@ -58,48 +67,66 @@ describe('~/environments/components/edit.vue', () => {
await waitForPromises();
};
- it('sets the title to Edit environment', () => {
- const header = wrapper.findByRole('heading', { name: 'Edit environment' });
- expect(header.exists()).toBe(true);
- });
+ describe('default', () => {
+ beforeEach(async () => {
+ mock = new MockAdapter(axios);
+ wrapper = createWrapper();
+ await waitForPromises();
+ });
- it('shows loader after form is submitted', async () => {
- const expected = { url: 'https://google.ca' };
+ it('sets the title to Edit environment', () => {
+ const header = wrapper.findByRole('heading', { name: __('Edit environment') });
+ expect(header.exists()).toBe(true);
+ });
- expect(showsLoading()).toBe(false);
+ it('shows loader after form is submitted', async () => {
+ const expected = { url: 'https://google.ca' };
- await submitForm(expected, [HTTP_STATUS_OK, { path: '/test' }]);
+ expect(showsLoading()).toBe(false);
- expect(showsLoading()).toBe(true);
- });
+ await submitForm(expected, [HTTP_STATUS_OK, { path: '/test' }]);
+
+ expect(showsLoading()).toBe(true);
+ });
- it('submits the updated environment on submit', async () => {
- const expected = { url: 'https://google.ca' };
+ it('submits the updated environment on submit', async () => {
+ const expected = { url: 'https://google.ca' };
- await submitForm(expected, [HTTP_STATUS_OK, { path: '/test' }]);
+ await submitForm(expected, [HTTP_STATUS_OK, { path: '/test' }]);
- expect(visitUrl).toHaveBeenCalledWith('/test');
- });
+ expect(visitUrl).toHaveBeenCalledWith('/test');
+ });
- it('shows errors on error', async () => {
- const expected = { url: 'https://google.ca' };
+ it('shows errors on error', async () => {
+ const expected = { url: 'https://google.ca' };
- await submitForm(expected, [HTTP_STATUS_BAD_REQUEST, { message: ['uh oh!'] }]);
+ await submitForm(expected, [HTTP_STATUS_BAD_REQUEST, { message: ['uh oh!'] }]);
- expect(createAlert).toHaveBeenCalledWith({ message: 'uh oh!' });
- expect(showsLoading()).toBe(false);
- });
+ expect(createAlert).toHaveBeenCalledWith({ message: 'uh oh!' });
+ expect(showsLoading()).toBe(false);
+ });
- it('renders a disabled "Name" field', () => {
- const nameInput = findNameInput();
+ it('renders a disabled "Name" field', () => {
+ const nameInput = findNameInput();
- expect(nameInput.attributes().disabled).toBe('disabled');
- expect(nameInput.element.value).toBe('foo');
+ expect(nameInput.attributes().disabled).toBe('disabled');
+ expect(nameInput.element.value).toBe(environment.name);
+ });
+
+ it('renders an "External URL" field', () => {
+ const urlInput = findExternalUrlInput();
+
+ expect(urlInput.element.value).toBe(environment.externalUrl);
+ });
});
- it('renders an "External URL" field', () => {
- const urlInput = findExternalUrlInput();
+ describe('when environment query is loading', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
- expect(urlInput.element.value).toBe('https://foo.example.com');
+ it('renders loading icon', () => {
+ expect(showsLoading()).toBe(true);
+ });
});
});
diff --git a/spec/models/import_failure_spec.rb b/spec/models/import_failure_spec.rb
index 101da1212cf..a8ada156dd7 100644
--- a/spec/models/import_failure_spec.rb
+++ b/spec/models/import_failure_spec.rb
@@ -36,23 +36,39 @@ RSpec.describe ImportFailure do
describe 'Associations' do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:group) }
+ it { is_expected.to belong_to(:user) }
end
describe 'Validations' do
- context 'has no group' do
+ let_it_be(:group) { build(:group) }
+ let_it_be(:project) { build(:project) }
+ let_it_be(:user) { build(:user) }
+
+ context 'has project' do
+ before do
+ allow(subject).to receive(:project).and_return(project)
+ end
+
+ it { is_expected.to validate_absence_of(:group) }
+ it { is_expected.to validate_absence_of(:user) }
+ end
+
+ context 'has group' do
before do
- allow(subject).to receive(:group).and_return(nil)
+ allow(subject).to receive(:group).and_return(group)
end
- it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_absence_of(:project) }
+ it { is_expected.to validate_absence_of(:user) }
end
- context 'has no project' do
+ context 'has user' do
before do
- allow(subject).to receive(:project).and_return(nil)
+ allow(subject).to receive(:user).and_return(user)
end
- it { is_expected.to validate_presence_of(:group) }
+ it { is_expected.to validate_absence_of(:project) }
+ it { is_expected.to validate_absence_of(:group) }
end
describe '#external_identifiers' do
diff --git a/spec/support/shared_examples/features/runners_shared_examples.rb b/spec/support/shared_examples/features/runners_shared_examples.rb
index 7edf306183e..4da684c4c10 100644
--- a/spec/support/shared_examples/features/runners_shared_examples.rb
+++ b/spec/support/shared_examples/features/runners_shared_examples.rb
@@ -232,7 +232,7 @@ RSpec.shared_examples 'creates runner and shows register page' do
before do
fill_in s_('Runners|Runner description'), with: 'runner-foo'
fill_in s_('Runners|Tags'), with: 'tag1'
- click_on _('Submit')
+ click_on s_('Runners|Create runner')
wait_for_requests
end
diff --git a/spec/workers/gitlab/github_gists_import/import_gist_worker_spec.rb b/spec/workers/gitlab/github_gists_import/import_gist_worker_spec.rb
index fcbe1b2cf99..2e89263bcf3 100644
--- a/spec/workers/gitlab/github_gists_import/import_gist_worker_spec.rb
+++ b/spec/workers/gitlab/github_gists_import/import_gist_worker_spec.rb
@@ -87,10 +87,13 @@ RSpec.describe Gitlab::GithubGistsImport::ImportGistWorker, feature_category: :i
context 'when failure' do
context 'when importer raised an error' do
- it 'raises an error' do
- exception = StandardError.new('_some_error_')
+ let(:exception) { StandardError.new('_some_error_') }
+
+ before do
+ allow(importer).to receive(:execute).and_raise(exception)
+ end
- expect(importer).to receive(:execute).and_raise(exception)
+ it 'raises an error' do
expect(Gitlab::GithubImport::Logger)
.to receive(:error)
.with(log_attributes.merge('message' => 'importer failed', 'error.message' => '_some_error_'))
@@ -103,8 +106,11 @@ RSpec.describe Gitlab::GithubGistsImport::ImportGistWorker, feature_category: :i
context 'when importer returns error' do
let(:importer_result) { instance_double('ServiceResponse', errors: 'error_message', success?: false) }
+ before do
+ allow(importer).to receive(:execute).and_return(importer_result)
+ end
+
it 'tracks and logs error' do
- expect(importer).to receive(:execute).and_return(importer_result)
expect(Gitlab::GithubImport::Logger)
.to receive(:error)
.with(log_attributes.merge('message' => 'importer failed', 'error.message' => 'error_message'))
@@ -120,14 +126,56 @@ RSpec.describe Gitlab::GithubGistsImport::ImportGistWorker, feature_category: :i
status: 'failed'
)
end
+
+ it 'persists failure' do
+ expect { subject.perform(user.id, gist_hash, 'some_key') }
+ .to change { ImportFailure.where(user: user).count }.from(0).to(1)
+
+ expect(ImportFailure.where(user_id: user.id).first).to have_attributes(
+ source: 'Gitlab::GithubGistsImport::Importer::GistImporter',
+ exception_class: 'Gitlab::GithubGistsImport::Importer::GistImporter::FileCountLimitError',
+ exception_message: 'Snippet maximum file count exceeded',
+ external_identifiers: {
+ 'id' => '055b70'
+ }
+ )
+ end
end
end
describe '.sidekiq_retries_exhausted' do
- it 'sends snowplow event' do
- job = { 'args' => [user.id, 'some_key', '1'], 'jid' => '123' }
+ subject(:sidekiq_retries_exhausted) do
+ described_class.sidekiq_retries_exhausted_block.call(job, StandardError.new)
+ end
- described_class.sidekiq_retries_exhausted_block.call(job)
+ let(:args) { [user.id, gist_hash, '1'] }
+
+ let(:job) do
+ {
+ 'args' => args,
+ 'jid' => '123',
+ 'correlation_id' => 'abc',
+ 'error_class' => 'StandardError',
+ 'error_message' => 'Some error'
+ }
+ end
+
+ it 'persists failure' do
+ expect { sidekiq_retries_exhausted }.to change { ImportFailure.where(user: user).count }.from(0).to(1)
+
+ expect(ImportFailure.where(user_id: user.id).first).to have_attributes(
+ source: 'Gitlab::GithubGistsImport::Importer::GistImporter',
+ exception_class: 'StandardError',
+ exception_message: 'Some error',
+ correlation_id_value: 'abc',
+ external_identifiers: {
+ 'id' => '055b70'
+ }
+ )
+ end
+
+ it 'sends snowplow event' do
+ sidekiq_retries_exhausted
expect_snowplow_event(
category: 'Gitlab::GithubGistsImport::ImportGistWorker',
@@ -137,6 +185,24 @@ RSpec.describe Gitlab::GithubGistsImport::ImportGistWorker, feature_category: :i
status: 'failed'
)
end
+
+ it 'notifies the JobWaiter' do
+ expect(Gitlab::JobWaiter)
+ .to receive(:notify)
+ .with(job['args'].last, job['jid'])
+
+ sidekiq_retries_exhausted
+ end
+
+ context 'when not all arguments are given' do
+ let(:args) { [user.id, gist_hash] }
+
+ it 'does not notify the JobWaiter' do
+ expect(Gitlab::JobWaiter).not_to receive(:notify)
+
+ sidekiq_retries_exhausted
+ end
+ end
end
end
end