summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/fixtures/api/schemas/entities/discussion.json2
-rw-r--r--spec/frontend/registry/explorer/pages/details_spec.js62
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb140
-rw-r--r--spec/models/ci/build_dependencies_spec.rb (renamed from spec/models/ci/processable/dependencies_spec.rb)2
-rw-r--r--spec/requests/api/graphql/mutations/jira_import/start_spec.rb130
-rw-r--r--spec/requests/api/project_clusters_spec.rb80
-rw-r--r--spec/support/helpers/stub_gitlab_calls.rb8
7 files changed, 222 insertions, 202 deletions
diff --git a/spec/fixtures/api/schemas/entities/discussion.json b/spec/fixtures/api/schemas/entities/discussion.json
index 92863d2e084..9d7ca62435e 100644
--- a/spec/fixtures/api/schemas/entities/discussion.json
+++ b/spec/fixtures/api/schemas/entities/discussion.json
@@ -36,7 +36,7 @@
"updated_at": { "type": "date" },
"system": { "type": "boolean" },
"noteable_id": { "type": "integer" },
- "noteable_iid": { "type": "integer" },
+ "noteable_iid": { "type": ["integer", "null"] },
"noteable_type": { "type": "string" },
"resolved": { "type": "boolean" },
"resolvable": { "type": "boolean" },
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js
index 60e509e4a88..15aa5008413 100644
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ b/spec/frontend/registry/explorer/pages/details_spec.js
@@ -29,10 +29,11 @@ describe('Details Page', () => {
const findAllDeleteButtons = () => wrapper.findAll('.js-delete-registry');
const findAllCheckboxes = () => wrapper.findAll('.js-row-checkbox');
const findCheckedCheckboxes = () => findAllCheckboxes().filter(c => c.attributes('checked'));
+ const findFirsTagColumn = () => wrapper.find('.js-tag-column');
const routeId = window.btoa(JSON.stringify({ name: 'foo', tags_path: 'bar' }));
- beforeEach(() => {
+ const mountComponent = options => {
wrapper = mount(component, {
store,
stubs: {
@@ -49,7 +50,11 @@ describe('Details Page', () => {
},
$toast,
},
+ ...options,
});
+ };
+
+ beforeEach(() => {
dispatchSpy = jest.spyOn(store, 'dispatch');
store.dispatch('receiveTagsListSuccess', tagsListResponse);
jest.spyOn(Tracking, 'event');
@@ -61,6 +66,7 @@ describe('Details Page', () => {
describe('when isLoading is true', () => {
beforeEach(() => {
+ mountComponent();
store.dispatch('receiveTagsListSuccess', { ...tagsListResponse, data: [] });
store.commit(SET_MAIN_LOADING, true);
});
@@ -81,6 +87,10 @@ describe('Details Page', () => {
});
describe('table', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
it.each([
'rowCheckbox',
'rowName',
@@ -93,6 +103,10 @@ describe('Details Page', () => {
});
describe('header checkbox', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
it('exists', () => {
expect(findMainCheckbox().exists()).toBe(true);
});
@@ -116,6 +130,10 @@ describe('Details Page', () => {
});
describe('row checkbox', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
it('if selected adds item to selectedItems', () => {
findFirstRowItem('rowCheckbox').vm.$emit('change');
return wrapper.vm.$nextTick().then(() => {
@@ -135,6 +153,10 @@ describe('Details Page', () => {
});
describe('header delete button', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
it('exists', () => {
expect(findBulkDeleteButton().exists()).toBe(true);
});
@@ -182,6 +204,10 @@ describe('Details Page', () => {
});
describe('row delete button', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
it('exists', () => {
expect(
findAllDeleteButtons()
@@ -213,9 +239,39 @@ describe('Details Page', () => {
});
});
});
+
+ describe('tag cell', () => {
+ describe('on desktop viewport', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('has class w-25', () => {
+ expect(findFirsTagColumn().classes()).toContain('w-25');
+ });
+ });
+
+ describe('on mobile viewport', () => {
+ beforeEach(() => {
+ mountComponent({
+ data() {
+ return { isDesktop: false };
+ },
+ });
+ });
+
+ it('does not has class w-25', () => {
+ expect(findFirsTagColumn().classes()).not.toContain('w-25');
+ });
+ });
+ });
});
describe('pagination', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
it('exists', () => {
expect(findPagination().exists()).toBe(true);
});
@@ -238,6 +294,10 @@ describe('Details Page', () => {
});
describe('modal', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
it('exists', () => {
expect(findDeleteModal().exists()).toBe(true);
});
diff --git a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb
index b5f0783cb42..fc95bb602c2 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb
@@ -10,146 +10,6 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject { described_class.new(pipeline, command) }
describe '#perform!' do
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(ci_root_config_content: false)
- end
-
- context 'when bridge job is passed in as parameter' do
- let(:ci_config_path) { nil }
- let(:bridge) { create(:ci_bridge) }
-
- before do
- command.bridge = bridge
- end
-
- context 'when bridge job has downstream yaml' do
- before do
- allow(bridge).to receive(:yaml_for_downstream).and_return('the-yaml')
- end
-
- it 'returns the content already available in command' do
- subject.perform!
-
- expect(pipeline.config_source).to eq 'bridge_source'
- expect(command.config_content).to eq 'the-yaml'
- end
- end
-
- context 'when bridge job does not have downstream yaml' do
- before do
- allow(bridge).to receive(:yaml_for_downstream).and_return(nil)
- end
-
- it 'returns the next available source' do
- subject.perform!
-
- expect(pipeline.config_source).to eq 'auto_devops_source'
- template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps')
- expect(command.config_content).to eq(template.content)
- end
- end
- end
-
- context 'when config is defined in a custom path in the repository' do
- let(:ci_config_path) { 'path/to/config.yml' }
-
- before do
- expect(project.repository)
- .to receive(:gitlab_ci_yml_for)
- .with(pipeline.sha, ci_config_path)
- .and_return('the-content')
- end
-
- it 'returns the content of the YAML file' do
- subject.perform!
-
- expect(pipeline.config_source).to eq 'repository_source'
- expect(pipeline.pipeline_config).to be_nil
- expect(command.config_content).to eq('the-content')
- end
- end
-
- context 'when config is defined remotely' do
- let(:ci_config_path) { 'http://example.com/path/to/ci/config.yml' }
-
- it 'does not support URLs and default to AutoDevops' do
- subject.perform!
-
- expect(pipeline.config_source).to eq 'auto_devops_source'
- expect(pipeline.pipeline_config).to be_nil
- template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps')
- expect(command.config_content).to eq(template.content)
- end
- end
-
- context 'when config is defined in a separate repository' do
- let(:ci_config_path) { 'path/to/.gitlab-ci.yml@another-group/another-repo' }
-
- it 'does not support YAML from external repository and default to AutoDevops' do
- subject.perform!
-
- expect(pipeline.config_source).to eq 'auto_devops_source'
- expect(pipeline.pipeline_config).to be_nil
- template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps')
- expect(command.config_content).to eq(template.content)
- end
- end
-
- context 'when config is defined in the default .gitlab-ci.yml' do
- let(:ci_config_path) { nil }
-
- before do
- expect(project.repository)
- .to receive(:gitlab_ci_yml_for)
- .with(pipeline.sha, '.gitlab-ci.yml')
- .and_return('the-content')
- end
-
- it 'returns the content of the canonical config file' do
- subject.perform!
-
- expect(pipeline.config_source).to eq 'repository_source'
- expect(pipeline.pipeline_config).to be_nil
- expect(command.config_content).to eq('the-content')
- end
- end
-
- context 'when config is the Auto-Devops template' do
- let(:ci_config_path) { nil }
-
- before do
- expect(project).to receive(:auto_devops_enabled?).and_return(true)
- end
-
- it 'returns the content of AutoDevops template' do
- subject.perform!
-
- expect(pipeline.config_source).to eq 'auto_devops_source'
- expect(pipeline.pipeline_config).to be_nil
- template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps')
- expect(command.config_content).to eq(template.content)
- end
- end
-
- context 'when config is not defined anywhere' do
- let(:ci_config_path) { nil }
-
- before do
- expect(project).to receive(:auto_devops_enabled?).and_return(false)
- end
-
- it 'builds root config including the auto-devops template' do
- subject.perform!
-
- expect(pipeline.config_source).to eq('unknown_source')
- expect(pipeline.pipeline_config).to be_nil
- expect(command.config_content).to be_nil
- expect(pipeline.errors.full_messages).to include('Missing CI config file')
- end
- end
- end
-
context 'when bridge job is passed in as parameter' do
let(:ci_config_path) { nil }
let(:bridge) { create(:ci_bridge) }
diff --git a/spec/models/ci/processable/dependencies_spec.rb b/spec/models/ci/build_dependencies_spec.rb
index f115ae51f9c..6db69d0f34c 100644
--- a/spec/models/ci/processable/dependencies_spec.rb
+++ b/spec/models/ci/build_dependencies_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe Ci::Processable::Dependencies do
+describe Ci::BuildDependencies do
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :repository) }
diff --git a/spec/requests/api/graphql/mutations/jira_import/start_spec.rb b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb
new file mode 100644
index 00000000000..3eb2ca6909b
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Starting a Jira Import' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project) }
+ let(:jira_project_key) { 'AA' }
+ let(:project_path) { project.full_path }
+
+ let(:mutation) do
+ variables = {
+ jira_project_key: jira_project_key,
+ project_path: project_path
+ }
+
+ graphql_mutation(:jira_import_start, variables)
+ end
+
+ def mutation_response
+ graphql_mutation_response(:jira_import_start)
+ end
+
+ def jira_import
+ mutation_response['jiraImport']
+ end
+
+ context 'when the user does not have permission' do
+ before do
+ stub_feature_flags(jira_issue_import: true)
+ end
+
+ shared_examples 'Jira import does not start' do
+ it 'does not start the Jira import' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(project.reload.import_state).to be nil
+ expect(project.reload.import_data).to be nil
+ end
+ end
+
+ context 'with anonymous user' do
+ let(:current_user) { nil }
+
+ it_behaves_like 'Jira import does not start'
+ it_behaves_like 'a mutation that returns top-level errors',
+ errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
+ end
+
+ context 'with user without permissions' do
+ let(:current_user) { user }
+ let(:project_path) { project.full_path }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ it_behaves_like 'Jira import does not start'
+ it_behaves_like 'a mutation that returns top-level errors',
+ errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
+ end
+ end
+
+ context 'when the user has permission' do
+ let(:current_user) { user }
+
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'with project' do
+ context 'when the project path is invalid' do
+ let(:project_path) { 'foobar' }
+
+ it 'returns an an error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+ errors = json_response['errors']
+
+ expect(errors.first['message']).to eq(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
+ end
+ end
+
+ context 'when feature jira_issue_import feature flag is disabled' do
+ before do
+ stub_feature_flags(jira_issue_import: false)
+ end
+
+ it_behaves_like 'a mutation that returns errors in the response', errors: ['Jira import feature is disabled.']
+ end
+
+ context 'when feature jira_issue_import feature flag is enabled' do
+ before do
+ stub_feature_flags(jira_issue_import: true)
+ end
+
+ context 'when project has no Jira service' do
+ it_behaves_like 'a mutation that returns errors in the response', errors: ['Jira integration not configured.']
+ end
+
+ context 'when when project has Jira service' do
+ let!(:service) { create(:jira_service, project: project) }
+
+ before do
+ project.reload
+ end
+
+ context 'when jira_project_key not provided' do
+ let(:jira_project_key) { '' }
+
+ it_behaves_like 'a mutation that returns errors in the response', errors: ['Unable to find Jira project to import data from.']
+ end
+
+ context 'when jira import successfully scheduled' do
+ it 'schedules a Jira import' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(jira_import['jiraProjectKey']).to eq 'AA'
+ expect(jira_import['scheduledBy']['username']).to eq current_user.username
+ expect(project.import_state).not_to be nil
+ expect(project.import_state.status).to eq 'scheduled'
+ expect(project.import_data.becomes(JiraImportData).projects.last.scheduled_by['user_id']).to eq current_user.id
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/project_clusters_spec.rb b/spec/requests/api/project_clusters_spec.rb
index 7cef40ff3b5..648577dce8d 100644
--- a/spec/requests/api/project_clusters_spec.rb
+++ b/spec/requests/api/project_clusters_spec.rb
@@ -5,9 +5,9 @@ require 'spec_helper'
describe API::ProjectClusters do
include KubernetesHelpers
- let(:current_user) { create(:user) }
- let(:developer_user) { create(:user) }
- let(:project) { create(:project) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:developer_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
before do
project.add_maintainer(current_user)
@@ -15,10 +15,10 @@ describe API::ProjectClusters do
end
describe 'GET /projects/:id/clusters' do
- let!(:extra_cluster) { create(:cluster, :provided_by_gcp, :project) }
+ let_it_be(:extra_cluster) { create(:cluster, :provided_by_gcp, :project) }
- let!(:clusters) do
- create_list(:cluster, 5, :provided_by_gcp, :project, :production_environment,
+ let_it_be(:clusters) do
+ create_list(:cluster, 2, :provided_by_gcp, :project, :production_environment,
projects: [project])
end
@@ -35,17 +35,15 @@ describe API::ProjectClusters do
get api("/projects/#{project.id}/clusters", current_user)
end
- it 'responds with 200' do
- expect(response).to have_gitlab_http_status(:ok)
- end
-
it 'includes pagination headers' do
+ expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
end
it 'onlies include authorized clusters' do
cluster_ids = json_response.map { |cluster| cluster['id'] }
+ expect(response).to have_gitlab_http_status(:ok)
expect(cluster_ids).to match_array(clusters.pluck(:id))
expect(cluster_ids).not_to include(extra_cluster.id)
end
@@ -139,7 +137,7 @@ describe API::ProjectClusters do
end
context 'with non-existing cluster' do
- let(:cluster_id) { 123 }
+ let(:cluster_id) { 0 }
it 'returns 404' do
expect(response).to have_gitlab_http_status(:not_found)
@@ -185,14 +183,11 @@ describe API::ProjectClusters do
end
context 'with valid params' do
- it 'responds with 201' do
- expect(response).to have_gitlab_http_status(:created)
- end
-
it 'creates a new Cluster::Cluster' do
cluster_result = Clusters::Cluster.find(json_response["id"])
platform_kubernetes = cluster_result.platform
+ expect(response).to have_gitlab_http_status(:created)
expect(cluster_result).to be_user
expect(cluster_result).to be_kubernetes
expect(cluster_result.project).to eq(project)
@@ -235,15 +230,9 @@ describe API::ProjectClusters do
context 'with invalid params' do
let(:namespace) { 'invalid_namespace' }
- it 'responds with 400' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
it 'does not create a new Clusters::Cluster' do
+ expect(response).to have_gitlab_http_status(:bad_request)
expect(project.reload.clusters).to be_empty
- end
-
- it 'returns validation errors' do
expect(json_response['message']['platform_kubernetes.namespace'].first).to be_present
end
end
@@ -259,8 +248,8 @@ describe API::ProjectClusters do
it 'responds with 400' do
expect(response).to have_gitlab_http_status(:bad_request)
-
- expect(json_response['message']['base'].first).to eq(_('Instance does not support multiple Kubernetes clusters'))
+ expect(json_response['message']['base'].first)
+ .to eq(_('Instance does not support multiple Kubernetes clusters'))
end
end
@@ -271,7 +260,6 @@ describe API::ProjectClusters do
it 'responds with 403' do
expect(response).to have_gitlab_http_status(:forbidden)
-
expect(json_response['message']).to eq('403 Forbidden')
end
end
@@ -281,7 +269,7 @@ describe API::ProjectClusters do
let(:api_url) { 'https://kubernetes.example.com' }
let(:namespace) { 'new-namespace' }
let(:platform_kubernetes_attributes) { { namespace: namespace } }
- let(:management_project) { create(:project, namespace: project.namespace) }
+ let_it_be(:management_project) { create(:project, namespace: project.namespace) }
let(:management_project_id) { management_project.id }
let(:update_params) do
@@ -321,11 +309,8 @@ describe API::ProjectClusters do
end
context 'with valid params' do
- it 'responds with 200' do
- expect(response).to have_gitlab_http_status(:ok)
- end
-
it 'updates cluster attributes' do
+ expect(response).to have_gitlab_http_status(:ok)
expect(cluster.domain).to eq('new-domain.com')
expect(cluster.platform_kubernetes.namespace).to eq('new-namespace')
expect(cluster.management_project).to eq(management_project)
@@ -335,29 +320,24 @@ describe API::ProjectClusters do
context 'with invalid params' do
let(:namespace) { 'invalid_namespace' }
- it 'responds with 400' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
it 'does not update cluster attributes' do
+ expect(response).to have_gitlab_http_status(:bad_request)
expect(cluster.domain).not_to eq('new_domain.com')
expect(cluster.platform_kubernetes.namespace).not_to eq('invalid_namespace')
expect(cluster.management_project).not_to eq(management_project)
end
it 'returns validation errors' do
- expect(json_response['message']['platform_kubernetes.namespace'].first).to match('can contain only lowercase letters')
+ expect(json_response['message']['platform_kubernetes.namespace'].first)
+ .to match('can contain only lowercase letters')
end
end
context 'current user does not have access to management_project_id' do
- let(:management_project_id) { create(:project).id }
-
- it 'responds with 400' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
+ let_it_be(:management_project_id) { create(:project).id }
it 'returns validation errors' do
+ expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']['management_project_id'].first).to match('don\'t have permission')
end
end
@@ -371,12 +351,10 @@ describe API::ProjectClusters do
}
end
- it 'responds with 400' do
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
it 'returns validation error' do
- expect(json_response['message']['platform_kubernetes.base'].first).to eq(_('Cannot modify managed Kubernetes cluster'))
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']['platform_kubernetes.base'].first)
+ .to eq(_('Cannot modify managed Kubernetes cluster'))
end
end
@@ -412,13 +390,10 @@ describe API::ProjectClusters do
}
end
- it 'responds with 200' do
- expect(response).to have_gitlab_http_status(:ok)
- end
-
it 'updates platform kubernetes attributes' do
platform_kubernetes = cluster.platform_kubernetes
+ expect(response).to have_gitlab_http_status(:ok)
expect(cluster.name).to eq('new-name')
expect(platform_kubernetes.namespace).to eq('new-namespace')
expect(platform_kubernetes.api_url).to eq('https://new-api-url.com')
@@ -439,7 +414,7 @@ describe API::ProjectClusters do
describe 'DELETE /projects/:id/clusters/:cluster_id' do
let(:cluster_params) { { cluster_id: cluster.id } }
- let(:cluster) do
+ let_it_be(:cluster) do
create(:cluster, :project, :provided_by_gcp,
projects: [project])
end
@@ -457,11 +432,8 @@ describe API::ProjectClusters do
delete api("/projects/#{project.id}/clusters/#{cluster.id}", current_user), params: cluster_params
end
- it 'responds with 204' do
- expect(response).to have_gitlab_http_status(:no_content)
- end
-
it 'deletes the cluster' do
+ expect(response).to have_gitlab_http_status(:no_content)
expect(Clusters::Cluster.exists?(id: cluster.id)).to be_falsy
end
diff --git a/spec/support/helpers/stub_gitlab_calls.rb b/spec/support/helpers/stub_gitlab_calls.rb
index ff4b9db8ad9..40f4151c0fb 100644
--- a/spec/support/helpers/stub_gitlab_calls.rb
+++ b/spec/support/helpers/stub_gitlab_calls.rb
@@ -30,11 +30,9 @@ module StubGitlabCalls
# Stub the first call to `include:[local: .gitlab-ci.yml]` when
# evaluating the CI root config content.
- if Feature.enabled?(:ci_root_config_content, default_enabled: true)
- allow_any_instance_of(Gitlab::Ci::Config::External::File::Local)
- .to receive(:content)
- .and_return(ci_yaml_content)
- end
+ allow_any_instance_of(Gitlab::Ci::Config::External::File::Local)
+ .to receive(:content)
+ .and_return(ci_yaml_content)
end
def stub_pipeline_modified_paths(pipeline, modified_paths)