diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-12 18:09:09 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-12 18:09:09 +0300 |
commit | 6cf30e964d54d536b0ff861916745f0a4bb31ebb (patch) | |
tree | c29ef6911c9c8347cbcd5195583462e91121506a /spec | |
parent | 4a31b8786892820e8029844c34fd5296c52c37c0 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
25 files changed, 357 insertions, 195 deletions
diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb index 24048aea838..c4e040b0287 100644 --- a/spec/controllers/projects/ci/lints_controller_spec.rb +++ b/spec/controllers/projects/ci/lints_controller_spec.rb @@ -123,20 +123,6 @@ RSpec.describe Projects::Ci::LintsController do subject end - - context 'when dry_run feature flag is disabled' do - before do - stub_feature_flags(ci_lint_creates_pipeline_with_dry_run: false) - end - - it_behaves_like 'returns a successful validation' - - it 'runs validations through YamlProcessor' do - expect(Gitlab::Ci::YamlProcessor).to receive(:new).and_call_original - - subject - end - end end end diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb index 420d818daeb..07fb03b39c6 100644 --- a/spec/controllers/projects/releases_controller_spec.rb +++ b/spec/controllers/projects/releases_controller_spec.rb @@ -201,102 +201,7 @@ RSpec.describe Projects::ReleasesController do end end - context 'GET #downloads' do - subject do - get :downloads, params: { namespace_id: project.namespace, project_id: project, tag: tag, filepath: filepath } - end - - before do - sign_in(user) - end - - let(:release) { create(:release, project: project, tag: tag ) } - let!(:link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: 'https://downloads.example.com/bin/gitlab-linux-amd64') } - let(:tag) { 'v11.9.0-rc2' } - - context 'valid filepath' do - let(:filepath) { CGI.escape('/binaries/linux-amd64') } - - it 'redirects to the asset direct link' do - subject - - expect(response).to redirect_to('https://downloads.example.com/bin/gitlab-linux-amd64') - end - - it 'redirects with a status of 302' do - subject - - expect(response).to have_gitlab_http_status(:redirect) - end - end - - context 'invalid filepath' do - let(:filepath) { CGI.escape('/binaries/win32') } - - it 'is not found' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context 'GET #downloads' do - subject do - get :downloads, params: { - namespace_id: project.namespace, - project_id: project, - tag: tag, - filepath: filepath - } - end - - before do - sign_in(user) - end - - let(:release) { create(:release, project: project, tag: tag ) } - let(:tag) { 'v11.9.0-rc2' } - let(:db_filepath) { '/binaries/linux-amd64' } - let!(:link) do - create :release_link, - release: release, - name: 'linux-amd64 binaries', - filepath: db_filepath, - url: 'https://downloads.example.com/bin/gitlab-linux-amd64' - end - - context 'valid filepath' do - let(:filepath) { CGI.escape('/binaries/linux-amd64') } - - it 'redirects to the asset direct link' do - subject - - expect(response).to redirect_to(link.url) - end - end - - context 'invalid filepath' do - let(:filepath) { CGI.escape('/binaries/win32') } - - it 'is not found' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'ignores filepath extension' do - let(:db_filepath) { '/binaries/linux-amd64.json' } - let(:filepath) { CGI.escape(db_filepath) } - - it 'redirects to the asset direct link' do - subject - - expect(response).to redirect_to(link.url) - end - end - end + # `GET #downloads` is addressed in spec/requests/projects/releases_controller_spec.rb private diff --git a/spec/factories/bulk_import/trackers.rb b/spec/factories/bulk_import/trackers.rb new file mode 100644 index 00000000000..7a1fa0849fc --- /dev/null +++ b/spec/factories/bulk_import/trackers.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :bulk_import_tracker, class: 'BulkImports::Tracker' do + association :entity, factory: :bulk_import_entity + + relation { :relation } + has_next_page { false } + end +end diff --git a/spec/features/groups/container_registry_spec.rb b/spec/features/groups/container_registry_spec.rb index acac8724edf..1b23b8b4bf9 100644 --- a/spec/features/groups/container_registry_spec.rb +++ b/spec/features/groups/container_registry_spec.rb @@ -89,6 +89,20 @@ RSpec.describe 'Container Registry', :js do end end + context 'when an image has the same name as the subgroup' do + before do + stub_container_registry_tags(tags: %w[latest], with_manifest: true) + project.container_repositories << create(:container_repository, name: group.name) + visit_container_registry + end + + it 'details page loads properly' do + find('a[data-testid="details-link"]').click + + expect(page).to have_content 'latest' + end + end + def visit_container_registry visit group_container_registries_path(group) end diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb index 304573ecd6e..97732374eb9 100644 --- a/spec/features/groups/show_spec.rb +++ b/spec/features/groups/show_spec.rb @@ -81,8 +81,7 @@ RSpec.describe 'Group show page' do it 'allows creating subgroups' do visit path - expect(page) - .to have_css("li[data-text='New subgroup']", visible: false) + expect(page).to have_link('New subgroup') end end end @@ -102,8 +101,7 @@ RSpec.describe 'Group show page' do path = group_path(relaxed_group) visit path - expect(page) - .to have_css("li[data-text='New subgroup']", visible: false) + expect(page).to have_link('New subgroup') end end @@ -116,9 +114,7 @@ RSpec.describe 'Group show page' do path = group_path(restricted_group) visit path - expect(page) - .not_to have_selector("li[data-text='New subgroup']", - visible: false) + expect(page).not_to have_link('New subgroup') end end end diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb index 8264ec2eddd..b9fd3a1a5cc 100644 --- a/spec/features/groups_spec.rb +++ b/spec/features/groups_spec.rb @@ -294,35 +294,43 @@ RSpec.describe 'Group' do describe 'new subgroup / project button' do let(:group) { create(:group, project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS, subgroup_creation_level: Gitlab::Access::OWNER_SUBGROUP_ACCESS) } - it 'new subgroup button is displayed without project creation permission' do - visit group_path(group) + context 'when user has subgroup creation permissions but not project creation permissions' do + it 'only displays "New subgroup" button' do + visit group_path(group) - page.within '.group-buttons' do - expect(page).to have_link('New subgroup') + page.within '[data-testid="group-buttons"]' do + expect(page).to have_link('New subgroup') + expect(page).not_to have_link('New project') + end end end - it 'new subgroup button is displayed together with new project button when having project creation permission' do - group.update!(project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS) - visit group_path(group) + context 'when user has project creation permissions but not subgroup creation permissions' do + it 'only displays "New project" button' do + group.update!(project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS) + user = create(:user) - page.within '.group-buttons' do - expect(page).to have_css("li[data-text='New subgroup']", visible: false) - expect(page).to have_css("li[data-text='New project']", visible: false) + group.add_maintainer(user) + sign_out(:user) + sign_in(user) + + visit group_path(group) + page.within '[data-testid="group-buttons"]' do + expect(page).to have_link('New project') + expect(page).not_to have_link('New subgroup') + end end end - it 'new project button is displayed without subgroup creation permission' do - group.update!(project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS) - user = create(:user) - - group.add_maintainer(user) - sign_out(:user) - sign_in(user) + context 'when user has project and subgroup creation permissions' do + it 'displays "New subgroup" and "New project" buttons' do + group.update!(project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS) + visit group_path(group) - visit group_path(group) - page.within '.group-buttons' do - expect(page).to have_link('New project') + page.within '[data-testid="group-buttons"]' do + expect(page).to have_link('New subgroup') + expect(page).to have_link('New project') + end end end end diff --git a/spec/features/projects/container_registry_spec.rb b/spec/features/projects/container_registry_spec.rb index 7514a26f020..45bf35a6aab 100644 --- a/spec/features/projects/container_registry_spec.rb +++ b/spec/features/projects/container_registry_spec.rb @@ -10,6 +10,10 @@ RSpec.describe 'Container Registry', :js do create(:container_repository, name: 'my/image') end + let(:nameless_container_repository) do + create(:container_repository, name: '') + end + before do sign_in(user) project.add_developer(user) @@ -96,6 +100,20 @@ RSpec.describe 'Container Registry', :js do end end + describe 'image repo details when image has no name' do + before do + stub_container_registry_tags(tags: %w[latest], with_manifest: true) + project.container_repositories << nameless_container_repository + visit_container_registry + end + + it 'renders correctly' do + find('a[data-testid="details-link"]').click + + expect(page).to have_content 'latest' + end + end + context 'when there are more than 10 images' do before do create_list(:container_repository, 12, project: project) diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb index 6ca5073c5a4..aabbc8cea7b 100644 --- a/spec/features/projects/releases/user_views_releases_spec.rb +++ b/spec/features/projects/releases/user_views_releases_spec.rb @@ -38,7 +38,7 @@ RSpec.describe 'User views releases', :js do context 'when there is a link as an asset' do let!(:release_link) { create(:release_link, release: release_v1, url: url ) } let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" } - let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << release_link.filepath } + let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release_v1) << "/downloads#{release_link.filepath}" } it 'sees the link' do page.within("##{release_v1.tag} .js-assets-list") do diff --git a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js index c7a9db82bea..04ecefa7140 100644 --- a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js +++ b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js @@ -24,11 +24,14 @@ const mockIntegrations = [ describe('AlertIntegrationsList', () => { let wrapper; - function mountComponent(propsData = {}) { + function mountComponent({ data = {}, props = {} } = {}) { wrapper = mount(AlertIntegrationsList, { + data() { + return { ...data }; + }, propsData: { integrations: mockIntegrations, - ...propsData, + ...props, }, stubs: { GlIcon: true, @@ -57,7 +60,7 @@ describe('AlertIntegrationsList', () => { }); it('renders an empty state when no integrations provided', () => { - mountComponent({ integrations: [] }); + mountComponent({ props: { integrations: [] } }); expect(findTableComponent().text()).toContain(i18n.emptyState); }); @@ -66,7 +69,7 @@ describe('AlertIntegrationsList', () => { }); it('renders an highlighted row when a current integration is selected to edit', () => { - mountComponent({ currentIntegration: { id: '1' } }); + mountComponent({ data: { currentIntegration: { id: '1' } } }); expect( findTableComponentRows() .at(0) diff --git a/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js index d5a1239f701..97a53c20b6b 100644 --- a/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js +++ b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js @@ -152,9 +152,9 @@ describe('AlertsSettingsFormNew', () => { createComponent({ data: { selectedIntegration: typeSet.http, + currentIntegration: { id: '1', name: 'Test integration pre' }, }, props: { - currentIntegration: { id: '1', name: 'Test integration pre' }, loading: false, }, }); @@ -183,9 +183,9 @@ describe('AlertsSettingsFormNew', () => { createComponent({ data: { selectedIntegration: typeSet.prometheus, + currentIntegration: { id: '1', apiUrl: 'https://test-pre.com' }, }, props: { - currentIntegration: { id: '1', apiUrl: 'https://test-pre.com' }, loading: false, }, }); @@ -219,10 +219,10 @@ describe('AlertsSettingsFormNew', () => { createComponent({ data: { selectedIntegration: typeSet.http, + currentIntegration: { id: '1', name: 'Test' }, active: true, }, props: { - currentIntegration: { id: '1', name: 'Test' }, loading: false, }, }); diff --git a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js b/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js index e85ee39f165..9f7a2758ae1 100644 --- a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js +++ b/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js @@ -19,7 +19,7 @@ describe('Image List Row', () => { let wrapper; const item = imagesListResponse.data[0]; - const findDetailsLink = () => wrapper.find('[data-testid="detailsLink"]'); + const findDetailsLink = () => wrapper.find('[data-testid="details-link"]'); const findTagsCount = () => wrapper.find('[data-testid="tagsCount"]'); const findDeleteBtn = () => wrapper.find(DeleteButton); const findClipboardButton = () => wrapper.find(ClipboardButton); diff --git a/spec/frontend/registry/explorer/stores/actions_spec.js b/spec/frontend/registry/explorer/stores/actions_spec.js index 17ce6a7054d..dcd4d8015a4 100644 --- a/spec/frontend/registry/explorer/stores/actions_spec.js +++ b/spec/frontend/registry/explorer/stores/actions_spec.js @@ -8,6 +8,11 @@ import * as actions from '~/registry/explorer/stores/actions'; import * as types from '~/registry/explorer/stores/mutation_types'; import { reposServerResponse, registryServerResponse } from '../mock_data'; import * as utils from '~/registry/explorer/utils'; +import { + FETCH_IMAGES_LIST_ERROR_MESSAGE, + FETCH_TAGS_LIST_ERROR_MESSAGE, + FETCH_IMAGE_DETAILS_ERROR_MESSAGE, +} from '~/registry/explorer/constants/index'; jest.mock('~/flash.js'); jest.mock('~/registry/explorer/utils'); @@ -129,7 +134,7 @@ describe('Actions RegistryExplorer Store', () => { ], [], () => { - expect(createFlash).toHaveBeenCalled(); + expect(createFlash).toHaveBeenCalledWith({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE }); done(); }, ); @@ -169,7 +174,7 @@ describe('Actions RegistryExplorer Store', () => { ], [], () => { - expect(createFlash).toHaveBeenCalled(); + expect(createFlash).toHaveBeenCalledWith({ message: FETCH_TAGS_LIST_ERROR_MESSAGE }); done(); }, ); @@ -261,7 +266,7 @@ describe('Actions RegistryExplorer Store', () => { ], [], () => { - expect(createFlash).toHaveBeenCalled(); + expect(createFlash).toHaveBeenCalledWith({ message: FETCH_IMAGE_DETAILS_ERROR_MESSAGE }); done(); }, ); diff --git a/spec/frontend/registry/explorer/utils_spec.js b/spec/frontend/registry/explorer/utils_spec.js index 365bfc9ea19..0cd4a1cec29 100644 --- a/spec/frontend/registry/explorer/utils_spec.js +++ b/spec/frontend/registry/explorer/utils_spec.js @@ -16,6 +16,20 @@ describe('Utils', () => { expect(pathGenerator(imageDetails, '/foo')).toBe('/foo/bar/registry/repository/1/tags/foo'); }); + it.each` + path | name | result + ${'foo/foo'} | ${''} | ${'/foo/foo/registry/repository/1/tags?format=json'} + ${'foo/foo/foo'} | ${'foo'} | ${'/foo/foo/registry/repository/1/tags?format=json'} + ${'baz/foo/foo/foo'} | ${'foo'} | ${'/baz/foo/foo/registry/repository/1/tags?format=json'} + ${'baz/foo/foo/foo'} | ${'foo'} | ${'/baz/foo/foo/registry/repository/1/tags?format=json'} + ${'foo/foo/baz/foo/foo'} | ${'foo/foo'} | ${'/foo/foo/baz/registry/repository/1/tags?format=json'} + ${'foo/foo/baz/foo/bar'} | ${'foo/bar'} | ${'/foo/foo/baz/registry/repository/1/tags?format=json'} + ${'baz/foo/foo'} | ${'foo'} | ${'/baz/foo/registry/repository/1/tags?format=json'} + ${'baz/foo/bar'} | ${'foo'} | ${'/baz/foo/bar/registry/repository/1/tags?format=json'} + `('returns the correct path when path is $path and name is $name', ({ name, path, result }) => { + expect(pathGenerator({ id: 1, name, path })).toBe(result); + }); + it('returns the url unchanged when imageDetails have no name', () => { const imageDetailsWithoutName = { path: 'foo/bar/baz', diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap index aefd1edb87e..f49d3d7b716 100644 --- a/spec/frontend/releases/__snapshots__/util_spec.js.snap +++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap @@ -18,7 +18,7 @@ Object { "count": 8, "links": Array [ Object { - "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-3", + "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-3", "external": true, "id": "gid://gitlab/Releases::Link/13", "linkType": "image", @@ -26,7 +26,7 @@ Object { "url": "https://example.com/image", }, Object { - "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-2", + "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-2", "external": true, "id": "gid://gitlab/Releases::Link/12", "linkType": "package", @@ -34,7 +34,7 @@ Object { "url": "https://example.com/package", }, Object { - "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-1", + "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-1", "external": false, "id": "gid://gitlab/Releases::Link/11", "linkType": "runbook", @@ -42,7 +42,7 @@ Object { "url": "http://localhost/releases-namespace/releases-project/runbook", }, Object { - "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/linux-amd64", + "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/linux-amd64", "external": true, "id": "gid://gitlab/Releases::Link/10", "linkType": "other", @@ -146,7 +146,7 @@ Object { "count": 8, "links": Array [ Object { - "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-3", + "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-3", "external": true, "id": "gid://gitlab/Releases::Link/13", "linkType": "image", @@ -154,7 +154,7 @@ Object { "url": "https://example.com/image", }, Object { - "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-2", + "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-2", "external": true, "id": "gid://gitlab/Releases::Link/12", "linkType": "package", @@ -162,7 +162,7 @@ Object { "url": "https://example.com/package", }, Object { - "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/awesome-app-1", + "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/awesome-app-1", "external": false, "id": "gid://gitlab/Releases::Link/11", "linkType": "runbook", @@ -170,7 +170,7 @@ Object { "url": "http://localhost/releases-namespace/releases-project/runbook", }, Object { - "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/binaries/linux-amd64", + "directAssetUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/downloads/binaries/linux-amd64", "external": true, "id": "gid://gitlab/Releases::Link/10", "linkType": "other", diff --git a/spec/graphql/mutations/commits/create_spec.rb b/spec/graphql/mutations/commits/create_spec.rb index fb1baafe7bd..82a5e3a62f5 100644 --- a/spec/graphql/mutations/commits/create_spec.rb +++ b/spec/graphql/mutations/commits/create_spec.rb @@ -5,8 +5,9 @@ require 'spec_helper' RSpec.describe Mutations::Commits::Create do subject(:mutation) { described_class.new(object: nil, context: context, field: nil) } - let_it_be(:project) { create(:project, :public, :repository) } let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :public, :repository) } + let(:context) do GraphQL::Query::Context.new( query: OpenStruct.new(schema: nil), @@ -18,9 +19,10 @@ RSpec.describe Mutations::Commits::Create do specify { expect(described_class).to require_graphql_authorizations(:push_code) } describe '#resolve' do - subject { mutation.resolve(project_path: project.full_path, branch: branch, message: message, actions: actions) } + subject { mutation.resolve(project_path: project.full_path, branch: branch, start_branch: start_branch, message: message, actions: actions) } let(:branch) { 'master' } + let(:start_branch) { nil } let(:message) { 'Commit message' } let(:actions) do [ @@ -142,6 +144,29 @@ RSpec.describe Mutations::Commits::Create do end end + context 'when branch does not exist and a start branch is provided' do + let(:branch) { 'my-branch' } + let(:start_branch) { 'master' } + let(:actions) do + [ + { + action: 'create', + file_path: 'ANOTHER_FILE.md', + content: 'Bye' + } + ] + end + + it 'returns a new commit' do + expect(mutated_commit).to have_attributes(message: message, project: project) + expect(subject[:errors]).to be_empty + + expect_to_contain_deltas([ + a_hash_including(a_mode: '0', b_mode: '100644', new_file: true, new_path: 'ANOTHER_FILE.md') + ]) + end + end + context 'when message is not set' do let(:message) { nil } diff --git a/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb b/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb new file mode 100644 index 00000000000..c2daa35703d --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillMergeRequestCleanupSchedules, schema: 20201103110018 do + let(:merge_requests) { table(:merge_requests) } + let(:cleanup_schedules) { table(:merge_request_cleanup_schedules) } + let(:metrics) { table(:merge_request_metrics) } + + let(:namespace) { table(:namespaces).create!(name: 'name', path: 'path') } + let(:project) { table(:projects).create!(namespace_id: namespace.id) } + + subject { described_class.new } + + describe '#perform' do + let!(:open_mr) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master') } + + let!(:closed_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) } + let!(:closed_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) } + let!(:closed_mr_1_metrics) { metrics.create!(merge_request_id: closed_mr_1.id, target_project_id: project.id, latest_closed_at: Time.current, created_at: Time.current, updated_at: Time.current) } + let!(:closed_mr_2_metrics) { metrics.create!(merge_request_id: closed_mr_2.id, target_project_id: project.id, latest_closed_at: Time.current, created_at: Time.current, updated_at: Time.current) } + let!(:closed_mr_2_cleanup_schedule) { cleanup_schedules.create!(merge_request_id: closed_mr_2.id, scheduled_at: Time.current) } + + let!(:merged_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3) } + let!(:merged_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3, updated_at: Time.current) } + let!(:merged_mr_1_metrics) { metrics.create!(merge_request_id: merged_mr_1.id, target_project_id: project.id, merged_at: Time.current, created_at: Time.current, updated_at: Time.current) } + + let!(:closed_mr_3) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) } + let!(:closed_mr_3_metrics) { metrics.create!(merge_request_id: closed_mr_3.id, target_project_id: project.id, latest_closed_at: Time.current, created_at: Time.current, updated_at: Time.current) } + + it 'creates records for all closed and merged merge requests in range' do + expect(Gitlab::BackgroundMigration::Logger).to receive(:info).with( + message: 'Backfilled merge_request_cleanup_schedules records', + count: 3 + ) + + subject.perform(open_mr.id, merged_mr_2.id) + + aggregate_failures do + expect(cleanup_schedules.all.pluck(:merge_request_id)) + .to contain_exactly(closed_mr_1.id, closed_mr_2.id, merged_mr_1.id, merged_mr_2.id) + expect(cleanup_schedules.find_by(merge_request_id: closed_mr_1.id).scheduled_at.to_s) + .to eq((closed_mr_1_metrics.latest_closed_at + 14.days).to_s) + expect(cleanup_schedules.find_by(merge_request_id: closed_mr_2.id).scheduled_at.to_s) + .to eq(closed_mr_2_cleanup_schedule.scheduled_at.to_s) + expect(cleanup_schedules.find_by(merge_request_id: merged_mr_1.id).scheduled_at.to_s) + .to eq((merged_mr_1_metrics.merged_at + 14.days).to_s) + expect(cleanup_schedules.find_by(merge_request_id: merged_mr_2.id).scheduled_at.to_s) + .to eq((merged_mr_2.updated_at + 14.days).to_s) + end + end + end +end diff --git a/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb b/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb new file mode 100644 index 00000000000..fa8dd38619a --- /dev/null +++ b/spec/migrations/schedule_merge_request_cleanup_schedules_backfill_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +require_migration! + +RSpec.describe ScheduleMergeRequestCleanupSchedulesBackfill, :sidekiq, schema: 20201023114628 do + let(:merge_requests) { table(:merge_requests) } + let(:cleanup_schedules) { table(:merge_request_cleanup_schedules) } + + let(:namespace) { table(:namespaces).create!(name: 'name', path: 'path') } + let(:project) { table(:projects).create!(namespace_id: namespace.id) } + + describe '#up' do + let!(:open_mr) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master') } + + let!(:closed_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) } + let!(:closed_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) } + + let!(:merged_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3) } + let!(:merged_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3) } + + before do + stub_const("#{described_class}::BATCH_SIZE", 2) + end + + it 'schdules BackfillMergeRequestCleanupSchedules background jobs' do + Sidekiq::Testing.fake! do + migrate! + + aggregate_failures do + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(2.minutes, closed_mr_1.id, closed_mr_2.id) + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(4.minutes, merged_mr_1.id, merged_mr_2.id) + expect(BackgroundMigrationWorker.jobs.size).to eq(2) + end + end + end + end +end diff --git a/spec/models/bulk_imports/tracker_spec.rb b/spec/models/bulk_imports/tracker_spec.rb new file mode 100644 index 00000000000..8eb5a6c27dd --- /dev/null +++ b/spec/models/bulk_imports/tracker_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe BulkImports::Tracker, type: :model do + describe 'associations' do + it { is_expected.to belong_to(:entity).required } + end + + describe 'validations' do + before do + create(:bulk_import_tracker) + end + + it { is_expected.to validate_presence_of(:relation) } + it { is_expected.to validate_uniqueness_of(:relation).scoped_to(:bulk_import_entity_id) } + + context 'when has_next_page is true' do + it "validates presence of `next_page`" do + tracker = build(:bulk_import_tracker, has_next_page: true) + + expect(tracker).not_to be_valid + expect(tracker.errors).to include(:next_page) + end + end + end +end diff --git a/spec/models/design_management/design_spec.rb b/spec/models/design_management/design_spec.rb index 946541a0602..d3ce2f2d48f 100644 --- a/spec/models/design_management/design_spec.rb +++ b/spec/models/design_management/design_spec.rb @@ -375,14 +375,6 @@ RSpec.describe DesignManagement::Design do end it { is_expected.to contain_exactly(version_author, note_author, mentioned_user) } - - context 'when the feature flag is disabled' do - before do - stub_feature_flags(design_management_design_notification_participants: false) - end - - it { is_expected.to be_empty } - end end end diff --git a/spec/requests/api/graphql/mutations/commits/create_spec.rb b/spec/requests/api/graphql/mutations/commits/create_spec.rb index ac4fa7cfe83..375d4f10b40 100644 --- a/spec/requests/api/graphql/mutations/commits/create_spec.rb +++ b/spec/requests/api/graphql/mutations/commits/create_spec.rb @@ -23,6 +23,18 @@ RSpec.describe 'Creation of a new commit' do let(:mutation) { graphql_mutation(:commit_create, input) } let(:mutation_response) { graphql_mutation_response(:commit_create) } + shared_examples 'a commit is successful' do + it 'creates a new commit' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + + expect(mutation_response['commit']).to include( + 'title' => message + ) + end + end + context 'the user is not allowed to create a commit' do it_behaves_like 'a mutation that returns a top-level access error' end @@ -32,14 +44,7 @@ RSpec.describe 'Creation of a new commit' do project.add_developer(current_user) end - it 'creates a new commit' do - post_graphql_mutation(mutation, current_user: current_user) - - expect(response).to have_gitlab_http_status(:success) - expect(mutation_response['commit']).to include( - 'title' => message - ) - end + it_behaves_like 'a commit is successful' context 'when branch is not correct' do let(:branch) { 'unknown' } @@ -47,5 +52,22 @@ RSpec.describe 'Creation of a new commit' do it_behaves_like 'a mutation that returns errors in the response', errors: ['You can only create or edit files when you are on a branch'] end + + context 'when branch is new, and a start_branch is defined' do + let(:input) { { project_path: project.full_path, branch: branch, start_branch: start_branch, message: message, actions: actions } } + let(:branch) { 'new-branch' } + let(:start_branch) { 'master' } + let(:actions) do + [ + { + action: 'CREATE', + filePath: 'ANOTHER_FILE.md', + content: 'Bye' + } + ] + end + + it_behaves_like 'a commit is successful' + end end end diff --git a/spec/requests/api/graphql/mutations/releases/create_spec.rb b/spec/requests/api/graphql/mutations/releases/create_spec.rb index 2402cf62a49..d745eb3083d 100644 --- a/spec/requests/api/graphql/mutations/releases/create_spec.rb +++ b/spec/requests/api/graphql/mutations/releases/create_spec.rb @@ -121,7 +121,7 @@ RSpec.describe 'Creation of a new release' do create_release release = mutation_response[:release] - expected_direct_asset_url = Gitlab::Routing.url_helpers.project_release_url(project, Release.find_by(tag: tag_name)) << asset_link[:directAssetPath] + expected_direct_asset_url = Gitlab::Routing.url_helpers.project_release_url(project, Release.find_by(tag: tag_name)) << "/downloads#{asset_link[:directAssetPath]}" expected_attributes = { tagName: tag_name, diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb index 57b620dbdf7..57dbe258ce4 100644 --- a/spec/requests/api/graphql/project/release_spec.rb +++ b/spec/requests/api/graphql/project/release_spec.rb @@ -147,7 +147,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do 'name' => link.name, 'url' => link.url, 'external' => link.external?, - 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << link.filepath : link.url + 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << "/downloads#{link.filepath}" : link.url } end diff --git a/spec/requests/api/release/links_spec.rb b/spec/requests/api/release/links_spec.rb index 82d0d64eba4..c03dd0331cf 100644 --- a/spec/requests/api/release/links_spec.rb +++ b/spec/requests/api/release/links_spec.rb @@ -146,7 +146,7 @@ RSpec.describe API::Release::Links do specify do get api("/projects/#{project.id}/releases/v0.1/assets/links/#{link.id}", maintainer) - expect(json_response['direct_asset_url']).to eq("http://localhost/#{project.namespace.path}/#{project.name}/-/releases/#{release.tag}/bin/bigfile.exe") + expect(json_response['direct_asset_url']).to eq("http://localhost/#{project.namespace.path}/#{project.name}/-/releases/#{release.tag}/downloads/bin/bigfile.exe") end end diff --git a/spec/requests/projects/releases_controller_spec.rb b/spec/requests/projects/releases_controller_spec.rb new file mode 100644 index 00000000000..8e492125ace --- /dev/null +++ b/spec/requests/projects/releases_controller_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Projects::ReleasesController' do + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user) } + + before do + project.add_developer(user) + login_as(user) + end + + # Added as a request spec because of https://gitlab.com/gitlab-org/gitlab/-/issues/232386 + describe 'GET #downloads' do + context 'filepath redirection' do + let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) } + let!(:link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: filepath, url: 'https://aws.example.com/s3/project/bin/hello-darwin-amd64') } + let_it_be(:url) { "#{project_releases_path(project)}/#{release.tag}/downloads/bin/darwin-amd64" } + + let(:subject) { get url } + + context 'valid filepath' do + let(:filepath) { '/bin/darwin-amd64' } + + it 'redirects to the asset direct link' do + subject + + expect(response).to redirect_to('https://aws.example.com/s3/project/bin/hello-darwin-amd64') + end + + it 'redirects with a status of 302' do + subject + + expect(response).to have_gitlab_http_status(:redirect) + end + end + + context 'invalid filepath' do + let(:filepath) { '/binaries/win32' } + + it 'is not found' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + context 'invalid filepath' do + let(:invalid_filepath) { 'bin/darwin-amd64' } + + let(:subject) { create(:release_link, name: 'linux-amd64 binaries', filepath: invalid_filepath, url: 'https://aws.example.com/s3/project/bin/hello-darwin-amd64') } + + it 'cannot create an invalid filepath' do + expect { subject }.to raise_error(ActiveRecord::RecordInvalid) + end + end + end +end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index e4ec3e56c20..6f7225fadbf 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -867,23 +867,6 @@ RSpec.describe NotificationService, :mailer do should_not_email(non_member_and_mentioned) should_not_email(note.author) end - - context 'when the feature flag is disabled' do - before do - stub_feature_flags(design_management_design_notification_participants: false) - end - - it 'sends a new note notification only to the mentioned member', :aggregate_failures do - notification.new_note(note) - - should_email(member_and_mentioned) - should_not_email(design.authors.first) - should_not_email(member_and_author_of_second_note) - should_not_email(member_and_not_mentioned) - should_not_email(non_member_and_mentioned) - should_not_email(note.author) - end - end end context 'design management is disabled' do |